From 387965661eaa775833b1e35b917f8e568ab7f5c6 Mon Sep 17 00:00:00 2001 From: dougb Date: Sat, 16 Jul 2011 10:49:33 +0000 Subject: Vendor import of BIND 9.8.0-P4 --- CHANGES | 1290 +- COPYRIGHT | 2 +- FAQ.xml | 2 +- HISTORY | 313 + KNOWN-DEFECTS | 15 - Makefile.in | 11 +- NSEC3-NOTES | 128 - README | 448 +- README.idnkit | 112 - README.pkcs11 | 61 - acconfig.h | 4 +- bin/Makefile.in | 7 +- bin/check/Makefile.in | 20 +- bin/check/check-tool.c | 5 +- bin/check/check-tool.h | 2 +- bin/check/named-checkconf.8 | 35 +- bin/check/named-checkconf.c | 43 +- bin/check/named-checkconf.docbook | 36 +- bin/check/named-checkconf.html | 41 +- bin/check/named-checkzone.8 | 19 +- bin/check/named-checkzone.c | 47 +- bin/check/named-checkzone.docbook | 22 +- bin/check/named-checkzone.html | 26 +- bin/confgen/Makefile.in | 101 + bin/confgen/ddns-confgen.8 | 143 + bin/confgen/ddns-confgen.c | 257 + bin/confgen/ddns-confgen.docbook | 218 + bin/confgen/ddns-confgen.html | 141 + bin/confgen/include/confgen/os.h | 39 + bin/confgen/keygen.c | 218 + bin/confgen/keygen.h | 41 + bin/confgen/rndc-confgen.8 | 211 + bin/confgen/rndc-confgen.c | 270 + bin/confgen/rndc-confgen.docbook | 287 + bin/confgen/rndc-confgen.html | 188 + bin/confgen/unix/Makefile.in | 35 + bin/confgen/unix/os.c | 43 + bin/confgen/util.c | 56 + bin/confgen/util.h | 52 + bin/dig/Makefile.in | 26 +- bin/dig/dig.1 | 11 +- bin/dig/dig.c | 176 +- bin/dig/dig.docbook | 16 +- bin/dig/dig.html | 28 +- bin/dig/dighost.c | 223 +- bin/dig/host.1 | 2 +- bin/dig/host.c | 5 +- bin/dig/host.docbook | 2 +- bin/dig/host.html | 2 +- bin/dig/include/dig/dig.h | 14 +- bin/dig/nslookup.1 | 2 +- bin/dig/nslookup.c | 20 +- bin/dig/nslookup.docbook | 2 +- bin/dig/nslookup.html | 2 +- bin/dnssec/Makefile.in | 41 +- bin/dnssec/dnssec-dsfromkey.8 | 55 +- bin/dnssec/dnssec-dsfromkey.c | 314 +- bin/dnssec/dnssec-dsfromkey.docbook | 78 +- bin/dnssec/dnssec-dsfromkey.html | 67 +- bin/dnssec/dnssec-keyfromlabel.8 | 86 +- bin/dnssec/dnssec-keyfromlabel.c | 336 +- bin/dnssec/dnssec-keyfromlabel.docbook | 195 +- bin/dnssec/dnssec-keyfromlabel.html | 136 +- bin/dnssec/dnssec-keygen.8 | 114 +- bin/dnssec/dnssec-keygen.c | 768 +- bin/dnssec/dnssec-keygen.docbook | 264 +- bin/dnssec/dnssec-keygen.html | 196 +- bin/dnssec/dnssec-revoke.8 | 83 + bin/dnssec/dnssec-revoke.c | 269 + bin/dnssec/dnssec-revoke.docbook | 149 + bin/dnssec/dnssec-revoke.html | 87 + bin/dnssec/dnssec-settime.8 | 166 + bin/dnssec/dnssec-settime.c | 576 + bin/dnssec/dnssec-settime.docbook | 319 + bin/dnssec/dnssec-settime.html | 208 + bin/dnssec/dnssec-signzone.8 | 154 +- bin/dnssec/dnssec-signzone.c | 1157 +- bin/dnssec/dnssec-signzone.docbook | 246 +- bin/dnssec/dnssec-signzone.html | 200 +- bin/dnssec/dnssectool.c | 223 +- bin/dnssec/dnssectool.h | 33 +- bin/named/Makefile.in | 33 +- bin/named/bind.keys.h | 99 + bin/named/bind9.xsl | 2 +- bin/named/bind9.xsl.h | 4 +- bin/named/builtin.c | 205 +- bin/named/client.c | 130 +- bin/named/config.c | 74 +- bin/named/control.c | 11 +- bin/named/include/named/client.h | 17 +- bin/named/include/named/config.h | 7 +- bin/named/include/named/control.h | 9 +- bin/named/include/named/globals.h | 21 +- bin/named/include/named/log.h | 2 +- bin/named/include/named/lwdclient.h | 2 +- bin/named/include/named/main.h | 9 +- bin/named/include/named/notify.h | 2 +- bin/named/include/named/query.h | 17 +- bin/named/include/named/server.h | 53 +- bin/named/include/named/tsigconf.h | 7 +- bin/named/include/named/types.h | 6 +- bin/named/include/named/zoneconf.h | 19 +- bin/named/interfacemgr.c | 2 +- bin/named/log.c | 2 +- bin/named/lwdgabn.c | 6 +- bin/named/lwdgrbn.c | 6 +- bin/named/lwresd.8 | 2 +- bin/named/lwresd.c | 7 +- bin/named/lwresd.docbook | 2 +- bin/named/lwresd.html | 2 +- bin/named/main.c | 132 +- bin/named/named.8 | 11 +- bin/named/named.conf.5 | 67 +- bin/named/named.conf.docbook | 68 +- bin/named/named.conf.html | 92 +- bin/named/named.docbook | 17 +- bin/named/named.html | 26 +- bin/named/query.c | 2507 ++- bin/named/server.c | 2460 ++- bin/named/statschannel.c | 19 +- bin/named/tkeyconf.c | 28 +- bin/named/tsigconf.c | 10 +- bin/named/unix/Makefile.in | 4 +- bin/named/unix/include/named/os.h | 8 +- bin/named/unix/os.c | 186 +- bin/named/update.c | 1060 +- bin/named/xfrout.c | 204 +- bin/named/zoneconf.c | 531 +- bin/nsupdate/Makefile.in | 19 +- bin/nsupdate/nsupdate.1 | 98 +- bin/nsupdate/nsupdate.c | 279 +- bin/nsupdate/nsupdate.docbook | 125 +- bin/nsupdate/nsupdate.html | 113 +- bin/rndc/Makefile.in | 40 +- bin/rndc/include/rndc/os.h | 8 +- bin/rndc/rndc-confgen.8 | 211 - bin/rndc/rndc-confgen.c | 342 - bin/rndc/rndc-confgen.docbook | 286 - bin/rndc/rndc-confgen.html | 188 - bin/rndc/rndc.8 | 2 +- bin/rndc/rndc.c | 25 +- bin/rndc/rndc.conf.5 | 2 +- bin/rndc/rndc.conf.html | 2 +- bin/rndc/rndc.html | 2 +- bin/rndc/unix/Makefile.in | 36 - bin/rndc/unix/os.c | 70 - bin/rndc/util.h | 10 +- bin/tools/Makefile.in | 103 + bin/tools/arpaname.1 | 48 + bin/tools/arpaname.c | 53 + bin/tools/arpaname.docbook | 76 + bin/tools/arpaname.html | 52 + bin/tools/genrandom.8 | 69 + bin/tools/genrandom.c | 136 + bin/tools/genrandom.docbook | 119 + bin/tools/genrandom.html | 73 + bin/tools/isc-hmac-fixup.8 | 61 + bin/tools/isc-hmac-fixup.c | 136 + bin/tools/isc-hmac-fixup.docbook | 109 + bin/tools/isc-hmac-fixup.html | 83 + bin/tools/named-journalprint.8 | 60 + bin/tools/named-journalprint.c | 86 + bin/tools/named-journalprint.docbook | 101 + bin/tools/named-journalprint.html | 73 + bin/tools/nsec3hash.8 | 70 + bin/tools/nsec3hash.c | 121 + bin/tools/nsec3hash.docbook | 125 + bin/tools/nsec3hash.html | 78 + config.guess | 2 +- config.h.in | 66 +- configure.in | 501 +- doc/arm/Bv9ARM-book.xml | 2055 +- doc/arm/Bv9ARM.ch01.html | 54 +- doc/arm/Bv9ARM.ch02.html | 30 +- doc/arm/Bv9ARM.ch03.html | 174 +- doc/arm/Bv9ARM.ch04.html | 969 +- doc/arm/Bv9ARM.ch05.html | 8 +- doc/arm/Bv9ARM.ch06.html | 1669 +- doc/arm/Bv9ARM.ch07.html | 29 +- doc/arm/Bv9ARM.ch08.html | 20 +- doc/arm/Bv9ARM.ch09.html | 657 +- doc/arm/Bv9ARM.ch10.html | 28 +- doc/arm/Bv9ARM.html | 217 +- doc/arm/Bv9ARM.pdf | 23307 ++++++++++++--------- doc/arm/Makefile.in | 2 +- doc/arm/dnssec.xml | 268 + doc/arm/libdns.xml | 530 + doc/arm/man.arpaname.html | 91 + doc/arm/man.ddns-confgen.html | 180 + doc/arm/man.dig.html | 28 +- doc/arm/man.dnssec-dsfromkey.html | 67 +- doc/arm/man.dnssec-keyfromlabel.html | 136 +- doc/arm/man.dnssec-keygen.html | 206 +- doc/arm/man.dnssec-revoke.html | 126 + doc/arm/man.dnssec-settime.html | 247 + doc/arm/man.dnssec-signzone.html | 210 +- doc/arm/man.genrandom.html | 112 + doc/arm/man.host.html | 12 +- doc/arm/man.isc-hmac-fixup.html | 122 + doc/arm/man.named-checkconf.html | 41 +- doc/arm/man.named-checkzone.html | 26 +- doc/arm/man.named-journalprint.html | 112 + doc/arm/man.named.html | 36 +- doc/arm/man.nsec3hash.html | 113 + doc/arm/man.nsupdate.html | 123 +- doc/arm/man.rndc-confgen.html | 24 +- doc/arm/man.rndc.conf.html | 14 +- doc/arm/man.rndc.html | 14 +- doc/arm/managed-keys.xml | 100 + doc/arm/pkcs11.xml | 390 + doc/misc/Makefile.in | 2 +- doc/misc/options | 104 +- lib/bind9/Makefile.in | 4 +- lib/bind9/api | 4 +- lib/bind9/check.c | 549 +- lib/bind9/include/bind9/getaddresses.h | 2 +- lib/dns/Makefile.in | 44 +- lib/dns/acl.c | 2 +- lib/dns/adb.c | 581 +- lib/dns/api | 4 +- lib/dns/byaddr.c | 47 +- lib/dns/cache.c | 78 +- lib/dns/client.c | 3019 +++ lib/dns/db.c | 46 +- lib/dns/diff.c | 19 +- lib/dns/dispatch.c | 93 +- lib/dns/dlz.c | 154 +- lib/dns/dns64.c | 299 + lib/dns/dnssec.c | 804 +- lib/dns/ds.c | 72 +- lib/dns/dst_api.c | 489 +- lib/dns/dst_internal.h | 40 +- lib/dns/dst_openssl.h | 9 +- lib/dns/dst_parse.c | 193 +- lib/dns/dst_parse.h | 21 +- lib/dns/ecdb.c | 810 + lib/dns/forward.c | 22 +- lib/dns/gen-unix.h | 2 +- lib/dns/gen.c | 6 +- lib/dns/gssapi_link.c | 91 +- lib/dns/gssapictx.c | 96 +- lib/dns/hmac_link.c | 211 +- lib/dns/include/dns/Makefile.in | 20 +- lib/dns/include/dns/acl.h | 2 +- lib/dns/include/dns/cache.h | 39 +- lib/dns/include/dns/client.h | 621 + lib/dns/include/dns/compress.h | 2 +- lib/dns/include/dns/db.h | 49 +- lib/dns/include/dns/diff.h | 2 +- lib/dns/include/dns/dispatch.h | 2 +- lib/dns/include/dns/dlz.h | 62 +- lib/dns/include/dns/dns64.h | 175 + lib/dns/include/dns/dnssec.h | 137 +- lib/dns/include/dns/ds.h | 9 +- lib/dns/include/dns/ecdb.h | 52 + lib/dns/include/dns/events.h | 7 +- lib/dns/include/dns/forward.h | 19 +- lib/dns/include/dns/journal.h | 2 +- lib/dns/include/dns/keydata.h | 55 + lib/dns/include/dns/keytable.h | 212 +- lib/dns/include/dns/keyvalues.h | 8 +- lib/dns/include/dns/lib.h | 18 +- lib/dns/include/dns/log.h | 3 +- lib/dns/include/dns/lookup.h | 2 +- lib/dns/include/dns/master.h | 5 +- lib/dns/include/dns/masterdump.h | 2 +- lib/dns/include/dns/message.h | 20 +- lib/dns/include/dns/name.h | 84 +- lib/dns/include/dns/ncache.h | 2 +- lib/dns/include/dns/nsec3.h | 61 +- lib/dns/include/dns/peer.h | 2 +- lib/dns/include/dns/private.h | 55 + lib/dns/include/dns/rbt.h | 19 +- lib/dns/include/dns/rdata.h | 55 +- lib/dns/include/dns/rdataset.h | 2 +- lib/dns/include/dns/request.h | 11 +- lib/dns/include/dns/resolver.h | 28 +- lib/dns/include/dns/result.h | 9 +- lib/dns/include/dns/rpz.h | 189 + lib/dns/include/dns/rriterator.h | 103 + lib/dns/include/dns/sdb.h | 2 +- lib/dns/include/dns/sdlz.h | 130 +- lib/dns/include/dns/secalg.h | 11 +- lib/dns/include/dns/soa.h | 26 +- lib/dns/include/dns/ssu.h | 31 +- lib/dns/include/dns/stats.h | 2 +- lib/dns/include/dns/tkey.h | 14 +- lib/dns/include/dns/tsec.h | 135 + lib/dns/include/dns/tsig.h | 32 +- lib/dns/include/dns/types.h | 18 +- lib/dns/include/dns/validator.h | 2 +- lib/dns/include/dns/view.h | 211 +- lib/dns/include/dns/xfrin.h | 2 +- lib/dns/include/dns/zone.h | 109 +- lib/dns/include/dst/dst.h | 241 +- lib/dns/include/dst/gssapi.h | 13 +- lib/dns/iptable.c | 2 +- lib/dns/journal.c | 8 +- lib/dns/keydata.c | 89 + lib/dns/keytable.c | 389 +- lib/dns/lib.c | 109 +- lib/dns/log.c | 5 +- lib/dns/master.c | 113 +- lib/dns/masterdump.c | 65 +- lib/dns/message.c | 59 +- lib/dns/name.c | 77 +- lib/dns/ncache.c | 57 +- lib/dns/nsec.c | 2 +- lib/dns/nsec3.c | 490 +- lib/dns/openssl_link.c | 231 +- lib/dns/openssldh_link.c | 45 +- lib/dns/openssldsa_link.c | 47 +- lib/dns/opensslgost_link.c | 418 + lib/dns/opensslrsa_link.c | 166 +- lib/dns/peer.c | 6 +- lib/dns/private.c | 295 + lib/dns/rbt.c | 9 +- lib/dns/rbtdb.c | 826 +- lib/dns/rcode.c | 27 +- lib/dns/rdata.c | 143 +- lib/dns/rdata/any_255/tsig_250.c | 9 +- lib/dns/rdata/ch_3/a_1.c | 12 +- lib/dns/rdata/generic/afsdb_18.c | 8 +- lib/dns/rdata/generic/cert_37.c | 10 +- lib/dns/rdata/generic/cname_5.c | 9 +- lib/dns/rdata/generic/dlv_32769.c | 36 +- lib/dns/rdata/generic/dname_39.c | 8 +- lib/dns/rdata/generic/dnskey_48.c | 41 +- lib/dns/rdata/generic/ds_43.c | 32 +- lib/dns/rdata/generic/gpos_27.c | 9 +- lib/dns/rdata/generic/hinfo_13.c | 8 +- lib/dns/rdata/generic/hip_55.c | 506 + lib/dns/rdata/generic/hip_55.h | 47 + lib/dns/rdata/generic/ipseckey_45.c | 41 +- lib/dns/rdata/generic/isdn_20.c | 9 +- lib/dns/rdata/generic/key_25.c | 37 +- lib/dns/rdata/generic/keydata_65533.c | 377 + lib/dns/rdata/generic/keydata_65533.h | 35 + lib/dns/rdata/generic/loc_29.c | 7 +- lib/dns/rdata/generic/mb_7.c | 15 +- lib/dns/rdata/generic/md_3.c | 15 +- lib/dns/rdata/generic/mf_4.c | 15 +- lib/dns/rdata/generic/mg_8.c | 15 +- lib/dns/rdata/generic/minfo_14.c | 21 +- lib/dns/rdata/generic/mr_9.c | 15 +- lib/dns/rdata/generic/mx_15.c | 13 +- lib/dns/rdata/generic/ns_2.c | 15 +- lib/dns/rdata/generic/nsec3_50.c | 7 +- lib/dns/rdata/generic/nsec3param_51.c | 7 +- lib/dns/rdata/generic/nsec_47.c | 36 +- lib/dns/rdata/generic/null_10.c | 9 +- lib/dns/rdata/generic/nxt_30.c | 8 +- lib/dns/rdata/generic/opt_41.c | 9 +- lib/dns/rdata/generic/proforma.c | 21 +- lib/dns/rdata/generic/ptr_12.c | 14 +- lib/dns/rdata/generic/rp_17.c | 20 +- lib/dns/rdata/generic/rrsig_46.c | 47 +- lib/dns/rdata/generic/rt_21.c | 13 +- lib/dns/rdata/generic/sig_24.c | 8 +- lib/dns/rdata/generic/soa_6.c | 7 +- lib/dns/rdata/generic/spf_99.c | 8 +- lib/dns/rdata/generic/sshfp_44.c | 9 +- lib/dns/rdata/generic/tkey_249.c | 8 +- lib/dns/rdata/generic/txt_16.c | 9 +- lib/dns/rdata/generic/unspec_103.c | 9 +- lib/dns/rdata/generic/x25_19.c | 9 +- lib/dns/rdata/hs_4/a_1.c | 9 +- lib/dns/rdata/in_1/a6_38.c | 9 +- lib/dns/rdata/in_1/a_1.c | 9 +- lib/dns/rdata/in_1/aaaa_28.c | 8 +- lib/dns/rdata/in_1/apl_42.c | 9 +- lib/dns/rdata/in_1/dhcid_49.c | 11 +- lib/dns/rdata/in_1/kx_36.c | 13 +- lib/dns/rdata/in_1/naptr_35.c | 136 +- lib/dns/rdata/in_1/nsap-ptr_23.c | 15 +- lib/dns/rdata/in_1/nsap_22.c | 9 +- lib/dns/rdata/in_1/px_26.c | 13 +- lib/dns/rdata/in_1/srv_33.c | 13 +- lib/dns/rdata/in_1/wks_11.c | 7 +- lib/dns/rdatalist.c | 2 +- lib/dns/rdataset.c | 2 +- lib/dns/rdataslab.c | 28 +- lib/dns/request.c | 10 +- lib/dns/resolver.c | 630 +- lib/dns/result.c | 7 +- lib/dns/rootns.c | 2 +- lib/dns/rpz.c | 1168 ++ lib/dns/rriterator.c | 202 + lib/dns/sdb.c | 8 +- lib/dns/sdlz.c | 413 +- lib/dns/soa.c | 40 +- lib/dns/spnego.c | 9 +- lib/dns/ssu.c | 68 +- lib/dns/ssu_external.c | 265 + lib/dns/stats.c | 2 +- lib/dns/time.c | 2 +- lib/dns/tkey.c | 53 +- lib/dns/tsec.c | 160 + lib/dns/tsig.c | 367 +- lib/dns/validator.c | 428 +- lib/dns/view.c | 421 +- lib/dns/xfrin.c | 43 +- lib/dns/zone.c | 13033 +++++++----- lib/export/Makefile.in | 27 + lib/export/dns/Makefile.in | 179 + lib/export/dns/include/Makefile.in | 23 + lib/export/dns/include/dns/Makefile.in | 56 + lib/export/dns/include/dst/Makefile.in | 36 + lib/export/irs/Makefile.in | 86 + lib/export/irs/include/Makefile.in | 24 + lib/export/irs/include/irs/Makefile.in | 46 + lib/export/isc/Makefile.in | 139 + lib/export/isc/include/Makefile.in | 24 + lib/export/isc/include/isc/Makefile.in | 66 + lib/export/isc/include/isc/bind9.h | 30 + lib/export/isc/nls/Makefile.in | 35 + lib/export/isc/nothreads/Makefile.in | 40 + lib/export/isc/nothreads/include/Makefile.in | 24 + lib/export/isc/nothreads/include/isc/Makefile.in | 36 + lib/export/isc/pthreads/Makefile.in | 38 + lib/export/isc/pthreads/include/Makefile.in | 24 + lib/export/isc/pthreads/include/isc/Makefile.in | 36 + lib/export/isc/unix/Makefile.in | 57 + lib/export/isc/unix/include/Makefile.in | 24 + lib/export/isc/unix/include/isc/Makefile.in | 37 + lib/export/isccfg/Makefile.in | 83 + lib/export/isccfg/include/Makefile.in | 24 + lib/export/isccfg/include/isccfg/Makefile.in | 42 + lib/export/samples/Makefile-postinstall.in | 78 + lib/export/samples/Makefile.in | 98 + lib/export/samples/nsprobe.c | 1220 ++ lib/export/samples/sample-async.c | 402 + lib/export/samples/sample-gai.c | 77 + lib/export/samples/sample-request.c | 263 + lib/export/samples/sample-update.c | 755 + lib/export/samples/sample.c | 378 + lib/irs/Makefile.in | 80 + lib/irs/api | 3 + lib/irs/context.c | 396 + lib/irs/dnsconf.c | 269 + lib/irs/gai_strerror.c | 93 + lib/irs/getaddrinfo.c | 1295 ++ lib/irs/getnameinfo.c | 410 + lib/irs/include/Makefile.in | 24 + lib/irs/include/irs/Makefile.in | 44 + lib/irs/include/irs/context.h | 159 + lib/irs/include/irs/dnsconf.h | 94 + lib/irs/include/irs/netdb.h.in | 167 + lib/irs/include/irs/platform.h.in | 45 + lib/irs/include/irs/resconf.h | 113 + lib/irs/include/irs/types.h | 31 + lib/irs/include/irs/version.h | 27 + lib/irs/resconf.c | 636 + lib/irs/version.c | 27 + lib/isc/Makefile.in | 38 +- lib/isc/alpha/include/isc/atomic.h | 2 +- lib/isc/api | 6 +- lib/isc/app_api.c | 136 + lib/isc/assertions.c | 64 +- lib/isc/backtrace-emptytbl.c | 34 + lib/isc/backtrace.c | 285 + lib/isc/base32.c | 2 +- lib/isc/base64.c | 2 +- lib/isc/entropy.c | 2 +- lib/isc/hash.c | 20 +- lib/isc/heap.c | 2 +- lib/isc/hmacmd5.c | 35 +- lib/isc/hmacsha.c | 269 +- lib/isc/httpd.c | 2 +- lib/isc/ia64/include/isc/atomic.h | 2 +- lib/isc/include/isc/Makefile.in | 10 +- lib/isc/include/isc/app.h | 173 +- lib/isc/include/isc/assertions.h | 8 +- lib/isc/include/isc/backtrace.h | 131 + lib/isc/include/isc/bind9.h | 30 + lib/isc/include/isc/buffer.h | 4 +- lib/isc/include/isc/entropy.h | 2 +- lib/isc/include/isc/error.h | 9 +- lib/isc/include/isc/file.h | 31 +- lib/isc/include/isc/fsaccess.h | 2 +- lib/isc/include/isc/hash.h | 2 +- lib/isc/include/isc/heap.h | 2 +- lib/isc/include/isc/hmacmd5.h | 13 +- lib/isc/include/isc/hmacsha.h | 17 +- lib/isc/include/isc/lib.h | 13 +- lib/isc/include/isc/log.h | 2 +- lib/isc/include/isc/md5.h | 14 +- lib/isc/include/isc/mem.h | 161 +- lib/isc/include/isc/msgs.h | 6 +- lib/isc/include/isc/namespace.h | 164 + lib/isc/include/isc/netaddr.h | 2 +- lib/isc/include/isc/netscope.h | 2 +- lib/isc/include/isc/platform.h.in | 24 +- lib/isc/include/isc/portset.h | 2 +- lib/isc/include/isc/radix.h | 2 +- lib/isc/include/isc/random.h | 2 +- lib/isc/include/isc/ratelimiter.h | 2 +- lib/isc/include/isc/refcount.h | 12 +- lib/isc/include/isc/result.h | 5 +- lib/isc/include/isc/resultclass.h | 5 +- lib/isc/include/isc/serial.h | 2 +- lib/isc/include/isc/sha1.h | 13 +- lib/isc/include/isc/sha2.h | 17 +- lib/isc/include/isc/sockaddr.h | 2 +- lib/isc/include/isc/socket.h | 149 +- lib/isc/include/isc/stats.h | 2 +- lib/isc/include/isc/symtab.h | 2 +- lib/isc/include/isc/task.h | 108 +- lib/isc/include/isc/timer.h | 93 +- lib/isc/include/isc/types.h | 9 +- lib/isc/include/isc/util.h | 2 +- lib/isc/inet_aton.c | 4 +- lib/isc/inet_ntop.c | 2 +- lib/isc/iterated_hash.c | 2 +- lib/isc/lib.c | 34 +- lib/isc/log.c | 2 +- lib/isc/md5.c | 30 +- lib/isc/mem.c | 573 +- lib/isc/mem_api.c | 303 + lib/isc/netaddr.c | 24 +- lib/isc/nls/Makefile.in | 4 +- lib/isc/nothreads/Makefile.in | 8 +- lib/isc/powerpc/include/isc/atomic.h | 2 +- lib/isc/print.c | 2 +- lib/isc/pthreads/Makefile.in | 4 +- lib/isc/pthreads/mutex.c | 2 +- lib/isc/radix.c | 2 +- lib/isc/random.c | 4 +- lib/isc/rwlock.c | 2 +- lib/isc/sha1.c | 41 +- lib/isc/sha2.c | 429 +- lib/isc/sockaddr.c | 8 +- lib/isc/socket_api.c | 216 + lib/isc/stats.c | 2 +- lib/isc/task.c | 517 +- lib/isc/task_api.c | 216 + lib/isc/task_p.h | 8 +- lib/isc/timer.c | 346 +- lib/isc/timer_api.c | 144 + lib/isc/timer_p.h | 8 +- lib/isc/unix/Makefile.in | 4 +- lib/isc/unix/app.c | 540 +- lib/isc/unix/dir.c | 4 +- lib/isc/unix/entropy.c | 4 +- lib/isc/unix/file.c | 90 +- lib/isc/unix/ifiter_getifaddrs.c | 2 +- lib/isc/unix/ifiter_ioctl.c | 2 +- lib/isc/unix/include/isc/net.h | 4 +- lib/isc/unix/include/isc/offset.h | 4 +- lib/isc/unix/include/isc/strerror.h | 4 +- lib/isc/unix/include/isc/time.h | 2 +- lib/isc/unix/interfaceiter.c | 4 +- lib/isc/unix/resource.c | 2 +- lib/isc/unix/socket.c | 952 +- lib/isc/unix/socket_p.h | 9 +- lib/isc/unix/strerror.c | 2 +- lib/isccc/Makefile.in | 6 +- lib/isccc/api | 4 +- lib/isccfg/Makefile.in | 8 +- lib/isccfg/aclconf.c | 25 +- lib/isccfg/api | 6 +- lib/isccfg/dnsconf.c | 69 + lib/isccfg/include/isccfg/aclconf.h | 14 +- lib/isccfg/include/isccfg/cfg.h | 38 +- lib/isccfg/include/isccfg/dnsconf.h | 35 + lib/isccfg/include/isccfg/grammar.h | 24 +- lib/isccfg/include/isccfg/log.h | 2 +- lib/isccfg/include/isccfg/namedconf.h | 16 +- lib/isccfg/namedconf.c | 588 +- lib/isccfg/parser.c | 92 +- lib/lwres/api | 4 +- lib/lwres/context.c | 2 +- lib/lwres/context_p.h | 2 +- lib/lwres/getaddrinfo.c | 4 +- lib/lwres/getipnode.c | 2 +- lib/lwres/include/lwres/context.h | 2 +- lib/lwres/include/lwres/netdb.h.in | 2 +- lib/lwres/lwconfig.c | 2 +- lib/lwres/man/lwres.3 | 2 +- lib/lwres/man/lwres.html | 14 +- lib/lwres/man/lwres_buffer.3 | 2 +- lib/lwres/man/lwres_buffer.html | 6 +- lib/lwres/man/lwres_config.3 | 2 +- lib/lwres/man/lwres_config.html | 12 +- lib/lwres/man/lwres_context.3 | 2 +- lib/lwres/man/lwres_context.html | 10 +- lib/lwres/man/lwres_gabn.3 | 2 +- lib/lwres/man/lwres_gabn.html | 10 +- lib/lwres/man/lwres_gai_strerror.3 | 2 +- lib/lwres/man/lwres_gai_strerror.html | 8 +- lib/lwres/man/lwres_getaddrinfo.3 | 2 +- lib/lwres/man/lwres_getaddrinfo.html | 10 +- lib/lwres/man/lwres_gethostent.3 | 2 +- lib/lwres/man/lwres_gethostent.html | 12 +- lib/lwres/man/lwres_getipnode.3 | 2 +- lib/lwres/man/lwres_getipnode.html | 10 +- lib/lwres/man/lwres_getnameinfo.3 | 2 +- lib/lwres/man/lwres_getnameinfo.html | 12 +- lib/lwres/man/lwres_getrrsetbyname.3 | 2 +- lib/lwres/man/lwres_getrrsetbyname.html | 10 +- lib/lwres/man/lwres_gnba.3 | 2 +- lib/lwres/man/lwres_gnba.html | 10 +- lib/lwres/man/lwres_hstrerror.3 | 2 +- lib/lwres/man/lwres_hstrerror.html | 10 +- lib/lwres/man/lwres_inetntop.3 | 2 +- lib/lwres/man/lwres_inetntop.html | 10 +- lib/lwres/man/lwres_noop.3 | 2 +- lib/lwres/man/lwres_noop.html | 10 +- lib/lwres/man/lwres_packet.3 | 2 +- lib/lwres/man/lwres_packet.html | 8 +- lib/lwres/man/lwres_resutil.3 | 2 +- lib/lwres/man/lwres_resutil.html | 10 +- lib/lwres/print_p.h | 2 +- make/rules.in | 91 +- version | 10 +- 615 files changed, 82699 insertions(+), 24697 deletions(-) create mode 100644 HISTORY delete mode 100644 KNOWN-DEFECTS delete mode 100644 NSEC3-NOTES delete mode 100644 README.idnkit delete mode 100644 README.pkcs11 create mode 100644 bin/confgen/Makefile.in create mode 100644 bin/confgen/ddns-confgen.8 create mode 100644 bin/confgen/ddns-confgen.c create mode 100644 bin/confgen/ddns-confgen.docbook create mode 100644 bin/confgen/ddns-confgen.html create mode 100644 bin/confgen/include/confgen/os.h create mode 100644 bin/confgen/keygen.c create mode 100644 bin/confgen/keygen.h create mode 100644 bin/confgen/rndc-confgen.8 create mode 100644 bin/confgen/rndc-confgen.c create mode 100644 bin/confgen/rndc-confgen.docbook create mode 100644 bin/confgen/rndc-confgen.html create mode 100644 bin/confgen/unix/Makefile.in create mode 100644 bin/confgen/unix/os.c create mode 100644 bin/confgen/util.c create mode 100644 bin/confgen/util.h create mode 100644 bin/dnssec/dnssec-revoke.8 create mode 100644 bin/dnssec/dnssec-revoke.c create mode 100644 bin/dnssec/dnssec-revoke.docbook create mode 100644 bin/dnssec/dnssec-revoke.html create mode 100644 bin/dnssec/dnssec-settime.8 create mode 100644 bin/dnssec/dnssec-settime.c create mode 100644 bin/dnssec/dnssec-settime.docbook create mode 100644 bin/dnssec/dnssec-settime.html create mode 100644 bin/named/bind.keys.h delete mode 100644 bin/rndc/rndc-confgen.8 delete mode 100644 bin/rndc/rndc-confgen.c delete mode 100644 bin/rndc/rndc-confgen.docbook delete mode 100644 bin/rndc/rndc-confgen.html delete mode 100644 bin/rndc/unix/Makefile.in delete mode 100644 bin/rndc/unix/os.c create mode 100644 bin/tools/Makefile.in create mode 100644 bin/tools/arpaname.1 create mode 100644 bin/tools/arpaname.c create mode 100644 bin/tools/arpaname.docbook create mode 100644 bin/tools/arpaname.html create mode 100644 bin/tools/genrandom.8 create mode 100644 bin/tools/genrandom.c create mode 100644 bin/tools/genrandom.docbook create mode 100644 bin/tools/genrandom.html create mode 100644 bin/tools/isc-hmac-fixup.8 create mode 100644 bin/tools/isc-hmac-fixup.c create mode 100644 bin/tools/isc-hmac-fixup.docbook create mode 100644 bin/tools/isc-hmac-fixup.html create mode 100644 bin/tools/named-journalprint.8 create mode 100644 bin/tools/named-journalprint.c create mode 100644 bin/tools/named-journalprint.docbook create mode 100644 bin/tools/named-journalprint.html create mode 100644 bin/tools/nsec3hash.8 create mode 100644 bin/tools/nsec3hash.c create mode 100644 bin/tools/nsec3hash.docbook create mode 100644 bin/tools/nsec3hash.html create mode 100644 doc/arm/dnssec.xml create mode 100644 doc/arm/libdns.xml create mode 100644 doc/arm/man.arpaname.html create mode 100644 doc/arm/man.ddns-confgen.html create mode 100644 doc/arm/man.dnssec-revoke.html create mode 100644 doc/arm/man.dnssec-settime.html create mode 100644 doc/arm/man.genrandom.html create mode 100644 doc/arm/man.isc-hmac-fixup.html create mode 100644 doc/arm/man.named-journalprint.html create mode 100644 doc/arm/man.nsec3hash.html create mode 100644 doc/arm/managed-keys.xml create mode 100644 doc/arm/pkcs11.xml create mode 100644 lib/dns/client.c create mode 100644 lib/dns/dns64.c create mode 100644 lib/dns/ecdb.c create mode 100644 lib/dns/include/dns/client.h create mode 100644 lib/dns/include/dns/dns64.h create mode 100644 lib/dns/include/dns/ecdb.h create mode 100644 lib/dns/include/dns/keydata.h create mode 100644 lib/dns/include/dns/private.h create mode 100644 lib/dns/include/dns/rpz.h create mode 100644 lib/dns/include/dns/rriterator.h create mode 100644 lib/dns/include/dns/tsec.h create mode 100644 lib/dns/keydata.c create mode 100644 lib/dns/opensslgost_link.c create mode 100644 lib/dns/private.c create mode 100644 lib/dns/rdata/generic/hip_55.c create mode 100644 lib/dns/rdata/generic/hip_55.h create mode 100644 lib/dns/rdata/generic/keydata_65533.c create mode 100644 lib/dns/rdata/generic/keydata_65533.h create mode 100644 lib/dns/rpz.c create mode 100644 lib/dns/rriterator.c create mode 100644 lib/dns/ssu_external.c create mode 100644 lib/dns/tsec.c create mode 100644 lib/export/Makefile.in create mode 100644 lib/export/dns/Makefile.in create mode 100644 lib/export/dns/include/Makefile.in create mode 100644 lib/export/dns/include/dns/Makefile.in create mode 100644 lib/export/dns/include/dst/Makefile.in create mode 100644 lib/export/irs/Makefile.in create mode 100644 lib/export/irs/include/Makefile.in create mode 100644 lib/export/irs/include/irs/Makefile.in create mode 100644 lib/export/isc/Makefile.in create mode 100644 lib/export/isc/include/Makefile.in create mode 100644 lib/export/isc/include/isc/Makefile.in create mode 100644 lib/export/isc/include/isc/bind9.h create mode 100644 lib/export/isc/nls/Makefile.in create mode 100644 lib/export/isc/nothreads/Makefile.in create mode 100644 lib/export/isc/nothreads/include/Makefile.in create mode 100644 lib/export/isc/nothreads/include/isc/Makefile.in create mode 100644 lib/export/isc/pthreads/Makefile.in create mode 100644 lib/export/isc/pthreads/include/Makefile.in create mode 100644 lib/export/isc/pthreads/include/isc/Makefile.in create mode 100644 lib/export/isc/unix/Makefile.in create mode 100644 lib/export/isc/unix/include/Makefile.in create mode 100644 lib/export/isc/unix/include/isc/Makefile.in create mode 100644 lib/export/isccfg/Makefile.in create mode 100644 lib/export/isccfg/include/Makefile.in create mode 100644 lib/export/isccfg/include/isccfg/Makefile.in create mode 100644 lib/export/samples/Makefile-postinstall.in create mode 100644 lib/export/samples/Makefile.in create mode 100644 lib/export/samples/nsprobe.c create mode 100644 lib/export/samples/sample-async.c create mode 100644 lib/export/samples/sample-gai.c create mode 100644 lib/export/samples/sample-request.c create mode 100644 lib/export/samples/sample-update.c create mode 100644 lib/export/samples/sample.c create mode 100644 lib/irs/Makefile.in create mode 100644 lib/irs/api create mode 100644 lib/irs/context.c create mode 100644 lib/irs/dnsconf.c create mode 100644 lib/irs/gai_strerror.c create mode 100644 lib/irs/getaddrinfo.c create mode 100644 lib/irs/getnameinfo.c create mode 100644 lib/irs/include/Makefile.in create mode 100644 lib/irs/include/irs/Makefile.in create mode 100644 lib/irs/include/irs/context.h create mode 100644 lib/irs/include/irs/dnsconf.h create mode 100644 lib/irs/include/irs/netdb.h.in create mode 100644 lib/irs/include/irs/platform.h.in create mode 100644 lib/irs/include/irs/resconf.h create mode 100644 lib/irs/include/irs/types.h create mode 100644 lib/irs/include/irs/version.h create mode 100644 lib/irs/resconf.c create mode 100644 lib/irs/version.c create mode 100644 lib/isc/app_api.c create mode 100644 lib/isc/backtrace-emptytbl.c create mode 100644 lib/isc/backtrace.c create mode 100644 lib/isc/include/isc/backtrace.h create mode 100644 lib/isc/include/isc/bind9.h create mode 100644 lib/isc/include/isc/namespace.h create mode 100644 lib/isc/mem_api.c create mode 100644 lib/isc/socket_api.c create mode 100644 lib/isc/task_api.c create mode 100644 lib/isc/timer_api.c create mode 100644 lib/isccfg/dnsconf.c create mode 100644 lib/isccfg/include/isccfg/dnsconf.h diff --git a/CHANGES b/CHANGES index 4a7cada..80ac38a 100644 --- a/CHANGES +++ b/CHANGES @@ -1,17 +1,28 @@ - --- 9.6-ESV-R4-P3 released --- + --- 9.8.0-P4 released --- 3124. [bug] Use an rdataset attribute flag to indicate negative-cache records rather than using rrtype 0; this will prevent problems when that rrtype is used in actual DNS packets. [RT #24777] - --- 9.6-ESV-R4-P2 released (withdrawn) --- + --- 9.8.0-P3 released (withdrawn) --- + +3126. [security] Using DNAME record to generate replacements caused + RPZ to exit with a assertion failure. [RT #23766] + +3125. [security] Using wildcard CNAME records as a replacement with + RPZ caused named to exit with a assertion failure. + [RT #24715] 3123. [security] Change #2912 exposed a latent flaw in dns_rdataset_totext() that could cause named to crash with an assertion failure. [RT #24777] - --- 9.6-ESV-R4-P1 released --- +3115. [bug] Named could fail to return requested data when + following a CNAME that points into the same zone. + [RT #2445] + + --- 9.8.0-P2 released --- 3121. [security] An authoritative name server sending a negative response containing a very large RRset could @@ -22,22 +33,114 @@ that validated insecure without using DLV and had DS records in the parent zone. [RT #24631] - --- 9.6-ESV-R4 released --- + --- 9.8.0-P1 released --- + +3100. [security] Certain response policy zone configurations could + trigger an INSIST when receiving a query of type + RRSIG. [RT #24280] + + --- 9.8.0 released --- + +3025. [bug] Fixed a possible deadlock due to zone resigning. + [RT #22964] + +3024. [func] RTT Banding removed due to minor security increase + but major impact on resolver latency. [RT #23310] + +3023. [bug] Named could be left in an inconsistent state when + receiving multiple AXFR response messages that were + not all TSIG-signed. [RT #23254] + +3022. [bug] Fixed rpz SERVFAILs after failed zone transfers + [RT #23246] + +3021. [bug] Change #3010 was incomplete. [RT #22296] + +3020. [bug] auto-dnssec failed to correctly update the zone when + changing the DNSKEY RRset. [RT #23232] + +3019. [test] Test: check apex NSEC3 records after adding DNSKEY + record via UPDATE. [RT #23229] + + --- 9.8.0rc1 released --- + +3018. [bug] Named failed to check for the "none;" acl when deciding + if a zone may need to be re-signed. [RT #23120] + +3017. [doc] dnssec-keyfromlabel -I was not properly documented. + [RT #22887] + +3016. [bug] rndc usage missing '-b'. [RT #22937] + +3015. [port] win32: fix IN6_IS_ADDR_LINKLOCAL and + IN6_IS_ADDR_SITELOCAL macros. [RT #22724] - --- 9.6.3 released --- +3013. [bug] The DNS64 ttl was not always being set as expected. + [RT #23034] + +3012. [bug] Remove DNSKEY TTL change pairs before generating + signing records for any remaining DNSKEY changes. + [RT #22590] + +3011. [func] Allow setting this in named.conf using the new + 'resolver-query-timeout' option, which specifies a max + time in seconds. 0 means 'default' and anything longer + than 30 will be silently set to 30. [RT #22852] + +3010. [bug] Fixed a bug where "rndc reconfig" stopped the timer + for refreshing managed-keys. [RT #22296] 3009. [bug] clients-per-query code didn't work as expected with particular query patterns. [RT #22972] - --- 9.6.3rc1 released --- + --- 9.8.0b1 released --- + +3008. [func] Response policy zones (RPZ) support. [RT #21726] 3007. [bug] Named failed to preserve the case of domain names in rdata which is not compressible when writing master files. [RT #22863] +3006. [func] Allow dynamically generated TSIG keys to be preserved + across restarts of named. Initially this is for + TSIG keys generated using GSSAPI. [RT #22639] + +3005. [port] Solaris: Work around the lack of + gsskrb5_register_acceptor_identity() by setting + the KRB5_KTNAME environment variable to the + contents of tkey-gssapi-keytab. Also fixed + test errors on MacOSX. [RT #22853] + +3004. [func] DNS64 reverse support. [RT #22769] + +3003. [experimental] Added update-policy match type "external", + enabling named to defer the decision of whether to + allow a dynamic update to an external daemon. + (Contributed by Andrew Tridgell.) [RT #22758] + 3002. [bug] isc_mutex_init_errcheck() failed to destroy attr. [RT #22766] +3001. [func] Added a default trust anchor for the root zone, which + can be switched on by setting "dnssec-validation auto;" + in the named.conf options. [RT #21727] + +3000. [bug] More TKEY/GSS fixes: + - nsupdate can now get the default realm from + the user's Kerberos principal + - corrected gsstest compilation flags + - improved documentation + - fixed some NULL dereferences + [RT #22795] + +2999. [func] Add GOST support (RFC 5933). [RT #20639] + +2998. [func] Add isc_task_beginexclusive and isc_task_endexclusive + to the task api. [RT #22776] + +2997. [func] named -V now reports the OpenSSL and libxml2 verions + it was compiled against. [RT #22687] + 2996. [security] Temporarily disable SO_ACCEPTFILTER support. [RT #22589] @@ -48,13 +151,52 @@ do not use threads on earlier versions. Also kill the unproven-pthreads, mit-pthreads, and ptl2 support. +2993. [func] Dynamically grow adb hash tables. [RT #21186] + +2992. [contrib] contrib/check-secure-delegation.pl: A simple tool + for looking at a secure delegation. [RT #22059] + +2991. [contrib] contrib/zone-edit.sh: A simple zone editing tool for + dynamic zones. [RT #22365] + +2990. [bug] 'dnssec-settime -S' no longer tests prepublication + interval validity when the interval is set to 0. + [RT #22761] + +2989. [func] Added support for writable DLZ zones. (Contributed + by Andrew Tridgell of the Samba project.) [RT #22629] + +2988. [experimental] Added a "dlopen" DLZ driver, allowing the creation + of external DLZ drivers that can be loaded as + shared objects at runtime rather than linked with + named. Currently this is switched on via a + compile-time option, "configure --with-dlz-dlopen". + Note: the syntax for configuring DLZ zones + is likely to be refined in future releases. + (Contributed by Andrew Tridgell of the Samba + project.) [RT #22629] + +2987. [func] Improve ease of configuring TKEY/GSS updates by + adding a "tkey-gssapi-keytab" option. If set, + updates will be allowed with any key matching + a principal in the specified keytab file. + "tkey-gssapi-credential" is no longer required + and is expected to be deprecated. (Contributed + by Andrew Tridgell of the Samba project.) + [RT #22629] + +2986. [func] Add new zone type "static-stub". It's like a stub + zone, but the nameserver names and/or their IP + addresses are statically configured. [RT #21474] + +2985. [bug] Add a regression test for change #2896. [RT #21324] + 2984. [bug] Don't run MX checks when the target of the MX record is ".". [RT #22645] -2817. [cleanup] Removed unnecessary isc_task_endexclusive() calls. - [RT #20768] +2983. [bug] Include "loadkeys" in rndc help output. [RT #22493] - --- 9.6.3b1 released --- + --- 9.8.0a1 released --- 2982. [bug] Reference count dst keys. dst_key_attach() can be used increment the reference count. @@ -63,34 +205,103 @@ always call dst_key_free() rather than setting it to NULL on success. [RT #22672] +2981. [func] Partial DNS64 support (AAAA synthesis). [RT #21991] + +2980. [bug] named didn't properly handle UPDATES that changed the + TTL of the NSEC3PARAM RRset. [RT #22363] + 2979. [bug] named could deadlock during shutdown if two "rndc stop" commands were issued at the same time. [RT #22108] 2978. [port] hpux: look for [RT #21919] +2977. [bug] 'nsupdate -l' report if the session key is missing. + [RT #21670] + 2976. [bug] named could die on exit after negotiating a GSS-TSIG key. [RT #22573] -2975. [bug] rbtdb.c:cleanup_dead_nodes_callback() aquired the +2975. [bug] rbtdb.c:cleanup_dead_nodes_callback() acquired the wrong lock which could lead to server deadlock. [RT #22614] +2974. [bug] Some valid UPDATE requests could fail due to a + consistency check examining the existing version + of the zone rather than the new version resulting + from the UPDATE. [RT #22413] + +2973. [bug] bind.keys.h was being removed by the "make clean" + at the end of configure resulting in build failures + where there is very old version of perl installed. + Move it to "make maintainer-clean". [RT #22230] + +2972. [bug] win32: address windows socket errors. [RT #21906] + +2971. [bug] Fixed a bug that caused journal files not to be + compacted on Windows systems as a result of + non-POSIX-compliant rename() semantics. [RT #22434] + +2970. [security] Adding a NO DATA negative cache entry failed to clear + any matching RRSIG records. A subsequent lookup of + of NO DATA cache entry could trigger a INSIST when the + unexpected RRSIG was also returned with the NO DATA + cache entry. + + CVE-2010-3613, VU#706148. [RT #22288] + +2969. [security] Fix acl type processing so that allow-query works + in options and view statements. Also add a new + set of tests to verify proper functioning. + + CVE-2010-3615, VU#510208. [RT #22418] + +2968. [security] Named could fail to prove a data set was insecure + before marking it as insecure. One set of conditions + that can trigger this occurs naturally when rolling + DNSKEY algorithms. + + CVE-2010-3614, VU#837744. [RT #22309] + +2967. [bug] 'host -D' now turns on debugging messages earlier. + [RT #22361] + +2966. [bug] isc_print_vsnprintf() failed to check if there was + space available in the buffer when adding a left + justified character with a non zero width, + (e.g. "%-1c"). [RT #22270] + 2965. [func] Test HMAC functions using test data from RFC 2104 and RFC 4634. [RT #21702] +2964. [placeholder] + +2963. [security] The allow-query acl was being applied instead of the + allow-query-cache acl to cache lookups. [RT #22114] + +2962. [port] win32: add more dependencies to BINDBuild.dsw. + [RT #22062] + +2961. [bug] Be still more selective about the non-authoritative + answers we apply change 2748 to. [RT #22074] + 2960. [func] Check that named accepts non-authoritative answers. [RT #21594] 2959. [func] Check that named starts with a missing masterfile. [RT #22076] +2958. [bug] named failed to start with a missing master file. + [RT #22076] + 2957. [bug] entropy_get() and entropy_getpseudo() failed to match the API for RAND_bytes() and RAND_pseudo_bytes() respectively. [RT #21962] 2956. [port] Enable atomic operations on the PowerPC64. [RT #21899] +2955. [func] Provide more detail in the recursing log. [RT #22043] + 2954. [bug] contrib: dlz_mysql_driver.c bad error handling on build_sqldbinstance failure. [RT #21623] @@ -98,10 +309,26 @@ exact match" message when returning a wildcard no data response. [RT #21744] +2952. [port] win32: named-checkzone and named-checkconf failed + to initialise winsock. [RT #21932] + +2951. [bug] named failed to generate a correct signed response + in a optout, delegation only zone with no secure + delegations. [RT #22007] + 2950. [bug] named failed to perform a SOA up to date check when falling back to TCP on UDP timeouts when ixfr-from-differences was set. [RT #21595] +2949. [bug] dns_view_setnewzones() contained a memory leak if + it was called multiple times. [RT #21942] + +2948. [port] MacOS: provide a mechanism to configure the test + interfaces at reboot. See bin/tests/system/README + for details. + +2947. [placeholder] + 2946. [doc] Document the default values for the minimum and maximum zone refresh and retry values in the ARM. [RT #21886] @@ -110,12 +337,59 @@ 2944. [maint] Remove ORCHID prefix from built in empty zones. [RT #21772] +2943. [func] Add support to load new keys into managed zones + without signing immediately with "rndc loadkeys". + Add support to link keys with "dnssec-keygen -S" + and "dnssec-settime -S". [RT #21351] + 2942. [contrib] zone2sqlite failed to setup the entropy sources. [RT #21610] 2941. [bug] sdb and sdlz (dlz's zone database) failed to support DNAME at the zone apex. [RT #21610] +2940. [port] Remove connection aborted error message on + Windows. [RT #21549] + +2939. [func] Check that named successfully skips NSEC3 records + that fail to match the NSEC3PARAM record currently + in use. [RT# 21868] + +2938. [bug] When generating signed responses, from a signed zone + that uses NSEC3, named would use a uninitialised + pointer if it needed to skip a NSEC3 record because + it didn't match the selected NSEC3PARAM record for + zone. [RT# 21868] + +2937. [bug] Worked around an apparent race condition in over + memory conditions. Without this fix a DNS cache DB or + ADB could incorrectly stay in an over memory state, + effectively refusing further caching, which + subsequently made a BIND 9 caching server unworkable. + This fix prevents this problem from happening by + polling the state of the memory context, rather than + making a copy of the state, which appeared to cause + a race. This is a "workaround" in that it doesn't + solve the possible race per se, but several experiments + proved this change solves the symptom. Also, the + polling overhead hasn't been reported to be an issue. + This bug should only affect a caching server that + specifies a finite max-cache-size. It's also quite + likely that the bug happens only when enabling threads, + but it's not confirmed yet. [RT #21818] + +2936. [func] Improved configuration syntax and multiple-view + support for addzone/delzone feature (see change + #2930). Removed "new-zone-file" option, replaced + with "allow-new-zones (yes|no)". The new-zone-file + for each view is now created automatically, with + a filename generated from a hash of the view name. + It is no longer necessary to "include" the + new-zone-file in named.conf; this happens + automatically. Zones that were not added via + "rndc addzone" can no longer be removed with + "rndc delzone". [RT #19447] + 2935. [bug] nsupdate: improve 'file not found' error message. [RT #21871] @@ -136,6 +410,17 @@ revisit the issue and complete the fix later. [RT #21710] +2930. [experimental] New "rndc addzone" and "rndc delzone" commads + allow dynamic addition and deletion of zones. + To enable this feature, specify a "new-zone-file" + option at the view or options level in named.conf. + Zone configuration information for the new zones + will be written into that file. To make the new + zones persist after a restart, "include" the file + into named.conf in the appropriate view. (Note: + This feature is not yet documented, and its syntax + is expected to change.) [RT #19447] + 2929. [bug] Improved handling of GSS security contexts: - added LRU expiration for generated TSIGs - added the ability to use a non-default realm @@ -145,19 +430,49 @@ smaller) [RT #19737] +2928. [bug] Be more selective about the non-authoritative + answer we apply change 2748 to. [RT #21594] + +2927. [placeholder] + +2926. [placeholder] +h +2925. [bug] Named failed to accept uncachable negative responses + from insecure zones. [RT# 21555] + +2924. [func] 'rndc secroots' dump a combined summary of the + current managed keys combined with trusted keys. + [RT #20904] + 2923. [bug] 'dig +trace' could drop core after "connection timeout". [RT #21514] 2922. [contrib] Update zkt to version 1.0. +2921. [bug] The resolver could attempt to destroy a fetch context + too soon. [RT #19878] + +2920. [func] Allow 'filter-aaaa-on-v4' to be applied selectively + to IPv4 clients. New acl 'filter-aaaa' (default any). + +2919. [func] Add autosign-ksk and autosign-zsk virtual time tests. + [RT #20840] + 2918. [maint] Add AAAA address for I.ROOT-SERVERS.NET. +2917. [func] Virtual time test framework. [RT #20801] + 2916. [func] Add framework to use IPv6 in tests. fd92:7065:b8e:ffff::1 ... fd92:7065:b8e:ffff::7 2915. [cleanup] Be smarter about which objects we attempt to compile based on configure options. [RT #21444] +2914. [bug] Make the "autosign" system test more portable. + [RT #20997] + +2913. [func] Add pkcs#11 system tests. [RT #20784] + 2912. [func] Windows clients don't like UPDATE responses that clear the zone section. [RT #20986] @@ -166,9 +481,17 @@ 2910. [func] Sanity check Kerberos credentials. [RT #20986] +2909. [bug] named-checkconf -p could die if "update-policy local;" + was specified in named.conf. [RT #21416] + 2908. [bug] It was possible for re-signing to stop after removing a DNSKEY. [RT #21384] +2907. [bug] The export version of libdns had undefined references. + [RT #21444] + +2906. [bug] Address RFC 5011 implementation issues. [RT #20903] + 2905. [port] aix: set use_atomic=yes with native compiler. [RT #21402] @@ -177,23 +500,55 @@ secure leading to negative proofs failing. This was a unintended outcome from change 2890. [RT# 21392] +2903. [bug] managed-keys-directory missing from namedconf.c. + [RT #21370] + +2902. [func] Add regression test for change 2897. [RT #21040] + 2901. [port] Use AC_C_FLEXIBLE_ARRAY_MEMBER. [RT #21316] +2900. [bug] The placeholder negative caching element was not + properly constructed triggering a INSIST in + dns_ncache_towire(). [RT #21346] + 2899. [port] win32: Support linking against OpenSSL 1.0.0. 2898. [bug] nslookup leaked memory when -domain=value was specified. [RT #21301] +2897. [bug] NSEC3 chains could be left behind when transitioning + to insecure. [RT #21040] + +2896. [bug] "rndc sign" failed to properly update the zone + when adding a DNSKEY for publication only. [RT #21045] + +2895. [func] genrandom: add support for the generation of multiple + files. [RT #20917] + 2894. [contrib] DLZ LDAP support now use '$' not '%'. [RT #21294] +2893. [bug] Improve managed keys support. New named.conf option + managed-keys-directory. [RT #20924] + +2892. [bug] Handle REVOKED keys better. [RT #20961] + 2891. [maint] Update empty-zones list to match draft-ietf-dnsop-default-local-zones-13. [RT# 21099] +2890. [bug] Handle the introduction of new trusted-keys and + DS, DLV RRsets better. [RT #21097] + 2889. [bug] Elements of the grammar where not properly reported. [RT #21046] 2888. [bug] Only the first EDNS option was displayed. [RT #21273] +2887. [bug] Report the keytag times in UTC in the .key file, + local time is presented as a comment within the + comment. [RT #21223] + +2886. [bug] ctime() is not thread safe. [RT #21223] + 2885. [bug] Improve -fno-strict-aliasing support probing in configure. [RT #21080] @@ -209,12 +564,21 @@ 2881. [bug] Reduce the amount of time the rbtdb write lock is held when closing a version. [RT #21198] +2880. [cleanup] Make the output of dnssec-keygen and dnssec-revoke + consistent. [RT #21078] + 2879. [contrib] DLZ bdbhpt driver fails to close correct cursor. [RT #21106] +2878. [func] Incrementally write the master file after performing + a AXFR. [RT #21010] + 2877. [bug] The validator failed to skip obviously mismatching RRSIGs. [RT #21138] +2876. [bug] Named could return SERVFAIL for negative responses + from unsigned zones. [RT #21131] + 2875. [bug] dns_time64_fromtext() could accept non digits. [RT #21033] @@ -222,8 +586,22 @@ successfully responds to the query using plain DNS. [RT #20930] +2873. [bug] Cancelling a dynamic update via the dns/client module + could trigger an assertion failure. [RT #21133] + +2872. [bug] Modify dns/client.c:dns_client_createx() to only + require one of IPv4 or IPv6 rather than both. + [RT #21122] + +2871. [bug] Type mismatch in mem_api.c between the definition and + the header file, causing build failure with + --enable-exportlib. [RT #21138] + 2870. [maint] Add AAAA address for L.ROOT-SERVERS.NET. +2869. [bug] Fix arguments to dns_keytable_findnextkeynode() call. + [RT #20877] + 2868. [cleanup] Run "make clean" at the end of configure to ensure any changes made by configure are integrated. Use --with-make-clean=no to disable. [RT #20994] @@ -245,6 +623,11 @@ 2862. [bug] nsupdate didn't default to the parent zone when updating DS records. [RT #20896] +2861. [doc] dnssec-settime man pages didn't correctly document the + inactivation time. [RT #21039] + +2860. [bug] named-checkconf's usage was out of date. [RT #21039] + 2859. [bug] When cancelling validation it was possible to leak memory. [RT #20800] @@ -257,111 +640,18 @@ 2856. [bug] The size of a memory allocation was not always properly recorded. [RT #20927] -2853. [bug] add_sigs() could run out of scratch space. [RT #21015] - -2851. [doc] nslookup.1, removed from the docbook - source as it produced bad nroff. [RT #21007] - - --- 9.6-ESV-R3 released --- - -2972. [bug] win32: address windows socket errors. [RT #21906] - -2971. [bug] Fixed a bug that caused journal files not to be - compacted on Windows systems as a result of - non-POSIX-compliant rename() semantics. [RT #22434] +2855. [func] nsupdate will now preserve the entered case of domain + names in update requests it sends. [RT #20928] -2970. [security] Adding a NO DATA negative cache entry failed to clear - any matching RRSIG records. A subsequent lookup of - of NO DATA cache entry could trigger a INSIST when the - unexpected RRSIG was also returned with the NO DATA - cache entry. - - CVE-2010-3613, VU#706148. [RT #22288] - -2969. [security] Fix acl type processing so that allow-query works - in options and view statements. Also add a new - set of tests to verify proper functioning. - - CVE-2010-3615, VU#510208. [RT #22418] - -2968. [security] Named could fail to prove a data set was insecure - before marking it as insecure. One set of conditions - that can trigger this occurs naturally when rolling - DNSKEY algorithms. - - CVE-2010-3614, VU#837744. [RT #22309] - -2967. [bug] 'host -D' now turns on debugging messages earlier. - [RT #22361] - -2966. [bug] isc_print_vsnprintf() failed to check if there was - space available in the buffer when adding a left - justified character with a non zero width, - (e.g. "%-1c"). [RT #22270] - -2964. [bug] view->queryacl was being overloaded. Seperate the - usage into view->queryacl, view->cacheacl and - view->queryonacl. [RT #22114] - -2962. [port] win32: add more dependencies to BINDBuild.dsw. - [RT #22062] - -2952. [port] win32: named-checkzone and named-checkconf failed - to initialise winsock. [RT #21932] - -2951. [bug] named failed to generate a correct signed response - in a optout, delegation only zone with no secure - delegations. [RT #22007] - - --- 9.6-ESV-R2 released --- - -2939. [func] Check that named successfully skips NSEC3 records - that fail to match the NSEC3PARAM record currently - in use. [RT# 21868] - -2937. [bug] Worked around an apparent race condition in over - memory conditions. Without this fix a DNS cache DB or - ADB could incorrectly stay in an over memory state, - effectively refusing further caching, which - subsequently made a BIND 9 caching server unworkable. - This fix prevents this problem from happening by - polling the state of the memory context, rather than - making a copy of the state, which appeared to cause - a race. This is a "workaround" in that it doesn't - solve the possible race per se, but several experiments - proved this change solves the symptom. Also, the - polling overhead hasn't been reported to be an issue. - This bug should only affect a caching server that - specifies a finite max-cache-size. It's also quite - likely that the bug happens only when enabling threads, - but it's not confirmed yet. [RT #21818] - -2925. [bug] Named failed to accept uncachable negative responses - from insecure zones. [RT# 21555] - -2921. [bug] The resolver could attempt to destroy a fetch context - too soon. [RT #19878] - -2900. [bug] The placeholder negative caching element was not - properly constructed triggering a INSIST in - dns_ncache_towire(). [RT #21346] - -2890. [bug] Handle the introduction of new trusted-keys and - DS, DLV RRsets better. [RT #21097] - -2869. [bug] Fix arguments to dns_keytable_findnextkeynode() call. - [RT #20877] - - --- 9.6-ESV-R1 released --- - -2876. [bug] Named could return SERVFAIL for negative responses - from unsigned zones. [RT #21131] +2854. [func] dig: allow the final soa record in a axfr response to + be suppressed, dig +onesoa. [RT #20929] - --- 9.6-ESV released --- +2853. [bug] add_sigs() could run out of scratch space. [RT #21015] 2852. [bug] Handle broken DNSSEC trust chains better. [RT #15619] - --- 9.6.2 released --- +2851. [doc] nslookup.1, removed from the docbook + source as it produced bad nroff. [RT #21007] 2850. [bug] If isc_heap_insert() failed due to memory shortage the heap would have corrupted entries. [RT #20951] @@ -369,61 +659,225 @@ 2849. [bug] Don't treat errors from the xml2 library as fatal. [RT #20945] +2848. [doc] Moved README.dnssec, README.libdns, README.pkcs11 and + README.rfc5011 into the ARM. [RT #20899] + +2847. [cleanup] Corrected usage message in dnssec-settime. [RT #20921] + 2846. [bug] EOF on unix domain sockets was not being handled correctly. [RT #20731] +2845. [bug] RFC 5011 client could crash on shutdown. [RT #20903] + 2844. [doc] notify-delay default in ARM was wrong. It should have been five (5) seconds. - --- 9.6.2rc1 released --- +2843. [func] Prevent dnssec-keygen and dnssec-keyfromlabel from + creating key files if there is a chance that the new + key ID will collide with an existing one after + either of the keys has been revoked. (To override + this in the case of dnssec-keyfromlabel, use the -y + option. dnssec-keygen will simply create a + different, non-colliding key, so an override is + not necessary.) [RT #20838] + +2842. [func] Added "smartsign" and improved "autosign" and + "dnssec" regression tests. [RT #20865] + +2841. [bug] Change 2836 was not complete. [RT #20883] -2838. [func] Backport support for SHA-2 DNSSEC algorithms, - RSASHA256 and RSASHA512, from BIND 9.7. (This - incorporates changes 2726 and 2738 from that - release branch.) [RT #20871] +2840. [bug] Temporary fixed pkcs11-destroy usage check. + [RT #20760] + +2839. [bug] A KSK revoked by named could not be deleted. + [RT #20881] + +2838. [placeholder] 2837. [port] Prevent Linux spurious warnings about fwrite(). [RT #20812] +2836. [bug] Keys that were scheduled to become active could + be delayed. [RT #20874] + +2835. [bug] Key inactivity dates were inadvertently stored in + the private key file with the outdated tag + "Unpublish" rather than "Inactive". This has been + fixed; however, any existing keys that had Inactive + dates set will now need to have them reset, using + 'dnssec-settime -I'. [RT #20868] + +2834. [bug] HMAC-SHA* keys that were longer than the algorithm + digest length were used incorrectly, leading to + interoperability problems with other DNS + implementations. This has been corrected. + (Note: If an oversize key is in use, and + compatibility is needed with an older release of + BIND, the new tool "isc-hmac-fixup" can convert + the key secret to a form that will work with all + versions.) [RT #20751] + +2833. [cleanup] Fix usage messages in dnssec-keygen and dnssec-settime. + [RT #20851] + +2832. [bug] Modify "struct stat" in lib/export/samples/nsprobe.c + to avoid redefinition in some OSs [RT 20831] + 2831. [security] Do not attempt to validate or cache out-of-bailiwick data returned with a secure answer; it must be re-fetched from its original source and validated in that context. [RT #20819] +2830. [bug] Changing the OPTOUT setting could take multiple + passes. [RT #20813] + +2829. [bug] Fixed potential node inconsistency in rbtdb.c. + [RT #20808] + 2828. [security] Cached CNAME or DNAME RR could be returned to clients without DNSSEC validation. [RT #20737] 2827. [security] Bogus NXDOMAIN could be cached as if valid. [RT #20712] +2826. [bug] NSEC3->NSEC transitions could fail due to a lock not + being released. [RT #20740] + 2825. [bug] Changing the setting of OPTOUT in a NSEC3 chain that was in the process of being created was not properly recorded in the zone. [RT #20786] +2824. [bug] "rndc sign" was not being run by the correct task. + [RT #20759] + 2823. [bug] rbtdb.c:getsigningtime() was missing locks. [RT #20781] +2822. [bug] rbtdb.c:loadnode() could return the wrong result. + [RT #20802] + +2821. [doc] Add note that named-checkconf doesn't automatically + read rndc.key and bind.keys [RT #20758] + +2820. [func] Handle read access failure of OpenSSL configuration + file more user friendly (PKCS#11 engine patch). + [RT #20668] + 2819. [cleanup] Removed unnecessary DNS_POINTER_MAXHOPS define. [RT #20771] 2818. [cleanup] rndc could return an incorrect error code when a zone was not found. [RT #20767] +2817. [cleanup] Removed unnecessary isc_task_endexclusive() calls. + [RT #20768] + +2816. [bug] previous_closest_nsec() could fail to return + data for NSEC3 nodes [RT #29730] + 2815. [bug] Exclusively lock the task when freezing a zone. [RT #19838] 2814. [func] Provide a definitive error message when a master zone is not loaded. [RT #20757] - --- 9.6.2b1 released --- +2813. [bug] Better handling of unreadable DNSSEC key files. + [RT #20710] + +2812. [bug] Make sure updates can't result in a zone with + NSEC-only keys and NSEC3 records. [RT 20748] + +2811. [cleanup] Add "rndc sign" to list of commands in rndc usage + output. [RT #20733] + +2810. [doc] Clarified the process of transitioning an NSEC3 zone + to insecure. [RT #20746] + +2809. [cleanup] Restored accidentally-deleted text in usage output + in dnssec-settime and dnssec-revoke [RT #20739] + +2808. [bug] Remove the attempt to install atomic.h from lib/isc. + atomic.h is correctly installed by the architecture + specific subdirectories. [RT #20722] + +2807. [bug] Fixed a possible ASSERT when reconfiguring zone + keys. [RT #20720] + + --- 9.7.0rc1 released --- + +2806. [bug] "rdnc sign" could delay re-signing the DNSKEY + when it had changed. [RT #20703] + +2805. [bug] Fixed namespace problems encountered when building + external programs using non-exported BIND9 libraries + (i.e., built without --enable-exportlib). [RT #20679] + +2804. [bug] Send notifies when a zone is signed with "rndc sign" + or as a result of a scheduled key change. [RT #20700] + +2803. [port] win32: Install named-journalprint, nsec3hash, arpaname + and genrandom under windows. [RT #20670] + +2802. [cleanup] Rename journalprint to named-journalprint. [RT #20670] + +2801. [func] Detect and report records that are different according + to DNSSEC but are semantically equal according to plain + DNS. Apply plain DNS comparisons rather than DNSSEC + comparisons when processing UPDATE requests. + dnssec-signzone now removes such semantically duplicate + records prior to signing the RRset. + + named-checkzone -r {ignore|warn|fail} (default warn) + named-compilezone -r {ignore|warn|fail} (default warn) + + named.conf: check-dup-records {ignore|warn|fail}; + +2800. [func] Reject zones which have NS records which refer to + CNAMEs, DNAMEs or don't have address record (class IN + only). Reject UPDATEs which would cause the zone + to fail the above checks if committed. [RT #20678] + +2799. [cleanup] Changed the "secure-to-insecure" option to + "dnssec-secure-to-insecure", and "dnskey-ksk-only" + to "dnssec-dnskey-kskonly", for clarity. [RT #20586] + +2798. [bug] Addressed bugs in managed-keys initialization + and rollover. [RT #20683] 2797. [bug] Don't decrement the dispatch manager's maxbuffers. [RT #20613] +2796. [bug] Missing dns_rdataset_disassociate() call in + dns_nsec3_delnsec3sx(). [RT #20681] + +2795. [cleanup] Add text to differentiate "update with no effect" + log messages. [RT #18889] + +2794. [bug] Install . [RT #20677] + +2793. [func] Add "autosign" and "metadata" tests to the + automatic tests. [RT #19946] + +2792. [func] "filter-aaaa-on-v4" can now be set in view + options (if compiled in). [RT #20635] + +2791. [bug] The installation of isc-config.sh was broken. + [RT #20667] + 2790. [bug] Handle DS queries to stub zones. [RT #20440] 2789. [bug] Fixed an INSIST in dispatch.c [RT #20576] +2788. [bug] dnssec-signzone could sign with keys that were + not requested [RT #20625] + +2787. [bug] Spurious log message when zone keys were + dynamically reconfigured. [RT #20659] + 2786. [bug] Additional could be promoted to answer. [RT #20663] + --- 9.7.0b3 released --- + +2785. [bug] Revoked keys could fail to self-sign [RT #20652] + 2784. [bug] TC was not always being set when required glue was dropped. [RT #20655] @@ -433,15 +887,65 @@ 2782. [port] win32: use getaddrinfo() for hostname lookups. [RT #20650] +2781. [bug] Inactive keys could be used for signing. [RT #20649] + +2780. [bug] dnssec-keygen -A none didn't properly unset the + activation date in all cases. [RT #20648] + +2779. [bug] Dynamic key revocation could fail. [RT #20644] + +2778. [bug] dnssec-signzone could fail when a key was revoked + without deleting the unrevoked version. [RT #20638] + 2777. [contrib] DLZ MYSQL auto reconnect support discovery was wrong. +2776. [bug] Change #2762 was not correct. [RT #20647] + +2775. [bug] Accept RSASHA256 and RSASHA512 as NSEC3 compatible + in dnssec-keyfromlabel. [RT #20643] + +2774. [bug] Existing cache DB wasn't being reused after + reconfiguration. [RT #20629] + +2773. [bug] In autosigned zones, the SOA could be signed + with the KSK. [RT #20628] + 2772. [security] When validating, track whether pending data was from the additional section or not and only return it if validates as secure. [RT #20438] +2771. [bug] dnssec-signzone: DNSKEY records could be + corrupted when importing from key files [RT #20624] + +2770. [cleanup] Add log messages to resolver.c to indicate events + causing FORMERR responses. [RT #20526] + +2769. [cleanup] Change #2742 was incomplete. [RT #19589] + +2768. [bug] dnssec-signzone: -S no longer implies -g [RT #20568] + +2767. [bug] named could crash on startup if a zone was + configured with auto-dnssec and there was no + key-directory. [RT #20615] + +2766. [bug] isc_socket_fdwatchpoke() should only update the + socketmgr state if the socket is not pending on a + read or write. [RT #20603] + 2765. [bug] Skip masters for which the TSIG key cannot be found. [RT #20595] +2764. [bug] "rndc-confgen -a" could trigger a REQUIRE. [RT #20610] + +2763. [bug] "rndc sign" didn't create an NSEC chain. [RT #20591] + +2762. [bug] DLV validation failed with a local slave DLV zone. + [RT #20577] + +2761. [cleanup] Enable internal symbol table for backtrace only for + systems that are known to work. Currently, BSD + variants, Linux and Solaris are supported. [RT# 20202] + 2760. [cleanup] Corrected named-compilezone usage summary. [RT #20533] 2759. [doc] Add information about .jbk/.jnw files to @@ -454,27 +958,115 @@ 2757. [bug] dig: assertion failure could occur in connect timeout. [RT #20599] -2755. [doc] Clarify documentation of keyset- files in - dnssec-signzone man page. [RT #19810] +2756. [bug] Fixed corrupt logfile message in update.c. [RT# 20597] + +2755. [placeholder] 2754. [bug] Secure-to-insecure transitions failed when zone was signed with NSEC3. [RT #20587] +2753. [bug] Removed an unnecessary warning that could appear when + building an NSEC chain. [RT #20589] + +2752. [bug] Locking violation. [RT #20587] + +2751. [bug] Fixed a memory leak in dnssec-keyfromlabel. [RT #20588] + 2750. [bug] dig: assertion failure could occur when a server didn't have an address. [RT #20579] 2749. [bug] ixfr-from-differences generated a non-minimal ixfr for NSEC3 signed zones. [RT #20452] +2748. [func] Identify bad answers from GTLD servers and treat them + as referrals. [RT #18884] + 2747. [bug] Journal roll forwards failed to set the re-signing time of RRSIGs correctly. [RT #20541] +2746. [port] hpux: address signed/unsigned expansion mismatch of + dns_rbtnode_t.nsec. [RT #20542] + +2745. [bug] configure script didn't probe the return type of + gai_strerror(3) correctly. [RT #20573] + +2744. [func] Log if a query was over TCP. [RT #19961] + 2743. [bug] RRSIG could be incorrectly set in the NSEC3 record for a insecure delegation. + --- 9.7.0b2 released --- + +2742. [cleanup] Clarify some DNSSEC-related log messages in + validator.c. [RT #19589] + +2741. [func] Allow the dnssec-keygen progress messages to be + suppressed (dnssec-keygen -q). Automatically + suppress the progress messages when stdin is not + a tty. [RT #20474] + +2740. [placeholder] + +2739. [cleanup] Clean up API for initializing and clearing trust + anchors for a view. [RT #20211] + +2738. [func] Add RSASHA256 and RSASHA512 tests to the dnssec system + test. [RT #20453] + +2737. [func] UPDATE requests can leak existence information. + [RT #17261] + +2736. [func] Improve the performance of NSEC signed zones with + more than a normal amount of glue below a delegation. + [RT #20191] + +2735. [bug] dnssec-signzone could fail to read keys + that were specified on the command line with + full paths, but weren't in the current + directory. [RT #20421] + +2734. [port] cygwin: arpaname did not compile. [RT #20473] + +2733. [cleanup] Clean up coding style in pkcs11-* tools. [RT #20355] + +2732. [func] Add optional filter-aaaa-on-v4 option, available + if built with './configure --enable-filter-aaaa'. + Filters out AAAA answers to clients connecting + via IPv4. (This is NOT recommended for general + use.) [RT #20339] + +2731. [func] Additional work on change 2709. The key parser + will now ignore unrecognized fields when the + minor version number of the private key format + has been increased. It will reject any key with + the major version number increased. [RT #20310] + +2730. [func] Have dnssec-keygen display a progress indication + a la 'openssl genrsa' on standard error. Note + when the first '.' is followed by a long stop + one has the choice between slow generation vs. + poor random quality, i.e., '-r /dev/urandom'. + [RT #20284] + 2729. [func] When constructing a CNAME from a DNAME use the DNAME TTL. [RT #20451] +2728. [bug] dnssec-keygen, dnssec-keyfromlabel and + dnssec-signzone now warn immediately if asked to + write into a nonexistent directory. [RT #20278] + +2727. [func] The 'key-directory' option can now specify a relative + path. [RT #20154] + +2726. [func] Added support for SHA-2 DNSSEC algorithms, + RSASHA256 and RSASHA512. [RT #20023] + +2725. [doc] Added information about the file "managed-keys.bind" + to the ARM. [RT #20235] + +2724. [bug] Updates to a existing node in secure zone using NSEC + were failing. [RT #20448] + 2723. [bug] isc_base32_totext(), isc_base32hex_totext(), and isc_base64_totext(), didn't always mark regions of memory as fully consumed after conversion. [RT #20445] @@ -486,11 +1078,24 @@ 2721. [port] Have dst__entropy_status() prime the random number generator. [RT #20369] +2720. [bug] RFC 5011 trust anchor updates could trigger an + assert if the DNSKEY record was unsigned. [RT #20406] + +2719. [func] Skip trusted/managed keys for unsupported algorithms. + [RT #20392] + 2718. [bug] The space calculations in opensslrsa_todns() were incorrect. [RT #20394] +2717. [bug] named failed to update the NSEC/NSEC3 record when + the last private type record was removed as a result + of completing the signing the zone with a key. + [RT #20399] + 2716. [bug] nslookup debug mode didn't return the ttl. [RT #20414] + --- 9.7.0b1 released --- + 2715. [bug] Require OpenSSL support to be explicitly disabled. [RT #20288] @@ -500,19 +1105,63 @@ 2713. [bug] powerpc: atomic operations missing asm("ics") / __isync() calls. +2712. [func] New 'auto-dnssec' zone option allows zone signing + to be fully automated in zones configured for + dynamic DNS. 'auto-dnssec allow;' permits a zone + to be signed by creating keys for it in the + key-directory and using 'rndc sign '. + 'auto-dnssec maintain;' allows that too, plus it + also keeps the zone's DNSSEC keys up to date + according to their timing metadata. [RT #19943] + +2711. [port] win32: Add the bin/pkcs11 tools into the full + build. [RT #20372] + +2710. [func] New 'dnssec-signzone -x' flag and 'dnskey-ksk-only' + zone option cause a zone to be signed with only KSKs + signing the DNSKEY RRset, not ZSKs. This reduces + the size of a DNSKEY answer. [RT #20340] + +2709. [func] Added some data fields, currently unused, to the + private key file format, to allow implementation + of explicit key rollover in a future release + without impairing backward or forward compatibility. + [RT #20310] + +2708. [func] Insecure to secure and NSEC3 parameter changes via + update are now fully supported and no longer require + defines to enable. We now no longer overload the + NSEC3PARAM flag field, nor the NSEC OPT bit at the + apex. Secure to insecure changes are controlled by + by the named.conf option 'secure-to-insecure'. + + Warning: If you had previously enabled support by + adding defines at compile time to BIND 9.6 you should + ensure that all changes that are in progress have + completed prior to upgrading to BIND 9.7. BIND 9.7 + is not backwards compatible. + +2707. [func] dnssec-keyfromlabel no longer require engine name + to be specified in the label if there is a default + engine or the -E option has been used. Also, it + now uses default algorithms as dnssec-keygen does + (i.e., RSASHA1, or NSEC3RSASHA1 if -3 is used). + [RT #20371] + 2706. [bug] Loading a zone with a very large NSEC3 salt could trigger an assert. [RT #20368] -2705. [bug] Reconcile the XML stats version number with a later - BIND9 release, by adding a "name" attribute to - "cache" elements and increasing the version number - to 2.2. (This is a minor version change, but may - affect XML parsers if they assume the cache element - doesn't take an attribute.) +2705. [placeholder] 2704. [bug] Serial of dynamic and stub zones could be inconsistent with their SOA serial. [RT #19387] +2703. [func] Introduce an OpenSSL "engine" argument with -E + for all binaries which can take benefit of + crypto hardware. [RT #20230] + +2702. [func] Update PKCS#11 tools (bin/pkcs11) [RT #20225 & all] + 2701. [doc] Correction to ARM: hmac-md5 is no longer the only supported TSIG key algorithm. [RT #18046] @@ -521,6 +1170,8 @@ 2699. [bug] Missing lock in rbtdb.c. [RT #20037] +2698. [placeholder] + 2697. [port] win32: ensure that S_IFMT, S_IFDIR, S_IFCHR and S_IFREG are defined after including . [RT #20309] @@ -528,8 +1179,25 @@ 2696. [bug] named failed to successfully process some valid acl constructs. [RT #20308] +2695. [func] DHCP/DDNS - update fdwatch code for use by + DHCP. Modify the api to isc_sockfdwatch_t (the + callback functon for isc_socket_fdwatchcreate) + to include information about the direction (read + or write) and add isc_socket_fdwatchpoke. + [RT #20253] + +2694. [bug] Reduce default NSEC3 iterations from 100 to 10. + [RT #19970] + +2693. [port] Add some noreturn attributes. [RT #20257] + 2692. [port] win32: 32/64 bit cleanups. [RT #20335] +2691. [func] dnssec-signzone: retain the existing NSEC or NSEC3 + chain when re-signing a previously-signed zone. + Use -u to modify NSEC3 parameters or switch + between NSEC and NSEC3. [RT #20304] + 2690. [bug] win32: fix isc_thread_key_getspecific() prototype. [RT #20315] @@ -538,25 +1206,102 @@ 2688. [bug] Use INTERFACE_F_POINTTOPOINT, not IFF_POINTOPOINT, to decide to fetch the destination address. [RT #20305] +2687. [bug] Fixed dnssec-signzone -S handling of revoked keys. + Also, added warnings when revoking a ZSK, as this is + not defined by protocol (but is legal). [RT #19943] + 2686. [bug] dnssec-signzone should clean the old NSEC chain when signing with NSEC3 and vice versa. [RT #20301] +2685. [contrib] Update contrib/zkt to version 0.99c. [RT #20054] + +2684. [cleanup] dig: formalize +ad and +cd as synonyms for + +adflag and +cdflag. [RT #19305] + 2683. [bug] dnssec-signzone should clean out old NSEC3 chains when the NSEC3 parameters used to sign the zone change. [RT #20246] +2682. [bug] "configure --enable-symtable=all" failed to + build. [RT #20282] + 2681. [bug] IPSECKEY RR of gateway type 3 was not correctly decoded. [RT #20269] +2680. [func] Move contrib/pkcs11-keygen to bin/pkcs11. [RT #20067] + +2679. [func] dig -k can now accept TSIG keys in named.conf + format. [RT #20031] + 2678. [func] Treat DS queries as if "minimal-response yes;" was set. [RT #20258] +2677. [func] Changes to key metadata behavior: + - Keys without "publish" or "active" dates set will + no longer be used for smart signing. However, + those dates will be set to "now" by default when + a key is created; to generate a key but not use + it yet, use dnssec-keygen -G. + - New "inactive" date (dnssec-keygen/settime -I) + sets the time when a key is no longer used for + signing but is still published. + - The "unpublished" date (-U) is deprecated in + favour of "deleted" (-D). + [RT #20247] + +2676. [bug] --with-export-installdir should have been + --with-export-includedir. [RT #20252] + +2675. [bug] dnssec-signzone could crash if the key directory + did not exist. [RT #20232] + + --- 9.7.0a3 released --- + +2674. [bug] "dnssec-lookaside auto;" crashed if named was built + without openssl. [RT #20231] + +2673. [bug] The managed-keys.bind zone file could fail to + load due to a spurious result from sync_keyzone() + [RT #20045] + 2672. [bug] Don't enable searching in 'host' when doing reverse lookups. [RT #20218] +2671. [bug] Add support for PKCS#11 providers not returning + the public exponent in RSA private keys + (OpenCryptoki for instance) in + dnssec-keyfromlabel. [RT #19294] + 2670. [bug] Unexpected connect failures failed to log enough information to be useful. [RT #20205] +2669. [func] Update PKCS#11 support to support Keyper HSM. + Update PKCS#11 patch to be against openssl-0.9.8i. + +2668. [func] Several improvements to dnssec-* tools, including: + - dnssec-keygen and dnssec-settime can now set key + metadata fields 0 (to unset a value, use "none") + - dnssec-revoke sets the revocation date in + addition to the revoke bit + - dnssec-settime can now print individual metadata + fields instead of always printing all of them, + and can print them in unix epoch time format for + use by scripts + [RT #19942] + +2667. [func] Add support for logging stack backtrace on assertion + failure (not available for all platforms). [RT #19780] + +2666. [func] Added an 'options' argument to dns_name_fromstring() + (API change from 9.7.0a2). [RT #20196] + +2665. [func] Clarify syntax for managed-keys {} statement, add + ARM documentation about RFC 5011 support. [RT #19874] + +2664. [bug] create_keydata() and minimal_update() in zone.c + didn't properly check return values for some + functions. [RT #19956] + 2663. [func] win32: allow named to run as a service using "NT AUTHORITY\LocalService" as the account. [RT #19977] @@ -567,19 +1312,40 @@ 2661. [bug] Check whether socket fd exceeds FD_SETSIZE when creating lwres context. [RT #20029] +2660. [func] Add a new set of DNS libraries for non-BIND9 + applications. See README.libdns. [RT #19369] + 2659. [doc] Clarify dnssec-keygen doc: key name must match zone name for DNSSEC keys. [RT #19938] +2658. [bug] dnssec-settime and dnssec-revoke didn't process + key file paths correctly. [RT #20078] + +2657. [cleanup] Lower "journal file does not exist, creating it" + log level to debug 1. [RT #20058] + 2656. [func] win32: add a "tools only" check box to the installer which causes it to only install dig, host, nslookup, nsupdate and relevant DLLs. [RT #19998] 2655. [doc] Document that key-directory does not affect - rndc.key. [RT #20155] + bind.keys, rndc.key or session.key. [RT #20155] + +2654. [bug] Improve error reporting on duplicated names for + deny-answer-xxx. [RT #20164] 2653. [bug] Treat ENGINE_load_private_key() failures as key not found rather than out of memory. [RT #18033] +2652. [func] Provide more detail about what record is being + deleted. [RT #20061] + +2651. [bug] Dates could print incorrectly in K*.key files on + 64-bit systems. [RT #20076] + +2650. [bug] Assertion failure in dnssec-signzone when trying + to read keyset-* files. [RT #20075] + 2649. [bug] Set the domain for forward only zones. [RT #19944] 2648. [port] win32: isc_time_seconds() was broken. [RT #19900] @@ -592,37 +1358,99 @@ 2645. [port] "gcc -m32" didn't work on amd64 and x86_64 platforms which default to 64 bits. [RT #19927] + --- 9.7.0a2 released --- + +2644. [bug] Change #2628 caused a regression on some systems; + named was unable to write the PID file and would + fail on startup. [RT #20001] + 2643. [bug] Stub zones interacted badly with NSEC3 support. [RT #19777] 2642. [bug] nsupdate could dump core on solaris when reading improperly formatted key files. [RT #20015] +2641. [bug] Fixed an error in parsing update-policy syntax, + added a regression test to check it. [RT #20007] + 2640. [security] A specially crafted update packet will cause named to exit. [RT #20000] 2639. [bug] Silence compiler warnings in gssapi code. [RT #19954] +2638. [bug] Install arpaname. [RT #19957] + 2637. [func] Rationalize dnssec-signzone's signwithkey() calling. [RT #19959] +2636. [func] Simplify zone signing and key maintenance with the + dnssec-* tools. Major changes: + - all dnssec-* tools now take a -K option to + specify a directory in which key files will be + stored + - DNSSEC can now store metadata indicating when + they are scheduled to be published, activated, + revoked or removed; these values can be set by + dnssec-keygen or overwritten by the new + dnssec-settime command + - dnssec-signzone -S (for "smart") option reads key + metadata and uses it to determine automatically + which keys to publish to the zone, use for + signing, revoke, or remove from the zone + [RT #19816] + 2635. [bug] isc_inet_ntop() incorrectly handled 0.0/16 addresses. [RT #19716] +2634. [port] win32: Add support for libxml2, enable + statschannel. [RT #19773] + 2633. [bug] Handle 15 bit rand() functions. [RT #19783] 2632. [func] util/kit.sh: warn if documentation appears to be out of date. [RT #19922] +2631. [bug] Handle "//", "/./" and "/../" in mkdirpath(). + [RT #19926 ] + +2630. [func] Improved syntax for DDNS autoconfiguration: use + "update-policy local;" to switch on local DDNS in a + zone. (The "ddns-autoconf" option has been removed.) + [RT #19875] + +2629. [port] Check for seteuid()/setegid(), use setresuid()/ + setresgid() if not present. [RT #19932] + +2628. [port] linux: Allow /var/run/named/named.pid to be opened + at startup with reduced capabilities in operation. + [RT #19884] + +2627. [bug] Named aborted if the same key was included in + trusted-keys more than once. [RT #19918] + +2626. [bug] Multiple trusted-keys could trigger an assertion + failure. [RT #19914] + 2625. [bug] Missing UNLOCK in rbtdb.c. [RT #19865] -2623. [bug] Named started seaches for DS non-optimally. [RT #19915] +2624. [func] 'named-checkconf -p' will print out the parsed + configuration. [RT #18871] + +2623. [bug] Named started searches for DS non-optimally. [RT #19915] -2621. [doc] Made copyright boilterplate consistent. [RT #19833] +2622. [bug] Printing of named.conf grammar was broken. [RT #19919] + +2621. [doc] Made copyright boilerplate consistent. [RT #19833] 2620. [bug] Delay thawing the zone until the reload of it has completed successfully. [RT #19750] +2619. [func] Add support for RFC 5011, automatic trust anchor + maintenance. The new "managed-keys" statement can + be used in place of "trusted-keys" for zones which + support this protocol. (Note: this syntax is + expected to change prior to 9.7.0 final.) [RT #19248] + 2618. [bug] The sdb and sdlz db_interator_seek() methods could loop infinitely. [RT #19847] @@ -638,11 +1466,33 @@ 2614. [port] win32: 'named -v' should automatically be executed in the foreground. [RT #19844] -2613. [bug] Option argument validation was missing for - dnssec-dsfromkey. [RT #19828] +2613. [placeholder] + + --- 9.7.0a1 released --- + +2612. [func] Add default values for the arguments to + dnssec-keygen. Without arguments, it will now + generate a 1024-bit RSASHA1 zone-signing key, + or with the -f KSK option, a 2048-bit RSASHA1 + key-signing key. [RT #19300] + +2611. [func] Add -l option to dnssec-dsfromkey to generate + DLV records instead of DS records. [RT #19300] 2610. [port] sunos: Change #2363 was not complete. [RT #19796] +2609. [func] Simplify the configuration of dynamic zones: + - add ddns-confgen command to generate + configuration text for named.conf + - add zone option "ddns-autoconf yes;", which + causes named to generate a TSIG session key + and allow updates to the zone using that key + - add '-l' (localhost) option to nsupdate, which + causes nsupdate to connect to a locally-running + named process using the session key generated + by named + [RT #19284] + 2608. [func] Perform post signing verification checks in dnssec-signzone. These can be disabled with -P. @@ -652,27 +1502,6 @@ self signed. That all records in the zone are signed by the algorithm. [RT #19653] -2601. [doc] Mention file creation mode mask in the - named manual page. - -2593. [bug] Improve a corner source of SERVFAILs [RT #19632] - -2589. [bug] dns_db_unregister() failed to clear '*dbimp'. - [RT #19626] - -2581. [contrib] dlz/mysql set MYSQL_OPT_RECONNECT option on connection. - Requires MySQL 5.0.19 or later. [RT #19084] - -2580. [bug] UpdateRej statistics counter could be incremented twice - for one rejection. [RT #19476] - -2533. [doc] ARM: document @ (at-sign). [RT #17144] - -2500. [contrib] contrib/sdb/pgsql/zonetodb.c called non-existent - function. [RT #18582] - - --- 9.6.1 released --- - 2607. [bug] named could incorrectly delete NSEC3 records for empty nodes when processing a update request. [RT #19749] @@ -683,6 +1512,11 @@ 2605. [bug] Accept DS responses from delegation only zones. [RT # 19296] +2604. [func] Add support for DNS rebinding attack prevention through + new options, deny-answer-addresses and + deny-answer-aliases. Based on contributed code from + JD Nurmi, Google. [RT #18192] + 2603. [port] win32: handle .exe extension of named-checkzone and named-comilezone argv[0] names under windows. [RT #19767] @@ -690,11 +1524,17 @@ 2602. [port] win32: fix debugging command line build of libisccfg. [RT #19767] - --- 9.6.1rc1 released --- +2601. [doc] Mention file creation mode mask in the + named manual page. + +2600. [doc] ARM: miscellaneous reformatting for different + page widths. [RT #19574] 2599. [bug] Address rapid memory growth when validation fails. [RT #19654] +2598. [func] Reserve the -F flag. [RT #19657] + 2597. [bug] Handle a validation failure with a insecure delegation from a NSEC3 signed master/slave zone. [RT #19464] @@ -704,16 +1544,31 @@ 2595. [bug] Fix unknown extended rcodes in dig. [RT #19625] +2594. [func] Have rndc warn if using its default configuration + file when the key file also exists. [RT #19424] + +2593. [bug] Improve a corner source of SERVFAILs [RT #19632] + 2592. [bug] Treat "any" as a type in nsupdate. [RT #19455] 2591. [bug] named could die when processing a update in removed_orphaned_ds(). [RT #19507] +2590. [func] Report zone/class of "update with no effect". + [RT #19542] + +2589. [bug] dns_db_unregister() failed to clear '*dbimp'. + [RT #19626] + 2588. [bug] SO_REUSEADDR could be set unconditionally after failure of bind(2) call. This should be rare and mostly harmless, but may cause interference with other processes that happen to use the same port. [RT #19642] +2587. [func] Improve logging by reporting serial numbers for + when zone serial has gone backwards or unchanged. + [RT #19506] + 2586. [bug] Missing cleanup of SIG rdataset in searching a DLZ DB or SDB. [RT #19577] @@ -730,28 +1585,57 @@ 2582. [bug] Don't emit warning log message when we attempt to remove non-existent journal. [RT #19516] +2581. [contrib] dlz/mysql set MYSQL_OPT_RECONNECT option on connection. + Requires MySQL 5.0.19 or later. [RT #19084] + +2580. [bug] UpdateRej statistics counter could be incremented twice + for one rejection. [RT #19476] + 2579. [bug] DNSSEC lookaside validation failed to handle unknown algorithms. [RT #19479] 2578. [bug] Changed default sig-signing-type to 65534, because 65535 turns out to be reserved. [RT #19477] -2499. [port] solaris: lib/lwres/getaddrinfo.c namespace clash. - [RT #18837] - - --- 9.6.1b1 released --- - 2577. [doc] Clarified some statistics counters. [RT #19454] 2576. [bug] NSEC record were not being correctly signed when a zone transitions from insecure to secure. Handle such incorrectly signed zones. [RT #19114] +2575. [func] New functions dns_name_fromstring() and + dns_name_tostring(), to simplify conversion + of a string to a dns_name structure and vice + versa. [RT #19451] + 2574. [doc] Document nsupdate -g and -o. [RT #19351] 2573. [bug] Replacing a non-CNAME record with a CNAME record in a single transaction in a signed zone failed. [RT #19397] +2572. [func] Simplify DLV configuration, with a new option + "dnssec-lookaside auto;" This is the equivalent + of "dnssec-lookaside . trust-anchor dlv.isc.org;" + plus setting a trusted-key for dlv.isc.org. + + Note: The trusted key is hard-coded into named, + but is also stored in (and can be overridden + by) $sysconfdir/bind.keys. As the ISC DLV key + rolls over it can be kept up to date by replacing + the bind.keys file with a key downloaded from + https://www.isc.org/solutions/dlv. [RT #18685] + +2571. [func] Add a new tool "arpaname" which translates IP addresses + to the corresponding IN-ADDR.ARPA or IP6.ARPA name. + [RT #18976] + +2570. [func] Log the destination address the query was sent to. + [RT #19209] + +2569. [func] Move journalprint, nsec3hash, and genrandom + commands from bin/tests into bin/tools; + "make install" will put them in $sbindir. [RT #19301] + 2568. [bug] Report when the write to indicate a otherwise successful start fails. [RT #19360] @@ -760,6 +1644,15 @@ dnssec-dsfromkey could miss write errors. [RT #19360] +2566. [cleanup] Clarify logged message when an insecure DNSSEC + response arrives from a zone thought to be secure: + "insecurity proof failed" instead of "not + insecure". [RT #19400] + +2565. [func] Add support for HIP record. Includes new functions + dns_rdata_hip_first(), dns_rdata_hip_next() + and dns_rdata_hip_current(). [RT #19384] + 2564. [bug] Only take EDNS fallback steps when processing timeouts. [RT #19405] @@ -776,6 +1669,10 @@ 2559. [bug] dnssec-dsfromkey could compute bad DS records when reading from a K* files. [RT #19357] +2558. [func] Set the ownership of missing directories created + for pid-file if -u has been specified on the command + line. [RT #19328] + 2557. [cleanup] PCI compliance: * new libisc log module file * isc_dir_chroot() now also changes the working @@ -787,6 +1684,9 @@ error checks in the correct order resulting in the wrong error code sometimes being returned. [RT #19249] +2555. [func] dig: when emitting a hex dump also display the + corresponding characters. [RT #19258] + 2554. [bug] Validation of uppercase queries from NSEC3 zones could fail. [RT #19297] @@ -810,6 +1710,10 @@ function isc_mem_reallocate() was introduced to address this bug. [RT #19313] +2546. [func] Add --enable-openssl-hash configure flag to use + OpenSSL (in place of internal routine) for hash + functions (MD5, SHA[12] and HMAC). [RT #18815] + 2545. [doc] ARM: Legal hostname checking (check-names) is for SRV RDATA too. [RT #19304] @@ -822,6 +1726,8 @@ 2541. [bug] Conditionally update dispatch manager statistics. [RT #19247] +2540. [func] Add a nibble mode to $GENERATE. [RT #18872] + 2539. [security] Update the interaction between recursion, allow-query, allow-query-cache and allow-recursion. [RT #19198] @@ -829,7 +1735,7 @@ especially with threads and smaller max-cache-size values. [RT #19240] -2537. [experimental] Added more statistics counters including those on socket +2537. [func] Added more statistics counters including those on socket I/O events and query RTT histograms. [RT #18802] 2536. [cleanup] Silence some warnings when -Werror=format-security is @@ -837,6 +1743,12 @@ 2535. [bug] dig +showsearch and +trace interacted badly. [RT #19091] +2534. [func] Check NAPTR records regular expressions and + replacement strings to ensure they are syntactically + valid and consistant. [RT #18168] + +2533. [doc] ARM: document @ (at-sign). [RT #17144] + 2532. [bug] dig: check the question section of the response to see if it matches the asked question. [RT #18495] @@ -851,10 +1763,14 @@ 2528. [cleanup] Silence spurious configure warning about --datarootdir [RT #19096] -2527. [bug] named could reuse cache on reload with - enabling/disabling validation. [RT #19119] +2527. [placeholder] -2525. [experimental] New logging category "query-errors" to provide detailed +2526. [func] New named option "attach-cache" that allows multiple + views to share a single cache to save memory and + improve lookup efficiency. Based on contributed code + from Barclay Osborn, Google. [RT #18905] + +2525. [func] New logging category "query-errors" to provide detailed internal information about query failures, especially about server failures. [RT #19027] @@ -867,10 +1783,17 @@ 2521. [bug] Improve epoll cross compilation support. [RT #19047] +2520. [bug] Update xml statistics version number to 2.0 as change + #2388 made the schema incompatible to the previous + version. [RT #19080] + 2519. [bug] dig/host with -4 or -6 didn't work if more than two nameserver addresses of the excluded address family preceded in resolv.conf. [RT #19081] +2518. [func] Add support for the new CERT types from RFC 4398. + [RT #19077] + 2517. [bug] dig +trace with -4 or -6 failed when it chose a nameserver address of the excluded address type. [RT #18843] @@ -878,45 +1801,56 @@ 2516. [bug] glue sort for responses was performed even when not needed. [RT #19039] +2515. [port] win32: build dnssec-dsfromkey and dnssec-keyfromlabel. + [RT #19063] + 2514. [bug] dig/host failed with -4 or -6 when resolv.conf contains a nameserver of the excluded address family. [RT #18848] +2513. [bug] Fix windows cli build. [RT #19062] + +2512. [func] Print a summary of the cached records which make up + the negative response. [RT #18885] + 2511. [cleanup] dns_rdata_tofmttext() add const to linebreak. [RT #18885] +2510. [bug] "dig +sigchase" could trigger REQUIRE failures. + [RT #19033] + +2509. [bug] Specifying a fixed query source port was broken. + [RT #19051] + +2508. [placeholder] + +2507. [func] Log the recursion quota values when killing the + oldest query or refusing to recurse due to quota. + [RT #19022] + 2506. [port] solaris: Check at configure time if hack_shutup_pthreadonceinit is needed. [RT #19037] 2505. [port] Treat amd64 similarly to x86_64 when determining atomic operation support. [RT #19031] +2504. [bug] Address race condition in the socket code. [RT #18899] + 2503. [port] linux: improve compatibility with Linux Standard Base. [RT #18793] 2502. [cleanup] isc_radix: Improve compliance with coding style, document function in . [RT #18534] - --- 9.6.0 released --- - -2520. [bug] Update xml statistics version number to 2.0 as change - #2388 made the schema incompatible to the previous - version. [RT #19080] - - --- 9.6.0rc2 released --- - -2515. [port] win32: build dnssec-dsfromkey and dnssec-keyfromlabel. - [RT #19063] - -2513. [bug] Fix windows cli build. [RT #19062] - -2510. [bug] "dig +sigchase" could trigger REQUIRE failures. - [RT #19033] +2501. [func] $GENERATE now supports all rdata types. Multi-field + rdata types need to be quoted. See the ARM for + details. [RT #18368] -2509. [bug] Specifying a fixed query source port was broken. - [RT #19051] +2500. [contrib] contrib/sdb/pgsql/zonetodb.c called non-existent + function. [RT #18582] -2504. [bug] Address race condition in the socket code. [RT #18899] +2499. [port] solaris: lib/lwres/getaddrinfo.c namespace clash. + [RT #18837] --- 9.6.0rc1 released --- diff --git a/COPYRIGHT b/COPYRIGHT index ee90ece..8721cec 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -13,7 +13,7 @@ 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. -$Id: COPYRIGHT,v 1.14.176.3 2011-01-04 23:45:42 tbox Exp $ +$Id: COPYRIGHT,v 1.17 2011-01-04 23:47:13 tbox Exp $ Portions Copyright (C) 1996-2001 Nominum, Inc. diff --git a/FAQ.xml b/FAQ.xml index a9b2b41..4c83f76 100644 --- a/FAQ.xml +++ b/FAQ.xml @@ -17,7 +17,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - +
Frequently Asked Questions about BIND 9 diff --git a/HISTORY b/HISTORY new file mode 100644 index 0000000..e98f9b4 --- /dev/null +++ b/HISTORY @@ -0,0 +1,313 @@ +Summary of functional enhancements from prior major releases of BIND 9: + +BIND 9.6.0 + + Full NSEC3 support + + Automatic zone re-signing + + New update-policy methods tcp-self and 6to4-self + + The BIND 8 resolver library, libbind, has been removed from the + BIND 9 distribution and is now available as a separate download. + + Change the default pid file location from /var/run to + /var/run/{named,lwresd} for improved chroot/setuid support. + +BIND 9.5.0 + + GSS-TSIG support (RFC 3645). + + DHCID support. + + Experimental http server and statistics support for named via xml. + + More detailed statistics counters including those supported in BIND 8. + + Faster ACL processing. + + Use Doxygen to generate internal documentation. + + Efficient LRU cache-cleaning mechanism. + + NSID support. + +BIND 9.4.0 + + Implemented "additional section caching (or acache)", an + internal cache framework for additional section content to + improve response performance. Several configuration options + were provided to control the behavior. + + New notify type 'master-only'. Enable notify for master + zones only. + + Accept 'notify-source' style syntax for query-source. + + rndc now allows addresses to be set in the server clauses. + + New option "allow-query-cache". This lets "allow-query" + be used to specify the default zone access level rather + than having to have every zone override the global value. + "allow-query-cache" can be set at both the options and view + levels. If "allow-query-cache" is not set then "allow-recursion" + is used if set, otherwise "allow-query" is used if set + unless "recursion no;" is set in which case "none;" is used, + otherwise the default (localhost; localnets;) is used. + + rndc: the source address can now be specified. + + ixfr-from-differences now takes master and slave in addition + to yes and no at the options and view levels. + + Allow the journal's name to be changed via named.conf. + + 'rndc notify zone [class [view]]' resend the NOTIFY messages + for the specified zone. + + 'dig +trace' now randomly selects the next servers to try. + Report if there is a bad delegation. + + Improve check-names error messages. + + Make public the function to read a key file, dst_key_read_public(). + + dig now returns the byte count for axfr/ixfr. + + allow-update is now settable at the options / view level. + + named-checkconf now checks the logging configuration. + + host now can turn on memory debugging flags with '-m'. + + Don't send notify messages to self. + + Perform sanity checks on NS records which refer to 'in zone' names. + + New zone option "notify-delay". Specify a minimum delay + between sets of NOTIFY messages. + + Extend adjusting TTL warning messages. + + Named and named-checkzone can now both check for non-terminal + wildcard records. + + "rndc freeze/thaw" now freezes/thaws all zones. + + named-checkconf now check acls to verify that they only + refer to existing acls. + + The server syntax has been extended to support a range of + servers. + + Report differences between hints and real NS rrset and + associated address records. + + Preserve the case of domain names in rdata during zone + transfers. + + Restructured the data locking framework using architecture + dependent atomic operations (when available), improving + response performance on multi-processor machines significantly. + x86, x86_64, alpha, powerpc, and mips are currently supported. + + UNIX domain controls are now supported. + + Add support for additional zone file formats for improving + loading performance. The masterfile-format option in + named.conf can be used to specify a non-default format. A + separate command named-compilezone was provided to generate + zone files in the new format. Additionally, the -I and -O + options for dnssec-signzone specify the input and output + formats. + + dnssec-signzone can now randomize signature end times + (dnssec-signzone -j jitter). + + Add support for CH A record. + + Add additional zone data constancy checks. named-checkzone + has extended checking of NS, MX and SRV record and the hosts + they reference. named has extended post zone load checks. + New zone options: check-mx and integrity-check. + + + edns-udp-size can now be overridden on a per server basis. + + dig can now specify the EDNS version when making a query. + + Added framework for handling multiple EDNS versions. + + Additional memory debugging support to track size and mctx + arguments. + + Detect duplicates of UDP queries we are recursing on and + drop them. New stats category "duplicates". + + "USE INTERNAL MALLOC" is now runtime selectable. + + The lame cache is now done on a basis + as some servers only appear to be lame for certain query + types. + + Limit the number of recursive clients that can be waiting + for a single query () to resolve. New + options clients-per-query and max-clients-per-query. + + dig: report the number of extra bytes still left in the + packet after processing all the records. + + Support for IPSECKEY rdata type. + + Raise the UDP recieve buffer size to 32k if it is less than 32k. + + x86 and x86_64 now have seperate atomic locking implementations. + + named-checkconf now validates update-policy entries. + + Attempt to make the amount of work performed in a iteration + self tuning. The covers nodes clean from the cache per + iteration, nodes written to disk when rewriting a master + file and nodes destroyed per iteration when destroying a + zone or a cache. + + ISC string copy API. + + Automatic empty zone creation for D.F.IP6.ARPA and friends. + Note: RFC 1918 zones are not yet covered by this but are + likely to be in a future release. + + New options: empty-server, empty-contact, empty-zones-enable + and disable-empty-zone. + + dig now has a '-q queryname' and '+showsearch' options. + + host/nslookup now continue (default)/fail on SERVFAIL. + + dig now warns if 'RA' is not set in the answer when 'RD' + was set in the query. host/nslookup skip servers that fail + to set 'RA' when 'RD' is set unless a server is explicitly + set. + + Integrate contibuted DLZ code into named. + + Integrate contibuted IDN code from JPNIC. + + libbind: corresponds to that from BIND 8.4.7. + +BIND 9.3.0 + + DNSSEC is now DS based (RFC 3658). + See also RFC 3845, doc/draft/draft-ietf-dnsext-dnssec-*. + + DNSSEC lookaside validation. + + check-names is now implemented. + rrset-order in more complete. + + IPv4/IPv6 transition support, dual-stack-servers. + + IXFR deltas can now be generated when loading master files, + ixfr-from-differences. + + It is now possible to specify the size of a journal, max-journal-size. + + It is now possible to define a named set of master servers to be + used in masters clause, masters. + + The advertised EDNS UDP size can now be set, edns-udp-size. + + allow-v6-synthesis has been obsoleted. + + NOTE: + * Zones containing MD and MF will now be rejected. + * dig, nslookup name. now report "Not Implemented" as + NOTIMP rather than NOTIMPL. This will have impact on scripts + that are looking for NOTIMPL. + + libbind: corresponds to that from BIND 8.4.5. + +BIND 9.2.0 + + The size of the cache can now be limited using the + "max-cache-size" option. + + The server can now automatically convert RFC1886-style recursive + lookup requests into RFC2874-style lookups, when enabled using the + new option "allow-v6-synthesis". This allows stub resolvers that + support AAAA records but not A6 record chains or binary labels to + perform lookups in domains that make use of these IPv6 DNS + features. + + Performance has been improved. + + The man pages now use the more portable "man" macros rather than + the "mandoc" macros, and are installed by "make install". + + The named.conf parser has been completely rewritten. It now + supports "include" directives in more places such as inside "view" + statements, and it no longer has any reserved words. + + The "rndc status" command is now implemented. + + rndc can now be configured automatically. + + A BIND 8 compatible stub resolver library is now included in + lib/bind. + + OpenSSL has been removed from the distribution. This means that to + use DNSSEC, OpenSSL must be installed and the --with-openssl option + must be supplied to configure. This does not apply to the use of + TSIG, which does not require OpenSSL. + + The source distribution now builds on Windows. See + win32utils/readme1.txt and win32utils/win32-build.txt for details. + + This distribution also includes a new lightweight stub + resolver library and associated resolver daemon that fully + support forward and reverse lookups of both IPv4 and IPv6 + addresses. This library is considered experimental and + is not a complete replacement for the BIND 8 resolver library. + Applications that use the BIND 8 res_* functions to perform + DNS lookups or dynamic updates still need to be linked against + the BIND 8 libraries. For DNS lookups, they can also use the + new "getrrsetbyname()" API. + + BIND 9.2 is capable of acting as an authoritative server + for DNSSEC secured zones. This functionality is believed to + be stable and complete except for lacking support for + verifications involving wildcard records in secure zones. + + When acting as a caching server, BIND 9.2 can be configured + to perform DNSSEC secure resolution on behalf of its clients. + This part of the DNSSEC implementation is still considered + experimental. For detailed information about the state of the + DNSSEC implementation, see the file doc/misc/dnssec. + + There are a few known bugs: + + On some systems, IPv6 and IPv4 sockets interact in + unexpected ways. For details, see doc/misc/ipv6. + To reduce the impact of these problems, the server + no longer listens for requests on IPv6 addresses + by default. If you need to accept DNS queries over + IPv6, you must specify "listen-on-v6 { any; };" + in the named.conf options statement. + + FreeBSD prior to 4.2 (and 4.2 if running as non-root) + and OpenBSD prior to 2.8 log messages like + "fcntl(8, F_SETFL, 4): Inappropriate ioctl for device". + This is due to a bug in "/dev/random" and impacts the + server's DNSSEC support. + + OS X 10.1.4 (Darwin 5.4), OS X 10.1.5 (Darwin 5.5) and + OS X 10.2 (Darwin 6.0) reports errors like + "fcntl(3, F_SETFL, 4): Operation not supported by device". + This is due to a bug in "/dev/random" and impacts the + server's DNSSEC support. + + --with-libtool does not work on AIX. + + A bug in some versions of the Microsoft DNS server can cause zone + transfers from a BIND 9 server to a W2K server to fail. For details, + see the "Zone Transfers" section in doc/misc/migration. diff --git a/KNOWN-DEFECTS b/KNOWN-DEFECTS deleted file mode 100644 index 83d7175..0000000 --- a/KNOWN-DEFECTS +++ /dev/null @@ -1,15 +0,0 @@ -dnssec-signzone was designed so that it could sign a zone partially, using -only a subset of the DNSSEC keys needed to produce a fully-signed zone. -This permits a zone administrator, for example, to sign a zone with one -key on one machine, move the resulting partially-signed zone to a second -machine, and sign it again with a second key. - -An unfortunate side-effect of this flexibility is that dnssec-signzone -does not check to make sure it's signing a zone with any valid keys at -all. An attempt to sign a zone without any keys will appear to succeed, -producing a "signed" zone with no signatures. There is no warning issued -when a zone is not signed. - -This will be corrected in a future release. In the meantime, ISC -recommends examining the output of dnssec-signzone to confirm that -the zone is properly signed by all keys before using it. diff --git a/Makefile.in b/Makefile.in index e4d5639..95944d9 100644 --- a/Makefile.in +++ b/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.52.48.2 2009-02-20 23:47:23 tbox Exp $ +# $Id: Makefile.in,v 1.58 2009-11-26 20:52:44 marka Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -21,13 +21,13 @@ top_srcdir = @top_srcdir@ @BIND9_VERSION@ -SUBDIRS = make lib bin doc +SUBDIRS = make lib bin doc @LIBEXPORT@ TARGETS = MANPAGES = isc-config.sh.1 - + HTMLPAGES = isc-config.sh.html - + MANOBJS = ${MANPAGES} ${HTMLPAGES} @BIND9_MAKE_RULES@ @@ -54,7 +54,8 @@ installdirs: install:: isc-config.sh installdirs ${INSTALL_SCRIPT} isc-config.sh ${DESTDIR}${bindir} - ${INSTALL_DATA} ${srcdir}/isc-config.sh.1 ${DESTDIR}${mandir}/man1 + ${INSTALL_DATA} ${top_srcdir}/isc-config.sh.1 ${DESTDIR}${mandir}/man1 + ${INSTALL_DATA} ${top_srcdir}/bind.keys ${DESTDIR}${sysconfdir} tags: rm -f TAGS diff --git a/NSEC3-NOTES b/NSEC3-NOTES deleted file mode 100644 index 3f8d8f9..0000000 --- a/NSEC3-NOTES +++ /dev/null @@ -1,128 +0,0 @@ - - DNSSEC and UPDATE - - Converting from insecure to secure - -As of BIND 9.6.0 it is possible to move a zone between being insecure -to secure and back again. A secure zone can be using NSEC or NSEC3. - -To move a zone from insecure to secure you need to configure named -so that it can see the K* files which contain the public and private -parts of the keys that will be used to sign the zone. These files -will have been generated by dnssec-keygen. You can do this by -placing them in the key-directory as specified in named.conf. - - zone example.net { - type master; - allow-update { .... }; - file "dynamic/example.net/example.net"; - key-directory "dynamic/example.net"; - }; - -Assuming one KSK and one ZSK DNSKEY key have been generated. Then -this will cause the zone to be signed with the ZSK and the DNSKEY -RRset to be signed with the KSK DNSKEY. A NSEC chain will also be -generated as part of the initial signing process. - - % nsupdate - > ttl 3600 - > update add example.net DNSKEY 256 3 7 AwEAAZn17pUF0KpbPA2c7Gz76Vb18v0teKT3EyAGfBfL8eQ8al35zz3Y I1m/SAQBxIqMfLtIwqWPdgthsu36azGQAX8= - > update add example.net DNSKEY 257 3 7 AwEAAd/7odU/64o2LGsifbLtQmtO8dFDtTAZXSX2+X3e/UNlq9IHq3Y0 XtC0Iuawl/qkaKVxXe2lo8Ct+dM6UehyCqk= - > send - -While the update request will complete almost immediately the zone -will not be completely signed until named has had time to walk the -zone and generate the NSEC and RRSIG records. Initially the NSEC -record at the zone apex will have the OPT bit set. When the NSEC -chain is complete the OPT bit will be cleared. Additionally when -the zone is fully signed the private type (default TYPE65534) records -will have a non zero value for the final octet. - -The private type record has 5 octets. - algorithm (octet 1) - key id in network order (octet 2 and 3) - removal flag (octet 4) - complete flag (octet 5) - -If you wish to go straight to a secure zone using NSEC3 you should -also add a NSEC3PARAM record to the update request with the flags -field set to indicate whether the NSEC3 chain will have the OPTOUT -bit set or not. - - % nsupdate - > ttl 3600 - > update add example.net DNSKEY 256 3 7 AwEAAZn17pUF0KpbPA2c7Gz76Vb18v0teKT3EyAGfBfL8eQ8al35zz3Y I1m/SAQBxIqMfLtIwqWPdgthsu36azGQAX8= - > update add example.net DNSKEY 257 3 7 AwEAAd/7odU/64o2LGsifbLtQmtO8dFDtTAZXSX2+X3e/UNlq9IHq3Y0 XtC0Iuawl/qkaKVxXe2lo8Ct+dM6UehyCqk= - > update add example.net NSEC3PARAM 1 1 100 1234567890 - > send - -Again the update request will complete almost immediately however the -NSEC3PARAM record will have additional flag bits set indicating that the -NSEC3 chain is under construction. When the NSEC3 chain is complete the -flags field will be set to zero. - -While the initial signing and NSEC/NSEC3 chain generation is happening -other updates are possible. - - DNSKEY roll overs via UPDATE - -It is possible to perform key rollovers via update. You need to -add the K* files for the new keys so that named can find them. You -can then add the new DNSKEY RRs via update. Named will then cause -the zone to be signed with the new keys. When the signing is -complete the private type records will be updated so that the last -octet is non zero. - -If this is for a KSK you need to inform the parent and any trust -anchor repositories of the new KSK. - -You should then wait for the maximum TLL in the zone before removing the -old DNSKEY. If it is a KSK that is being updated you also need to wait -for the DS RRset in the parent to be updated and its TTL to expire. -This ensures that all clients will be able to verify at least a signature -when you remove the old DNSKEY. - -The old DNSKEY can be removed via UPDATE. Take care to specify -the correct key. Named will clean out any signatures generated by -the old key after the update completes. - - NSEC3PARAM rollovers via UPDATE. - -Add the new NSEC3PARAM record via update. When the new NSEC3 chain -has been generated the NSEC3PARAM flag field will be zero. At this -point you can remove the old NSEC3PARAM record. The old chain will -be removed after the update request completes. - - Converting from NSEC to NSEC3 - -To do this you just need to add a NSEC3PARAM record. When the -conversion is complete the NSEC chain will have been removed and -the NSEC3PARAM record will have a zero flag field. The NSEC3 chain -will be generated before the NSEC chain is destroyed. - - Converting from NSEC3 to NSEC - -To do this remove all NSEC3PARAM records with a zero flag field. The -NSEC chain will be generated before the NSEC3 chain is removed. - - Converting from secure to insecure - -To do this remove all the DNSKEY records. Any NSEC or NSEC3 chains -will be removed as well as associated NSEC3PARAM records. This will -take place after the update requests completes. - - Periodic re-signing. - -Named will periodically re-sign RRsets which have not been re-signed -as a result of some update action. The signature lifetimes will -be adjusted so as to spread the re-sign load over time rather than -all at once. - - NSEC3 and OPTOUT - -Named only supports creating new NSEC3 chains where all the NSEC3 -records in the zone have the same OPTOUT state. Named supports -UPDATES to zones where the NSEC3 records in the chain have mixed -OPTOUT state. Named does not support changing the OPTOUT state of -an individual NSEC3 record, the entire chain needs to be changed if -the OPTOUT state of an individual NSEC3 needs to be changed. diff --git a/README b/README index 54d90fe..00010c3 100644 --- a/README +++ b/README @@ -42,368 +42,95 @@ BIND 9 Stichting NLnet - NLnet Foundation Nominum, Inc. -BIND 9.6.3 - - BIND 9.6.3 is a maintenance release, fixing bugs in 9.6.2. - -BIND 9.6.2 - - BIND 9.6.2 is a maintenance release, fixing bugs in 9.6.1. - It also introduces support for the SHA-2 DNSSEC algorithms, - RSASHA256 and RSASHA512. - - Known issues in this release: - - - A validating resolver that has been incorrectly configured with - an invalid trust anchor will be unable to resolve names covered - by that trust anchor. In all current versions of BIND 9, such a - resolver will also generate significant unnecessary DNS traffic - while trying to validate. The latter problem will be addressed - in future BIND 9 releases. In the meantime, to avoid these - problems, exercise caution when configuring "trusted-keys": - make sure all keys are correct and current when you add them, - and update your configuration in a timely manner when keys - roll over. - -BIND 9.6.1 - - BIND 9.6.1 is a maintenance release, fixing bugs in 9.6.0. - -BIND 9.6.0 - - BIND 9.6.0 includes a number of changes from BIND 9.5 and earlier - releases, including: - - Full NSEC3 support - - Automatic zone re-signing - - New update-policy methods tcp-self and 6to4-self - - The BIND 8 resolver library, libbind, has been removed from the - BIND 9 distribution and is now available as a separate download. - - Change the default pid file location from /var/run to - /var/run/{named,lwresd} for improved chroot/setuid support. - -BIND 9.5.0 - - BIND 9.5.0 has a number of new features over 9.4, - including: - - GSS-TSIG support (RFC 3645). - - DHCID support. - - Experimental http server and statistics support for named via xml. - - More detailed statistics counters including those supported in BIND 8. - - Faster ACL processing. - - Use Doxygen to generate internal documentation. - - Efficient LRU cache-cleaning mechanism. - - NSID support. - -BIND 9.4.0 - - BIND 9.4.0 has a number of new features over 9.3, - including: - - Implemented "additional section caching (or acache)", an - internal cache framework for additional section content to - improve response performance. Several configuration options - were provided to control the behavior. - - New notify type 'master-only'. Enable notify for master - zones only. - - Accept 'notify-source' style syntax for query-source. - - rndc now allows addresses to be set in the server clauses. - - New option "allow-query-cache". This lets "allow-query" - be used to specify the default zone access level rather - than having to have every zone override the global value. - "allow-query-cache" can be set at both the options and view - levels. If "allow-query-cache" is not set then "allow-recursion" - is used if set, otherwise "allow-query" is used if set - unless "recursion no;" is set in which case "none;" is used, - otherwise the default (localhost; localnets;) is used. - - rndc: the source address can now be specified. - - ixfr-from-differences now takes master and slave in addition - to yes and no at the options and view levels. - - Allow the journal's name to be changed via named.conf. - - 'rndc notify zone [class [view]]' resend the NOTIFY messages - for the specified zone. - - 'dig +trace' now randomly selects the next servers to try. - Report if there is a bad delegation. - - Improve check-names error messages. - - Make public the function to read a key file, dst_key_read_public(). - - dig now returns the byte count for axfr/ixfr. - - allow-update is now settable at the options / view level. - - named-checkconf now checks the logging configuration. - - host now can turn on memory debugging flags with '-m'. - - Don't send notify messages to self. - - Perform sanity checks on NS records which refer to 'in zone' names. - - New zone option "notify-delay". Specify a minimum delay - between sets of NOTIFY messages. - - Extend adjusting TTL warning messages. - - Named and named-checkzone can now both check for non-terminal - wildcard records. - - "rndc freeze/thaw" now freezes/thaws all zones. - - named-checkconf now check acls to verify that they only - refer to existing acls. - - The server syntax has been extended to support a range of - servers. - - Report differences between hints and real NS rrset and - associated address records. - - Preserve the case of domain names in rdata during zone - transfers. - - Restructured the data locking framework using architecture - dependent atomic operations (when available), improving - response performance on multi-processor machines significantly. - x86, x86_64, alpha, powerpc, and mips are currently supported. - - UNIX domain controls are now supported. - - Add support for additional zone file formats for improving - loading performance. The masterfile-format option in - named.conf can be used to specify a non-default format. A - separate command named-compilezone was provided to generate - zone files in the new format. Additionally, the -I and -O - options for dnssec-signzone specify the input and output - formats. - - dnssec-signzone can now randomize signature end times - (dnssec-signzone -j jitter). - - Add support for CH A record. - - Add additional zone data constancy checks. named-checkzone - has extended checking of NS, MX and SRV record and the hosts - they reference. named has extended post zone load checks. - New zone options: check-mx and integrity-check. - - - edns-udp-size can now be overridden on a per server basis. - - dig can now specify the EDNS version when making a query. - - Added framework for handling multiple EDNS versions. - - Additional memory debugging support to track size and mctx - arguments. - - Detect duplicates of UDP queries we are recursing on and - drop them. New stats category "duplicates". - - "USE INTERNAL MALLOC" is now runtime selectable. - - The lame cache is now done on a basis - as some servers only appear to be lame for certain query - types. - - Limit the number of recursive clients that can be waiting - for a single query () to resolve. New - options clients-per-query and max-clients-per-query. - - dig: report the number of extra bytes still left in the - packet after processing all the records. - - Support for IPSECKEY rdata type. - - Raise the UDP recieve buffer size to 32k if it is less than 32k. - - x86 and x86_64 now have seperate atomic locking implementations. - - named-checkconf now validates update-policy entries. - - Attempt to make the amount of work performed in a iteration - self tuning. The covers nodes clean from the cache per - iteration, nodes written to disk when rewriting a master - file and nodes destroyed per iteration when destroying a - zone or a cache. - - ISC string copy API. - - Automatic empty zone creation for D.F.IP6.ARPA and friends. - Note: RFC 1918 zones are not yet covered by this but are - likely to be in a future release. - - New options: empty-server, empty-contact, empty-zones-enable - and disable-empty-zone. - - dig now has a '-q queryname' and '+showsearch' options. - - host/nslookup now continue (default)/fail on SERVFAIL. - - dig now warns if 'RA' is not set in the answer when 'RD' - was set in the query. host/nslookup skip servers that fail - to set 'RA' when 'RD' is set unless a server is explicitly - set. - - Integrate contibuted DLZ code into named. - - Integrate contibuted IDN code from JPNIC. - - libbind: corresponds to that from BIND 8.4.7. - -BIND 9.3.0 - - BIND 9.3.0 has a number of new features over 9.2, - including: - - DNSSEC is now DS based (RFC 3658). - See also RFC 3845, doc/draft/draft-ietf-dnsext-dnssec-*. - - DNSSEC lookaside validation. - - check-names is now implemented. - rrset-order in more complete. - - IPv4/IPv6 transition support, dual-stack-servers. - - IXFR deltas can now be generated when loading master files, - ixfr-from-differences. - - It is now possible to specify the size of a journal, max-journal-size. - - It is now possible to define a named set of master servers to be - used in masters clause, masters. - - The advertised EDNS UDP size can now be set, edns-udp-size. - - allow-v6-synthesis has been obsoleted. - - NOTE: - * Zones containing MD and MF will now be rejected. - * dig, nslookup name. now report "Not Implemented" as - NOTIMP rather than NOTIMPL. This will have impact on scripts - that are looking for NOTIMPL. - - libbind: corresponds to that from BIND 8.4.5. - -BIND 9.2.0 - - BIND 9.2.0 has a number of new features over 9.1, - including: - - - The size of the cache can now be limited using the - "max-cache-size" option. - - - The server can now automatically convert RFC1886-style - recursive lookup requests into RFC2874-style lookups, - when enabled using the new option "allow-v6-synthesis". - This allows stub resolvers that support AAAA records - but not A6 record chains or binary labels to perform - lookups in domains that make use of these IPv6 DNS - features. - - - Performance has been improved. - - - The man pages now use the more portable "man" macros - rather than the "mandoc" macros, and are installed - by "make install". - - - The named.conf parser has been completely rewritten. - It now supports "include" directives in more - places such as inside "view" statements, and it no - longer has any reserved words. - - - The "rndc status" command is now implemented. - - - rndc can now be configured automatically. - - - A BIND 8 compatible stub resolver library is now - included in lib/bind. - - - OpenSSL has been removed from the distribution. This - means that to use DNSSEC, OpenSSL must be installed and - the --with-openssl option must be supplied to configure. - This does not apply to the use of TSIG, which does not - require OpenSSL. - - - The source distribution now builds on Windows. - See win32utils/readme1.txt and win32utils/win32-build.txt - for details. - - This distribution also includes a new lightweight stub - resolver library and associated resolver daemon that fully - support forward and reverse lookups of both IPv4 and IPv6 - addresses. This library is considered experimental and - is not a complete replacement for the BIND 8 resolver library. - Applications that use the BIND 8 res_* functions to perform - DNS lookups or dynamic updates still need to be linked against - the BIND 8 libraries. For DNS lookups, they can also use the - new "getrrsetbyname()" API. - - BIND 9.2 is capable of acting as an authoritative server - for DNSSEC secured zones. This functionality is believed to - be stable and complete except for lacking support for - verifications involving wildcard records in secure zones. - - When acting as a caching server, BIND 9.2 can be configured - to perform DNSSEC secure resolution on behalf of its clients. - This part of the DNSSEC implementation is still considered - experimental. For detailed information about the state of the - DNSSEC implementation, see the file doc/misc/dnssec. - - There are a few known bugs: - - On some systems, IPv6 and IPv4 sockets interact in - unexpected ways. For details, see doc/misc/ipv6. - To reduce the impact of these problems, the server - no longer listens for requests on IPv6 addresses - by default. If you need to accept DNS queries over - IPv6, you must specify "listen-on-v6 { any; };" - in the named.conf options statement. - - FreeBSD prior to 4.2 (and 4.2 if running as non-root) - and OpenBSD prior to 2.8 log messages like - "fcntl(8, F_SETFL, 4): Inappropriate ioctl for device". - This is due to a bug in "/dev/random" and impacts the - server's DNSSEC support. - - OS X 10.1.4 (Darwin 5.4), OS X 10.1.5 (Darwin 5.5) and - OS X 10.2 (Darwin 6.0) reports errors like - "fcntl(3, F_SETFL, 4): Operation not supported by device". - This is due to a bug in "/dev/random" and impacts the - server's DNSSEC support. - - --with-libtool does not work on AIX. - - A bug in some versions of the Microsoft DNS server can cause zone - transfers from a BIND 9 server to a W2K server to fail. For details, - see the "Zone Transfers" section in doc/misc/migration. + For a summary of functional enhancements in previous + releases, see the HISTORY file. For a detailed list of user-visible changes from previous releases, see the CHANGES file. +BIND 9.8.0 + + BIND 9.8.0 includes a number of changes from BIND 9.7 and earlier + releases. New features include: + + - Built-in trust anchor for the root zone, which can be + switched on via "dnssec-validation auto;" + - Support for DNS64. + - Support for response policy zones (RPZ). + - Support for writable DLZ zones. + - Improved ease of configuration of GSS/TSIG for + interoperability with Active Directory + - Support for GOST signing algorithm for DNSSEC. + - Removed RTT Banding from server selection algorithm. + - New "static-stub" zone type. + - Allow configuration of resolver timeouts via + "resolver-query-timeout" option. + +BIND 9.7.0 + + BIND 9.7.0 includes a number of changes from BIND 9.6 and earlier + releases. Most are intended to simplify DNSSEC configuration. + + New features include: + + - Fully automatic signing of zones by "named". + - Simplified configuration of DNSSEC Lookaside Validation (DLV). + - Simplified configuration of Dynamic DNS, using the "ddns-confgen" + command line tool or the "local" update-policy option. (As a side + effect, this also makes it easier to configure automatic zone + re-signing.) + - New named option "attach-cache" that allows multiple views to + share a single cache. + - DNS rebinding attack prevention. + - New default values for dnssec-keygen parameters. + - Support for RFC 5011 automated trust anchor maintenance + - Smart signing: simplified tools for zone signing and key + maintenance. + - The "statistics-channels" option is now available on Windows. + - A new DNSSEC-aware libdns API for use by non-BIND9 applications + - On some platforms, named and other binaries can now print out + a stack backtrace on assertion failure, to aid in debugging. + - A "tools only" installation mode on Windows, which only installs + dig, host, nslookup and nsupdate. + - Improved PKCS#11 support, including Keyper support and explicit + OpenSSL engine selection. + + Known issues in this release: + + - In rare cases, DNSSEC validation can leak memory. When this + happens, it will cause an assertion failure when named exits, + but is otherwise harmless. A fix exists, but was too late for + this release; it will be included in BIND 9.7.1. + + Compatibility notes: + + - If you had built BIND 9.6 with any of ALLOW_NSEC3PARAM_UPDATE, + ALLOW_SECURE_TO_INSECURE or ALLOW_INSECURE_TO_SECURE defined, then + you should ensure that all changes that are in progress have + completed prior to upgrading to BIND 9.7. BIND 9.7 implements + those features in a way which is not backwards compatible. + + - Prior releases had a bug which caused HMAC-SHA* keys with long + secrets to be used incorrectly. Fixing this bug means that older + versions of BIND 9 may fail to interoperate with this version + when using TSIG keys. If this occurs, the new "isc-hmac-fixup" + tool will convert a key with a long secret into a form that works + correctly with all versions of BIND 9. See the "isc-hmac-fixup" + man page for additional details. + + - Revoking a DNSSEC key with "dnssec-revoke" changes its key ID. + It is possible for the new key ID to collide with that of a + different key. Newly generated keys will not have this problem, + as "dnssec-keygen" looks for potential collisions before + generating keys, but exercise caution if using key revokation + with keys that were generated by older versions of BIND 9. See + the Administrator's Reference Manual, section 4.10 ("Dynamic + Trust Anchor Management") for more details. + + - A bug was fixed in which a key's scheduled inactivity date was + stored incorectly. Users who participated in the 9.7.0 BETA test + and had DNSSEC keys with scheduled inactivity dates will need to + reset those keys' dates using "dnssec-settime -I". Building @@ -417,7 +144,7 @@ Building FreeBSD 4.10, 5.2.1, 6.2 HP-UX 11.11 Mac OS X 10.5 - NetBSD 3.x and 4.0-beta + NetBSD 3.x, 4.0-beta, 5.0-beta OpenBSD 3.3 and up Solaris 8, 9, 9 (x86), 10 Ubuntu 7.04, 7.10 @@ -594,6 +321,9 @@ Documentation Frequently asked questions and their answers can be found in FAQ. + Additional information on various subjects can be found + in the other README files. + Bug Reports and Mailing Lists diff --git a/README.idnkit b/README.idnkit deleted file mode 100644 index f5255f5..0000000 --- a/README.idnkit +++ /dev/null @@ -1,112 +0,0 @@ - - BIND-9 IDN patch - - Japan Network Information Center (JPNIC) - - -* What is this patch for? - -This patch adds internationalized domain name (IDN) support to BIND-9. -You'll get internationalized version of dig/host/nslookup commands. - - + internationalized dig/host/nslookup - dig/host/nslookup accepts non-ASCII domain names in the local - codeset (such as Shift JIS, Big5 or ISO8859-1) determined by - the locale information. The domain names are normalized and - converted to the encoding on the DNS protocol, and sent to DNS - servers. The replies are converted back to the local codeset - and displayed. - - -* Compilation & installation - -0. Prerequisite - -You have to build and install idnkit before building this patched version -of bind-9. - -1. Running configure script - -Run `configure' in the top directory. See `README' for the -configuration options. - -This patch adds the following 4 options to `configure'. You should -at least specify `--with-idn' option to enable IDN support. - - --with-idn[=IDN_PREFIX] - To enable IDN support, you have to specify `--with-idn' option. - The argument IDN_PREFIX is the install prefix of idnkit. If - IDN_PREFIX is omitted, PREFIX (derived from `--prefix=PREFIX') - is assumed. - - --with-libiconv[=LIBICONV_PREFIX] - Specify this option if idnkit you have installed links GNU - libiconv. The argument LIBICONV_PREFIX is install prefix of - GNU libiconv. If the argument is omitted, PREFIX (derived - from `--prefix=PREFIX') is assumed. - - `--with-libiconv' is shorthand option for GNU libiconv. - - --with-libiconv=/usr/local - - This is equivalent to: - - --with-iconv='-L/usr/local/lib -R/usr/local/lib -liconv' - - `--with-libiconv' assumes that your C compiler has `-R' - option, and that the option adds the specified run-time path - to an executable binary. If `-R' option of your compiler has - different meaning, or your compiler lacks the option, you - should use `--with-iconv' option instead. Binary command - without run-time path information might be unexecutable. - In that case, you would see an error message like: - - error in loading shared libraries: libiconv.so.2: cannot - open shared object file - - If both `--with-libiconv' and `--with-iconv' options are - specified, `--with-iconv' is prior to `--with-libiconv'. - - --with-iconv=ICONV_LIBSPEC - If your libc doesn't provide iconv(), you need to specify the - library containing iconv() with this option. `ICONV_LIBSPEC' - is the argument(s) to `cc' or `ld' to link the library, for - example, `--with-iconv="-L/usr/local/lib -liconv"'. - You don't need to specify the header file directory for "iconv.h" - to the compiler, as it isn't included directly by bind-9 with - this patch. - - --with-idnlib=IDN_LIBSPEC - With this option, you can explicitly specify the argument(s) - to `cc' or `ld' to link the idnkit's library, `libidnkit'. If - this option is not specified, `-L${PREFIX}/lib -lidnkit' is - assumed, where ${PREFIX} is the installation prefix specified - with `--with-idn' option above. You may need to use this - option to specify extra arguments, for example, - `--with-idnlib="-L/usr/local/lib -R/usr/local/lib -lidnkit"'. - -Please consult `README' for other configuration options. - -Note that if you want to specify some extra header file directories, -you should use the environment variable STD_CINCLUDES instead of -CFLAGS, as described in README. - -2. Compilation and installation - -After running "configure", just do - - make - make install - -for compiling and installing. - - -* Contact information - -Please see http//www.nic.ad.jp/en/idn/ for the latest news -about idnkit and this patch. - -Bug reports and comments on this kit should be sent to -mdnkit-bugs@nic.ad.jp and idn-cmt@nic.ad.jp, respectively. - -; $Id: README.idnkit,v 1.2.762.1 2009-01-18 23:25:14 marka Exp $ diff --git a/README.pkcs11 b/README.pkcs11 deleted file mode 100644 index b58640d..0000000 --- a/README.pkcs11 +++ /dev/null @@ -1,61 +0,0 @@ - - BIND-9 PKCS#11 support - -Prerequisite - -The PKCS#11 support needs a PKCS#11 OpenSSL engine based on the Solaris one, -released the 2007-11-21 for OpenSSL 0.9.8g, with a bug fix (call to free) -and some improvements, including user friendly PIN management. - -Compilation - -"configure --with-pkcs11 ..." - -PKCS#11 Libraries - -Tested with Solaris one with a SCA board and with openCryptoki with the -software token. - -OpenSSL Engines - -With PKCS#11 support the PKCS#11 engine is statically loaded but at its -initialization it dynamically loads the PKCS#11 objects. -Even the pre commands are therefore unused they are defined with: - SO_PATH: - define: PKCS11_SO_PATH - default: /usr/local/lib/engines/engine_pkcs11.so - MODULE_PATH: - define: PKCS11_MODULE_PATH - default: /usr/lib/libpkcs11.so -Without PKCS#11 support, a specific OpenSSL engine can be still used -by defining ENGINE_ID at compile time. - -PKCS#11 tools - -The contrib/pkcs11-keygen directory contains a set of experimental tools -to handle keys stored in a Hardware Security Module at the benefit of BIND. - -The patch for OpenSSL 0.9.8g is in this directory. Read its README.pkcs11 -for the way to use it (these are the original notes so with the original -path, etc. Define OPENCRYPTOKI to use it with openCryptoki.) - -PIN management - -With the just fixed PKCS#11 OpenSSL engine, the PIN should be entered -each time it is required. With the improved engine, the PIN should be -entered the first time it is required or can be configured in the -OpenSSL configuration file (aka. openssl.cnf) by adding in it: - - at the beginning: - openssl_conf = openssl_def - - at any place these sections: - [ openssl_def ] - engines = engine_section - [ engine_section ] - pkcs11 = pkcs11_section - [ pkcs11_section ] - PIN = put__your__pin__value__here - -Note - -Some names here are registered trademarks, at least Solaris is a trademark -of Sun Microsystems Inc... diff --git a/acconfig.h b/acconfig.h index d64404a..d9da221 100644 --- a/acconfig.h +++ b/acconfig.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: acconfig.h,v 1.51.334.2 2009-02-16 23:47:15 tbox Exp $ */ +/* $Id: acconfig.h,v 1.53 2008-12-01 23:47:44 tbox Exp $ */ /*! \file */ diff --git a/bin/Makefile.in b/bin/Makefile.in index 1694268..d263d79 100644 --- a/bin/Makefile.in +++ b/bin/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 1998-2001 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,13 +13,14 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.25 2007-06-19 23:46:59 tbox Exp $ +# $Id: Makefile.in,v 1.29 2009-10-05 12:07:08 fdupont Exp $ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ -SUBDIRS = named rndc dig dnssec tests nsupdate check +SUBDIRS = named rndc dig dnssec tests tools nsupdate \ + check confgen @PKCS11_TOOLS@ TARGETS = @BIND9_MAKE_RULES@ diff --git a/bin/check/Makefile.in b/bin/check/Makefile.in index 46271c7..d5827dc 100644 --- a/bin/check/Makefile.in +++ b/bin/check/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 2000-2003 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.32 2007-06-19 23:46:59 tbox Exp $ +# $Id: Makefile.in,v 1.36 2009-12-05 23:31:40 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -32,6 +32,7 @@ CWARNINGS = DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ ISCLIBS = ../../lib/isc/libisc.@A@ +ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ BIND9LIBS = ../../lib/bind9/libbind9.@A@ DNSDEPLIBS = ../../lib/dns/libdns.@A@ @@ -39,7 +40,8 @@ ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ ISCDEPLIBS = ../../lib/isc/libisc.@A@ BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@ -LIBS = @LIBS@ +LIBS = ${ISCLIBS} @LIBS@ +NOSYMLIBS = ${ISCNOSYMLIBS} @LIBS@ SUBDIRS = @@ -69,14 +71,14 @@ named-checkzone.@O@: named-checkzone.c named-checkconf@EXEEXT@: named-checkconf.@O@ check-tool.@O@ ${ISCDEPLIBS} \ ${ISCCFGDEPLIBS} ${BIND9DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - named-checkconf.@O@ check-tool.@O@ ${BIND9LIBS} ${ISCCFGLIBS} \ - ${DNSLIBS} ${ISCLIBS} ${LIBS} + export BASEOBJS="named-checkconf.@O@ check-tool.@O@"; \ + export LIBS0="${BIND9LIBS} ${ISCCFGLIBS} ${DNSLIBS}"; \ + ${FINALBUILDCMD} named-checkzone@EXEEXT@: named-checkzone.@O@ check-tool.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - named-checkzone.@O@ check-tool.@O@ ${ISCCFGLIBS} ${DNSLIBS} \ - ${ISCLIBS} ${LIBS} + export BASEOBJS="named-checkzone.@O@ check-tool.@O@"; \ + export LIBS0="${ISCCFGLIBS} ${DNSLIBS}"; \ + ${FINALBUILDCMD} doc man:: ${MANOBJS} diff --git a/bin/check/check-tool.c b/bin/check/check-tool.c index ed9224b..4d2ca5c 100644 --- a/bin/check/check-tool.c +++ b/bin/check/check-tool.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: check-tool.c,v 1.35.36.5 2010-09-07 23:46:05 tbox Exp $ */ +/* $Id: check-tool.c,v 1.41 2010-09-07 23:46:59 tbox Exp $ */ /*! \file */ @@ -601,8 +601,7 @@ load_zone(isc_mem_t *mctx, const char *zonename, const char *filename, isc_buffer_add(&buffer, strlen(zonename)); dns_fixedname_init(&fixorigin); origin = dns_fixedname_name(&fixorigin); - CHECK(dns_name_fromtext(origin, &buffer, dns_rootname, - ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(origin, &buffer, dns_rootname, 0, NULL)); CHECK(dns_zone_setorigin(zone, origin)); CHECK(dns_zone_setdbtype(zone, 1, (const char * const *) dbtype)); CHECK(dns_zone_setfile2(zone, filename, fileformat)); diff --git a/bin/check/check-tool.h b/bin/check/check-tool.h index f9273ff..4371ae2 100644 --- a/bin/check/check-tool.h +++ b/bin/check/check-tool.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: check-tool.h,v 1.14.334.2 2010-09-07 23:46:05 tbox Exp $ */ +/* $Id: check-tool.h,v 1.16 2010-09-07 23:46:59 tbox Exp $ */ #ifndef CHECK_TOOL_H #define CHECK_TOOL_H diff --git a/bin/check/named-checkconf.8 b/bin/check/named-checkconf.8 index 7131007..fabcfa9 100644 --- a/bin/check/named-checkconf.8 +++ b/bin/check/named-checkconf.8 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") .\" Copyright (C) 2000-2002 Internet Software Consortium. .\" .\" Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: named-checkconf.8,v 1.30.334.1 2009-07-11 01:55:20 tbox Exp $ +.\" $Id: named-checkconf.8,v 1.33 2009-12-29 01:14:03 tbox Exp $ .\" .hy 0 .ad l @@ -33,11 +33,29 @@ named\-checkconf \- named configuration file syntax checking tool .SH "SYNOPSIS" .HP 16 -\fBnamed\-checkconf\fR [\fB\-h\fR] [\fB\-v\fR] [\fB\-j\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] {filename} [\fB\-z\fR] +\fBnamed\-checkconf\fR [\fB\-h\fR] [\fB\-v\fR] [\fB\-j\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] {filename} [\fB\-p\fR] [\fB\-z\fR] .SH "DESCRIPTION" .PP \fBnamed\-checkconf\fR -checks the syntax, but not the semantics, of a named configuration file. +checks the syntax, but not the semantics, of a +\fBnamed\fR +configuration file. The file is parsed and checked for syntax errors, along with all files included by it. If no file is specified, +\fI/etc/named.conf\fR +is read by default. +.PP +Note: files that +\fBnamed\fR +reads in separate parser contexts, such as +\fIrndc.key\fR +and +\fIbind.keys\fR, are not automatically read by +\fBnamed\-checkconf\fR. Configuration errors in these files may cause +\fBnamed\fR +to fail to run, even if +\fBnamed\-checkconf\fR +was successful. +\fBnamed\-checkconf\fR +can be run on these files explicitly, however. .SH "OPTIONS" .PP \-h @@ -59,6 +77,13 @@ Print the version of the program and exit. .RE .PP +\-p +.RS 4 +Print out the +\fInamed.conf\fR +and included files in canonical form if no errors were detected. +.RE +.PP \-z .RS 4 Perform a test load of all master zones found in @@ -88,7 +113,7 @@ BIND 9 Administrator Reference Manual. .PP Internet Systems Consortium .SH "COPYRIGHT" -Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") +Copyright \(co 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") .br Copyright \(co 2000\-2002 Internet Software Consortium. .br diff --git a/bin/check/named-checkconf.c b/bin/check/named-checkconf.c index 20983b5..521ed31 100644 --- a/bin/check/named-checkconf.c +++ b/bin/check/named-checkconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: named-checkconf.c,v 1.46.222.4 2010-09-07 23:46:05 tbox Exp $ */ +/* $Id: named-checkconf.c,v 1.54 2010-09-07 01:49:08 marka Exp $ */ /*! \file */ @@ -59,9 +59,12 @@ isc_log_t *logc = NULL; } while (0) /*% usage */ +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + static void usage(void) { - fprintf(stderr, "usage: %s [-h] [-j] [-v] [-z] [-t directory] " + fprintf(stderr, "usage: %s [-h] [-j] [-p] [-v] [-z] [-t directory] " "[named.conf]\n", program); exit(1); } @@ -203,6 +206,24 @@ configure_zone(const char *vclass, const char *view, zfile = cfg_obj_asstring(fileobj); obj = NULL; + if (get_maps(maps, "check-dup-records", &obj)) { + if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { + zone_options |= DNS_ZONEOPT_CHECKDUPRR; + zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; + } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { + zone_options |= DNS_ZONEOPT_CHECKDUPRR; + zone_options |= DNS_ZONEOPT_CHECKDUPRRFAIL; + } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { + zone_options &= ~DNS_ZONEOPT_CHECKDUPRR; + zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; + } else + INSIST(0); + } else { + zone_options |= DNS_ZONEOPT_CHECKDUPRR; + zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; + } + + obj = NULL; if (get_maps(maps, "check-mx", &obj)) { if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { zone_options |= DNS_ZONEOPT_CHECKMX; @@ -387,6 +408,15 @@ load_zones_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx) { return (result); } +static void +output(void *closure, const char *text, int textlen) { + UNUSED(closure); + if (fwrite(text, 1, textlen, stdout) != (size_t)textlen) { + perror("fwrite"); + exit(1); + } +} + /*% The main processing routine */ int main(int argc, char **argv) { @@ -399,10 +429,11 @@ main(int argc, char **argv) { int exit_status = 0; isc_entropy_t *ectx = NULL; isc_boolean_t load_zones = ISC_FALSE; + isc_boolean_t print = ISC_FALSE; isc_commandline_errprint = ISC_FALSE; - while ((c = isc_commandline_parse(argc, argv, "dhjt:vz")) != EOF) { + while ((c = isc_commandline_parse(argc, argv, "dhjt:pvz")) != EOF) { switch (c) { case 'd': debug++; @@ -421,6 +452,10 @@ main(int argc, char **argv) { } break; + case 'p': + print = ISC_TRUE; + break; + case 'v': printf(VERSION "\n"); exit(0); @@ -485,6 +520,8 @@ main(int argc, char **argv) { exit_status = 1; } + if (print && exit_status == 0) + cfg_print(config, output, NULL); cfg_obj_destroy(parser, &config); cfg_parser_destroy(&parser); diff --git a/bin/check/named-checkconf.docbook b/bin/check/named-checkconf.docbook index e0c43d1..fe12cb3 100644 --- a/bin/check/named-checkconf.docbook +++ b/bin/check/named-checkconf.docbook @@ -2,7 +2,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" []> - + June 14, 2000 @@ -35,6 +35,7 @@ 2004 2005 2007 + 2009 Internet Systems Consortium, Inc. ("ISC") @@ -58,6 +59,7 @@ filename + @@ -65,8 +67,21 @@ DESCRIPTION named-checkconf - checks the syntax, but not the semantics, of a named - configuration file. + checks the syntax, but not the semantics, of a + named configuration file. The file is parsed + and checked for syntax errors, along with all files included by it. + If no file is specified, /etc/named.conf is read + by default. + + + Note: files that named reads in separate + parser contexts, such as rndc.key and + bind.keys, are not automatically read + by named-checkconf. Configuration + errors in these files may cause named to + fail to run, even if named-checkconf was + successful. named-checkconf can be run + on these files explicitly, however. @@ -87,8 +102,7 @@ -t directory - Chroot to directory so that - include + Chroot to directory so that include directives in the configuration file are processed as if run by a similarly chrooted named. @@ -106,6 +120,16 @@ + -p + + + Print out the named.conf and included files + in canonical form if no errors were detected. + + + + + -z diff --git a/bin/check/named-checkconf.html b/bin/check/named-checkconf.html index 458b486..f5e4cd3 100644 --- a/bin/check/named-checkconf.html +++ b/bin/check/named-checkconf.html @@ -1,5 +1,5 @@ - + @@ -29,17 +29,30 @@

Synopsis

-

named-checkconf [-h] [-v] [-j] [-t directory] {filename} [-z]

+

named-checkconf [-h] [-v] [-j] [-t directory] {filename} [-p] [-z]

-

DESCRIPTION

+

DESCRIPTION

named-checkconf - checks the syntax, but not the semantics, of a named - configuration file. + checks the syntax, but not the semantics, of a + named configuration file. The file is parsed + and checked for syntax errors, along with all files included by it. + If no file is specified, /etc/named.conf is read + by default. +

+

+ Note: files that named reads in separate + parser contexts, such as rndc.key and + bind.keys, are not automatically read + by named-checkconf. Configuration + errors in these files may cause named to + fail to run, even if named-checkconf was + successful. named-checkconf can be run + on these files explicitly, however.

-

OPTIONS

+

OPTIONS

-h

@@ -47,8 +60,7 @@

-t directory

- Chroot to directory so that - include + Chroot to directory so that include directives in the configuration file are processed as if run by a similarly chrooted named.

@@ -57,6 +69,11 @@ Print the version of the named-checkconf program and exit.

+
-p
+

+ Print out the named.conf and included files + in canonical form if no errors were detected. +

-z

Perform a test load of all master zones found in @@ -74,21 +91,21 @@

-

RETURN VALUES

+

RETURN VALUES

named-checkconf returns an exit status of 1 if errors were detected and 0 otherwise.

-

SEE ALSO

+

SEE ALSO

named(8), named-checkzone(8), BIND 9 Administrator Reference Manual.

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

diff --git a/bin/check/named-checkzone.8 b/bin/check/named-checkzone.8 index e5f0790..1bb7846 100644 --- a/bin/check/named-checkzone.8 +++ b/bin/check/named-checkzone.8 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") .\" Copyright (C) 2000-2002 Internet Software Consortium. .\" .\" Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: named-checkzone.8,v 1.42.334.3 2009-11-11 01:56:22 tbox Exp $ +.\" $Id: named-checkzone.8,v 1.47 2010-01-17 01:14:02 tbox Exp $ .\" .hy 0 .ad l @@ -33,9 +33,9 @@ named\-checkzone, named\-compilezone \- zone file validity checking or converting tool .SH "SYNOPSIS" .HP 16 -\fBnamed\-checkzone\fR [\fB\-d\fR] [\fB\-h\fR] [\fB\-j\fR] [\fB\-q\fR] [\fB\-v\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-f\ \fR\fB\fIformat\fR\fR] [\fB\-F\ \fR\fB\fIformat\fR\fR] [\fB\-i\ \fR\fB\fImode\fR\fR] [\fB\-k\ \fR\fB\fImode\fR\fR] [\fB\-m\ \fR\fB\fImode\fR\fR] [\fB\-M\ \fR\fB\fImode\fR\fR] [\fB\-n\ \fR\fB\fImode\fR\fR] [\fB\-s\ \fR\fB\fIstyle\fR\fR] [\fB\-S\ \fR\fB\fImode\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-w\ \fR\fB\fIdirectory\fR\fR] [\fB\-D\fR] [\fB\-W\ \fR\fB\fImode\fR\fR] {zonename} {filename} +\fBnamed\-checkzone\fR [\fB\-d\fR] [\fB\-h\fR] [\fB\-j\fR] [\fB\-q\fR] [\fB\-v\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-f\ \fR\fB\fIformat\fR\fR] [\fB\-F\ \fR\fB\fIformat\fR\fR] [\fB\-i\ \fR\fB\fImode\fR\fR] [\fB\-k\ \fR\fB\fImode\fR\fR] [\fB\-m\ \fR\fB\fImode\fR\fR] [\fB\-M\ \fR\fB\fImode\fR\fR] [\fB\-n\ \fR\fB\fImode\fR\fR] [\fB\-o\ \fR\fB\fIfilename\fR\fR] [\fB\-r\ \fR\fB\fImode\fR\fR] [\fB\-s\ \fR\fB\fIstyle\fR\fR] [\fB\-S\ \fR\fB\fImode\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-w\ \fR\fB\fIdirectory\fR\fR] [\fB\-D\fR] [\fB\-W\ \fR\fB\fImode\fR\fR] {zonename} {filename} .HP 18 -\fBnamed\-compilezone\fR [\fB\-d\fR] [\fB\-j\fR] [\fB\-q\fR] [\fB\-v\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-C\ \fR\fB\fImode\fR\fR] [\fB\-f\ \fR\fB\fIformat\fR\fR] [\fB\-F\ \fR\fB\fIformat\fR\fR] [\fB\-i\ \fR\fB\fImode\fR\fR] [\fB\-k\ \fR\fB\fImode\fR\fR] [\fB\-m\ \fR\fB\fImode\fR\fR] [\fB\-n\ \fR\fB\fImode\fR\fR] [\fB\-o\ \fR\fB\fIfilename\fR\fR] [\fB\-s\ \fR\fB\fIstyle\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-w\ \fR\fB\fIdirectory\fR\fR] [\fB\-D\fR] [\fB\-W\ \fR\fB\fImode\fR\fR] {\fB\-o\ \fR\fB\fIfilename\fR\fR} {zonename} {filename} +\fBnamed\-compilezone\fR [\fB\-d\fR] [\fB\-j\fR] [\fB\-q\fR] [\fB\-v\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-C\ \fR\fB\fImode\fR\fR] [\fB\-f\ \fR\fB\fIformat\fR\fR] [\fB\-F\ \fR\fB\fIformat\fR\fR] [\fB\-i\ \fR\fB\fImode\fR\fR] [\fB\-k\ \fR\fB\fImode\fR\fR] [\fB\-m\ \fR\fB\fImode\fR\fR] [\fB\-n\ \fR\fB\fImode\fR\fR] [\fB\-r\ \fR\fB\fImode\fR\fR] [\fB\-s\ \fR\fB\fIstyle\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-w\ \fR\fB\fIdirectory\fR\fR] [\fB\-D\fR] [\fB\-W\ \fR\fB\fImode\fR\fR] {\fB\-o\ \fR\fB\fIfilename\fR\fR} {zonename} {filename} .SH "DESCRIPTION" .PP \fBnamed\-checkzone\fR @@ -201,6 +201,15 @@ then write to standard out. This is mandatory for \fBnamed\-compilezone\fR. .RE .PP +\-r \fImode\fR +.RS 4 +Check for records that are treated as different by DNSSEC but are semantically equal in plain DNS. Possible modes are +\fB"fail"\fR, +\fB"warn"\fR +(default) and +\fB"ignore"\fR. +.RE +.PP \-s \fIstyle\fR .RS 4 Specify the style of the dumped zone file. Possible styles are @@ -272,7 +281,7 @@ BIND 9 Administrator Reference Manual. .PP Internet Systems Consortium .SH "COPYRIGHT" -Copyright \(co 2004\-2007, 2009 Internet Systems Consortium, Inc. ("ISC") +Copyright \(co 2004\-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") .br Copyright \(co 2000\-2002 Internet Software Consortium. .br diff --git a/bin/check/named-checkzone.c b/bin/check/named-checkzone.c index 3b86e57..100e809 100644 --- a/bin/check/named-checkzone.c +++ b/bin/check/named-checkzone.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: named-checkzone.c,v 1.51.34.6 2010-09-07 23:46:06 tbox Exp $ */ +/* $Id: named-checkzone.c,v 1.61 2010-09-07 23:46:59 tbox Exp $ */ /*! \file */ @@ -70,6 +70,9 @@ static enum { progmode_check, progmode_compile } progmode; } \ } while (0) +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + static void usage(void) { fprintf(stderr, @@ -77,12 +80,13 @@ usage(void) { "[-f inputformat] [-F outputformat] " "[-t directory] [-w directory] [-k (ignore|warn|fail)] " "[-n (ignore|warn|fail)] [-m (ignore|warn|fail)] " + "[-r (ignore|warn|fail)] " "[-i (full|full-sibling|local|local-sibling|none)] " "[-M (ignore|warn|fail)] [-S (ignore|warn|fail)] " "[-W (ignore|warn)] " "%s zonename filename\n", prog_name, - progmode == progmode_check ? "[-o filename]" : "{-o filename}"); + progmode == progmode_check ? "[-o filename]" : "-o filename"); exit(1); } @@ -140,17 +144,19 @@ main(int argc, char **argv) { if (progmode == progmode_compile) { zone_options |= (DNS_ZONEOPT_CHECKNS | DNS_ZONEOPT_FATALNS | + DNS_ZONEOPT_CHECKDUPRR | DNS_ZONEOPT_CHECKNAMES | DNS_ZONEOPT_CHECKNAMESFAIL | DNS_ZONEOPT_CHECKWILDCARD); - } + } else + zone_options |= DNS_ZONEOPT_CHECKDUPRR; #define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0) isc_commandline_errprint = ISC_FALSE; while ((c = isc_commandline_parse(argc, argv, - "c:df:hi:jk:m:n:qs:t:o:vw:DF:M:S:W:")) + "c:df:hi:jk:m:n:qr:s:t:o:vw:DF:M:S:W:")) != EOF) { switch (c) { case 'c': @@ -262,16 +268,27 @@ main(int argc, char **argv) { } break; + case 'o': + output_filename = isc_commandline_argument; + break; + case 'q': quiet++; break; - case 't': - result = isc_dir_chroot(isc_commandline_argument); - if (result != ISC_R_SUCCESS) { - fprintf(stderr, "isc_dir_chroot: %s: %s\n", - isc_commandline_argument, - isc_result_totext(result)); + case 'r': + if (ARGCMP("warn")) { + zone_options |= DNS_ZONEOPT_CHECKDUPRR; + zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; + } else if (ARGCMP("fail")) { + zone_options |= DNS_ZONEOPT_CHECKDUPRR | + DNS_ZONEOPT_CHECKDUPRRFAIL; + } else if (ARGCMP("ignore")) { + zone_options &= ~(DNS_ZONEOPT_CHECKDUPRR | + DNS_ZONEOPT_CHECKDUPRRFAIL); + } else { + fprintf(stderr, "invalid argument to -r: %s\n", + isc_commandline_argument); exit(1); } break; @@ -289,8 +306,14 @@ main(int argc, char **argv) { } break; - case 'o': - output_filename = isc_commandline_argument; + case 't': + result = isc_dir_chroot(isc_commandline_argument); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "isc_dir_chroot: %s: %s\n", + isc_commandline_argument, + isc_result_totext(result)); + exit(1); + } break; case 'v': diff --git a/bin/check/named-checkzone.docbook b/bin/check/named-checkzone.docbook index 0e04c03..415ee1c 100644 --- a/bin/check/named-checkzone.docbook +++ b/bin/check/named-checkzone.docbook @@ -2,7 +2,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" []> - + June 13, 2000 @@ -37,6 +37,7 @@ 2006 2007 2009 + 2010 Internet Systems Consortium, Inc. ("ISC")
@@ -69,6 +70,8 @@ + + @@ -92,7 +95,7 @@ - + @@ -320,6 +323,19 @@ + -r mode + + + Check for records that are treated as different by DNSSEC but + are semantically equal in plain DNS. + Possible modes are "fail", + "warn" (default) and + "ignore". + + + + + -s style diff --git a/bin/check/named-checkzone.html b/bin/check/named-checkzone.html index 24f5c05..e0532af 100644 --- a/bin/check/named-checkzone.html +++ b/bin/check/named-checkzone.html @@ -1,5 +1,5 @@ - + @@ -29,11 +29,11 @@

Synopsis

-

named-checkzone [-d] [-h] [-j] [-q] [-v] [-c class] [-f format] [-F format] [-i mode] [-k mode] [-m mode] [-M mode] [-n mode] [-s style] [-S mode] [-t directory] [-w directory] [-D] [-W mode] {zonename} {filename}

-

named-compilezone [-d] [-j] [-q] [-v] [-c class] [-C mode] [-f format] [-F format] [-i mode] [-k mode] [-m mode] [-n mode] [-o filename] [-s style] [-t directory] [-w directory] [-D] [-W mode] {-o filename} {zonename} {filename}

+

named-checkzone [-d] [-h] [-j] [-q] [-v] [-c class] [-f format] [-F format] [-i mode] [-k mode] [-m mode] [-M mode] [-n mode] [-o filename] [-r mode] [-s style] [-S mode] [-t directory] [-w directory] [-D] [-W mode] {zonename} {filename}

+

named-compilezone [-d] [-j] [-q] [-v] [-c class] [-C mode] [-f format] [-F format] [-i mode] [-k mode] [-m mode] [-n mode] [-r mode] [-s style] [-t directory] [-w directory] [-D] [-W mode] {-o filename} {zonename} {filename}

-

DESCRIPTION

+

DESCRIPTION

named-checkzone checks the syntax and integrity of a zone file. It performs the same checks as named does when loading a @@ -53,7 +53,7 @@

-

OPTIONS

+

OPTIONS

-d

@@ -177,6 +177,14 @@ write to standard out. This is mandatory for named-compilezone.

+
-r mode
+

+ Check for records that are treated as different by DNSSEC but + are semantically equal in plain DNS. + Possible modes are "fail", + "warn" (default) and + "ignore". +

-s style

Specify the style of the dumped zone file. @@ -239,14 +247,14 @@

-

RETURN VALUES

+

RETURN VALUES

named-checkzone returns an exit status of 1 if errors were detected and 0 otherwise.

-

SEE ALSO

+

SEE ALSO

named(8), named-checkconf(8), RFC 1035, @@ -254,7 +262,7 @@

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

diff --git a/bin/confgen/Makefile.in b/bin/confgen/Makefile.in new file mode 100644 index 0000000..da35879 --- /dev/null +++ b/bin/confgen/Makefile.in @@ -0,0 +1,101 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.8 2009-12-05 23:31:40 each Exp $ + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I${srcdir}/include ${ISC_INCLUDES} ${ISCCC_INCLUDES} \ + ${ISCCFG_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} + +CDEFINES = +CWARNINGS = + +ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ +ISCCCLIBS = ../../lib/isccc/libisccc.@A@ +ISCLIBS = ../../lib/isc/libisc.@A@ +ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ +DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ +BIND9LIBS = ../../lib/bind9/libbind9.@A@ + +ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ +ISCCCDEPLIBS = ../../lib/isccc/libisccc.@A@ +ISCDEPLIBS = ../../lib/isc/libisc.@A@ +DNSDEPLIBS = ../../lib/dns/libdns.@A@ +BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@ + +RNDCLIBS = ${ISCCFGLIBS} ${ISCCCLIBS} ${BIND9LIBS} ${DNSLIBS} ${ISCLIBS} @LIBS@ +RNDCDEPLIBS = ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${BIND9DEPLIBS} ${DNSDEPLIBS} ${ISCDEPLIBS} + +LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@ + +NOSYMLIBS = ${DNSLIBS} ${ISCNOSYMLIBS} @LIBS@ + +CONFDEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS} + +SRCS= rndc-confgen.c ddns-confgen.c + +SUBDIRS = unix + +TARGETS = rndc-confgen@EXEEXT@ ddns-confgen@EXEEXT@ + +MANPAGES = rndc-confgen.8 ddns-confgen.8 + +HTMLPAGES = rndc-confgen.html ddns-confgen.html + +MANOBJS = ${MANPAGES} ${HTMLPAGES} + +UOBJS = unix/os.@O@ + +@BIND9_MAKE_RULES@ + +rndc-confgen.@O@: rndc-confgen.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ + -DRNDC_KEYFILE=\"${sysconfdir}/rndc.key\" \ + -c ${srcdir}/rndc-confgen.c + +ddns-confgen.@O@: ddns-confgen.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c ${srcdir}/ddns-confgen.c + +rndc-confgen@EXEEXT@: rndc-confgen.@O@ util.@O@ keygen.@O@ ${UOBJS} ${CONFDEPLIBS} + export BASEOBJS="rndc-confgen.@O@ util.@O@ keygen.@O@ ${UOBJS}"; \ + ${FINALBUILDCMD} + +ddns-confgen@EXEEXT@: ddns-confgen.@O@ util.@O@ keygen.@O@ ${UOBJS} ${CONFDEPLIBS} + export BASEOBJS="ddns-confgen.@O@ util.@O@ keygen.@O@ ${UOBJS}"; \ + ${FINALBUILDCMD} + +doc man:: ${MANOBJS} + +docclean manclean maintainer-clean:: + rm -f ${MANOBJS} + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 + +install:: rndc-confgen@EXEEXT@ ddns-confgen@EXEEXT@ installdirs + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} rndc-confgen@EXEEXT@ ${DESTDIR}${sbindir} + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} ddns-confgen@EXEEXT@ ${DESTDIR}${sbindir} + ${INSTALL_DATA} ${srcdir}/rndc-confgen.8 ${DESTDIR}${mandir}/man8 + ${INSTALL_DATA} ${srcdir}/ddns-confgen.8 ${DESTDIR}${mandir}/man8 + +clean distclean maintainer-clean:: + rm -f ${TARGETS} diff --git a/bin/confgen/ddns-confgen.8 b/bin/confgen/ddns-confgen.8 new file mode 100644 index 0000000..d69af39 --- /dev/null +++ b/bin/confgen/ddns-confgen.8 @@ -0,0 +1,143 @@ +.\" Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +.\" +.\" 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 ISC DISCLAIMS ALL WARRANTIES WITH +.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +.\" AND FITNESS. IN NO EVENT SHALL ISC 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. +.\" +.\" $Id: ddns-confgen.8,v 1.10 2009-09-19 01:14:52 tbox Exp $ +.\" +.hy 0 +.ad l +.\" Title: ddns\-confgen +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.71.1 +.\" Date: Jan 29, 2009 +.\" Manual: BIND9 +.\" Source: BIND9 +.\" +.TH "DDNS\-CONFGEN" "8" "Jan 29, 2009" "BIND9" "BIND9" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +ddns\-confgen \- ddns key generation tool +.SH "SYNOPSIS" +.HP 13 +\fBddns\-confgen\fR [\fB\-a\ \fR\fB\fIalgorithm\fR\fR] [\fB\-h\fR] [\fB\-k\ \fR\fB\fIkeyname\fR\fR] [\fB\-r\ \fR\fB\fIrandomfile\fR\fR] [\-s\ \fIname\fR | \-z\ \fIzone\fR] [\fB\-q\fR] [name] +.SH "DESCRIPTION" +.PP +\fBddns\-confgen\fR +generates a key for use by +\fBnsupdate\fR +and +\fBnamed\fR. It simplifies configuration of dynamic zones by generating a key and providing the +\fBnsupdate\fR +and +\fBnamed.conf\fR +syntax that will be needed to use it, including an example +\fBupdate\-policy\fR +statement. +.PP +If a domain name is specified on the command line, it will be used in the name of the generated key and in the sample +\fBnamed.conf\fR +syntax. For example, +\fBddns\-confgen example.com\fR +would generate a key called "ddns\-key.example.com", and sample +\fBnamed.conf\fR +command that could be used in the zone definition for "example.com". +.PP +Note that +\fBnamed\fR +itself can configure a local DDNS key for use with +\fBnsupdate \-l\fR. +\fBddns\-confgen\fR +is only needed when a more elaborate configuration is required: for instance, if +\fBnsupdate\fR +is to be used from a remote system. +.SH "OPTIONS" +.PP +\-a \fIalgorithm\fR +.RS 4 +Specifies the algorithm to use for the TSIG key. Available choices are: hmac\-md5, hmac\-sha1, hmac\-sha224, hmac\-sha256, hmac\-sha384 and hmac\-sha512. The default is hmac\-sha256. +.RE +.PP +\-h +.RS 4 +Prints a short summary of the options and arguments to +\fBddns\-confgen\fR. +.RE +.PP +\-k \fIkeyname\fR +.RS 4 +Specifies the key name of the DDNS authentication key. The default is +\fBddns\-key\fR +when neither the +\fB\-s\fR +nor +\fB\-z\fR +option is specified; otherwise, the default is +\fBddns\-key\fR +as a separate label followed by the argument of the option, e.g., +\fBddns\-key.example.com.\fR +The key name must have the format of a valid domain name, consisting of letters, digits, hyphens and periods. +.RE +.PP +\-q +.RS 4 +Quiet mode: Print only the key, with no explanatory text or usage examples. +.RE +.PP +\-r \fIrandomfile\fR +.RS 4 +Specifies a source of random data for generating the authorization. If the operating system does not provide a +\fI/dev/random\fR +or equivalent device, the default source of randomness is keyboard input. +\fIrandomdev\fR +specifies the name of a character device or file containing random data to be used instead of the default. The special value +\fIkeyboard\fR +indicates that keyboard input should be used. +.RE +.PP +\-s \fIname\fR +.RS 4 +Single host mode: The example +\fBnamed.conf\fR +text shows how to set an update policy for the specified +\fIname\fR +using the "name" nametype. The default key name is ddns\-key.\fIname\fR. Note that the "self" nametype cannot be used, since the name to be updated may differ from the key name. This option cannot be used with the +\fB\-z\fR +option. +.RE +.PP +\-z \fIzone\fR +.RS 4 +zone mode: The example +\fBnamed.conf\fR +text shows how to set an update policy for the specified +\fIzone\fR +using the "zonesub" nametype, allowing updates to all subdomain names within that +\fIzone\fR. This option cannot be used with the +\fB\-s\fR +option. +.RE +.SH "SEE ALSO" +.PP +\fBnsupdate\fR(1), +\fBnamed.conf\fR(5), +\fBnamed\fR(8), +BIND 9 Administrator Reference Manual. +.SH "AUTHOR" +.PP +Internet Systems Consortium +.SH "COPYRIGHT" +Copyright \(co 2009 Internet Systems Consortium, Inc. ("ISC") +.br diff --git a/bin/confgen/ddns-confgen.c b/bin/confgen/ddns-confgen.c new file mode 100644 index 0000000..814a565 --- /dev/null +++ b/bin/confgen/ddns-confgen.c @@ -0,0 +1,257 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: ddns-confgen.c,v 1.9 2009-09-29 15:06:05 fdupont Exp $ */ + +/*! \file */ + +/** + * ddns-confgen generates configuration files for dynamic DNS. It can + * be used as a convenient alternative to writing the ddns.key file + * and the corresponding key and update-policy statements in named.conf. + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "util.h" +#include "keygen.h" + +#define DEFAULT_KEYNAME "ddns-key" + +static char program[256]; +const char *progname; + +isc_boolean_t verbose = ISC_FALSE; + +ISC_PLATFORM_NORETURN_PRE static void +usage(int status) ISC_PLATFORM_NORETURN_POST; + +static void +usage(int status) { + + fprintf(stderr, "\ +Usage:\n\ + %s [-a alg] [-k keyname] [-r randomfile] [-q] [-s name | -z zone]\n\ + -a alg: algorithm (default hmac-sha256)\n\ + -k keyname: name of the key as it will be used in named.conf\n\ + -r randomfile: source of random data (use \"keyboard\" for key timing)\n\ + -s name: domain name to be updated using the created key\n\ + -z zone: name of the zone as it will be used in named.conf\n\ + -q: quiet mode: print the key, with no explanatory text\n", + progname); + + exit (status); +} + +int +main(int argc, char **argv) { + isc_boolean_t show_final_mem = ISC_FALSE; + isc_boolean_t quiet = ISC_FALSE; + isc_buffer_t key_txtbuffer; + char key_txtsecret[256]; + isc_mem_t *mctx = NULL; + isc_result_t result = ISC_R_SUCCESS; + const char *randomfile = NULL; + const char *keyname = NULL; + const char *zone = NULL; + const char *self_domain = NULL; + char *keybuf = NULL; + dns_secalg_t alg = DST_ALG_HMACSHA256; + const char *algname = alg_totext(alg); + int keysize = 256; + int len = 0; + int ch; + + result = isc_file_progname(*argv, program, sizeof(program)); + if (result != ISC_R_SUCCESS) + memcpy(program, "ddns-confgen", 13); + progname = program; + + isc_commandline_errprint = ISC_FALSE; + + while ((ch = isc_commandline_parse(argc, argv, + "a:hk:Mmr:qs:Vy:z:")) != -1) { + switch (ch) { + case 'a': + algname = isc_commandline_argument; + alg = alg_fromtext(algname); + if (alg == DST_ALG_UNKNOWN) + fatal("Unsupported algorithm '%s'", algname); + keysize = alg_bits(alg); + break; + case 'h': + usage(0); + case 'k': + case 'y': + keyname = isc_commandline_argument; + break; + case 'M': + isc_mem_debugging = ISC_MEM_DEBUGTRACE; + break; + case 'm': + show_final_mem = ISC_TRUE; + break; + case 'q': + quiet = ISC_TRUE; + break; + case 'r': + randomfile = isc_commandline_argument; + break; + case 's': + self_domain = isc_commandline_argument; + break; + case 'V': + verbose = ISC_TRUE; + break; + case 'z': + zone = isc_commandline_argument; + break; + case '?': + if (isc_commandline_option != '?') { + fprintf(stderr, "%s: invalid argument -%c\n", + program, isc_commandline_option); + usage(1); + } else + usage(0); + break; + default: + fprintf(stderr, "%s: unhandled option -%c\n", + program, isc_commandline_option); + exit(1); + } + } + + argc -= isc_commandline_index; + argv += isc_commandline_index; + + if (self_domain != NULL && zone != NULL) + usage(1); /* -s and -z cannot coexist */ + + if (argc > 0) + usage(1); + + DO("create memory context", isc_mem_create(0, 0, &mctx)); + + if (keyname == NULL) { + const char *suffix = NULL; + + keyname = DEFAULT_KEYNAME; + if (self_domain != NULL) + suffix = self_domain; + else if (zone != NULL) + suffix = zone; + if (suffix != NULL) { + len = strlen(keyname) + strlen(suffix) + 2; + keybuf = isc_mem_get(mctx, len); + if (keybuf == NULL) + fatal("failed to allocate memory for keyname"); + snprintf(keybuf, len, "%s.%s", keyname, suffix); + keyname = (const char *) keybuf; + } + } + + isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret)); + + generate_key(mctx, randomfile, alg, keysize, &key_txtbuffer); + + + if (!quiet) + printf("\ +# To activate this key, place the following in named.conf, and\n\ +# in a separate keyfile on the system or systems from which nsupdate\n\ +# will be run:\n"); + + printf("\ +key \"%s\" {\n\ + algorithm %s;\n\ + secret \"%.*s\";\n\ +};\n", + keyname, algname, + (int)isc_buffer_usedlength(&key_txtbuffer), + (char *)isc_buffer_base(&key_txtbuffer)); + + if (!quiet) { + if (self_domain != NULL) { + printf("\n\ +# Then, in the \"zone\" statement for the zone containing the\n\ +# name \"%s\", place an \"update-policy\" statement\n\ +# like this one, adjusted as needed for your preferred permissions:\n\ +update-policy {\n\ + grant %s name %s ANY;\n\ +};\n", + self_domain, keyname, self_domain); + } else if (zone != NULL) { + printf("\n\ +# Then, in the \"zone\" definition statement for \"%s\",\n\ +# place an \"update-policy\" statement like this one, adjusted as \n\ +# needed for your preferred permissions:\n\ +update-policy {\n\ + grant %s zonesub ANY;\n\ +};\n", + zone, keyname); + } else { + printf("\n\ +# Then, in the \"zone\" statement for each zone you wish to dynamically\n\ +# update, place an \"update-policy\" statement granting update permission\n\ +# to this key. For example, the following statement grants this key\n\ +# permission to update any name within the zone:\n\ +update-policy {\n\ + grant %s zonesub ANY;\n\ +};\n", + keyname); + } + + printf("\n\ +# After the keyfile has been placed, the following command will\n\ +# execute nsupdate using this key:\n\ +nsupdate -k \n"); + + } + + if (keybuf != NULL) + isc_mem_put(mctx, keybuf, len); + + if (show_final_mem) + isc_mem_stats(mctx, stderr); + + isc_mem_destroy(&mctx); + + return (0); +} diff --git a/bin/confgen/ddns-confgen.docbook b/bin/confgen/ddns-confgen.docbook new file mode 100644 index 0000000..2b3e1c0 --- /dev/null +++ b/bin/confgen/ddns-confgen.docbook @@ -0,0 +1,218 @@ +]> + + + + + + Jan 29, 2009 + + + + ddns-confgen + 8 + BIND9 + + + + ddns-confgen + ddns key generation tool + + + + + 2009 + Internet Systems Consortium, Inc. ("ISC") + + + + + + ddns-confgen + + + + + + -s name + -z zone + + + name + + + + + DESCRIPTION + ddns-confgen + generates a key for use by nsupdate + and named. It simplifies configuration + of dynamic zones by generating a key and providing the + nsupdate and named.conf + syntax that will be needed to use it, including an example + update-policy statement. + + + + If a domain name is specified on the command line, it will + be used in the name of the generated key and in the sample + named.conf syntax. For example, + ddns-confgen example.com would + generate a key called "ddns-key.example.com", and sample + named.conf command that could be used + in the zone definition for "example.com". + + + + Note that named itself can configure a + local DDNS key for use with nsupdate -l. + ddns-confgen is only needed when a + more elaborate configuration is required: for instance, if + nsupdate is to be used from a remote system. + + + + + OPTIONS + + + + -a algorithm + + + Specifies the algorithm to use for the TSIG key. Available + choices are: hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, + hmac-sha384 and hmac-sha512. The default is hmac-sha256. + + + + + + -h + + + Prints a short summary of the options and arguments to + ddns-confgen. + + + + + + -k keyname + + + Specifies the key name of the DDNS authentication key. + The default is ddns-key when neither + the nor option is + specified; otherwise, the default + is ddns-key as a separate label + followed by the argument of the option, e.g., + ddns-key.example.com. + The key name must have the format of a valid domain name, + consisting of letters, digits, hyphens and periods. + + + + + + -q + + + Quiet mode: Print only the key, with no explanatory text or + usage examples. + + + + + + -r randomfile + + + Specifies a source of random data for generating the + authorization. If the operating system does not provide a + /dev/random or equivalent device, the + default source of randomness is keyboard input. + randomdev specifies the name of a + character device or file containing random data to be used + instead of the default. The special value + keyboard indicates that keyboard input + should be used. + + + + + + -s name + + + Single host mode: The example named.conf text + shows how to set an update policy for the specified + name + using the "name" nametype. + The default key name is + ddns-key.name. + Note that the "self" nametype cannot be used, since + the name to be updated may differ from the key name. + This option cannot be used with the option. + + + + + + -z zone + + + zone mode: The example named.conf text + shows how to set an update policy for the specified + zone + using the "zonesub" nametype, allowing updates to all subdomain + names within + that zone. + This option cannot be used with the option. + + + + + + + + SEE ALSO + + nsupdate1 + , + + named.conf5 + , + + named8 + , + BIND 9 Administrator Reference Manual. + + + + + AUTHOR + Internet Systems Consortium + + + + diff --git a/bin/confgen/ddns-confgen.html b/bin/confgen/ddns-confgen.html new file mode 100644 index 0000000..17c3f26 --- /dev/null +++ b/bin/confgen/ddns-confgen.html @@ -0,0 +1,141 @@ + + + + + +ddns-confgen + + +
+
+
+

Name

+

ddns-confgen — ddns key generation tool

+
+
+

Synopsis

+

ddns-confgen [-a algorithm] [-h] [-k keyname] [-r randomfile] [ -s name | -z zone ] [-q] [name]

+
+
+

DESCRIPTION

+

ddns-confgen + generates a key for use by nsupdate + and named. It simplifies configuration + of dynamic zones by generating a key and providing the + nsupdate and named.conf + syntax that will be needed to use it, including an example + update-policy statement. +

+

+ If a domain name is specified on the command line, it will + be used in the name of the generated key and in the sample + named.conf syntax. For example, + ddns-confgen example.com would + generate a key called "ddns-key.example.com", and sample + named.conf command that could be used + in the zone definition for "example.com". +

+

+ Note that named itself can configure a + local DDNS key for use with nsupdate -l. + ddns-confgen is only needed when a + more elaborate configuration is required: for instance, if + nsupdate is to be used from a remote system. +

+
+
+

OPTIONS

+
+
-a algorithm
+

+ Specifies the algorithm to use for the TSIG key. Available + choices are: hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, + hmac-sha384 and hmac-sha512. The default is hmac-sha256. +

+
-h
+

+ Prints a short summary of the options and arguments to + ddns-confgen. +

+
-k keyname
+

+ Specifies the key name of the DDNS authentication key. + The default is ddns-key when neither + the -s nor -z option is + specified; otherwise, the default + is ddns-key as a separate label + followed by the argument of the option, e.g., + ddns-key.example.com. + The key name must have the format of a valid domain name, + consisting of letters, digits, hyphens and periods. +

+
-q
+

+ Quiet mode: Print only the key, with no explanatory text or + usage examples. +

+
-r randomfile
+

+ Specifies a source of random data for generating the + authorization. If the operating system does not provide a + /dev/random or equivalent device, the + default source of randomness is keyboard input. + randomdev specifies the name of a + character device or file containing random data to be used + instead of the default. The special value + keyboard indicates that keyboard input + should be used. +

+
-s name
+

+ Single host mode: The example named.conf text + shows how to set an update policy for the specified + name + using the "name" nametype. + The default key name is + ddns-key.name. + Note that the "self" nametype cannot be used, since + the name to be updated may differ from the key name. + This option cannot be used with the -z option. +

+
-z zone
+

+ zone mode: The example named.conf text + shows how to set an update policy for the specified + zone + using the "zonesub" nametype, allowing updates to all subdomain + names within + that zone. + This option cannot be used with the -s option. +

+
+
+
+

SEE ALSO

+

nsupdate(1), + named.conf(5), + named(8), + BIND 9 Administrator Reference Manual. +

+
+
+

AUTHOR

+

Internet Systems Consortium +

+
+
+ diff --git a/bin/confgen/include/confgen/os.h b/bin/confgen/include/confgen/os.h new file mode 100644 index 0000000..bf80f00 --- /dev/null +++ b/bin/confgen/include/confgen/os.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: os.h,v 1.3 2009-06-11 23:47:55 tbox Exp $ */ + +/*! \file */ + +#ifndef RNDC_OS_H +#define RNDC_OS_H 1 + +#include +#include + +ISC_LANG_BEGINDECLS + +int set_user(FILE *fd, const char *user); +/*%< + * Set the owner of the file referenced by 'fd' to 'user'. + * Returns: + * 0 success + * -1 insufficient permissions, or 'user' does not exist. + */ + +ISC_LANG_ENDDECLS + +#endif diff --git a/bin/confgen/keygen.c b/bin/confgen/keygen.c new file mode 100644 index 0000000..c259e7e --- /dev/null +++ b/bin/confgen/keygen.c @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: keygen.c,v 1.4 2009-11-12 14:02:38 marka Exp $ */ + +/*! \file */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "util.h" +#include "keygen.h" + +/*% + * Convert algorithm type to string. + */ +const char * +alg_totext(dns_secalg_t alg) { + switch (alg) { + case DST_ALG_HMACMD5: + return "hmac-md5"; + case DST_ALG_HMACSHA1: + return "hmac-sha1"; + case DST_ALG_HMACSHA224: + return "hmac-sha224"; + case DST_ALG_HMACSHA256: + return "hmac-sha256"; + case DST_ALG_HMACSHA384: + return "hmac-sha384"; + case DST_ALG_HMACSHA512: + return "hmac-sha512"; + default: + return "(unknown)"; + } +} + +/*% + * Convert string to algorithm type. + */ +dns_secalg_t +alg_fromtext(const char *name) { + if (strcmp(name, "hmac-md5") == 0) + return DST_ALG_HMACMD5; + if (strcmp(name, "hmac-sha1") == 0) + return DST_ALG_HMACSHA1; + if (strcmp(name, "hmac-sha224") == 0) + return DST_ALG_HMACSHA224; + if (strcmp(name, "hmac-sha256") == 0) + return DST_ALG_HMACSHA256; + if (strcmp(name, "hmac-sha384") == 0) + return DST_ALG_HMACSHA384; + if (strcmp(name, "hmac-sha512") == 0) + return DST_ALG_HMACSHA512; + return DST_ALG_UNKNOWN; +} + +/*% + * Return default keysize for a given algorithm type. + */ +int +alg_bits(dns_secalg_t alg) { + switch (alg) { + case DST_ALG_HMACMD5: + return 128; + case DST_ALG_HMACSHA1: + return 160; + case DST_ALG_HMACSHA224: + return 224; + case DST_ALG_HMACSHA256: + return 256; + case DST_ALG_HMACSHA384: + return 384; + case DST_ALG_HMACSHA512: + return 512; + default: + return 0; + } +} + +/*% + * Generate a key of size 'keysize' using entropy source 'randomfile', + * and place it in 'key_txtbuffer' + */ +void +generate_key(isc_mem_t *mctx, const char *randomfile, dns_secalg_t alg, + int keysize, isc_buffer_t *key_txtbuffer) { + isc_result_t result = ISC_R_SUCCESS; + isc_entropysource_t *entropy_source = NULL; + int open_keyboard = ISC_ENTROPY_KEYBOARDMAYBE; + int entropy_flags = 0; + isc_entropy_t *ectx = NULL; + isc_buffer_t key_rawbuffer; + isc_region_t key_rawregion; + char key_rawsecret[64]; + dst_key_t *key = NULL; + + switch (alg) { + case DST_ALG_HMACMD5: + if (keysize < 1 || keysize > 512) + fatal("keysize %d out of range (must be 1-512)\n", + keysize); + break; + case DST_ALG_HMACSHA256: + if (keysize < 1 || keysize > 256) + fatal("keysize %d out of range (must be 1-256)\n", + keysize); + break; + default: + fatal("unsupported algorithm %d\n", alg); + } + + + DO("create entropy context", isc_entropy_create(mctx, &ectx)); + + if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) { + randomfile = NULL; + open_keyboard = ISC_ENTROPY_KEYBOARDYES; + } + DO("start entropy source", isc_entropy_usebestsource(ectx, + &entropy_source, + randomfile, + open_keyboard)); + + entropy_flags = ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY; + + DO("initialize dst library", dst_lib_init(mctx, ectx, entropy_flags)); + + DO("generate key", dst_key_generate(dns_rootname, alg, + keysize, 0, 0, + DNS_KEYPROTO_ANY, + dns_rdataclass_in, mctx, &key)); + + isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret)); + + DO("dump key to buffer", dst_key_tobuffer(key, &key_rawbuffer)); + + isc_buffer_usedregion(&key_rawbuffer, &key_rawregion); + + DO("bsse64 encode secret", isc_base64_totext(&key_rawregion, -1, "", + key_txtbuffer)); + + /* + * Shut down the entropy source now so the "stop typing" message + * does not muck with the output. + */ + if (entropy_source != NULL) + isc_entropy_destroysource(&entropy_source); + + if (key != NULL) + dst_key_free(&key); + + isc_entropy_detach(&ectx); + dst_lib_destroy(); +} + +/*% + * Write a key file to 'keyfile'. If 'user' is non-NULL, + * make that user the owner of the file. The key will have + * the name 'keyname' and the secret in the buffer 'secret'. + */ +void +write_key_file(const char *keyfile, const char *user, + const char *keyname, isc_buffer_t *secret, + dns_secalg_t alg) { + isc_result_t result; + const char *algname = alg_totext(alg); + FILE *fd = NULL; + + DO("create keyfile", isc_file_safecreate(keyfile, &fd)); + + if (user != NULL) { + if (set_user(fd, user) == -1) + fatal("unable to set file owner\n"); + } + + fprintf(fd, "key \"%s\" {\n\talgorithm %s;\n" + "\tsecret \"%.*s\";\n};\n", + keyname, algname, + (int)isc_buffer_usedlength(secret), + (char *)isc_buffer_base(secret)); + fflush(fd); + if (ferror(fd)) + fatal("write to %s failed\n", keyfile); + if (fclose(fd)) + fatal("fclose(%s) failed\n", keyfile); + fprintf(stderr, "wrote key file \"%s\"\n", keyfile); +} + diff --git a/bin/confgen/keygen.h b/bin/confgen/keygen.h new file mode 100644 index 0000000..cea25dd --- /dev/null +++ b/bin/confgen/keygen.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: keygen.h,v 1.3 2009-06-11 23:47:55 tbox Exp $ */ + +#ifndef RNDC_KEYGEN_H +#define RNDC_KEYGEN_H 1 + +/*! \file */ + +#include + +ISC_LANG_BEGINDECLS + +void generate_key(isc_mem_t *mctx, const char *randomfile, dns_secalg_t alg, + int keysize, isc_buffer_t *key_txtbuffer); + +void write_key_file(const char *keyfile, const char *user, + const char *keyname, isc_buffer_t *secret, + dns_secalg_t alg); + +const char *alg_totext(dns_secalg_t alg); +dns_secalg_t alg_fromtext(const char *name); +int alg_bits(dns_secalg_t alg); + +ISC_LANG_ENDDECLS + +#endif /* RNDC_KEYGEN_H */ diff --git a/bin/confgen/rndc-confgen.8 b/bin/confgen/rndc-confgen.8 new file mode 100644 index 0000000..a1b3ae8 --- /dev/null +++ b/bin/confgen/rndc-confgen.8 @@ -0,0 +1,211 @@ +.\" Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2001, 2003 Internet Software Consortium. +.\" +.\" 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 ISC DISCLAIMS ALL WARRANTIES WITH +.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +.\" AND FITNESS. IN NO EVENT SHALL ISC 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. +.\" +.\" $Id: rndc-confgen.8,v 1.7 2009-07-11 01:12:45 tbox Exp $ +.\" +.hy 0 +.ad l +.\" Title: rndc\-confgen +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.71.1 +.\" Date: Aug 27, 2001 +.\" Manual: BIND9 +.\" Source: BIND9 +.\" +.TH "RNDC\-CONFGEN" "8" "Aug 27, 2001" "BIND9" "BIND9" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +rndc\-confgen \- rndc key generation tool +.SH "SYNOPSIS" +.HP 13 +\fBrndc\-confgen\fR [\fB\-a\fR] [\fB\-b\ \fR\fB\fIkeysize\fR\fR] [\fB\-c\ \fR\fB\fIkeyfile\fR\fR] [\fB\-h\fR] [\fB\-k\ \fR\fB\fIkeyname\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-r\ \fR\fB\fIrandomfile\fR\fR] [\fB\-s\ \fR\fB\fIaddress\fR\fR] [\fB\-t\ \fR\fB\fIchrootdir\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] +.SH "DESCRIPTION" +.PP +\fBrndc\-confgen\fR +generates configuration files for +\fBrndc\fR. It can be used as a convenient alternative to writing the +\fIrndc.conf\fR +file and the corresponding +\fBcontrols\fR +and +\fBkey\fR +statements in +\fInamed.conf\fR +by hand. Alternatively, it can be run with the +\fB\-a\fR +option to set up a +\fIrndc.key\fR +file and avoid the need for a +\fIrndc.conf\fR +file and a +\fBcontrols\fR +statement altogether. +.SH "OPTIONS" +.PP +\-a +.RS 4 +Do automatic +\fBrndc\fR +configuration. This creates a file +\fIrndc.key\fR +in +\fI/etc\fR +(or whatever +\fIsysconfdir\fR +was specified as when +BIND +was built) that is read by both +\fBrndc\fR +and +\fBnamed\fR +on startup. The +\fIrndc.key\fR +file defines a default command channel and authentication key allowing +\fBrndc\fR +to communicate with +\fBnamed\fR +on the local host with no further configuration. +.sp +Running +\fBrndc\-confgen \-a\fR +allows BIND 9 and +\fBrndc\fR +to be used as drop\-in replacements for BIND 8 and +\fBndc\fR, with no changes to the existing BIND 8 +\fInamed.conf\fR +file. +.sp +If a more elaborate configuration than that generated by +\fBrndc\-confgen \-a\fR +is required, for example if rndc is to be used remotely, you should run +\fBrndc\-confgen\fR +without the +\fB\-a\fR +option and set up a +\fIrndc.conf\fR +and +\fInamed.conf\fR +as directed. +.RE +.PP +\-b \fIkeysize\fR +.RS 4 +Specifies the size of the authentication key in bits. Must be between 1 and 512 bits; the default is 128. +.RE +.PP +\-c \fIkeyfile\fR +.RS 4 +Used with the +\fB\-a\fR +option to specify an alternate location for +\fIrndc.key\fR. +.RE +.PP +\-h +.RS 4 +Prints a short summary of the options and arguments to +\fBrndc\-confgen\fR. +.RE +.PP +\-k \fIkeyname\fR +.RS 4 +Specifies the key name of the rndc authentication key. This must be a valid domain name. The default is +\fBrndc\-key\fR. +.RE +.PP +\-p \fIport\fR +.RS 4 +Specifies the command channel port where +\fBnamed\fR +listens for connections from +\fBrndc\fR. The default is 953. +.RE +.PP +\-r \fIrandomfile\fR +.RS 4 +Specifies a source of random data for generating the authorization. If the operating system does not provide a +\fI/dev/random\fR +or equivalent device, the default source of randomness is keyboard input. +\fIrandomdev\fR +specifies the name of a character device or file containing random data to be used instead of the default. The special value +\fIkeyboard\fR +indicates that keyboard input should be used. +.RE +.PP +\-s \fIaddress\fR +.RS 4 +Specifies the IP address where +\fBnamed\fR +listens for command channel connections from +\fBrndc\fR. The default is the loopback address 127.0.0.1. +.RE +.PP +\-t \fIchrootdir\fR +.RS 4 +Used with the +\fB\-a\fR +option to specify a directory where +\fBnamed\fR +will run chrooted. An additional copy of the +\fIrndc.key\fR +will be written relative to this directory so that it will be found by the chrooted +\fBnamed\fR. +.RE +.PP +\-u \fIuser\fR +.RS 4 +Used with the +\fB\-a\fR +option to set the owner of the +\fIrndc.key\fR +file generated. If +\fB\-t\fR +is also specified only the file in the chroot area has its owner changed. +.RE +.SH "EXAMPLES" +.PP +To allow +\fBrndc\fR +to be used with no manual configuration, run +.PP +\fBrndc\-confgen \-a\fR +.PP +To print a sample +\fIrndc.conf\fR +file and corresponding +\fBcontrols\fR +and +\fBkey\fR +statements to be manually inserted into +\fInamed.conf\fR, run +.PP +\fBrndc\-confgen\fR +.SH "SEE ALSO" +.PP +\fBrndc\fR(8), +\fBrndc.conf\fR(5), +\fBnamed\fR(8), +BIND 9 Administrator Reference Manual. +.SH "AUTHOR" +.PP +Internet Systems Consortium +.SH "COPYRIGHT" +Copyright \(co 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") +.br +Copyright \(co 2001, 2003 Internet Software Consortium. +.br diff --git a/bin/confgen/rndc-confgen.c b/bin/confgen/rndc-confgen.c new file mode 100644 index 0000000..766e3b4 --- /dev/null +++ b/bin/confgen/rndc-confgen.c @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2001, 2003 Internet Software Consortium. + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: rndc-confgen.c,v 1.5 2009-09-29 15:06:05 fdupont Exp $ */ + +/*! \file */ + +/** + * rndc-confgen generates configuration files for rndc. It can be used + * as a convenient alternative to writing the rndc.conf file and the + * corresponding controls and key statements in named.conf by hand. + * Alternatively, it can be run with the -a option to set up a + * rndc.key file and avoid the need for a rndc.conf file and a + * controls statement altogether. + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "util.h" +#include "keygen.h" + +#define DEFAULT_KEYLENGTH 128 /*% Bits. */ +#define DEFAULT_KEYNAME "rndc-key" +#define DEFAULT_SERVER "127.0.0.1" +#define DEFAULT_PORT 953 + +static char program[256]; +const char *progname; + +isc_boolean_t verbose = ISC_FALSE; + +const char *keyfile, *keydef; + +ISC_PLATFORM_NORETURN_PRE static void +usage(int status) ISC_PLATFORM_NORETURN_POST; + +static void +usage(int status) { + + fprintf(stderr, "\ +Usage:\n\ + %s [-a] [-b bits] [-c keyfile] [-k keyname] [-p port] [-r randomfile] \ +[-s addr] [-t chrootdir] [-u user]\n\ + -a: generate just the key clause and write it to keyfile (%s)\n\ + -b bits: from 1 through 512, default %d; total length of the secret\n\ + -c keyfile: specify an alternate key file (requires -a)\n\ + -k keyname: the name as it will be used in named.conf and rndc.conf\n\ + -p port: the port named will listen on and rndc will connect to\n\ + -r randomfile: source of random data (use \"keyboard\" for key timing)\n\ + -s addr: the address to which rndc should connect\n\ + -t chrootdir: write a keyfile in chrootdir as well (requires -a)\n\ + -u user: set the keyfile owner to \"user\" (requires -a)\n", + progname, keydef, DEFAULT_KEYLENGTH); + + exit (status); +} + +int +main(int argc, char **argv) { + isc_boolean_t show_final_mem = ISC_FALSE; + isc_buffer_t key_txtbuffer; + char key_txtsecret[256]; + isc_mem_t *mctx = NULL; + isc_result_t result = ISC_R_SUCCESS; + const char *keyname = NULL; + const char *randomfile = NULL; + const char *serveraddr = NULL; + dns_secalg_t alg = DST_ALG_HMACMD5; + const char *algname = alg_totext(alg); + char *p; + int ch; + int port; + int keysize; + struct in_addr addr4_dummy; + struct in6_addr addr6_dummy; + char *chrootdir = NULL; + char *user = NULL; + isc_boolean_t keyonly = ISC_FALSE; + int len; + + keydef = keyfile = RNDC_KEYFILE; + + result = isc_file_progname(*argv, program, sizeof(program)); + if (result != ISC_R_SUCCESS) + memcpy(program, "rndc-confgen", 13); + progname = program; + + keyname = DEFAULT_KEYNAME; + keysize = DEFAULT_KEYLENGTH; + serveraddr = DEFAULT_SERVER; + port = DEFAULT_PORT; + + isc_commandline_errprint = ISC_FALSE; + + while ((ch = isc_commandline_parse(argc, argv, + "ab:c:hk:Mmp:r:s:t:u:Vy")) != -1) { + switch (ch) { + case 'a': + keyonly = ISC_TRUE; + break; + case 'b': + keysize = strtol(isc_commandline_argument, &p, 10); + if (*p != '\0' || keysize < 0) + fatal("-b requires a non-negative number"); + if (keysize < 1 || keysize > 512) + fatal("-b must be in the range 1 through 512"); + break; + case 'c': + keyfile = isc_commandline_argument; + break; + case 'h': + usage(0); + case 'k': + case 'y': /* Compatible with rndc -y. */ + keyname = isc_commandline_argument; + break; + case 'M': + isc_mem_debugging = ISC_MEM_DEBUGTRACE; + break; + + case 'm': + show_final_mem = ISC_TRUE; + break; + case 'p': + port = strtol(isc_commandline_argument, &p, 10); + if (*p != '\0' || port < 0 || port > 65535) + fatal("port '%s' out of range", + isc_commandline_argument); + break; + case 'r': + randomfile = isc_commandline_argument; + break; + case 's': + serveraddr = isc_commandline_argument; + if (inet_pton(AF_INET, serveraddr, &addr4_dummy) != 1 && + inet_pton(AF_INET6, serveraddr, &addr6_dummy) != 1) + fatal("-s should be an IPv4 or IPv6 address"); + break; + case 't': + chrootdir = isc_commandline_argument; + break; + case 'u': + user = isc_commandline_argument; + break; + case 'V': + verbose = ISC_TRUE; + break; + case '?': + if (isc_commandline_option != '?') { + fprintf(stderr, "%s: invalid argument -%c\n", + program, isc_commandline_option); + usage(1); + } else + usage(0); + break; + default: + fprintf(stderr, "%s: unhandled option -%c\n", + program, isc_commandline_option); + exit(1); + } + } + + argc -= isc_commandline_index; + argv += isc_commandline_index; + + if (argc > 0) + usage(1); + + DO("create memory context", isc_mem_create(0, 0, &mctx)); + isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret)); + + generate_key(mctx, randomfile, alg, keysize, &key_txtbuffer); + + if (keyonly) { + write_key_file(keyfile, chrootdir == NULL ? user : NULL, + keyname, &key_txtbuffer, alg); + + if (chrootdir != NULL) { + char *buf; + len = strlen(chrootdir) + strlen(keyfile) + 2; + buf = isc_mem_get(mctx, len); + if (buf == NULL) + fatal("isc_mem_get(%d) failed\n", len); + snprintf(buf, len, "%s%s%s", chrootdir, + (*keyfile != '/') ? "/" : "", keyfile); + + write_key_file(buf, user, keyname, &key_txtbuffer, alg); + isc_mem_put(mctx, buf, len); + } + } else { + printf("\ +# Start of rndc.conf\n\ +key \"%s\" {\n\ + algorithm %s;\n\ + secret \"%.*s\";\n\ +};\n\ +\n\ +options {\n\ + default-key \"%s\";\n\ + default-server %s;\n\ + default-port %d;\n\ +};\n\ +# End of rndc.conf\n\ +\n\ +# Use with the following in named.conf, adjusting the allow list as needed:\n\ +# key \"%s\" {\n\ +# algorithm %s;\n\ +# secret \"%.*s\";\n\ +# };\n\ +# \n\ +# controls {\n\ +# inet %s port %d\n\ +# allow { %s; } keys { \"%s\"; };\n\ +# };\n\ +# End of named.conf\n", + keyname, algname, + (int)isc_buffer_usedlength(&key_txtbuffer), + (char *)isc_buffer_base(&key_txtbuffer), + keyname, serveraddr, port, + keyname, algname, + (int)isc_buffer_usedlength(&key_txtbuffer), + (char *)isc_buffer_base(&key_txtbuffer), + serveraddr, port, serveraddr, keyname); + } + + if (show_final_mem) + isc_mem_stats(mctx, stderr); + + isc_mem_destroy(&mctx); + + return (0); +} diff --git a/bin/confgen/rndc-confgen.docbook b/bin/confgen/rndc-confgen.docbook new file mode 100644 index 0000000..d43fcfb --- /dev/null +++ b/bin/confgen/rndc-confgen.docbook @@ -0,0 +1,287 @@ +]> + + + + + + Aug 27, 2001 + + + + rndc-confgen + 8 + BIND9 + + + + rndc-confgen + rndc key generation tool + + + + + 2004 + 2005 + 2007 + 2009 + Internet Systems Consortium, Inc. ("ISC") + + + 2001 + 2003 + Internet Software Consortium. + + + + + + rndc-confgen + + + + + + + + + + + + + + + DESCRIPTION + rndc-confgen + generates configuration files + for rndc. It can be used as a + convenient alternative to writing the + rndc.conf file + and the corresponding controls + and key + statements in named.conf by hand. + Alternatively, it can be run with the -a + option to set up a rndc.key file and + avoid the need for a rndc.conf file + and a controls statement altogether. + + + + + + OPTIONS + + + + -a + + + Do automatic rndc configuration. + This creates a file rndc.key + in /etc (or whatever + sysconfdir + was specified as when BIND was + built) + that is read by both rndc + and named on startup. The + rndc.key file defines a default + command channel and authentication key allowing + rndc to communicate with + named on the local host + with no further configuration. + + + Running rndc-confgen -a allows + BIND 9 and rndc to be used as + drop-in + replacements for BIND 8 and ndc, + with no changes to the existing BIND 8 + named.conf file. + + + If a more elaborate configuration than that + generated by rndc-confgen -a + is required, for example if rndc is to be used remotely, + you should run rndc-confgen without + the + -a option and set up a + rndc.conf and + named.conf + as directed. + + + + + + -b keysize + + + Specifies the size of the authentication key in bits. + Must be between 1 and 512 bits; the default is 128. + + + + + + -c keyfile + + + Used with the -a option to specify + an alternate location for rndc.key. + + + + + + -h + + + Prints a short summary of the options and arguments to + rndc-confgen. + + + + + + -k keyname + + + Specifies the key name of the rndc authentication key. + This must be a valid domain name. + The default is rndc-key. + + + + + + -p port + + + Specifies the command channel port where named + listens for connections from rndc. + The default is 953. + + + + + + -r randomfile + + + Specifies a source of random data for generating the + authorization. If the operating + system does not provide a /dev/random + or equivalent device, the default source of randomness + is keyboard input. randomdev + specifies + the name of a character device or file containing random + data to be used instead of the default. The special value + keyboard indicates that keyboard + input should be used. + + + + + + -s address + + + Specifies the IP address where named + listens for command channel connections from + rndc. The default is the loopback + address 127.0.0.1. + + + + + + -t chrootdir + + + Used with the -a option to specify + a directory where named will run + chrooted. An additional copy of the rndc.key + will be written relative to this directory so that + it will be found by the chrooted named. + + + + + + -u user + + + Used with the -a option to set the + owner + of the rndc.key file generated. + If + -t is also specified only the file + in + the chroot area has its owner changed. + + + + + + + + + EXAMPLES + + To allow rndc to be used with + no manual configuration, run + + rndc-confgen -a + + + To print a sample rndc.conf file and + corresponding controls and key + statements to be manually inserted into named.conf, + run + + rndc-confgen + + + + + SEE ALSO + + rndc8 + , + + rndc.conf5 + , + + named8 + , + BIND 9 Administrator Reference Manual. + + + + + AUTHOR + Internet Systems Consortium + + + + diff --git a/bin/confgen/rndc-confgen.html b/bin/confgen/rndc-confgen.html new file mode 100644 index 0000000..82a7120 --- /dev/null +++ b/bin/confgen/rndc-confgen.html @@ -0,0 +1,188 @@ + + + + + +rndc-confgen + + +
+
+
+

Name

+

rndc-confgen — rndc key generation tool

+
+
+

Synopsis

+

rndc-confgen [-a] [-b keysize] [-c keyfile] [-h] [-k keyname] [-p port] [-r randomfile] [-s address] [-t chrootdir] [-u user]

+
+
+

DESCRIPTION

+

rndc-confgen + generates configuration files + for rndc. It can be used as a + convenient alternative to writing the + rndc.conf file + and the corresponding controls + and key + statements in named.conf by hand. + Alternatively, it can be run with the -a + option to set up a rndc.key file and + avoid the need for a rndc.conf file + and a controls statement altogether. +

+
+
+

OPTIONS

+
+
-a
+
+

+ Do automatic rndc configuration. + This creates a file rndc.key + in /etc (or whatever + sysconfdir + was specified as when BIND was + built) + that is read by both rndc + and named on startup. The + rndc.key file defines a default + command channel and authentication key allowing + rndc to communicate with + named on the local host + with no further configuration. +

+

+ Running rndc-confgen -a allows + BIND 9 and rndc to be used as + drop-in + replacements for BIND 8 and ndc, + with no changes to the existing BIND 8 + named.conf file. +

+

+ If a more elaborate configuration than that + generated by rndc-confgen -a + is required, for example if rndc is to be used remotely, + you should run rndc-confgen without + the + -a option and set up a + rndc.conf and + named.conf + as directed. +

+
+
-b keysize
+

+ Specifies the size of the authentication key in bits. + Must be between 1 and 512 bits; the default is 128. +

+
-c keyfile
+

+ Used with the -a option to specify + an alternate location for rndc.key. +

+
-h
+

+ Prints a short summary of the options and arguments to + rndc-confgen. +

+
-k keyname
+

+ Specifies the key name of the rndc authentication key. + This must be a valid domain name. + The default is rndc-key. +

+
-p port
+

+ Specifies the command channel port where named + listens for connections from rndc. + The default is 953. +

+
-r randomfile
+

+ Specifies a source of random data for generating the + authorization. If the operating + system does not provide a /dev/random + or equivalent device, the default source of randomness + is keyboard input. randomdev + specifies + the name of a character device or file containing random + data to be used instead of the default. The special value + keyboard indicates that keyboard + input should be used. +

+
-s address
+

+ Specifies the IP address where named + listens for command channel connections from + rndc. The default is the loopback + address 127.0.0.1. +

+
-t chrootdir
+

+ Used with the -a option to specify + a directory where named will run + chrooted. An additional copy of the rndc.key + will be written relative to this directory so that + it will be found by the chrooted named. +

+
-u user
+

+ Used with the -a option to set the + owner + of the rndc.key file generated. + If + -t is also specified only the file + in + the chroot area has its owner changed. +

+
+
+
+

EXAMPLES

+

+ To allow rndc to be used with + no manual configuration, run +

+

rndc-confgen -a +

+

+ To print a sample rndc.conf file and + corresponding controls and key + statements to be manually inserted into named.conf, + run +

+

rndc-confgen +

+
+
+

SEE ALSO

+

rndc(8), + rndc.conf(5), + named(8), + BIND 9 Administrator Reference Manual. +

+
+
+

AUTHOR

+

Internet Systems Consortium +

+
+
+ diff --git a/bin/confgen/unix/Makefile.in b/bin/confgen/unix/Makefile.in new file mode 100644 index 0000000..1785e0d --- /dev/null +++ b/bin/confgen/unix/Makefile.in @@ -0,0 +1,35 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.3 2009-06-11 23:47:55 tbox Exp $ + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I${srcdir}/include -I${srcdir}/../include \ + ${DNS_INCLUDES} ${ISC_INCLUDES} + +CDEFINES = +CWARNINGS = + +OBJS = os.@O@ + +SRCS = os.c + +TARGETS = ${OBJS} + +@BIND9_MAKE_RULES@ diff --git a/bin/confgen/unix/os.c b/bin/confgen/unix/os.c new file mode 100644 index 0000000..e439a51 --- /dev/null +++ b/bin/confgen/unix/os.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: os.c,v 1.3 2009-06-11 23:47:55 tbox Exp $ */ + +/*! \file */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +int +set_user(FILE *fd, const char *user) { + struct passwd *pw; + + pw = getpwnam(user); + if (pw == NULL) { + errno = EINVAL; + return (-1); + } + return (fchown(fileno(fd), pw->pw_uid, -1)); +} diff --git a/bin/confgen/util.c b/bin/confgen/util.c new file mode 100644 index 0000000..158a8d3 --- /dev/null +++ b/bin/confgen/util.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: util.c,v 1.3 2009-06-11 23:47:55 tbox Exp $ */ + +/*! \file */ + +#include + +#include +#include +#include + +#include + +#include "util.h" + +extern isc_boolean_t verbose; +extern const char *progname; + +void +notify(const char *fmt, ...) { + va_list ap; + + if (verbose) { + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fputs("\n", stderr); + } +} + +void +fatal(const char *format, ...) { + va_list args; + + fprintf(stderr, "%s: ", progname); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + exit(1); +} diff --git a/bin/confgen/util.h b/bin/confgen/util.h new file mode 100644 index 0000000..651b6e5 --- /dev/null +++ b/bin/confgen/util.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: util.h,v 1.4 2009-09-29 15:06:05 fdupont Exp $ */ + +#ifndef RNDC_UTIL_H +#define RNDC_UTIL_H 1 + +/*! \file */ + +#include +#include + +#include + +#define NS_CONTROL_PORT 953 + +#undef DO +#define DO(name, function) \ + do { \ + result = function; \ + if (result != ISC_R_SUCCESS) \ + fatal("%s: %s", name, isc_result_totext(result)); \ + else \ + notify("%s", name); \ + } while (0) + +ISC_LANG_BEGINDECLS + +void +notify(const char *fmt, ...) ISC_FORMAT_PRINTF(1, 2); + +ISC_PLATFORM_NORETURN_PRE void +fatal(const char *format, ...) +ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; + +ISC_LANG_ENDDECLS + +#endif /* RNDC_UTIL_H */ diff --git a/bin/dig/Makefile.in b/bin/dig/Makefile.in index ad20553..bebef6f 100644 --- a/bin/dig/Makefile.in +++ b/bin/dig/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 2000-2002 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.41 2007-06-19 23:46:59 tbox Exp $ +# $Id: Makefile.in,v 1.47 2009-12-05 23:31:40 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -24,7 +24,7 @@ top_srcdir = @top_srcdir@ @BIND9_MAKE_INCLUDES@ CINCLUDES = -I${srcdir}/include ${DNS_INCLUDES} ${BIND9_INCLUDES} \ - ${ISC_INCLUDES} ${LWRES_INCLUDES} + ${ISC_INCLUDES} ${LWRES_INCLUDES} ${ISCCFG_INCLUDES} CDEFINES = -DVERSION=\"${VERSION}\" CWARNINGS = @@ -33,6 +33,7 @@ ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ BIND9LIBS = ../../lib/bind9/libbind9.@A@ ISCLIBS = ../../lib/isc/libisc.@A@ +ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ LWRESLIBS = ../../lib/lwres/liblwres.@A@ ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ @@ -44,8 +45,11 @@ LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@ DEPLIBS = ${DNSDEPLIBS} ${BIND9DEPLIBS} ${ISCDEPLIBS} ${ISCCFGDEPLIBS} \ ${LWRESDEPLIBS} -LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCLIBS} \ - ${ISCCFGLIBS} @IDNLIBS@ @LIBS@ +LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \ + ${ISCLIBS} @IDNLIBS@ @LIBS@ + +NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \ + ${ISCNOSYMLIBS} @IDNLIBS@ @LIBS@ SUBDIRS = @@ -66,16 +70,16 @@ MANOBJS = ${MANPAGES} ${HTMLPAGES} @BIND9_MAKE_RULES@ dig@EXEEXT@: dig.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - dig.@O@ dighost.@O@ ${UOBJS} ${LIBS} + export BASEOBJS="dig.@O@ dighost.@O@ ${UOBJS}"; \ + ${FINALBUILDCMD} host@EXEEXT@: host.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - host.@O@ dighost.@O@ ${UOBJS} ${LIBS} + export BASEOBJS="host.@O@ dighost.@O@ ${UOBJS}"; \ + ${FINALBUILDCMD} nslookup@EXEEXT@: nslookup.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - nslookup.@O@ dighost.@O@ ${UOBJS} ${LIBS} + export BASEOBJS="nslookup.@O@ dighost.@O@ ${UOBJS}"; \ + ${FINALBUILDCMD} doc man:: ${MANOBJS} diff --git a/bin/dig/dig.1 b/bin/dig/dig.1 index 93f90b2..87d5045 100644 --- a/bin/dig/dig.1 +++ b/bin/dig/dig.1 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") .\" Copyright (C) 2000-2003 Internet Software Consortium. .\" .\" Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: dig.1,v 1.50.44.3 2009-07-11 01:55:20 tbox Exp $ +.\" $Id: dig.1,v 1.54 2010-03-05 01:14:15 tbox Exp $ .\" .hy 0 .ad l @@ -455,6 +455,11 @@ Print records like the SOA records in a verbose multi\-line format with human\-r output. .RE .PP +\fB+[no]onesoa\fR +.RS 4 +Print only one (starting) SOA record when performing an AXFR. The default is to print both the starting and ending SOA records. +.RE +.PP \fB+[no]fail\fR .RS 4 Do not try the next server if you receive a SERVFAIL. The default is to not try the next server which is the reverse of normal stub resolver behavior. @@ -562,7 +567,7 @@ RFC1035. .PP There are probably too many query options. .SH "COPYRIGHT" -Copyright \(co 2004\-2009 Internet Systems Consortium, Inc. ("ISC") +Copyright \(co 2004\-2010 Internet Systems Consortium, Inc. ("ISC") .br Copyright \(co 2000\-2003 Internet Software Consortium. .br diff --git a/bin/dig/dig.c b/bin/dig/dig.c index 7de934b..a3143c9 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dig.c,v 1.225.26.7 2010-05-13 00:43:37 marka Exp $ */ +/* $Id: dig.c,v 1.237 2010-05-13 00:40:46 marka Exp $ */ /*! \file */ @@ -68,7 +68,8 @@ static char domainopt[DNS_NAME_MAXTEXT]; static isc_boolean_t short_form = ISC_FALSE, printcmd = ISC_TRUE, ip6_int = ISC_FALSE, plusquest = ISC_FALSE, pluscomm = ISC_FALSE, - multiline = ISC_FALSE, nottl = ISC_FALSE, noclass = ISC_FALSE; + multiline = ISC_FALSE, nottl = ISC_FALSE, noclass = ISC_FALSE, + onesoa = ISC_FALSE; /*% opcode text */ static const char * const opcodetext[] = { @@ -138,6 +139,9 @@ print_usage(FILE *fp) { " [ host [@local-server] {local-d-opt} [...]]\n", fp); } +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + static void usage(void) { print_usage(stderr); @@ -222,6 +226,7 @@ help(void) { #endif #endif " +[no]multiline (Print records in an expanded format)\n" +" +[no]onesoa (AXFR prints only one soa record)\n" " global d-opts and servers (before host name) affect all queries.\n" " local d-opts and servers (after host name) affect only that lookup.\n" " -h (print help and exit)\n" @@ -468,6 +473,9 @@ printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { flags |= DNS_MESSAGETEXTFLAG_NOHEADERS; flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS; } + if (onesoa && query->lookup->rdtype == dns_rdatatype_axfr) + flags |= (query->msg_count == 0) ? DNS_MESSAGETEXTFLAG_ONESOA : + DNS_MESSAGETEXTFLAG_OMITSOA; if (!query->lookup->comments) flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS; @@ -673,19 +681,6 @@ printgreeting(int argc, char **argv, dig_lookup_t *lookup) { } } -static isc_uint32_t -parse_uint(char *arg, const char *desc, isc_uint32_t max) { - isc_result_t result; - isc_uint32_t tmp; - - result = isc_parse_uint32(&tmp, arg, 10); - if (result == ISC_R_SUCCESS && tmp > max) - result = ISC_R_RANGE; - if (result != ISC_R_SUCCESS) - fatal("%s '%s': %s", desc, arg, isc_result_totext(result)); - return (tmp); -} - /*% * We're not using isc_commandline_parse() here since the command line * syntax of dig is quite a bit different from that which can be described @@ -697,8 +692,10 @@ static void plus_option(char *option, isc_boolean_t is_batchfile, dig_lookup_t *lookup) { + isc_result_t result; char option_store[256]; char *cmd, *value, *ptr; + isc_uint32_t num; isc_boolean_t state = ISC_TRUE; #ifdef DIG_SIGCHASE size_t n; @@ -746,6 +743,7 @@ plus_option(char *option, isc_boolean_t is_batchfile, lookup->section_additional = state; break; case 'f': /* adflag */ + case '\0': /* +ad is a synonym for +adflag */ FULLCHECK("adflag"); lookup->adflag = state; break; @@ -787,8 +785,11 @@ plus_option(char *option, isc_boolean_t is_batchfile, goto need_value; if (!state) goto invalid_option; - lookup->udpsize = (isc_uint16_t) parse_uint(value, - "buffer size", COMMSIZE); + result = parse_uint(&num, value, COMMSIZE, + "buffer size"); + if (result != ISC_R_SUCCESS) + fatal("Couldn't parse buffer size"); + lookup->udpsize = num; break; default: goto invalid_option; @@ -797,8 +798,15 @@ plus_option(char *option, isc_boolean_t is_batchfile, case 'c': switch (cmd[1]) { case 'd':/* cdflag */ - FULLCHECK("cdflag"); - lookup->cdflag = state; + switch (cmd[2]) { + case 'f': /* cdflag */ + case '\0': /* +cd is a synonym for +cdflag */ + FULLCHECK("cdflag"); + lookup->cdflag = state; + break; + default: + goto invalid_option; + } break; case 'l': /* cl */ FULLCHECK("cl"); @@ -853,7 +861,10 @@ plus_option(char *option, isc_boolean_t is_batchfile, } if (value == NULL) goto need_value; - lookup->edns = (isc_int16_t) parse_uint(value, "edns", 255); + result = parse_uint(&num, value, 255, "edns"); + if (result != ISC_R_SUCCESS) + fatal("Couldn't parse edns"); + lookup->edns = num; break; case 'f': /* fail */ FULLCHECK("fail"); @@ -883,7 +894,10 @@ plus_option(char *option, isc_boolean_t is_batchfile, goto need_value; if (!state) goto invalid_option; - ndots = parse_uint(value, "ndots", MAXNDOTS); + result = parse_uint(&num, value, MAXNDOTS, "ndots"); + if (result != ISC_R_SUCCESS) + fatal("Couldn't parse ndots"); + ndots = num; break; case 's': switch (cmd[2]) { @@ -918,6 +932,10 @@ plus_option(char *option, isc_boolean_t is_batchfile, goto invalid_option; } break; + case 'o': + FULLCHECK("onesoa"); + onesoa = state; + break; case 'q': switch (cmd[1]) { case 'r': /* qr */ @@ -948,8 +966,10 @@ plus_option(char *option, isc_boolean_t is_batchfile, goto need_value; if (!state) goto invalid_option; - lookup->retries = parse_uint(value, "retries", - MAXTRIES - 1); + result = parse_uint(&lookup->retries, value, + MAXTRIES - 1, "retries"); + if (result != ISC_R_SUCCESS) + fatal("Couldn't parse retries"); lookup->retries++; break; default: @@ -1025,7 +1045,10 @@ plus_option(char *option, isc_boolean_t is_batchfile, goto need_value; if (!state) goto invalid_option; - timeout = parse_uint(value, "timeout", MAXTIMEOUT); + result = parse_uint(&timeout, value, MAXTIMEOUT, + "timeout"); + if (result != ISC_R_SUCCESS) + fatal("Couldn't parse timeout"); if (timeout == 0) timeout = 1; break; @@ -1058,8 +1081,10 @@ plus_option(char *option, isc_boolean_t is_batchfile, goto need_value; if (!state) goto invalid_option; - lookup->retries = parse_uint(value, "tries", - MAXTRIES); + result = parse_uint(&lookup->retries, value, + MAXTRIES, "tries"); + if (result != ISC_R_SUCCESS) + fatal("Couldn't parse tries"); if (lookup->retries == 0) lookup->retries = 1; break; @@ -1125,6 +1150,7 @@ dash_option(char *option, char *next, dig_lookup_t **lookup, struct in6_addr in6; in_port_t srcport; char *hash, *cmd; + isc_uint32_t num; while (strpbrk(option, single_dash_opts) == &option[0]) { /* @@ -1140,6 +1166,7 @@ dash_option(char *option, char *next, dig_lookup_t **lookup, have_ipv6 = ISC_FALSE; } else { fatal("can't find IPv4 networking"); + /* NOTREACHED */ return (ISC_FALSE); } break; @@ -1149,6 +1176,7 @@ dash_option(char *option, char *next, dig_lookup_t **lookup, have_ipv4 = ISC_FALSE; } else { fatal("can't find IPv6 networking"); + /* NOTREACHED */ return (ISC_FALSE); } break; @@ -1199,9 +1227,11 @@ dash_option(char *option, char *next, dig_lookup_t **lookup, case 'b': hash = strchr(value, '#'); if (hash != NULL) { - srcport = (in_port_t) - parse_uint(hash + 1, - "port number", MAXPORT); + result = parse_uint(&num, hash + 1, MAXPORT, + "port number"); + if (result != ISC_R_SUCCESS) + fatal("Couldn't parse port number"); + srcport = num; *hash = '\0'; } else srcport = 0; @@ -1245,7 +1275,10 @@ dash_option(char *option, char *next, dig_lookup_t **lookup, keyfile[sizeof(keyfile)-1]=0; return (value_from_next); case 'p': - port = (in_port_t) parse_uint(value, "port number", MAXPORT); + result = parse_uint(&num, value, MAXPORT, "port number"); + if (result != ISC_R_SUCCESS) + fatal("Couldn't parse port number"); + port = num; return (value_from_next); case 'q': if (!config_only) { @@ -1288,11 +1321,14 @@ dash_option(char *option, char *next, dig_lookup_t **lookup, "extra type option\n"); } if (rdtype == dns_rdatatype_ixfr) { + isc_uint32_t serial; (*lookup)->rdtype = dns_rdatatype_ixfr; (*lookup)->rdtypeset = ISC_TRUE; - (*lookup)->ixfr_serial = - parse_uint(&value[5], "serial number", - MAXSERIAL); + result = parse_uint(&serial, &value[5], + MAXSERIAL, "serial number"); + if (result != ISC_R_SUCCESS) + fatal("Couldn't parse serial number"); + (*lookup)->ixfr_serial = serial; (*lookup)->section_question = plusquest; (*lookup)->comments = pluscomm; (*lookup)->tcp_mode = ISC_TRUE; @@ -1320,65 +1356,7 @@ dash_option(char *option, char *next, dig_lookup_t **lookup, usage(); ptr3 = next_token(&value,":"); /* secret or NULL */ if (ptr3 != NULL) { - if (strcasecmp(ptr, "hmac-md5") == 0) { - hmacname = DNS_TSIG_HMACMD5_NAME; - digestbits = 0; - } else if (strncasecmp(ptr, "hmac-md5-", 9) == 0) { - hmacname = DNS_TSIG_HMACMD5_NAME; - digestbits = parse_uint(&ptr[9], - "digest-bits [0..128]", - 128); - digestbits = (digestbits + 7) & ~0x7U; - } else if (strcasecmp(ptr, "hmac-sha1") == 0) { - hmacname = DNS_TSIG_HMACSHA1_NAME; - digestbits = 0; - } else if (strncasecmp(ptr, "hmac-sha1-", 10) == 0) { - hmacname = DNS_TSIG_HMACSHA1_NAME; - digestbits = parse_uint(&ptr[10], - "digest-bits [0..160]", - 160); - digestbits = (digestbits + 7) & ~0x7U; - } else if (strcasecmp(ptr, "hmac-sha224") == 0) { - hmacname = DNS_TSIG_HMACSHA224_NAME; - digestbits = 0; - } else if (strncasecmp(ptr, "hmac-sha224-", 12) == 0) { - hmacname = DNS_TSIG_HMACSHA224_NAME; - digestbits = parse_uint(&ptr[12], - "digest-bits [0..224]", - 224); - digestbits = (digestbits + 7) & ~0x7U; - } else if (strcasecmp(ptr, "hmac-sha256") == 0) { - hmacname = DNS_TSIG_HMACSHA256_NAME; - digestbits = 0; - } else if (strncasecmp(ptr, "hmac-sha256-", 12) == 0) { - hmacname = DNS_TSIG_HMACSHA256_NAME; - digestbits = parse_uint(&ptr[12], - "digest-bits [0..256]", - 256); - digestbits = (digestbits + 7) & ~0x7U; - } else if (strcasecmp(ptr, "hmac-sha384") == 0) { - hmacname = DNS_TSIG_HMACSHA384_NAME; - digestbits = 0; - } else if (strncasecmp(ptr, "hmac-sha384-", 12) == 0) { - hmacname = DNS_TSIG_HMACSHA384_NAME; - digestbits = parse_uint(&ptr[12], - "digest-bits [0..384]", - 384); - digestbits = (digestbits + 7) & ~0x7U; - } else if (strcasecmp(ptr, "hmac-sha512") == 0) { - hmacname = DNS_TSIG_HMACSHA512_NAME; - digestbits = 0; - } else if (strncasecmp(ptr, "hmac-sha512-", 12) == 0) { - hmacname = DNS_TSIG_HMACSHA512_NAME; - digestbits = parse_uint(&ptr[12], - "digest-bits [0..512]", - 512); - digestbits = (digestbits + 7) & ~0x7U; - } else { - fprintf(stderr, ";; Warning, ignoring " - "invalid TSIG algorithm %s\n", ptr); - return (value_from_next); - } + parse_hmac(ptr); ptr = ptr2; ptr2 = ptr3; } else { @@ -1422,6 +1400,7 @@ dash_option(char *option, char *next, dig_lookup_t **lookup, fprintf(stderr, "Invalid option: -%s\n", option); usage(); } + /* NOTREACHED */ return (ISC_FALSE); } @@ -1626,13 +1605,18 @@ parse_args(isc_boolean_t is_batchfile, isc_boolean_t config_only, "extra type option\n"); } if (rdtype == dns_rdatatype_ixfr) { + isc_uint32_t serial; lookup->rdtype = dns_rdatatype_ixfr; lookup->rdtypeset = ISC_TRUE; - lookup->ixfr_serial = - parse_uint(&rv[0][5], - "serial number", - MAXSERIAL); + result = parse_uint(&serial, + &rv[0][5], + MAXSERIAL, + "serial number"); + if (result != ISC_R_SUCCESS) + fatal("Couldn't parse " + "serial number"); + lookup->ixfr_serial = serial; lookup->section_question = plusquest; lookup->comments = pluscomm; diff --git a/bin/dig/dig.docbook b/bin/dig/dig.docbook index d8e3586..19e2ca2 100644 --- a/bin/dig/dig.docbook +++ b/bin/dig/dig.docbook @@ -2,7 +2,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" []> - + @@ -44,6 +44,7 @@ 2007 2008 2009 + 2010 Internet Systems Consortium, Inc. ("ISC")
@@ -766,6 +767,17 @@ + + + + + Print only one (starting) SOA record when performing + an AXFR. The default is to print both the starting and + ending SOA records. + + + + diff --git a/bin/dig/dig.html b/bin/dig/dig.html index 17fd5bb..c9ce8f0 100644 --- a/bin/dig/dig.html +++ b/bin/dig/dig.html @@ -1,5 +1,5 @@ - + @@ -34,7 +34,7 @@

dig [global-queryopt...] [query...]

-

DESCRIPTION

+

DESCRIPTION

dig (domain information groper) is a flexible tool for interrogating DNS name servers. It performs DNS lookups and @@ -80,7 +80,7 @@

-

SIMPLE USAGE

+

SIMPLE USAGE

A typical invocation of dig looks like:

@@ -126,7 +126,7 @@

-

OPTIONS

+

OPTIONS

The -b option sets the source IP address of the query to address. This must be a valid @@ -230,7 +230,7 @@

-

QUERY OPTIONS

+

QUERY OPTIONS

dig provides a number of query options which affect the way in which lookups are made and the results displayed. Some of @@ -499,6 +499,12 @@ each record on a single line, to facilitate machine parsing of the dig output.

+
+[no]onesoa
+

+ Print only one (starting) SOA record when performing + an AXFR. The default is to print both the starting and + ending SOA records. +

+[no]fail

Do not try the next server if you receive a SERVFAIL. The @@ -555,7 +561,7 @@

-

MULTIPLE QUERIES

+

MULTIPLE QUERIES

The BIND 9 implementation of dig supports @@ -601,7 +607,7 @@ dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr

-

IDN SUPPORT

+

IDN SUPPORT

If dig has been built with IDN (internationalized domain name) support, it can accept and display non-ASCII domain names. @@ -615,14 +621,14 @@ dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr

-

FILES

+

FILES

/etc/resolv.conf

${HOME}/.digrc

-

SEE ALSO

+

SEE ALSO

host(1), named(8), dnssec-keygen(8), @@ -630,7 +636,7 @@ dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr

-

BUGS

+

BUGS

There are probably too many query options.

diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index df5a0c0..e92bc6e 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dighost.c,v 1.311.70.17 2010-12-09 01:12:54 marka Exp $ */ +/* $Id: dighost.c,v 1.336 2010-12-09 00:54:33 marka Exp $ */ /*! \file * \note @@ -53,6 +53,7 @@ #include #endif #include +#include #include #include #include @@ -71,10 +72,12 @@ #include #include #include +#include #include #ifdef DIG_SIGCHASE #include #endif +#include #include #include #include @@ -84,6 +87,8 @@ #include #include +#include + #include #include @@ -121,6 +126,7 @@ in_port_t port = 53; unsigned int timeout = 0; unsigned int extrabytes; isc_mem_t *mctx = NULL; +isc_log_t *lctx = NULL; isc_taskmgr_t *taskmgr = NULL; isc_task_t *global_task = NULL; isc_timermgr_t *timermgr = NULL; @@ -393,7 +399,7 @@ count_dots(char *string) { static void hex_dump(isc_buffer_t *b) { - unsigned int len; + unsigned int len, i; isc_region_t r; isc_buffer_usedregion(b, &r); @@ -401,11 +407,29 @@ hex_dump(isc_buffer_t *b) { printf("%d bytes\n", r.length); for (len = 0; len < r.length; len++) { printf("%02x ", r.base[len]); - if (len % 16 == 15) + if (len % 16 == 15) { + fputs(" ", stdout); + for (i = len - 15; i <= len; i++) { + if (r.base[i] >= '!' && r.base[i] <= '}') + putchar(r.base[i]); + else + putchar('.'); + } printf("\n"); + } } - if (len % 16 != 0) + if (len % 16 != 0) { + for (i = len; (i % 16) != 0; i++) + fputs(" ", stdout); + fputs(" ", stdout); + for (i = ((len>>4)<<4); i < len; i++) { + if (r.base[i] >= '!' && r.base[i] <= '}') + putchar(r.base[i]); + else + putchar('.'); + } printf("\n"); + } } /*% @@ -903,9 +927,7 @@ setup_text_key(void) { secretsize = isc_buffer_usedlength(&secretbuf); - result = dns_name_fromtext(&keyname, namebuf, - dns_rootname, ISC_FALSE, - namebuf); + result = dns_name_fromtext(&keyname, namebuf, dns_rootname, 0, namebuf); if (result != ISC_R_SUCCESS) goto failure; @@ -924,14 +946,164 @@ setup_text_key(void) { isc_buffer_free(&namebuf); } +isc_result_t +parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max, + const char *desc) { + isc_uint32_t n; + isc_result_t result = isc_parse_uint32(&n, value, 10); + if (result == ISC_R_SUCCESS && n > max) + result = ISC_R_RANGE; + if (result != ISC_R_SUCCESS) { + printf("invalid %s '%s': %s\n", desc, + value, isc_result_totext(result)); + return (result); + } + *uip = n; + return (ISC_R_SUCCESS); +} + +static isc_uint32_t +parse_bits(char *arg, const char *desc, isc_uint32_t max) { + isc_result_t result; + isc_uint32_t tmp; + + result = parse_uint(&tmp, arg, max, desc); + if (result != ISC_R_SUCCESS) + fatal("couldn't parse digest bits"); + tmp = (tmp + 7) & ~0x7U; + return (tmp); +} + + +/* + * Parse HMAC algorithm specification + */ +void +parse_hmac(const char *hmac) { + char buf[20]; + int len; + + REQUIRE(hmac != NULL); + + len = strlen(hmac); + if (len >= (int) sizeof(buf)) + fatal("unknown key type '%.*s'", len, hmac); + strncpy(buf, hmac, sizeof(buf)); + + digestbits = 0; + + if (strcasecmp(buf, "hmac-md5") == 0) { + hmacname = DNS_TSIG_HMACMD5_NAME; + } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) { + hmacname = DNS_TSIG_HMACMD5_NAME; + digestbits = parse_bits(&buf[9], "digest-bits [0..128]", 128); + } else if (strcasecmp(buf, "hmac-sha1") == 0) { + hmacname = DNS_TSIG_HMACSHA1_NAME; + digestbits = 0; + } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) { + hmacname = DNS_TSIG_HMACSHA1_NAME; + digestbits = parse_bits(&buf[10], "digest-bits [0..160]", 160); + } else if (strcasecmp(buf, "hmac-sha224") == 0) { + hmacname = DNS_TSIG_HMACSHA224_NAME; + } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) { + hmacname = DNS_TSIG_HMACSHA224_NAME; + digestbits = parse_bits(&buf[12], "digest-bits [0..224]", 224); + } else if (strcasecmp(buf, "hmac-sha256") == 0) { + hmacname = DNS_TSIG_HMACSHA256_NAME; + } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) { + hmacname = DNS_TSIG_HMACSHA256_NAME; + digestbits = parse_bits(&buf[12], "digest-bits [0..256]", 256); + } else if (strcasecmp(buf, "hmac-sha384") == 0) { + hmacname = DNS_TSIG_HMACSHA384_NAME; + } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) { + hmacname = DNS_TSIG_HMACSHA384_NAME; + digestbits = parse_bits(&buf[12], "digest-bits [0..384]", 384); + } else if (strcasecmp(buf, "hmac-sha512") == 0) { + hmacname = DNS_TSIG_HMACSHA512_NAME; + } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) { + hmacname = DNS_TSIG_HMACSHA512_NAME; + digestbits = parse_bits(&buf[12], "digest-bits [0..512]", 512); + } else { + fprintf(stderr, ";; Warning, ignoring " + "invalid TSIG algorithm %s\n", buf); + } +} + +/* + * Get a key from a named.conf format keyfile + */ +static isc_result_t +read_confkey(void) { + isc_log_t *lctx = NULL; + cfg_parser_t *pctx = NULL; + cfg_obj_t *file = NULL; + const cfg_obj_t *key = NULL; + const cfg_obj_t *secretobj = NULL; + const cfg_obj_t *algorithmobj = NULL; + const char *keyname; + const char *secretstr; + const char *algorithm; + isc_result_t result; + + if (! isc_file_exists(keyfile)) + return (ISC_R_FILENOTFOUND); + + result = cfg_parser_create(mctx, lctx, &pctx); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey, + &file); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = cfg_map_get(file, "key", &key); + if (result != ISC_R_SUCCESS) + goto cleanup; + + (void) cfg_map_get(key, "secret", &secretobj); + (void) cfg_map_get(key, "algorithm", &algorithmobj); + if (secretobj == NULL || algorithmobj == NULL) + fatal("key must have algorithm and secret"); + + keyname = cfg_obj_asstring(cfg_map_getname(key)); + secretstr = cfg_obj_asstring(secretobj); + algorithm = cfg_obj_asstring(algorithmobj); + + strncpy(keynametext, keyname, sizeof(keynametext)); + strncpy(keysecret, secretstr, sizeof(keysecret)); + parse_hmac(algorithm); + setup_text_key(); + + cleanup: + if (pctx != NULL) { + if (file != NULL) + cfg_obj_destroy(pctx, &file); + cfg_parser_destroy(&pctx); + } + + return (result); +} + static void setup_file_key(void) { isc_result_t result; dst_key_t *dstkey = NULL; debug("setup_file_key()"); - result = dst_key_fromnamedfile(keyfile, DST_TYPE_PRIVATE | DST_TYPE_KEY, - mctx, &dstkey); + + /* Try reading the key from a K* pair */ + result = dst_key_fromnamedfile(keyfile, NULL, + DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, + &dstkey); + + /* If that didn't work, try reading it as a session.key keyfile */ + if (result != ISC_R_SUCCESS) { + result = read_confkey(); + if (result == ISC_R_SUCCESS) + return; + } + if (result != ISC_R_SUCCESS) { fprintf(stderr, "Couldn't read key from %s: %s\n", keyfile, isc_result_totext(result)); @@ -1119,6 +1291,7 @@ set_search_domain(char *domain) { void setup_libs(void) { isc_result_t result; + isc_logconfig_t *logconfig = NULL; debug("setup_libs()"); @@ -1135,6 +1308,18 @@ setup_libs(void) { result = isc_mem_create(0, 0, &mctx); check_result(result, "isc_mem_create"); + result = isc_log_create(mctx, &lctx, &logconfig); + check_result(result, "isc_log_create"); + + isc_log_setcontext(lctx); + dns_log_init(lctx); + dns_log_setcontext(lctx); + + result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL); + check_result(result, "isc_log_usechannel"); + + isc_log_setdebuglevel(lctx, 0); + result = isc_taskmgr_create(mctx, 1, 0, &taskmgr); check_result(result, "isc_taskmgr_create"); @@ -1871,7 +2056,7 @@ setup_lookup(dig_lookup_t *lookup) { isc_buffer_init(&b, lookup->origin->origin, len); isc_buffer_add(&b, len); result = dns_name_fromtext(lookup->oname, &b, dns_rootname, - ISC_FALSE, &lookup->onamebuf); + 0, &lookup->onamebuf); if (result != ISC_R_SUCCESS) { dns_message_puttempname(lookup->sendmsg, &lookup->name); @@ -1888,7 +2073,7 @@ setup_lookup(dig_lookup_t *lookup) { isc_buffer_init(&b, lookup->textname, len); isc_buffer_add(&b, len); result = dns_name_fromtext(lookup->name, &b, - lookup->oname, ISC_FALSE, + lookup->oname, 0, &lookup->namebuf); } if (result != ISC_R_SUCCESS) { @@ -1912,16 +2097,14 @@ setup_lookup(dig_lookup_t *lookup) { isc_buffer_init(&b, idn_textname, len); isc_buffer_add(&b, len); result = dns_name_fromtext(lookup->name, &b, - dns_rootname, - ISC_FALSE, + dns_rootname, 0, &lookup->namebuf); #else len = strlen(lookup->textname); isc_buffer_init(&b, lookup->textname, len); isc_buffer_add(&b, len); result = dns_name_fromtext(lookup->name, &b, - dns_rootname, - ISC_FALSE, + dns_rootname, 0, &lookup->namebuf); #endif } @@ -3549,9 +3732,11 @@ destroy_libs(void) { free_name(&chase_signame, mctx); #endif - debug("Destroy memory"); - #endif + debug("Removing log context"); + isc_log_destroy(&lctx); + + debug("Destroy memory"); if (memdebugging != 0) isc_mem_stats(mctx, stderr); if (mctx != NULL) @@ -4041,7 +4226,7 @@ get_trusted_key(isc_mem_t *mctx) return (ISC_R_FAILURE); } fclose(fptemp); - result = dst_key_fromnamedfile(filetemp, DST_TYPE_PUBLIC, + result = dst_key_fromnamedfile(filetemp, NULL, DST_TYPE_PUBLIC, mctx, &key); removetmpkey(mctx, filetemp); isc_mem_free(mctx, filetemp); @@ -4075,7 +4260,7 @@ nameFromString(const char *str, dns_name_t *p_ret) { dns_fixedname_init(&fixedname); result = dns_name_fromtext(dns_fixedname_name(&fixedname), &buffer, - dns_rootname, ISC_TRUE, NULL); + dns_rootname, DNS_NAME_DOWNCASE, NULL); check_result(result, "nameFromString"); if (dns_name_dynamic(p_ret)) diff --git a/bin/dig/host.1 b/bin/dig/host.1 index 1573eff..464d517 100644 --- a/bin/dig/host.1 +++ b/bin/dig/host.1 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: host.1,v 1.29.114.2 2009-07-11 01:55:20 tbox Exp $ +.\" $Id: host.1,v 1.31 2009-07-11 01:12:45 tbox Exp $ .\" .hy 0 .ad l diff --git a/bin/dig/host.c b/bin/dig/host.c index ab0be99..13569f6 100644 --- a/bin/dig/host.c +++ b/bin/dig/host.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: host.c,v 1.116.216.5 2010-10-19 23:45:58 tbox Exp $ */ +/* $Id: host.c,v 1.124 2010-11-16 05:38:30 marka Exp $ */ /*! \file */ @@ -141,6 +141,9 @@ rcode_totext(dns_rcode_t rcode) return totext.deconsttext; } +ISC_PLATFORM_NORETURN_PRE static void +show_usage(void) ISC_PLATFORM_NORETURN_POST; + static void show_usage(void) { fputs( diff --git a/bin/dig/host.docbook b/bin/dig/host.docbook index 41175aa..9ffd8e6 100644 --- a/bin/dig/host.docbook +++ b/bin/dig/host.docbook @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + diff --git a/bin/dig/host.html b/bin/dig/host.html index de4b579..531fc1d 100644 --- a/bin/dig/host.html +++ b/bin/dig/host.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h index 3d696c7..c0f778b 100644 --- a/bin/dig/include/dig/dig.h +++ b/bin/dig/include/dig/dig.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dig.h,v 1.107.120.2 2009-01-06 23:47:26 tbox Exp $ */ +/* $Id: dig.h,v 1.111 2009-09-29 15:06:06 fdupont Exp $ */ #ifndef DIG_H #define DIG_H @@ -292,8 +292,9 @@ isc_result_t get_reverse(char *reverse, size_t len, char *value, isc_boolean_t ip6_int, isc_boolean_t strict); -void -fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); +ISC_PLATFORM_NORETURN_PRE void +fatal(const char *format, ...) +ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; void debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); @@ -325,6 +326,13 @@ setup_libs(void); void setup_system(void); +isc_result_t +parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max, + const char *desc); + +void +parse_hmac(const char *hmacstr); + dig_lookup_t * requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers); diff --git a/bin/dig/nslookup.1 b/bin/dig/nslookup.1 index a8331f9..e97ee1f 100644 --- a/bin/dig/nslookup.1 +++ b/bin/dig/nslookup.1 @@ -12,7 +12,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: nslookup.1,v 1.14.354.2 2010-02-23 01:56:02 tbox Exp $ +.\" $Id: nslookup.1,v 1.16 2010-02-23 01:14:31 tbox Exp $ .\" .hy 0 .ad l diff --git a/bin/dig/nslookup.c b/bin/dig/nslookup.c index 8a166fd..0d368b1 100644 --- a/bin/dig/nslookup.c +++ b/bin/dig/nslookup.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nslookup.c,v 1.117.334.5 2009-10-20 01:11:22 marka Exp $ */ +/* $Id: nslookup.c,v 1.127 2010-11-17 23:47:08 tbox Exp $ */ #include @@ -541,22 +541,6 @@ safecpy(char *dest, char *src, int size) { dest[size-1] = 0; } -static isc_result_t -parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max, - const char *desc) { - isc_uint32_t n; - isc_result_t result = isc_parse_uint32(&n, value, 10); - if (result == ISC_R_SUCCESS && n > max) - result = ISC_R_RANGE; - if (result != ISC_R_SUCCESS) { - printf("invalid %s '%s': %s\n", desc, - value, isc_result_totext(result)); - return result; - } - *uip = n; - return (ISC_R_SUCCESS); -} - static void set_port(const char *value) { isc_uint32_t n; diff --git a/bin/dig/nslookup.docbook b/bin/dig/nslookup.docbook index fb6e706..9c4789d 100644 --- a/bin/dig/nslookup.docbook +++ b/bin/dig/nslookup.docbook @@ -17,7 +17,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + - + diff --git a/bin/dnssec/Makefile.in b/bin/dnssec/Makefile.in index 50429be..0f5e4e8 100644 --- a/bin/dnssec/Makefile.in +++ b/bin/dnssec/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 2000-2002 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.35 2008-11-07 02:28:49 marka Exp $ +# $Id: Makefile.in,v 1.42 2009-12-05 23:31:40 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -25,11 +25,12 @@ top_srcdir = @top_srcdir@ CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} -CDEFINES = -DVERSION=\"${VERSION}\" +CDEFINES = -DVERSION=\"${VERSION}\" @USE_PKCS11@ CWARNINGS = DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ ISCLIBS = ../../lib/isc/libisc.@A@ +ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ DNSDEPLIBS = ../../lib/dns/libdns.@A@ ISCDEPLIBS = ../../lib/isc/libisc.@A@ @@ -38,44 +39,56 @@ DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS} LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@ +NOSYMLIBS = ${DNSLIBS} ${ISCNOSYMLIBS} @LIBS@ + # Alphabetically TARGETS = dnssec-keygen@EXEEXT@ dnssec-signzone@EXEEXT@ \ - dnssec-keyfromlabel@EXEEXT@ dnssec-dsfromkey@EXEEXT@ + dnssec-keyfromlabel@EXEEXT@ dnssec-dsfromkey@EXEEXT@ \ + dnssec-revoke@EXEEXT@ dnssec-settime@EXEEXT@ OBJS = dnssectool.@O@ SRCS = dnssec-dsfromkey.c dnssec-keyfromlabel.c dnssec-keygen.c \ - dnssec-signzone.c dnssectool.c + dnssec-revoke.c dnssec-settime.c dnssec-signzone.c dnssectool.c MANPAGES = dnssec-dsfromkey.8 dnssec-keyfromlabel.8 dnssec-keygen.8 \ - dnssec-signzone.8 + dnssec-revoke.8 dnssec-settime.8 dnssec-signzone.8 HTMLPAGES = dnssec-dsfromkey.html dnssec-keyfromlabel.html \ - dnssec-keygen.html dnssec-signzone.html + dnssec-keygen.html dnssec-revoke.html \ + dnssec-settime.html dnssec-signzone.html MANOBJS = ${MANPAGES} ${HTMLPAGES} @BIND9_MAKE_RULES@ dnssec-dsfromkey@EXEEXT@: dnssec-dsfromkey.@O@ ${OBJS} ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - dnssec-dsfromkey.@O@ ${OBJS} ${LIBS} + export BASEOBJS="dnssec-dsfromkey.@O@ ${OBJS}"; \ + ${FINALBUILDCMD} dnssec-keyfromlabel@EXEEXT@: dnssec-keyfromlabel.@O@ ${OBJS} ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - dnssec-keyfromlabel.@O@ ${OBJS} ${LIBS} + export BASEOBJS="dnssec-keyfromlabel.@O@ ${OBJS}"; \ + ${FINALBUILDCMD} dnssec-keygen@EXEEXT@: dnssec-keygen.@O@ ${OBJS} ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - dnssec-keygen.@O@ ${OBJS} ${LIBS} + export BASEOBJS="dnssec-keygen.@O@ ${OBJS}"; \ + ${FINALBUILDCMD} dnssec-signzone.@O@: dnssec-signzone.c ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -DVERSION=\"${VERSION}\" \ -c ${srcdir}/dnssec-signzone.c dnssec-signzone@EXEEXT@: dnssec-signzone.@O@ ${OBJS} ${DEPLIBS} + export BASEOBJS="dnssec-signzone.@O@ ${OBJS}"; \ + ${FINALBUILDCMD} + +dnssec-revoke@EXEEXT@: dnssec-revoke.@O@ ${OBJS} ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + dnssec-revoke.@O@ ${OBJS} ${LIBS} + +dnssec-settime@EXEEXT@: dnssec-settime.@O@ ${OBJS} ${DEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - dnssec-signzone.@O@ ${OBJS} ${LIBS} + dnssec-settime.@O@ ${OBJS} ${LIBS} doc man:: ${MANOBJS} diff --git a/bin/dnssec/dnssec-dsfromkey.8 b/bin/dnssec/dnssec-dsfromkey.8 index c49ccdc..25aa2bf 100644 --- a/bin/dnssec/dnssec-dsfromkey.8 +++ b/bin/dnssec/dnssec-dsfromkey.8 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2008-2010 Internet Systems Consortium, Inc. ("ISC") .\" .\" Permission to use, copy, modify, and/or distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above @@ -12,18 +12,18 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: dnssec-dsfromkey.8,v 1.5.14.1 2010-05-19 02:06:11 tbox Exp $ +.\" $Id: dnssec-dsfromkey.8,v 1.13 2010-12-24 01:14:20 tbox Exp $ .\" .hy 0 .ad l .\" Title: dnssec\-dsfromkey .\" Author: .\" Generator: DocBook XSL Stylesheets v1.71.1 -.\" Date: November 29, 2008 +.\" Date: August 26, 2009 .\" Manual: BIND9 .\" Source: BIND9 .\" -.TH "DNSSEC\-DSFROMKEY" "8" "November 29, 2008" "BIND9" "BIND9" +.TH "DNSSEC\-DSFROMKEY" "8" "August 26, 2009" "BIND9" "BIND9" .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) @@ -32,9 +32,9 @@ dnssec\-dsfromkey \- DNSSEC DS RR generation tool .SH "SYNOPSIS" .HP 17 -\fBdnssec\-dsfromkey\fR [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-1\fR] [\fB\-2\fR] [\fB\-a\ \fR\fB\fIalg\fR\fR] {keyfile} +\fBdnssec\-dsfromkey\fR [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-1\fR] [\fB\-2\fR] [\fB\-a\ \fR\fB\fIalg\fR\fR] [\fB\-l\ \fR\fB\fIdomain\fR\fR] {keyfile} .HP 17 -\fBdnssec\-dsfromkey\fR {\-s} [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-1\fR] [\fB\-2\fR] [\fB\-a\ \fR\fB\fIalg\fR\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-d\ \fR\fB\fIdir\fR\fR] {dnsname} +\fBdnssec\-dsfromkey\fR {\-s} [\fB\-1\fR] [\fB\-2\fR] [\fB\-a\ \fR\fB\fIalg\fR\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-l\ \fR\fB\fIdomain\fR\fR] [\fB\-s\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-f\ \fR\fB\fIfile\fR\fR] [\fB\-A\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] {dnsname} .SH "DESCRIPTION" .PP \fBdnssec\-dsfromkey\fR @@ -55,31 +55,49 @@ Use SHA\-256 as the digest algorithm. .RS 4 Select the digest algorithm. The value of \fBalgorithm\fR -must be one of SHA\-1 (SHA1) or SHA\-256 (SHA256). These values are case insensitive. +must be one of SHA\-1 (SHA1), SHA\-256 (SHA256) or GOST. These values are case insensitive. .RE .PP -\-v \fIlevel\fR +\-K \fIdirectory\fR .RS 4 -Sets the debugging level. +Look for key files (or, in keyset mode, +\fIkeyset\-\fR +files) in +\fBdirectory\fR. +.RE +.PP +\-f \fIfile\fR +.RS 4 +Zone file mode: in place of the keyfile name, the argument is the DNS domain name of a zone master file, which can be read from +\fBfile\fR. If the zone name is the same as +\fBfile\fR, then it may be omitted. +.RE +.PP +\-A +.RS 4 +Include ZSK's when generating DS records. Without this option, only keys which have the KSK flag set will be converted to DS records and printed. Useful only in zone file mode. +.RE +.PP +\-l \fIdomain\fR +.RS 4 +Generate a DLV set instead of a DS set. The specified +\fBdomain\fR +is appended to the name for each record in the set. The DNSSEC Lookaside Validation (DLV) RR is described in RFC 4431. .RE .PP \-s .RS 4 -Keyset mode: in place of the keyfile name, the argument is the DNS domain name of a keyset file. Following options make sense only in this mode. +Keyset mode: in place of the keyfile name, the argument is the DNS domain name of a keyset file. .RE .PP \-c \fIclass\fR .RS 4 -Specifies the DNS class (default is IN), useful only in the keyset mode. +Specifies the DNS class (default is IN). Useful only in keyset or zone file mode. .RE .PP -\-d \fIdirectory\fR +\-v \fIlevel\fR .RS 4 -Look for -\fIkeyset\fR -files in -\fBdirectory\fR -as the directory, ignored when not in the keyset mode. +Sets the debugging level. .RE .SH "EXAMPLE" .PP @@ -115,10 +133,11 @@ A keyfile error can give a "file not found" even if the file exists. \fBdnssec\-signzone\fR(8), BIND 9 Administrator Reference Manual, RFC 3658, +RFC 4431. RFC 4509. .SH "AUTHOR" .PP Internet Systems Consortium .SH "COPYRIGHT" -Copyright \(co 2008 Internet Systems Consortium, Inc. ("ISC") +Copyright \(co 2008\-2010 Internet Systems Consortium, Inc. ("ISC") .br diff --git a/bin/dnssec/dnssec-dsfromkey.c b/bin/dnssec/dnssec-dsfromkey.c index 934d25b..b7f84a0 100644 --- a/bin/dnssec/dnssec-dsfromkey.c +++ b/bin/dnssec/dnssec-dsfromkey.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-dsfromkey.c,v 1.2.14.6 2010-01-11 23:47:22 tbox Exp $ */ +/* $Id: dnssec-dsfromkey.c,v 1.19 2010-12-23 04:07:59 marka Exp $ */ /*! \file */ @@ -36,6 +36,8 @@ #include #include #include +#include +#include #include #include #include @@ -48,54 +50,40 @@ #include "dnssectool.h" +#ifndef PATH_MAX +#define PATH_MAX 1024 /* AIX, WIN32, and others don't define this. */ +#endif + const char *program = "dnssec-dsfromkey"; int verbose; static dns_rdataclass_t rdclass; -static dns_fixedname_t fixed; -static dns_name_t *name = NULL; -static dns_db_t *db = NULL; -static dns_dbnode_t *node = NULL; -static dns_rdataset_t keyset; -static isc_mem_t *mctx = NULL; +static dns_fixedname_t fixed; +static dns_name_t *name = NULL; +static isc_mem_t *mctx = NULL; -static void -loadkeys(char *dirname, char *setname) -{ - isc_result_t result; - char filename[1024]; - isc_buffer_t buf; +static isc_result_t +initname(char *setname) { + isc_result_t result; + isc_buffer_t buf; - dns_rdataset_init(&keyset); dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); isc_buffer_init(&buf, setname, strlen(setname)); isc_buffer_add(&buf, strlen(setname)); - result = dns_name_fromtext(name, &buf, dns_rootname, ISC_FALSE, NULL); - if (result != ISC_R_SUCCESS) - fatal("can't convert DNS name %s", setname); + result = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); + return (result); +} - isc_buffer_init(&buf, filename, sizeof(filename)); - if (dirname != NULL) { - if (isc_buffer_availablelength(&buf) < strlen(dirname)) - fatal("directory name '%s' too long", dirname); - isc_buffer_putstr(&buf, dirname); - if (dirname[strlen(dirname) - 1] != '/') { - if (isc_buffer_availablelength(&buf) < 1) - fatal("directory name '%s' too long", dirname); - isc_buffer_putstr(&buf, "/"); - } - } +static isc_result_t +loadsetfromfile(char *filename, dns_rdataset_t *rdataset) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbnode_t *node = NULL; + char setname[DNS_NAME_FORMATSIZE]; - if (isc_buffer_availablelength(&buf) < strlen("keyset-")) - fatal("directory name '%s' too long", dirname); - isc_buffer_putstr(&buf, "keyset-"); - result = dns_name_tofilenametext(name, ISC_FALSE, &buf); - check_result(result, "dns_name_tofilenametext()"); - if (isc_buffer_availablelength(&buf) == 0) - fatal("name %s too long", setname); - isc_buffer_putuint8(&buf, 0); + dns_name_format(name, setname, sizeof(setname)); result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone, rdclass, 0, NULL, &db); @@ -111,11 +99,49 @@ loadkeys(char *dirname, char *setname) fatal("can't find %s node in %s", setname, filename); result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, - 0, 0, &keyset, NULL); + 0, 0, rdataset, NULL); + if (result == ISC_R_NOTFOUND) fatal("no DNSKEY RR for %s in %s", setname, filename); else if (result != ISC_R_SUCCESS) fatal("dns_db_findrdataset"); + + if (node != NULL) + dns_db_detachnode(db, &node); + if (db != NULL) + dns_db_detach(&db); + return (result); +} + +static isc_result_t +loadkeyset(char *dirname, dns_rdataset_t *rdataset) { + isc_result_t result; + char filename[PATH_MAX + 1]; + isc_buffer_t buf; + + dns_rdataset_init(rdataset); + + isc_buffer_init(&buf, filename, sizeof(filename)); + if (dirname != NULL) { + /* allow room for a trailing slash */ + if (strlen(dirname) >= isc_buffer_availablelength(&buf)) + return (ISC_R_NOSPACE); + isc_buffer_putstr(&buf, dirname); + if (dirname[strlen(dirname) - 1] != '/') + isc_buffer_putstr(&buf, "/"); + } + + if (isc_buffer_availablelength(&buf) < 7) + return (ISC_R_NOSPACE); + isc_buffer_putstr(&buf, "keyset-"); + + result = dns_name_tofilenametext(name, ISC_FALSE, &buf); + check_result(result, "dns_name_tofilenametext()"); + if (isc_buffer_availablelength(&buf) == 0) + return (ISC_R_NOSPACE); + isc_buffer_putuint8(&buf, 0); + + return (loadsetfromfile(filename, rdataset)); } static void @@ -127,20 +153,20 @@ loadkey(char *filename, unsigned char *key_buf, unsigned int key_buf_size, isc_buffer_t keyb; isc_region_t r; - dns_rdataset_init(&keyset); dns_rdata_init(rdata); isc_buffer_init(&keyb, key_buf, key_buf_size); - result = dst_key_fromnamedfile(filename, DST_TYPE_PUBLIC, mctx, &key); + result = dst_key_fromnamedfile(filename, NULL, DST_TYPE_PUBLIC, + mctx, &key); if (result != ISC_R_SUCCESS) fatal("invalid keyfile name %s: %s", filename, isc_result_totext(result)); if (verbose > 2) { - char keystr[KEY_FORMATSIZE]; + char keystr[DST_KEY_FORMATSIZE]; - key_format(key, keystr, sizeof(keystr)); + dst_key_format(key, keystr, sizeof(keystr)); fprintf(stderr, "%s: %s\n", program, keystr); } @@ -169,7 +195,7 @@ logkey(dns_rdata_t *rdata) isc_result_t result; dst_key_t *key = NULL; isc_buffer_t buf; - char keystr[KEY_FORMATSIZE]; + char keystr[DST_KEY_FORMATSIZE]; isc_buffer_init(&buf, rdata->data, rdata->length); isc_buffer_add(&buf, rdata->length); @@ -177,89 +203,132 @@ logkey(dns_rdata_t *rdata) if (result != ISC_R_SUCCESS) return; - key_format(key, keystr, sizeof(keystr)); + dst_key_format(key, keystr, sizeof(keystr)); fprintf(stderr, "%s: %s\n", program, keystr); dst_key_free(&key); } static void -emitds(unsigned int dtype, dns_rdata_t *rdata) +emit(unsigned int dtype, isc_boolean_t showall, char *lookaside, + dns_rdata_t *rdata) { - isc_result_t result; - unsigned char buf[DNS_DS_BUFFERSIZE]; - char text_buf[DST_KEY_MAXTEXTSIZE]; - char class_buf[10]; - isc_buffer_t textb, classb; - isc_region_t r; - dns_rdata_t ds; + isc_result_t result; + unsigned char buf[DNS_DS_BUFFERSIZE]; + char text_buf[DST_KEY_MAXTEXTSIZE]; + char name_buf[DNS_NAME_MAXWIRE]; + char class_buf[10]; + isc_buffer_t textb, nameb, classb; + isc_region_t r; + dns_rdata_t ds; + dns_rdata_dnskey_t dnskey; isc_buffer_init(&textb, text_buf, sizeof(text_buf)); + isc_buffer_init(&nameb, name_buf, sizeof(name_buf)); isc_buffer_init(&classb, class_buf, sizeof(class_buf)); dns_rdata_init(&ds); + result = dns_rdata_tostruct(rdata, &dnskey, NULL); + if (result != ISC_R_SUCCESS) + fatal("can't convert DNSKEY"); + + if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 && !showall) + return; + result = dns_ds_buildrdata(name, rdata, dtype, buf, &ds); if (result != ISC_R_SUCCESS) - fatal("can't build DS"); + fatal("can't build record"); + + result = dns_name_totext(name, ISC_FALSE, &nameb); + if (result != ISC_R_SUCCESS) + fatal("can't print name"); + + /* Add lookaside origin, if set */ + if (lookaside != NULL) { + if (isc_buffer_availablelength(&nameb) < strlen(lookaside)) + fatal("DLV origin '%s' is too long", lookaside); + isc_buffer_putstr(&nameb, lookaside); + if (lookaside[strlen(lookaside) - 1] != '.') { + if (isc_buffer_availablelength(&nameb) < 1) + fatal("DLV origin '%s' is too long", lookaside); + isc_buffer_putstr(&nameb, "."); + } + } result = dns_rdata_totext(&ds, (dns_name_t *) NULL, &textb); if (result != ISC_R_SUCCESS) - fatal("can't print DS rdata"); + fatal("can't print rdata"); result = dns_rdataclass_totext(rdclass, &classb); if (result != ISC_R_SUCCESS) - fatal("can't print DS class"); + fatal("can't print class"); - result = dns_name_print(name, stdout); - if (result != ISC_R_SUCCESS) - fatal("can't print DS name"); + isc_buffer_usedregion(&nameb, &r); + isc_util_fwrite(r.base, 1, r.length, stdout); putchar(' '); isc_buffer_usedregion(&classb, &r); isc_util_fwrite(r.base, 1, r.length, stdout); - printf(" DS "); + if (lookaside == NULL) + printf(" DS "); + else + printf(" DLV "); isc_buffer_usedregion(&textb, &r); isc_util_fwrite(r.base, 1, r.length, stdout); putchar('\n'); } +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + static void usage(void) { fprintf(stderr, "Usage:\n"); - fprintf(stderr, " %s options keyfile\n\n", program); - fprintf(stderr, " %s options [-c class] [-d dir] -s dnsname\n\n", + fprintf(stderr, " %s options [-K dir] keyfile\n\n", program); + fprintf(stderr, " %s options [-K dir] [-c class] -s dnsname\n\n", program); + fprintf(stderr, " %s options -f zonefile (as zone name)\n\n", program); + fprintf(stderr, " %s options -f zonefile zonename\n\n", program); fprintf(stderr, "Version: %s\n", VERSION); fprintf(stderr, "Options:\n"); fprintf(stderr, " -v \n"); + fprintf(stderr, " -K : directory in which to find " + "key file or keyset file\n"); + fprintf(stderr, " -a algorithm: digest algorithm " + "(SHA-1, SHA-256 or GOST)\n"); fprintf(stderr, " -1: use SHA-1\n"); fprintf(stderr, " -2: use SHA-256\n"); - fprintf(stderr, " -a algorithm: use algorithm\n"); - fprintf(stderr, "Keyset options:\n"); - fprintf(stderr, " -s: keyset mode\n"); - fprintf(stderr, " -c class\n"); - fprintf(stderr, " -d directory\n"); - fprintf(stderr, "Output: DS RRs\n"); + fprintf(stderr, " -l: add lookaside zone and print DLV records\n"); + fprintf(stderr, " -s: read keyset from keyset- file\n"); + fprintf(stderr, " -c class: rdata class for DS set (default: IN)\n"); + fprintf(stderr, " -f file: read keyset from zone file\n"); + fprintf(stderr, " -A: when used with -f, " + "include all keys in DS set, not just KSKs\n"); + fprintf(stderr, "Output: DS or DLV RRs\n"); exit (-1); } int main(int argc, char **argv) { - char *algname = NULL, *classname = NULL, *dirname = NULL; - char *endp; - int ch; - unsigned int dtype = DNS_DSDIGEST_SHA1; - isc_boolean_t both = ISC_TRUE; - isc_boolean_t usekeyset = ISC_FALSE; - isc_result_t result; - isc_log_t *log = NULL; - isc_entropy_t *ectx = NULL; - dns_rdata_t rdata; + char *algname = NULL, *classname = NULL; + char *filename = NULL, *dir = NULL, *namestr; + char *lookaside = NULL; + char *endp; + int ch; + unsigned int dtype = DNS_DSDIGEST_SHA1; + isc_boolean_t both = ISC_TRUE; + isc_boolean_t usekeyset = ISC_FALSE; + isc_boolean_t showall = ISC_FALSE; + isc_result_t result; + isc_log_t *log = NULL; + isc_entropy_t *ectx = NULL; + dns_rdataset_t rdataset; + dns_rdata_t rdata; dns_rdata_init(&rdata); @@ -275,7 +344,7 @@ main(int argc, char **argv) { isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, - "12a:c:d:sv:h")) != -1) { + "12Aa:c:d:Ff:K:l:sv:h")) != -1) { switch (ch) { case '1': dtype = DNS_DSDIGEST_SHA1; @@ -285,6 +354,9 @@ main(int argc, char **argv) { dtype = DNS_DSDIGEST_SHA256; both = ISC_FALSE; break; + case 'A': + showall = ISC_TRUE; + break; case 'a': algname = isc_commandline_argument; both = ISC_FALSE; @@ -293,7 +365,21 @@ main(int argc, char **argv) { classname = isc_commandline_argument; break; case 'd': - dirname = isc_commandline_argument; + fprintf(stderr, "%s: the -d option is deprecated; " + "use -K\n", program); + /* fall through */ + case 'K': + dir = isc_commandline_argument; + if (strlen(dir) == 0U) + fatal("directory must be non-empty string"); + break; + case 'f': + filename = isc_commandline_argument; + break; + case 'l': + lookaside = isc_commandline_argument; + if (strlen(lookaside) == 0U) + fatal("lookaside must be a non-empty string"); break; case 's': usekeyset = ISC_TRUE; @@ -303,11 +389,14 @@ main(int argc, char **argv) { if (*endp != '\0') fatal("-v must be followed by a number"); break; + case 'F': + /* Reserved for FIPS mode */ + /* FALLTHROUGH */ case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); - /* Falls into */ + /* FALLTHROUGH */ case 'h': usage(); @@ -325,13 +414,24 @@ main(int argc, char **argv) { else if (strcasecmp(algname, "SHA256") == 0 || strcasecmp(algname, "SHA-256") == 0) dtype = DNS_DSDIGEST_SHA256; +#ifdef HAVE_OPENSSL_GOST + else if (strcasecmp(algname, "GOST") == 0) + dtype = DNS_DSDIGEST_GOST; +#endif else fatal("unknown algorithm %s", algname); } rdclass = strtoclass(classname); - if (argc < isc_commandline_index + 1) + if (usekeyset && filename != NULL) + fatal("cannot use both -s and -f"); + + /* When not using -f, -A is implicit */ + if (filename == NULL) + showall = ISC_TRUE; + + if (argc < isc_commandline_index + 1 && filename == NULL) fatal("the key file name was not specified"); if (argc > isc_commandline_index + 1) fatal("extraneous arguments"); @@ -344,28 +444,50 @@ main(int argc, char **argv) { result = dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); if (result != ISC_R_SUCCESS) - fatal("could not initialize dst"); + fatal("could not initialize dst: %s", + isc_result_totext(result)); isc_entropy_stopcallbacksources(ectx); setup_logging(verbose, mctx, &log); - if (usekeyset) { - loadkeys(dirname, argv[isc_commandline_index]); + dns_rdataset_init(&rdataset); + + if (usekeyset || filename != NULL) { + if (argc < isc_commandline_index + 1 && filename != NULL) { + /* using zone name as the zone file name */ + namestr = filename; + } else + namestr = argv[isc_commandline_index]; - for (result = dns_rdataset_first(&keyset); + result = initname(namestr); + if (result != ISC_R_SUCCESS) + fatal("could not initialize name %s", namestr); + + if (usekeyset) + result = loadkeyset(dir, &rdataset); + else + result = loadsetfromfile(filename, &rdataset); + + if (result != ISC_R_SUCCESS) + fatal("could not load DNSKEY set: %s\n", + isc_result_totext(result)); + + for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; - result = dns_rdataset_next(&keyset)) { + result = dns_rdataset_next(&rdataset)) { dns_rdata_init(&rdata); - dns_rdataset_current(&keyset, &rdata); + dns_rdataset_current(&rdataset, &rdata); if (verbose > 2) logkey(&rdata); if (both) { - emitds(DNS_DSDIGEST_SHA1, &rdata); - emitds(DNS_DSDIGEST_SHA256, &rdata); + emit(DNS_DSDIGEST_SHA1, showall, lookaside, + &rdata); + emit(DNS_DSDIGEST_SHA256, showall, lookaside, + &rdata); } else - emitds(dtype, &rdata); + emit(dtype, showall, lookaside, &rdata); } } else { unsigned char key_buf[DST_KEY_MAXSIZE]; @@ -374,18 +496,14 @@ main(int argc, char **argv) { DST_KEY_MAXSIZE, &rdata); if (both) { - emitds(DNS_DSDIGEST_SHA1, &rdata); - emitds(DNS_DSDIGEST_SHA256, &rdata); + emit(DNS_DSDIGEST_SHA1, showall, lookaside, &rdata); + emit(DNS_DSDIGEST_SHA256, showall, lookaside, &rdata); } else - emitds(dtype, &rdata); + emit(dtype, showall, lookaside, &rdata); } - if (dns_rdataset_isassociated(&keyset)) - dns_rdataset_disassociate(&keyset); - if (node != NULL) - dns_db_detachnode(db, &node); - if (db != NULL) - dns_db_detach(&db); + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); cleanup_logging(&log); dst_lib_destroy(); isc_hash_destroy(); diff --git a/bin/dnssec/dnssec-dsfromkey.docbook b/bin/dnssec/dnssec-dsfromkey.docbook index c4ea38d..36410d5 100644 --- a/bin/dnssec/dnssec-dsfromkey.docbook +++ b/bin/dnssec/dnssec-dsfromkey.docbook @@ -2,7 +2,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" []> - + - November 29, 2008 + August 26, 2009 @@ -37,6 +37,8 @@ 2008 + 2009 + 2010 Internet Systems Consortium, Inc. ("ISC") @@ -48,17 +50,22 @@ + keyfile dnssec-dsfromkey -s - + + + - + + + dnsname @@ -99,17 +106,55 @@ Select the digest algorithm. The value of - must be one of SHA-1 (SHA1) or - SHA-256 (SHA256). These values are case insensitive. + must be one of SHA-1 (SHA1), + SHA-256 (SHA256) or GOST. These values are case insensitive. - -v level + -K directory - Sets the debugging level. + Look for key files (or, in keyset mode, + keyset- files) in + . + + + + + + -f file + + + Zone file mode: in place of the keyfile name, the argument is + the DNS domain name of a zone master file, which can be read + from . If the zone name is the same as + , then it may be omitted. + + + + + + -A + + + Include ZSK's when generating DS records. Without this option, + only keys which have the KSK flag set will be converted to DS + records and printed. Useful only in zone file mode. + + + + + + -l domain + + + Generate a DLV set instead of a DS set. The specified + is appended to the name for each + record in the set. + The DNSSEC Lookaside Validation (DLV) RR is described + in RFC 4431. @@ -119,8 +164,7 @@ Keyset mode: in place of the keyfile name, the argument is - the DNS domain name of a keyset file. Following options make sense - only in this mode. + the DNS domain name of a keyset file. @@ -129,23 +173,20 @@ -c class - Specifies the DNS class (default is IN), useful only - in the keyset mode. + Specifies the DNS class (default is IN). Useful only + in keyset or zone file mode. - -d directory + -v level - Look for keyset files in - as the directory, ignored when - not in the keyset mode. + Sets the debugging level. - @@ -197,6 +238,7 @@ , BIND 9 Administrator Reference Manual, RFC 3658, + RFC 4431. RFC 4509. diff --git a/bin/dnssec/dnssec-dsfromkey.html b/bin/dnssec/dnssec-dsfromkey.html index 6186481..54cc1ab 100644 --- a/bin/dnssec/dnssec-dsfromkey.html +++ b/bin/dnssec/dnssec-dsfromkey.html @@ -1,5 +1,5 @@ - + @@ -28,18 +28,18 @@

Synopsis

-

dnssec-dsfromkey [-v level] [-1] [-2] [-a alg] {keyfile}

-

dnssec-dsfromkey {-s} [-v level] [-1] [-2] [-a alg] [-c class] [-d dir] {dnsname}

+

dnssec-dsfromkey [-v level] [-1] [-2] [-a alg] [-l domain] {keyfile}

+

dnssec-dsfromkey {-s} [-1] [-2] [-a alg] [-K directory] [-l domain] [-s] [-c class] [-f file] [-A] [-v level] {dnsname}

-

DESCRIPTION

+

DESCRIPTION

dnssec-dsfromkey outputs the Delegation Signer (DS) resource record (RR), as defined in RFC 3658 and RFC 4509, for the given key(s).

-

OPTIONS

+

OPTIONS

-1

@@ -53,34 +53,54 @@

-a algorithm

Select the digest algorithm. The value of - algorithm must be one of SHA-1 (SHA1) or - SHA-256 (SHA256). These values are case insensitive. + algorithm must be one of SHA-1 (SHA1), + SHA-256 (SHA256) or GOST. These values are case insensitive.

-
-v level
+
-K directory

- Sets the debugging level. + Look for key files (or, in keyset mode, + keyset- files) in + directory. +

+
-f file
+

+ Zone file mode: in place of the keyfile name, the argument is + the DNS domain name of a zone master file, which can be read + from file. If the zone name is the same as + file, then it may be omitted. +

+
-A
+

+ Include ZSK's when generating DS records. Without this option, + only keys which have the KSK flag set will be converted to DS + records and printed. Useful only in zone file mode. +

+
-l domain
+

+ Generate a DLV set instead of a DS set. The specified + domain is appended to the name for each + record in the set. + The DNSSEC Lookaside Validation (DLV) RR is described + in RFC 4431.

-s

Keyset mode: in place of the keyfile name, the argument is - the DNS domain name of a keyset file. Following options make sense - only in this mode. + the DNS domain name of a keyset file.

-c class

- Specifies the DNS class (default is IN), useful only - in the keyset mode. + Specifies the DNS class (default is IN). Useful only + in keyset or zone file mode.

-
-d directory
+
-v level

- Look for keyset files in - directory as the directory, ignored when - not in the keyset mode. + Sets the debugging level.

-

EXAMPLE

+

EXAMPLE

To build the SHA-256 DS RR from the Kexample.com.+003+26160 @@ -95,7 +115,7 @@

-

FILES

+

FILES

The keyfile can be designed by the key identification Knnnn.+aaa+iiiii or the full file name @@ -109,22 +129,23 @@

-

CAVEAT

+

CAVEAT

A keyfile error can give a "file not found" even if the file exists.

-

SEE ALSO

+

SEE ALSO

dnssec-keygen(8), dnssec-signzone(8), BIND 9 Administrator Reference Manual, RFC 3658, + RFC 4431. RFC 4509.

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

diff --git a/bin/dnssec/dnssec-keyfromlabel.8 b/bin/dnssec/dnssec-keyfromlabel.8 index 45fc087..d8c19f2 100644 --- a/bin/dnssec/dnssec-keyfromlabel.8 +++ b/bin/dnssec/dnssec-keyfromlabel.8 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2008, 2010 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2008-2011 Internet Systems Consortium, Inc. ("ISC") .\" .\" Permission to use, copy, modify, and/or distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above @@ -12,7 +12,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: dnssec-keyfromlabel.8,v 1.6.14.3 2010-01-16 01:55:32 tbox Exp $ +.\" $Id: dnssec-keyfromlabel.8,v 1.18.14.1.2.1 2011-06-09 03:41:05 tbox Exp $ .\" .hy 0 .ad l @@ -32,18 +32,22 @@ dnssec\-keyfromlabel \- DNSSEC key generation tool .SH "SYNOPSIS" .HP 20 -\fBdnssec\-keyfromlabel\fR {\-a\ \fIalgorithm\fR} {\-l\ \fIlabel\fR} [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-f\ \fR\fB\fIflag\fR\fR] [\fB\-k\fR] [\fB\-n\ \fR\fB\fInametype\fR\fR] [\fB\-p\ \fR\fB\fIprotocol\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] {name} +\fBdnssec\-keyfromlabel\fR {\-l\ \fIlabel\fR} [\fB\-3\fR] [\fB\-a\ \fR\fB\fIalgorithm\fR\fR] [\fB\-A\ \fR\fB\fIdate/offset\fR\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-D\ \fR\fB\fIdate/offset\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-f\ \fR\fB\fIflag\fR\fR] [\fB\-G\fR] [\fB\-I\ \fR\fB\fIdate/offset\fR\fR] [\fB\-k\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-n\ \fR\fB\fInametype\fR\fR] [\fB\-P\ \fR\fB\fIdate/offset\fR\fR] [\fB\-p\ \fR\fB\fIprotocol\fR\fR] [\fB\-R\ \fR\fB\fIdate/offset\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-y\fR] {name} .SH "DESCRIPTION" .PP \fBdnssec\-keyfromlabel\fR gets keys with the given label from a crypto hardware and builds key files for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034. +.PP +The +\fBname\fR +of the key is specified on the command line. This must match the name of the zone for which the key is being generated. .SH "OPTIONS" .PP \-a \fIalgorithm\fR .RS 4 Selects the cryptographic algorithm. The value of \fBalgorithm\fR -must be one of RSAMD5, RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512 or DH (Diffie Hellman). These values are case insensitive. +must be one of RSAMD5, RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512 or ECCGOST. These values are case insensitive. .sp If no algorithm is specified, then RSASHA1 will be used by default, unless the \fB\-3\fR @@ -56,9 +60,19 @@ Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement algorithm, and DSA Note 2: DH automatically sets the \-k flag. .RE .PP +\-3 +.RS 4 +Use an NSEC3\-capable algorithm to generate a DNSSEC key. If this option is used and no algorithm is explicitly set on the command line, NSEC3RSASHA1 will be used by default. +.RE +.PP +\-E \fIengine\fR +.RS 4 +Specifies the name of the crypto hardware (OpenSSL engine). When compiled with PKCS#11 support it defaults to "pkcs11". +.RE +.PP \-l \fIlabel\fR .RS 4 -Specifies the label of keys in the crypto hardware (PKCS#11 device). +Specifies the label of the key pair in the crypto hardware. The label may be preceded by an optional OpenSSL engine name, separated by a colon, as in "pkcs11:keylabel". .RE .PP \-n \fInametype\fR @@ -68,6 +82,15 @@ Specifies the owner type of the key. The value of must either be ZONE (for a DNSSEC zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with a host (KEY)), USER (for a key associated with a user(KEY)) or OTHER (DNSKEY). These values are case insensitive. .RE .PP +\-C +.RS 4 +Compatibility mode: generates an old\-style key, without any metadata. By default, +\fBdnssec\-keyfromlabel\fR +will include the key's creation date in the metadata stored with the private key, and other dates may be set there as well (publication date, activation date, etc). Keys that include this data may be incompatible with older versions of BIND; the +\fB\-C\fR +option suppresses them. +.RE +.PP \-c \fIclass\fR .RS 4 Indicates that the DNS record containing the key should have the specified class. If not specified, class IN is used. @@ -75,13 +98,23 @@ Indicates that the DNS record containing the key should have the specified class .PP \-f \fIflag\fR .RS 4 -Set the specified flag in the flag field of the KEY/DNSKEY record. The only recognized flag is KSK (Key Signing Key) DNSKEY. +Set the specified flag in the flag field of the KEY/DNSKEY record. The only recognized flags are KSK (Key Signing Key) and REVOKE. +.RE +.PP +\-G +.RS 4 +Generate a key, but do not publish it or sign with it. This option is incompatible with \-P and \-A. .RE .PP \-h .RS 4 Prints a short summary of the options and arguments to -\fBdnssec\-keygen\fR. +\fBdnssec\-keyfromlabel\fR. +.RE +.PP +\-K \fIdirectory\fR +.RS 4 +Sets the directory in which the key files are to be written. .RE .PP \-k @@ -91,7 +124,7 @@ Generate KEY records rather than DNSKEY records. .PP \-p \fIprotocol\fR .RS 4 -Sets the protocol value for the generated key. The protocol is a number between 0 and 255. The default is 3 (DNSSEC). Other possible values for this argument are listed in RFC 2535 and its successors. +Sets the protocol value for the key. The protocol is a number between 0 and 255. The default is 3 (DNSSEC). Other possible values for this argument are listed in RFC 2535 and its successors. .RE .PP \-t \fItype\fR @@ -105,6 +138,39 @@ must be one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default is AUTHCONF. .RS 4 Sets the debugging level. .RE +.PP +\-y +.RS 4 +Allows DNSSEC key files to be generated even if the key ID would collide with that of an existing key, in the event of either key being revoked. (This is only safe to use if you are sure you won't be using RFC 5011 trust anchor maintenance with either of the keys involved.) +.RE +.SH "TIMING OPTIONS" +.PP +Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the argument begins with a '+' or '\-', it is interpreted as an offset from the present time. For convenience, if such an offset is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the offset is computed in years (defined as 365 24\-hour days, ignoring leap years), months (defined as 30 24\-hour days), weeks, days, hours, or minutes, respectively. Without a suffix, the offset is computed in seconds. +.PP +\-P \fIdate/offset\fR +.RS 4 +Sets the date on which a key is to be published to the zone. After that date, the key will be included in the zone but will not be used to sign it. If not set, and if the \-G option has not been used, the default is "now". +.RE +.PP +\-A \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be activated. After that date, the key will be included in the zone and used to sign it. If not set, and if the \-G option has not been used, the default is "now". +.RE +.PP +\-R \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be revoked. After that date, the key will be flagged as revoked. It will be included in the zone and will be used to sign it. +.RE +.PP +\-I \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be retired. After that date, the key will still be included in the zone, but it will not be used to sign it. +.RE +.PP +\-D \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be deleted. After that date, the key will no longer be included in the zone. (It may remain in the key repository, however.) +.RE .SH "GENERATED KEY FILES" .PP When @@ -138,7 +204,7 @@ file contains a DNS KEY record that can be inserted into a zone file (directly o .PP The \fI.private\fR -file contains algorithm specific fields. For obvious security reasons, this file does not have general read permission. +file contains algorithm\-specific fields. For obvious security reasons, this file does not have general read permission. .SH "SEE ALSO" .PP \fBdnssec\-keygen\fR(8), @@ -149,5 +215,5 @@ RFC 4034. .PP Internet Systems Consortium .SH "COPYRIGHT" -Copyright \(co 2008, 2010 Internet Systems Consortium, Inc. ("ISC") +Copyright \(co 2008\-2011 Internet Systems Consortium, Inc. ("ISC") .br diff --git a/bin/dnssec/dnssec-keyfromlabel.c b/bin/dnssec/dnssec-keyfromlabel.c index 8e9a53b..323f918 100644 --- a/bin/dnssec/dnssec-keyfromlabel.c +++ b/bin/dnssec/dnssec-keyfromlabel.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2007-2010 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,12 +14,13 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-keyfromlabel.c,v 1.4.50.2 2010-01-15 23:47:31 tbox Exp $ */ +/* $Id: dnssec-keyfromlabel.c,v 1.32 2010-12-23 04:07:59 marka Exp $ */ /*! \file */ #include +#include #include #include @@ -27,9 +28,11 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -47,35 +50,60 @@ const char *program = "dnssec-keyfromlabel"; int verbose; +#define DEFAULT_ALGORITHM "RSASHA1" +#define DEFAULT_NSEC3_ALGORITHM "NSEC3RSASHA1" + static const char *algs = "RSA | RSAMD5 | DH | DSA | RSASHA1 |" " NSEC3DSA | NSEC3RSASHA1 |" - " RSASHA256 | RSASHA512"; + " RSASHA256 | RSASHA512 | ECCGOST"; + +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; static void usage(void) { fprintf(stderr, "Usage:\n"); - fprintf(stderr, " %s -a alg -l label [options] name\n\n", + fprintf(stderr, " %s -l label [options] name\n\n", program); fprintf(stderr, "Version: %s\n", VERSION); fprintf(stderr, "Required options:\n"); - fprintf(stderr, " -a algorithm: %s\n", algs); - fprintf(stderr, " -l label: label of the key\n"); + fprintf(stderr, " -l label: label of the key pair\n"); fprintf(stderr, " name: owner of the key\n"); fprintf(stderr, "Other options:\n"); + fprintf(stderr, " -a algorithm: %s\n", algs); + fprintf(stderr, " (default: RSASHA1, or " + "NSEC3RSASHA1 if using -3)\n"); + fprintf(stderr, " -3: use NSEC3-capable algorithm\n"); + fprintf(stderr, " -c class (default: IN)\n"); +#ifdef USE_PKCS11 + fprintf(stderr, " -E enginename (default: pkcs11)\n"); +#else + fprintf(stderr, " -E enginename\n"); +#endif + fprintf(stderr, " -f keyflag: KSK | REVOKE\n"); + fprintf(stderr, " -K directory: directory in which to place " + "key files\n"); + fprintf(stderr, " -k: generate a TYPE=KEY key\n"); fprintf(stderr, " -n nametype: ZONE | HOST | ENTITY | USER | OTHER\n"); fprintf(stderr, " (DNSKEY generation defaults to ZONE\n"); - fprintf(stderr, " -c (default: IN)\n"); - fprintf(stderr, " -f keyflag: KSK\n"); - fprintf(stderr, " -t : " + fprintf(stderr, " -p protocol: default: 3 [dnssec]\n"); + fprintf(stderr, " -t type: " "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF " "(default: AUTHCONF)\n"); - fprintf(stderr, " -p : " - "default: 3 [dnssec]\n"); - fprintf(stderr, " -v \n"); - fprintf(stderr, " -k : generate a TYPE=KEY key\n"); + fprintf(stderr, " -y: permit keys that might collide\n"); + fprintf(stderr, " -v verbose level\n"); + fprintf(stderr, "Date options:\n"); + fprintf(stderr, " -P date/[+-]offset: set key publication date\n"); + fprintf(stderr, " -A date/[+-]offset: set key activation date\n"); + fprintf(stderr, " -R date/[+-]offset: set key revocation date\n"); + fprintf(stderr, " -I date/[+-]offset: set key inactivation date\n"); + fprintf(stderr, " -D date/[+-]offset: set key deletion date\n"); + fprintf(stderr, " -G: generate key only; do not set -P or -A\n"); + fprintf(stderr, " -C: generate a backward-compatible key, omitting" + " all dates\n"); fprintf(stderr, "Output:\n"); fprintf(stderr, " K++.key, " - "K++.private\n"); + "K++.private\n"); exit (-1); } @@ -83,14 +111,20 @@ usage(void) { int main(int argc, char **argv) { char *algname = NULL, *nametype = NULL, *type = NULL; + const char *directory = NULL; +#ifdef USE_PKCS11 + const char *engine = "pkcs11"; +#else + const char *engine = NULL; +#endif char *classname = NULL; char *endp; - dst_key_t *key = NULL, *oldkey; + dst_key_t *key = NULL; dns_fixedname_t fname; dns_name_t *name; - isc_uint16_t flags = 0, ksk = 0; + isc_uint16_t flags = 0, kskflag = 0, revflag = 0; dns_secalg_t alg; - isc_boolean_t null_key = ISC_FALSE; + isc_boolean_t oldstyle = ISC_FALSE; isc_mem_t *mctx = NULL; int ch; int protocol = -1, signatory = 0; @@ -103,6 +137,20 @@ main(int argc, char **argv) { dns_rdataclass_t rdclass; int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC; char *label = NULL; + isc_stdtime_t publish = 0, activate = 0, revoke = 0; + isc_stdtime_t inactive = 0, delete = 0; + isc_stdtime_t now; + isc_boolean_t setpub = ISC_FALSE, setact = ISC_FALSE; + isc_boolean_t setrev = ISC_FALSE, setinact = ISC_FALSE; + isc_boolean_t setdel = ISC_FALSE; + isc_boolean_t unsetpub = ISC_FALSE, unsetact = ISC_FALSE; + isc_boolean_t unsetrev = ISC_FALSE, unsetinact = ISC_FALSE; + isc_boolean_t unsetdel = ISC_FALSE; + isc_boolean_t genonly = ISC_FALSE; + isc_boolean_t use_nsec3 = ISC_FALSE; + isc_boolean_t avoid_collisions = ISC_TRUE; + isc_boolean_t exact; + unsigned char c; if (argc == 1) usage(); @@ -113,28 +161,49 @@ main(int argc, char **argv) { isc_commandline_errprint = ISC_FALSE; + isc_stdtime_get(&now); + while ((ch = isc_commandline_parse(argc, argv, - "a:c:f:kl:n:p:t:v:h")) != -1) + "3a:Cc:E:f:K:kl:n:p:t:v:yFhGP:A:R:I:D:")) != -1) { switch (ch) { + case '3': + use_nsec3 = ISC_TRUE; + break; case 'a': algname = isc_commandline_argument; break; + case 'C': + oldstyle = ISC_TRUE; + break; case 'c': classname = isc_commandline_argument; break; + case 'E': + engine = isc_commandline_argument; + break; case 'f': - if (strcasecmp(isc_commandline_argument, "KSK") == 0) - ksk = DNS_KEYFLAG_KSK; + c = (unsigned char)(isc_commandline_argument[0]); + if (toupper(c) == 'K') + kskflag = DNS_KEYFLAG_KSK; + else if (toupper(c) == 'R') + revflag = DNS_KEYFLAG_REVOKE; else fatal("unknown flag '%s'", isc_commandline_argument); break; + case 'K': + directory = isc_commandline_argument; + ret = try_dir(directory); + if (ret != ISC_R_SUCCESS) + fatal("cannot open directory %s: %s", + directory, isc_result_totext(ret)); + break; case 'k': options |= DST_TYPE_KEY; break; case 'l': - label = isc_commandline_argument; + label = isc_mem_strdup(mctx, isc_commandline_argument); break; case 'n': nametype = isc_commandline_argument; @@ -153,11 +222,80 @@ main(int argc, char **argv) { if (*endp != '\0') fatal("-v must be followed by a number"); break; - + case 'y': + avoid_collisions = ISC_FALSE; + break; + case 'G': + genonly = ISC_TRUE; + break; + case 'P': + if (setpub || unsetpub) + fatal("-P specified more than once"); + + if (strcasecmp(isc_commandline_argument, "none")) { + setpub = ISC_TRUE; + publish = strtotime(isc_commandline_argument, + now, now); + } else { + unsetpub = ISC_TRUE; + } + break; + case 'A': + if (setact || unsetact) + fatal("-A specified more than once"); + + if (strcasecmp(isc_commandline_argument, "none")) { + setact = ISC_TRUE; + activate = strtotime(isc_commandline_argument, + now, now); + } else { + unsetact = ISC_TRUE; + } + break; + case 'R': + if (setrev || unsetrev) + fatal("-R specified more than once"); + + if (strcasecmp(isc_commandline_argument, "none")) { + setrev = ISC_TRUE; + revoke = strtotime(isc_commandline_argument, + now, now); + } else { + unsetrev = ISC_TRUE; + } + break; + case 'I': + if (setinact || unsetinact) + fatal("-I specified more than once"); + + if (strcasecmp(isc_commandline_argument, "none")) { + setinact = ISC_TRUE; + inactive = strtotime(isc_commandline_argument, + now, now); + } else { + unsetinact = ISC_TRUE; + } + break; + case 'D': + if (setdel || unsetdel) + fatal("-D specified more than once"); + + if (strcasecmp(isc_commandline_argument, "none")) { + setdel = ISC_TRUE; + delete = strtotime(isc_commandline_argument, + now, now); + } else { + unsetdel = ISC_TRUE; + } + break; + case 'F': + /* Reserved for FIPS mode */ + /* FALLTHROUGH */ case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); + /* FALLTHROUGH */ case 'h': usage(); @@ -170,10 +308,11 @@ main(int argc, char **argv) { if (ectx == NULL) setup_entropy(mctx, NULL, &ectx); - ret = dst_lib_init(mctx, ectx, - ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); + ret = dst_lib_init2(mctx, ectx, engine, + ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); if (ret != ISC_R_SUCCESS) - fatal("could not initialize dst"); + fatal("could not initialize dst: %s", + isc_result_totext(ret)); setup_logging(verbose, mctx, &log); @@ -184,8 +323,30 @@ main(int argc, char **argv) { if (argc > isc_commandline_index + 1) fatal("extraneous arguments"); - if (algname == NULL) - fatal("no algorithm was specified"); + if (strchr(label, ':') == NULL && + engine != NULL && strlen(engine) != 0U) { + char *l; + int len; + + len = strlen(label) + strlen(engine) + 2; + l = isc_mem_allocate(mctx, len); + if (l == NULL) + fatal("cannot allocate memory"); + snprintf(l, len, "%s:%s", engine, label); + isc_mem_free(mctx, label); + label = l; + } + + if (algname == NULL) { + if (use_nsec3) + algname = strdup(DEFAULT_NSEC3_ALGORITHM); + else + algname = strdup(DEFAULT_ALGORITHM); + if (verbose > 0) + fprintf(stderr, "no algorithm specified; " + "defaulting to %s\n", algname); + } + if (strcasecmp(algname, "RSA") == 0) { fprintf(stderr, "The use of RSA (RSAMD5) is not recommended.\n" "If you still wish to use RSA (RSAMD5) please " @@ -201,6 +362,14 @@ main(int argc, char **argv) { options |= DST_TYPE_KEY; } + if (use_nsec3 && + alg != DST_ALG_NSEC3DSA && alg != DST_ALG_NSEC3RSASHA1 && + alg != DST_ALG_RSASHA256 && alg != DST_ALG_RSASHA512 && + alg != DST_ALG_ECCGOST) { + fatal("%s is incompatible with NSEC3; " + "do not use the -3 option", algname); + } + if (type != NULL && (options & DST_TYPE_KEY) != 0) { if (strcasecmp(type, "NOAUTH") == 0) flags |= DNS_KEYTYPE_NOAUTH; @@ -234,10 +403,15 @@ main(int argc, char **argv) { rdclass = strtoclass(classname); + if (directory == NULL) + directory = "."; + if ((options & DST_TYPE_KEY) != 0) /* KEY */ flags |= signatory; - else if ((flags & DNS_KEYOWNER_ZONE) != 0) /* DNSKEY */ - flags |= ksk; + else if ((flags & DNS_KEYOWNER_ZONE) != 0) { /* DNSKEY */ + flags |= kskflag; + flags |= revflag; + } if (protocol == -1) protocol = DNS_KEYPROTO_DNSSEC; @@ -260,53 +434,108 @@ main(int argc, char **argv) { isc_buffer_init(&buf, argv[isc_commandline_index], strlen(argv[isc_commandline_index])); isc_buffer_add(&buf, strlen(argv[isc_commandline_index])); - ret = dns_name_fromtext(name, &buf, dns_rootname, ISC_FALSE, NULL); + ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); if (ret != ISC_R_SUCCESS) fatal("invalid key name %s: %s", argv[isc_commandline_index], isc_result_totext(ret)); - if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) - null_key = ISC_TRUE; - isc_buffer_init(&buf, filename, sizeof(filename) - 1); /* associate the key */ ret = dst_key_fromlabel(name, alg, flags, protocol, - rdclass, "", label, NULL, mctx, &key); + rdclass, engine, label, NULL, mctx, &key); isc_entropy_stopcallbacksources(ectx); if (ret != ISC_R_SUCCESS) { char namestr[DNS_NAME_FORMATSIZE]; - char algstr[ALG_FORMATSIZE]; + char algstr[DNS_SECALG_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); - alg_format(alg, algstr, sizeof(algstr)); - fatal("failed to generate key %s/%s: %s\n", + dns_secalg_format(alg, algstr, sizeof(algstr)); + fatal("failed to get key %s/%s: %s\n", namestr, algstr, isc_result_totext(ret)); + /* NOTREACHED */ exit(-1); } /* - * Try to read a key with the same name, alg and id from disk. - * If there is one we must continue generating a new one - * unless we were asked to generate a null key, in which - * case we return failure. + * Set key timing metadata (unless using -C) + * + * Publish and activation dates are set to "now" by default, but + * can be overridden. Creation date is always set to "now". */ - ret = dst_key_fromfile(name, dst_key_id(key), alg, - DST_TYPE_PRIVATE, NULL, mctx, &oldkey); - /* do not overwrite an existing key */ - if (ret == ISC_R_SUCCESS) { + if (!oldstyle) { + dst_key_settime(key, DST_TIME_CREATED, now); + + if (genonly && (setpub || setact)) + fatal("cannot use -G together with -P or -A options"); + + if (setpub) + dst_key_settime(key, DST_TIME_PUBLISH, publish); + else if (setact) + dst_key_settime(key, DST_TIME_PUBLISH, activate); + else if (!genonly && !unsetpub) + dst_key_settime(key, DST_TIME_PUBLISH, now); + + if (setact) + dst_key_settime(key, DST_TIME_ACTIVATE, activate); + else if (!genonly && !unsetact) + dst_key_settime(key, DST_TIME_ACTIVATE, now); + + if (setrev) { + if (kskflag == 0) + fprintf(stderr, "%s: warning: Key is " + "not flagged as a KSK, but -R " + "was used. Revoking a ZSK is " + "legal, but undefined.\n", + program); + dst_key_settime(key, DST_TIME_REVOKE, revoke); + } + + if (setinact) + dst_key_settime(key, DST_TIME_INACTIVE, inactive); + + if (setdel) + dst_key_settime(key, DST_TIME_DELETE, delete); + } else { + if (setpub || setact || setrev || setinact || + setdel || unsetpub || unsetact || + unsetrev || unsetinact || unsetdel || genonly) + fatal("cannot use -C together with " + "-P, -A, -R, -I, -D, or -G options"); + /* + * Compatibility mode: Private-key-format + * should be set to 1.2. + */ + dst_key_setprivateformat(key, 1, 2); + } + + /* + * Do not overwrite an existing key. Warn LOUDLY if there + * is a risk of ID collision due to this key or another key + * being revoked. + */ + if (key_collision(dst_key_id(key), name, directory, alg, mctx, &exact)) + { isc_buffer_clear(&buf); - ret = dst_key_buildfilename(key, 0, NULL, &buf); - fprintf(stderr, "%s: %s already exists\n", - program, filename); - dst_key_free(&key); - exit (1); + ret = dst_key_buildfilename(key, 0, directory, &buf); + if (exact) + fatal("%s: %s already exists\n", program, filename); + + if (avoid_collisions) + fatal("%s: %s could collide with another key upon " + "revokation\n", program, filename); + + fprintf(stderr, "%s: WARNING: Key %s could collide with " + "another key upon revokation. If you plan " + "to revoke keys, destroy this key and " + "generate a different one.\n", + program, filename); } - ret = dst_key_tofile(key, options, NULL); + ret = dst_key_tofile(key, options, directory); if (ret != ISC_R_SUCCESS) { - char keystr[KEY_FORMATSIZE]; - key_format(key, keystr, sizeof(keystr)); + char keystr[DST_KEY_FORMATSIZE]; + dst_key_format(key, keystr, sizeof(keystr)); fatal("failed to write key %s: %s\n", keystr, isc_result_totext(ret)); } @@ -322,6 +551,7 @@ main(int argc, char **argv) { dns_name_destroy(); if (verbose > 10) isc_mem_stats(mctx, stdout); + isc_mem_free(mctx, label); isc_mem_destroy(&mctx); return (0); diff --git a/bin/dnssec/dnssec-keyfromlabel.docbook b/bin/dnssec/dnssec-keyfromlabel.docbook index a2fff5a..be38a24 100644 --- a/bin/dnssec/dnssec-keyfromlabel.docbook +++ b/bin/dnssec/dnssec-keyfromlabel.docbook @@ -2,7 +2,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" []> - + February 8, 2008 @@ -37,7 +37,9 @@ 2008 + 2009 2010 + 2011 Internet Systems Consortium, Inc. ("ISC") @@ -45,15 +47,25 @@ dnssec-keyfromlabel - -a algorithm -l label + + + + + + + + + + + name @@ -65,6 +77,11 @@ key files for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034. + + The of the key is specified on the command + line. This must match the name of the zone for which the key is + being generated. + @@ -76,9 +93,8 @@ Selects the cryptographic algorithm. The value of - must be one of RSAMD5, - RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, - RSASHA512 or DH (Diffie Hellman). + must be one of RSAMD5, RSASHA1, + DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512 or ECCGOST. These values are case insensitive. @@ -99,11 +115,34 @@
+ -3 + + + Use an NSEC3-capable algorithm to generate a DNSSEC key. + If this option is used and no algorithm is explicitly + set on the command line, NSEC3RSASHA1 will be used by + default. + + + + + + -E engine + + + Specifies the name of the crypto hardware (OpenSSL engine). + When compiled with PKCS#11 support it defaults to "pkcs11". + + + + + -l label - Specifies the label of keys in the crypto hardware - (PKCS#11 device). + Specifies the label of the key pair in the crypto hardware. + The label may be preceded by an optional OpenSSL engine name, + separated by a colon, as in "pkcs11:keylabel". @@ -117,8 +156,22 @@ zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with a host (KEY)), USER (for a key associated with a user(KEY)) or OTHER (DNSKEY). - These values are - case insensitive. + These values are case insensitive. + + + + + + -C + + + Compatibility mode: generates an old-style key, without + any metadata. By default, dnssec-keyfromlabel + will include the key's creation date in the metadata stored + with the private key, and other dates may be set there as well + (publication date, activation date, etc). Keys that include + this data may be incompatible with older versions of BIND; the + option suppresses them. @@ -138,7 +191,17 @@ Set the specified flag in the flag field of the KEY/DNSKEY record. - The only recognized flag is KSK (Key Signing Key) DNSKEY. + The only recognized flags are KSK (Key Signing Key) and REVOKE. + + + + + + -G + + + Generate a key, but do not publish it or sign with it. This + option is incompatible with -P and -A. @@ -148,7 +211,16 @@ Prints a short summary of the options and arguments to - dnssec-keygen. + dnssec-keyfromlabel. + + + + + + -K directory + + + Sets the directory in which the key files are to be written. @@ -166,7 +238,7 @@ -p protocol - Sets the protocol value for the generated key. The protocol + Sets the protocol value for the key. The protocol is a number between 0 and 255. The default is 3 (DNSSEC). Other possible values for this argument are listed in RFC 2535 and its successors. @@ -195,6 +267,93 @@ + + -y + + + Allows DNSSEC key files to be generated even if the key ID + would collide with that of an existing key, in the event of + either key being revoked. (This is only safe to use if you + are sure you won't be using RFC 5011 trust anchor maintenance + with either of the keys involved.) + + + + + + + + + TIMING OPTIONS + + + Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. + If the argument begins with a '+' or '-', it is interpreted as + an offset from the present time. For convenience, if such an offset + is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', + then the offset is computed in years (defined as 365 24-hour days, + ignoring leap years), months (defined as 30 24-hour days), weeks, + days, hours, or minutes, respectively. Without a suffix, the offset + is computed in seconds. + + + + + -P date/offset + + + Sets the date on which a key is to be published to the zone. + After that date, the key will be included in the zone but will + not be used to sign it. If not set, and if the -G option has + not been used, the default is "now". + + + + + + -A date/offset + + + Sets the date on which the key is to be activated. After that + date, the key will be included in the zone and used to sign + it. If not set, and if the -G option has not been used, the + default is "now". + + + + + + -R date/offset + + + Sets the date on which the key is to be revoked. After that + date, the key will be flagged as revoked. It will be included + in the zone and will be used to sign it. + + + + + + -I date/offset + + + Sets the date on which the key is to be retired. After that + date, the key will still be included in the zone, but it + will not be used to sign it. + + + + + + -D date/offset + + + Sets the date on which the key is to be deleted. After that + date, the key will no longer be included in the zone. (It + may remain in the key repository, however.) + + + @@ -214,8 +373,7 @@ aaa is the numeric representation - of the - algorithm. + of the algorithm. @@ -229,8 +387,7 @@ on the printed string. Knnnn.+aaa+iiiii.key contains the public key, and Knnnn.+aaa+iiiii.private contains the - private - key. + private key. The .key file contains a DNS KEY record @@ -239,8 +396,8 @@ statement). - The .private file contains algorithm - specific + The .private file contains + algorithm-specific fields. For obvious security reasons, this file does not have general read permission. diff --git a/bin/dnssec/dnssec-keyfromlabel.html b/bin/dnssec/dnssec-keyfromlabel.html index ad2a562..2b1b236 100644 --- a/bin/dnssec/dnssec-keyfromlabel.html +++ b/bin/dnssec/dnssec-keyfromlabel.html @@ -1,5 +1,5 @@ - + @@ -28,26 +28,30 @@

Synopsis

-

dnssec-keyfromlabel {-a algorithm} {-l label} [-c class] [-f flag] [-k] [-n nametype] [-p protocol] [-t type] [-v level] {name}

+

dnssec-keyfromlabel {-l label} [-3] [-a algorithm] [-A date/offset] [-c class] [-D date/offset] [-E engine] [-f flag] [-G] [-I date/offset] [-k] [-K directory] [-n nametype] [-P date/offset] [-p protocol] [-R date/offset] [-t type] [-v level] [-y] {name}

-

DESCRIPTION

+

DESCRIPTION

dnssec-keyfromlabel gets keys with the given label from a crypto hardware and builds key files for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034.

+

+ The name of the key is specified on the command + line. This must match the name of the zone for which the key is + being generated. +

-

OPTIONS

+

OPTIONS

-a algorithm

Selects the cryptographic algorithm. The value of - algorithm must be one of RSAMD5, - RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, - RSASHA512 or DH (Diffie Hellman). + algorithm must be one of RSAMD5, RSASHA1, + DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512 or ECCGOST. These values are case insensitive.

@@ -65,10 +69,23 @@ Note 2: DH automatically sets the -k flag.

+
-3
+

+ Use an NSEC3-capable algorithm to generate a DNSSEC key. + If this option is used and no algorithm is explicitly + set on the command line, NSEC3RSASHA1 will be used by + default. +

+
-E engine
+

+ Specifies the name of the crypto hardware (OpenSSL engine). + When compiled with PKCS#11 support it defaults to "pkcs11". +

-l label

- Specifies the label of keys in the crypto hardware - (PKCS#11 device). + Specifies the label of the key pair in the crypto hardware. + The label may be preceded by an optional OpenSSL engine name, + separated by a colon, as in "pkcs11:keylabel".

-n nametype

@@ -77,8 +94,17 @@ zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with a host (KEY)), USER (for a key associated with a user(KEY)) or OTHER (DNSKEY). - These values are - case insensitive. + These values are case insensitive. +

+
-C
+

+ Compatibility mode: generates an old-style key, without + any metadata. By default, dnssec-keyfromlabel + will include the key's creation date in the metadata stored + with the private key, and other dates may be set there as well + (publication date, activation date, etc). Keys that include + this data may be incompatible with older versions of BIND; the + -C option suppresses them.

-c class

@@ -88,12 +114,21 @@

-f flag

Set the specified flag in the flag field of the KEY/DNSKEY record. - The only recognized flag is KSK (Key Signing Key) DNSKEY. + The only recognized flags are KSK (Key Signing Key) and REVOKE. +

+
-G
+

+ Generate a key, but do not publish it or sign with it. This + option is incompatible with -P and -A.

-h

Prints a short summary of the options and arguments to - dnssec-keygen. + dnssec-keyfromlabel. +

+
-K directory
+

+ Sets the directory in which the key files are to be written.

-k

@@ -101,7 +136,7 @@

-p protocol

- Sets the protocol value for the generated key. The protocol + Sets the protocol value for the key. The protocol is a number between 0 and 255. The default is 3 (DNSSEC). Other possible values for this argument are listed in RFC 2535 and its successors. @@ -117,10 +152,65 @@

Sets the debugging level.

+
-y
+

+ Allows DNSSEC key files to be generated even if the key ID + would collide with that of an existing key, in the event of + either key being revoked. (This is only safe to use if you + are sure you won't be using RFC 5011 trust anchor maintenance + with either of the keys involved.) +

+
+
+
+

TIMING OPTIONS

+

+ Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. + If the argument begins with a '+' or '-', it is interpreted as + an offset from the present time. For convenience, if such an offset + is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', + then the offset is computed in years (defined as 365 24-hour days, + ignoring leap years), months (defined as 30 24-hour days), weeks, + days, hours, or minutes, respectively. Without a suffix, the offset + is computed in seconds. +

+
+
-P date/offset
+

+ Sets the date on which a key is to be published to the zone. + After that date, the key will be included in the zone but will + not be used to sign it. If not set, and if the -G option has + not been used, the default is "now". +

+
-A date/offset
+

+ Sets the date on which the key is to be activated. After that + date, the key will be included in the zone and used to sign + it. If not set, and if the -G option has not been used, the + default is "now". +

+
-R date/offset
+

+ Sets the date on which the key is to be revoked. After that + date, the key will be flagged as revoked. It will be included + in the zone and will be used to sign it. +

+
-I date/offset
+

+ Sets the date on which the key is to be retired. After that + date, the key will still be included in the zone, but it + will not be used to sign it. +

+
-D date/offset
+

+ Sets the date on which the key is to be deleted. After that + date, the key will no longer be included in the zone. (It + may remain in the key repository, however.) +

-

GENERATED KEY FILES

+

GENERATED KEY FILES

When dnssec-keyfromlabel completes successfully, @@ -132,8 +222,7 @@

  • nnnn is the key name.

  • aaa is the numeric representation - of the - algorithm. + of the algorithm.

  • iiiii is the key identifier (or footprint). @@ -144,8 +233,7 @@ on the printed string. Knnnn.+aaa+iiiii.key contains the public key, and Knnnn.+aaa+iiiii.private contains the - private - key. + private key.

    The .key file contains a DNS KEY record @@ -154,14 +242,14 @@ statement).

    - The .private file contains algorithm - specific + The .private file contains + algorithm-specific fields. For obvious security reasons, this file does not have general read permission.

  • -

    SEE ALSO

    +

    SEE ALSO

    dnssec-keygen(8), dnssec-signzone(8), BIND 9 Administrator Reference Manual, @@ -169,7 +257,7 @@

    -

    AUTHOR

    +

    AUTHOR

    Internet Systems Consortium

    diff --git a/bin/dnssec/dnssec-keygen.8 b/bin/dnssec/dnssec-keygen.8 index c4be24e..ea4690e 100644 --- a/bin/dnssec/dnssec-keygen.8 +++ b/bin/dnssec/dnssec-keygen.8 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: dnssec-keygen.8,v 1.40.44.4 2010-01-16 01:55:32 tbox Exp $ +.\" $Id: dnssec-keygen.8,v 1.55 2010-12-24 01:14:19 tbox Exp $ .\" .hy 0 .ad l @@ -33,11 +33,11 @@ dnssec\-keygen \- DNSSEC key generation tool .SH "SYNOPSIS" .HP 14 -\fBdnssec\-keygen\fR {\-a\ \fIalgorithm\fR} {\-b\ \fIkeysize\fR} {\-n\ \fInametype\fR} [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-e\fR] [\fB\-f\ \fR\fB\fIflag\fR\fR] [\fB\-g\ \fR\fB\fIgenerator\fR\fR] [\fB\-h\fR] [\fB\-k\fR] [\fB\-p\ \fR\fB\fIprotocol\fR\fR] [\fB\-r\ \fR\fB\fIrandomdev\fR\fR] [\fB\-s\ \fR\fB\fIstrength\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] {name} +\fBdnssec\-keygen\fR [\fB\-a\ \fR\fB\fIalgorithm\fR\fR] [\fB\-b\ \fR\fB\fIkeysize\fR\fR] [\fB\-n\ \fR\fB\fInametype\fR\fR] [\fB\-3\fR] [\fB\-A\ \fR\fB\fIdate/offset\fR\fR] [\fB\-C\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-D\ \fR\fB\fIdate/offset\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-e\fR] [\fB\-f\ \fR\fB\fIflag\fR\fR] [\fB\-G\fR] [\fB\-g\ \fR\fB\fIgenerator\fR\fR] [\fB\-h\fR] [\fB\-I\ \fR\fB\fIdate/offset\fR\fR] [\fB\-i\ \fR\fB\fIinterval\fR\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-k\fR] [\fB\-P\ \fR\fB\fIdate/offset\fR\fR] [\fB\-p\ \fR\fB\fIprotocol\fR\fR] [\fB\-q\fR] [\fB\-R\ \fR\fB\fIdate/offset\fR\fR] [\fB\-r\ \fR\fB\fIrandomdev\fR\fR] [\fB\-S\ \fR\fB\fIkey\fR\fR] [\fB\-s\ \fR\fB\fIstrength\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-z\fR] {name} .SH "DESCRIPTION" .PP \fBdnssec\-keygen\fR -generates keys for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034. It can also generate keys for use with TSIG (Transaction Signatures), as defined in RFC 2845. +generates keys for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034. It can also generate keys for use with TSIG (Transaction Signatures) as defined in RFC 2845, or TKEY (Transaction Key) as defined in RFC 2930. .PP The \fBname\fR @@ -48,16 +48,28 @@ of the key is specified on the command line. For DNSSEC keys, this must match th .RS 4 Selects the cryptographic algorithm. For DNSSEC keys, the value of \fBalgorithm\fR -must be one of RSAMD5, RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256 or RSASHA512. For TSIG/TKEY, the value must be DH (Diffie Hellman), HMAC\-MD5, HMAC\-SHA1, HMAC\-SHA224, HMAC\-SHA256, HMAC\-SHA384, or HMAC\-SHA512. These values are case insensitive. +must be one of RSAMD5, RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512 or ECCGOST. For TSIG/TKEY, the value must be DH (Diffie Hellman), HMAC\-MD5, HMAC\-SHA1, HMAC\-SHA224, HMAC\-SHA256, HMAC\-SHA384, or HMAC\-SHA512. These values are case insensitive. +.sp +If no algorithm is specified, then RSASHA1 will be used by default, unless the +\fB\-3\fR +option is specified, in which case NSEC3RSASHA1 will be used instead. (If +\fB\-3\fR +is used and an algorithm is specified, that algorithm will be checked for compatibility with NSEC3.) .sp Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement algorithm, and DSA is recommended. For TSIG, HMAC\-MD5 is mandatory. .sp -Note 2: HMAC\-MD5 and DH automatically set the \-k flag. +Note 2: DH, HMAC\-MD5, and HMAC\-SHA1 through HMAC\-SHA512 automatically set the \-T KEY option. .RE .PP \-b \fIkeysize\fR .RS 4 Specifies the number of bits in the key. The choice of key size depends on the algorithm used. RSA keys must be between 512 and 2048 bits. Diffie Hellman keys must be between 128 and 4096 bits. DSA keys must be between 512 and 1024 bits and an exact multiple of 64. HMAC keys must be between 1 and 512 bits. +.sp +The key size does not need to be specified if using a default algorithm. The default key size is 1024 bits for zone signing keys (ZSK's) and 2048 bits for key signing keys (KSK's, generated with +\fB\-f KSK\fR). However, if an algorithm is explicitly specified with the +\fB\-a\fR, then there is no default key size, and the +\fB\-b\fR +must be used. .RE .PP \-n \fInametype\fR @@ -67,11 +79,30 @@ Specifies the owner type of the key. The value of must either be ZONE (for a DNSSEC zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with a host (KEY)), USER (for a key associated with a user(KEY)) or OTHER (DNSKEY). These values are case insensitive. Defaults to ZONE for DNSKEY generation. .RE .PP +\-3 +.RS 4 +Use an NSEC3\-capable algorithm to generate a DNSSEC key. If this option is used and no algorithm is explicitly set on the command line, NSEC3RSASHA1 will be used by default. Note that RSASHA256, RSASHA512 and ECCGOST algorithms are NSEC3\-capable. +.RE +.PP +\-C +.RS 4 +Compatibility mode: generates an old\-style key, without any metadata. By default, +\fBdnssec\-keygen\fR +will include the key's creation date in the metadata stored with the private key, and other dates may be set there as well (publication date, activation date, etc). Keys that include this data may be incompatible with older versions of BIND; the +\fB\-C\fR +option suppresses them. +.RE +.PP \-c \fIclass\fR .RS 4 Indicates that the DNS record containing the key should have the specified class. If not specified, class IN is used. .RE .PP +\-E \fIengine\fR +.RS 4 +Uses a crypto hardware (OpenSSL engine) for random number and, when supported, key generation. When compiled with PKCS#11 support it defaults to pkcs11; the empty name resets it to no engine. +.RE +.PP \-e .RS 4 If generating an RSAMD5/RSASHA1 key, use a large exponent. @@ -79,7 +110,12 @@ If generating an RSAMD5/RSASHA1 key, use a large exponent. .PP \-f \fIflag\fR .RS 4 -Set the specified flag in the flag field of the KEY/DNSKEY record. The only recognized flag is KSK (Key Signing Key) DNSKEY. +Set the specified flag in the flag field of the KEY/DNSKEY record. The only recognized flags are KSK (Key Signing Key) and REVOKE. +.RE +.PP +\-G +.RS 4 +Generate a key, but do not publish it or sign with it. This option is incompatible with \-P and \-A. .RE .PP \-g \fIgenerator\fR @@ -93,9 +129,14 @@ Prints a short summary of the options and arguments to \fBdnssec\-keygen\fR. .RE .PP +\-K \fIdirectory\fR +.RS 4 +Sets the directory in which the key files are to be written. +.RE +.PP \-k .RS 4 -Generate KEY records rather than DNSKEY records. +Deprecated in favor of \-T KEY. .RE .PP \-p \fIprotocol\fR @@ -103,6 +144,15 @@ Generate KEY records rather than DNSKEY records. Sets the protocol value for the generated key. The protocol is a number between 0 and 255. The default is 3 (DNSSEC). Other possible values for this argument are listed in RFC 2535 and its successors. .RE .PP +\-q +.RS 4 +Quiet mode: Suppresses unnecessary output, including progress indication. Without this option, when +\fBdnssec\-keygen\fR +is run interactively to generate an RSA or DSA key pair, it will print a string of symbols to +\fIstderr\fR +indicating the progress of the key generation. A '.' indicates that a random number has been found which passed an initial sieve test; '+' means a number has passed a single round of the Miller\-Rabin primality test; a space means that the number has passed all the tests and is a satisfactory key. +.RE +.PP \-r \fIrandomdev\fR .RS 4 Specifies the source of randomness. If the operating system does not provide a @@ -114,11 +164,24 @@ specifies the name of a character device or file containing random data to be us indicates that keyboard input should be used. .RE .PP +\-S \fIkey\fR +.RS 4 +Create a new key which is an explicit successor to an existing key. The name, algorithm, size, and type of the key will be set to match the existing key. The activation date of the new key will be set to the inactivation date of the existing one. The publication date will be set to the activation date minus the prepublication interval, which defaults to 30 days. +.RE +.PP \-s \fIstrength\fR .RS 4 Specifies the strength value of the key. The strength is a number between 0 and 15, and currently has no defined purpose in DNSSEC. .RE .PP +\-T \fIrrtype\fR +.RS 4 +Specifies the resource record type to use for the key. +\fBrrtype\fR +must be either DNSKEY or KEY. The default is DNSKEY when using a DNSSEC algorithm, but it can be overridden to KEY for use with SIG(0). +Using any TSIG algorithm (HMAC\-* or DH) forces this option to KEY. +.RE +.PP \-t \fItype\fR .RS 4 Indicates the use of the key. @@ -130,6 +193,43 @@ must be one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default is AUTHCONF. .RS 4 Sets the debugging level. .RE +.SH "TIMING OPTIONS" +.PP +Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the argument begins with a '+' or '\-', it is interpreted as an offset from the present time. For convenience, if such an offset is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the offset is computed in years (defined as 365 24\-hour days, ignoring leap years), months (defined as 30 24\-hour days), weeks, days, hours, or minutes, respectively. Without a suffix, the offset is computed in seconds. +.PP +\-P \fIdate/offset\fR +.RS 4 +Sets the date on which a key is to be published to the zone. After that date, the key will be included in the zone but will not be used to sign it. If not set, and if the \-G option has not been used, the default is "now". +.RE +.PP +\-A \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be activated. After that date, the key will be included in the zone and used to sign it. If not set, and if the \-G option has not been used, the default is "now". +.RE +.PP +\-R \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be revoked. After that date, the key will be flagged as revoked. It will be included in the zone and will be used to sign it. +.RE +.PP +\-I \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be retired. After that date, the key will still be included in the zone, but it will not be used to sign it. +.RE +.PP +\-D \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be deleted. After that date, the key will no longer be included in the zone. (It may remain in the key repository, however.) +.RE +.PP +\-i \fIinterval\fR +.RS 4 +Sets the prepublication interval for a key. If set, then the publication and activation dates must be separated by at least this much time. If the activation date is specified but the publication date isn't, then the publication date will default to this much time before the activation date; conversely, if the publication date is specified but activation date isn't, then activation will be set to this much time after publication. +.sp +If the key is being created as an explicit successor to another key, then the default prepublication interval is 30 days; otherwise it is zero. +.sp +As with date offsets, if the argument is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the interval is measured in years, months, weeks, days, hours, or minutes, respectively. Without a suffix, the interval is measured in seconds. +.RE .SH "GENERATED KEYS" .PP When diff --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c index 2184122..f369326 100644 --- a/bin/dnssec/dnssec-keygen.c +++ b/bin/dnssec/dnssec-keygen.c @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -29,13 +29,15 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-keygen.c,v 1.81.48.2 2010-01-15 23:47:31 tbox Exp $ */ +/* $Id: dnssec-keygen.c,v 1.115 2010-12-23 04:07:59 marka Exp $ */ /*! \file */ #include +#include #include +#include #include #include @@ -45,6 +47,7 @@ #include #include +#include #include #include #include @@ -62,103 +65,224 @@ const char *program = "dnssec-keygen"; int verbose; -static const char *algs = "RSA | RSAMD5 | DH | DSA | RSASHA1 | RSASHA256 |" - " RSASHA512 | NSEC3DSA | NSEC3RSASHA1 | HMAC-MD5 |" - " HMAC-SHA1 | HMAC-SHA224 | HMAC-SHA256 |" - " HMAC-SHA384 | HMAC-SHA512"; +#define DEFAULT_ALGORITHM "RSASHA1" +#define DEFAULT_NSEC3_ALGORITHM "NSEC3RSASHA1" -static isc_boolean_t -dsa_size_ok(int size) { - return (ISC_TF(size >= 512 && size <= 1024 && size % 64 == 0)); -} +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + +static void progress(int p); static void usage(void) { fprintf(stderr, "Usage:\n"); - fprintf(stderr, " %s -a alg -b bits [-n type] [options] name\n\n", - program); + fprintf(stderr, " %s [options] name\n\n", program); fprintf(stderr, "Version: %s\n", VERSION); - fprintf(stderr, "Required options:\n"); - fprintf(stderr, " -a algorithm: %s\n", algs); - fprintf(stderr, " -b key size, in bits:\n"); - fprintf(stderr, " RSAMD5:\t\t[512..%d]\n", MAX_RSA); - fprintf(stderr, " RSASHA1:\t\t[512..%d]\n", MAX_RSA); - fprintf(stderr, " NSEC3RSASHA1:\t\t[512..%d]\n", MAX_RSA); - fprintf(stderr, " RSASHA256:\t[512..%d]\n", MAX_RSA); - fprintf(stderr, " RSASHA512:\t[1024..%d]\n", MAX_RSA); + fprintf(stderr, " name: owner of the key\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -K : write keys into directory\n"); + fprintf(stderr, " -a :\n"); + fprintf(stderr, " RSA | RSAMD5 | DSA | RSASHA1 | NSEC3RSASHA1" + " | NSEC3DSA |\n"); + fprintf(stderr, " RSASHA256 | RSASHA512 | ECCGOST |\n"); + fprintf(stderr, " DH | HMAC-MD5 | HMAC-SHA1 | HMAC-SHA224 | " + "HMAC-SHA256 | \n"); + fprintf(stderr, " HMAC-SHA384 | HMAC-SHA512\n"); + fprintf(stderr, " (default: RSASHA1, or " + "NSEC3RSASHA1 if using -3)\n"); + fprintf(stderr, " -3: use NSEC3-capable algorithm\n"); + fprintf(stderr, " -b :\n"); + fprintf(stderr, " RSAMD5:\t[512..%d]\n", MAX_RSA); + fprintf(stderr, " RSASHA1:\t[512..%d]\n", MAX_RSA); + fprintf(stderr, " NSEC3RSASHA1:\t[512..%d]\n", MAX_RSA); + fprintf(stderr, " RSASHA256:\t[512..%d]\n", MAX_RSA); + fprintf(stderr, " RSASHA512:\t[1024..%d]\n", MAX_RSA); fprintf(stderr, " DH:\t\t[128..4096]\n"); fprintf(stderr, " DSA:\t\t[512..1024] and divisible by 64\n"); - fprintf(stderr, " NSEC3DSA:\t\t[512..1024] and divisible by 64\n"); + fprintf(stderr, " NSEC3DSA:\t[512..1024] and divisible " + "by 64\n"); + fprintf(stderr, " ECCGOST:\tignored\n"); fprintf(stderr, " HMAC-MD5:\t[1..512]\n"); fprintf(stderr, " HMAC-SHA1:\t[1..160]\n"); fprintf(stderr, " HMAC-SHA224:\t[1..224]\n"); fprintf(stderr, " HMAC-SHA256:\t[1..256]\n"); fprintf(stderr, " HMAC-SHA384:\t[1..384]\n"); fprintf(stderr, " HMAC-SHA512:\t[1..512]\n"); - fprintf(stderr, " -n nametype: ZONE | HOST | ENTITY | USER | OTHER\n"); - fprintf(stderr, " (DNSKEY generation defaults to ZONE\n"); - fprintf(stderr, " name: owner of the key\n"); - fprintf(stderr, "Other options:\n"); - fprintf(stderr, " -c (default: IN)\n"); + fprintf(stderr, " (if using the default algorithm, key size\n" + " defaults to 2048 for KSK, or 1024 for all " + "others)\n"); + fprintf(stderr, " -n : ZONE | HOST | ENTITY | " + "USER | OTHER\n"); + fprintf(stderr, " (DNSKEY generation defaults to ZONE)\n"); + fprintf(stderr, " -c : (default: IN)\n"); fprintf(stderr, " -d (0 => max, default)\n"); - fprintf(stderr, " -e use large exponent (RSAMD5/RSASHA1 only)\n"); - fprintf(stderr, " -f keyflag: KSK\n"); - fprintf(stderr, " -g use specified generator " - "(DH only)\n"); +#ifdef USE_PKCS11 + fprintf(stderr, " -E (default \"pkcs11\")\n"); +#else + fprintf(stderr, " -E \n"); +#endif + fprintf(stderr, " -e: use large exponent (RSAMD5/RSASHA1 only)\n"); + fprintf(stderr, " -f : KSK | REVOKE\n"); + fprintf(stderr, " -g : use specified generator " + "(DH only)\n"); + fprintf(stderr, " -p : (default: 3 [dnssec])\n"); + fprintf(stderr, " -s : strength value this key signs DNS " + "records with (default: 0)\n"); + fprintf(stderr, " -T : DNSKEY | KEY (default: DNSKEY; " + "use KEY for SIG(0))\n"); + fprintf(stderr, " ECCGOST:\tignored\n"); fprintf(stderr, " -t : " - "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF " - "(default: AUTHCONF)\n"); - fprintf(stderr, " -p : " - "default: 3 [dnssec]\n"); - fprintf(stderr, " -s strength value this key signs DNS " - "records with (default: 0)\n"); + "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF " + "(default: AUTHCONF)\n"); fprintf(stderr, " -r : a file containing random data\n"); - fprintf(stderr, " -v \n"); - fprintf(stderr, " -k : generate a TYPE=KEY key\n"); + + fprintf(stderr, " -h: print usage and exit\n"); + fprintf(stderr, " -m :\n"); + fprintf(stderr, " usage | trace | record | size | mctx\n"); + fprintf(stderr, " -v : set verbosity level (0 - 10)\n"); + fprintf(stderr, "Timing options:\n"); + fprintf(stderr, " -P date/[+-]offset/none: set key publication date " + "(default: now)\n"); + fprintf(stderr, " -A date/[+-]offset/none: set key activation date " + "(default: now)\n"); + fprintf(stderr, " -R date/[+-]offset/none: set key " + "revocation date\n"); + fprintf(stderr, " -I date/[+-]offset/none: set key " + "inactivation date\n"); + fprintf(stderr, " -D date/[+-]offset/none: set key deletion date\n"); + fprintf(stderr, " -G: generate key only; do not set -P or -A\n"); + fprintf(stderr, " -C: generate a backward-compatible key, omitting " + "all dates\n"); + fprintf(stderr, " -S : generate a successor to an existing " + "key\n"); + fprintf(stderr, " -i : prepublication interval for " + "successor key " + "(default: 30 days)\n"); fprintf(stderr, "Output:\n"); fprintf(stderr, " K++.key, " - "K++.private\n"); + "K++.private\n"); exit (-1); } +static isc_boolean_t +dsa_size_ok(int size) { + return (ISC_TF(size >= 512 && size <= 1024 && size % 64 == 0)); +} + +static void +progress(int p) +{ + char c = '*'; + + switch (p) { + case 0: + c = '.'; + break; + case 1: + c = '+'; + break; + case 2: + c = '*'; + break; + case 3: + c = ' '; + break; + default: + break; + } + (void) putc(c, stderr); + (void) fflush(stderr); +} + int main(int argc, char **argv) { char *algname = NULL, *nametype = NULL, *type = NULL; char *classname = NULL; char *endp; - dst_key_t *key = NULL, *oldkey; + dst_key_t *key = NULL; dns_fixedname_t fname; dns_name_t *name; - isc_uint16_t flags = 0, ksk = 0; + isc_uint16_t flags = 0, kskflag = 0, revflag = 0; dns_secalg_t alg; isc_boolean_t conflict = ISC_FALSE, null_key = ISC_FALSE; + isc_boolean_t oldstyle = ISC_FALSE; isc_mem_t *mctx = NULL; int ch, rsa_exp = 0, generator = 0, param = 0; int protocol = -1, size = -1, signatory = 0; isc_result_t ret; isc_textregion_t r; char filename[255]; + const char *directory = NULL; + const char *predecessor = NULL; + dst_key_t *prevkey = NULL; isc_buffer_t buf; isc_log_t *log = NULL; isc_entropy_t *ectx = NULL; +#ifdef USE_PKCS11 + const char *engine = "pkcs11"; +#else + const char *engine = NULL; +#endif dns_rdataclass_t rdclass; int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC; int dbits = 0; + isc_boolean_t use_default = ISC_FALSE, use_nsec3 = ISC_FALSE; + isc_stdtime_t publish = 0, activate = 0, revoke = 0; + isc_stdtime_t inactive = 0, delete = 0; + isc_stdtime_t now; + int prepub = -1; + isc_boolean_t setpub = ISC_FALSE, setact = ISC_FALSE; + isc_boolean_t setrev = ISC_FALSE, setinact = ISC_FALSE; + isc_boolean_t setdel = ISC_FALSE; + isc_boolean_t unsetpub = ISC_FALSE, unsetact = ISC_FALSE; + isc_boolean_t unsetrev = ISC_FALSE, unsetinact = ISC_FALSE; + isc_boolean_t unsetdel = ISC_FALSE; + isc_boolean_t genonly = ISC_FALSE; + isc_boolean_t quiet = ISC_FALSE; + isc_boolean_t show_progress = ISC_FALSE; + unsigned char c; if (argc == 1) usage(); - RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); - dns_result_register(); isc_commandline_errprint = ISC_FALSE; - while ((ch = isc_commandline_parse(argc, argv, - "a:b:c:d:ef:g:kn:t:p:s:r:v:h")) != -1) - { + /* + * Process memory debugging argument first. + */ +#define CMDLINE_FLAGS "3A:a:b:Cc:D:d:E:eFf:Gg:hI:i:K:km:n:P:p:qR:r:S:s:T:t:v:" + while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { + switch (ch) { + case 'm': + if (strcasecmp(isc_commandline_argument, "record") == 0) + isc_mem_debugging |= ISC_MEM_DEBUGRECORD; + if (strcasecmp(isc_commandline_argument, "trace") == 0) + isc_mem_debugging |= ISC_MEM_DEBUGTRACE; + if (strcasecmp(isc_commandline_argument, "usage") == 0) + isc_mem_debugging |= ISC_MEM_DEBUGUSAGE; + if (strcasecmp(isc_commandline_argument, "size") == 0) + isc_mem_debugging |= ISC_MEM_DEBUGSIZE; + if (strcasecmp(isc_commandline_argument, "mctx") == 0) + isc_mem_debugging |= ISC_MEM_DEBUGCTX; + break; + default: + break; + } + } + isc_commandline_reset = ISC_TRUE; + + RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); + + isc_stdtime_get(&now); + + while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { switch (ch) { + case '3': + use_nsec3 = ISC_TRUE; + break; case 'a': algname = isc_commandline_argument; break; @@ -167,6 +291,9 @@ main(int argc, char **argv) { if (*endp != '\0' || size < 0) fatal("-b requires a non-negative number"); break; + case 'C': + oldstyle = ISC_TRUE; + break; case 'c': classname = isc_commandline_argument; break; @@ -175,12 +302,18 @@ main(int argc, char **argv) { if (*endp != '\0' || dbits < 0) fatal("-d requires a non-negative number"); break; + case 'E': + engine = isc_commandline_argument; + break; case 'e': rsa_exp = 1; break; case 'f': - if (strcasecmp(isc_commandline_argument, "KSK") == 0) - ksk = DNS_KEYFLAG_KSK; + c = (unsigned char)(isc_commandline_argument[0]); + if (toupper(c) == 'K') + kskflag = DNS_KEYFLAG_KSK; + else if (toupper(c) == 'R') + revflag = DNS_KEYFLAG_REVOKE; else fatal("unknown flag '%s'", isc_commandline_argument); @@ -191,14 +324,22 @@ main(int argc, char **argv) { if (*endp != '\0' || generator <= 0) fatal("-g requires a positive number"); break; + case 'K': + directory = isc_commandline_argument; + ret = try_dir(directory); + if (ret != ISC_R_SUCCESS) + fatal("cannot open directory %s: %s", + directory, isc_result_totext(ret)); + break; case 'k': - options |= DST_TYPE_KEY; + fatal("The -k option has been deprecated.\n" + "To generate a key-signing key, use -f KSK.\n" + "To generate a key with TYPE=KEY, use -T KEY.\n"); break; case 'n': nametype = isc_commandline_argument; break; - case 't': - type = isc_commandline_argument; + case 'm': break; case 'p': protocol = strtol(isc_commandline_argument, &endp, 10); @@ -206,6 +347,12 @@ main(int argc, char **argv) { fatal("-p must be followed by a number " "[0..255]"); break; + case 'q': + quiet = ISC_TRUE; + break; + case 'r': + setup_entropy(mctx, isc_commandline_argument, &ectx); + break; case 's': signatory = strtol(isc_commandline_argument, &endp, 10); @@ -213,8 +360,19 @@ main(int argc, char **argv) { fatal("-s must be followed by a number " "[0..15]"); break; - case 'r': - setup_entropy(mctx, isc_commandline_argument, &ectx); + case 'T': + if (strcasecmp(isc_commandline_argument, "KEY") == 0) + options |= DST_TYPE_KEY; + else if (strcasecmp(isc_commandline_argument, + "DNSKEY") == 0) + /* default behavior */ + ; + else + fatal("unknown type '%s'", + isc_commandline_argument); + break; + case 't': + type = isc_commandline_argument; break; case 'v': endp = NULL; @@ -222,11 +380,86 @@ main(int argc, char **argv) { if (*endp != '\0') fatal("-v must be followed by a number"); break; - + case 'z': + /* already the default */ + break; + case 'G': + genonly = ISC_TRUE; + break; + case 'P': + if (setpub || unsetpub) + fatal("-P specified more than once"); + + if (strcasecmp(isc_commandline_argument, "none")) { + setpub = ISC_TRUE; + publish = strtotime(isc_commandline_argument, + now, now); + } else { + unsetpub = ISC_TRUE; + } + break; + case 'A': + if (setact || unsetact) + fatal("-A specified more than once"); + + if (strcasecmp(isc_commandline_argument, "none")) { + setact = ISC_TRUE; + activate = strtotime(isc_commandline_argument, + now, now); + } else { + unsetact = ISC_TRUE; + } + break; + case 'R': + if (setrev || unsetrev) + fatal("-R specified more than once"); + + if (strcasecmp(isc_commandline_argument, "none")) { + setrev = ISC_TRUE; + revoke = strtotime(isc_commandline_argument, + now, now); + } else { + unsetrev = ISC_TRUE; + } + break; + case 'I': + if (setinact || unsetinact) + fatal("-I specified more than once"); + + if (strcasecmp(isc_commandline_argument, "none")) { + setinact = ISC_TRUE; + inactive = strtotime(isc_commandline_argument, + now, now); + } else { + unsetinact = ISC_TRUE; + } + break; + case 'D': + if (setdel || unsetdel) + fatal("-D specified more than once"); + + if (strcasecmp(isc_commandline_argument, "none")) { + setdel = ISC_TRUE; + delete = strtotime(isc_commandline_argument, + now, now); + } else { + unsetdel = ISC_TRUE; + } + break; + case 'S': + predecessor = isc_commandline_argument; + break; + case 'i': + prepub = strtottl(isc_commandline_argument); + break; + case 'F': + /* Reserved for FIPS mode */ + /* FALLTHROUGH */ case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); + /* FALLTHROUGH */ case 'h': usage(); @@ -237,73 +470,219 @@ main(int argc, char **argv) { } } + if (!isatty(0)) + quiet = ISC_TRUE; + if (ectx == NULL) setup_entropy(mctx, NULL, &ectx); - ret = dst_lib_init(mctx, ectx, - ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); + ret = dst_lib_init2(mctx, ectx, engine, + ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); if (ret != ISC_R_SUCCESS) - fatal("could not initialize dst"); + fatal("could not initialize dst: %s", + isc_result_totext(ret)); setup_logging(verbose, mctx, &log); - if (argc < isc_commandline_index + 1) - fatal("the key name was not specified"); - if (argc > isc_commandline_index + 1) - fatal("extraneous arguments"); - - if (algname == NULL) - fatal("no algorithm was specified"); - if (strcasecmp(algname, "RSA") == 0) { - fprintf(stderr, "The use of RSA (RSAMD5) is not recommended.\n" - "If you still wish to use RSA (RSAMD5) please " - "specify \"-a RSAMD5\"\n"); - return (1); - } else if (strcasecmp(algname, "HMAC-MD5") == 0) { - options |= DST_TYPE_KEY; - alg = DST_ALG_HMACMD5; - } else if (strcasecmp(algname, "HMAC-SHA1") == 0) { - options |= DST_TYPE_KEY; - alg = DST_ALG_HMACSHA1; - } else if (strcasecmp(algname, "HMAC-SHA224") == 0) { - options |= DST_TYPE_KEY; - alg = DST_ALG_HMACSHA224; - } else if (strcasecmp(algname, "HMAC-SHA256") == 0) { - options |= DST_TYPE_KEY; - alg = DST_ALG_HMACSHA256; - } else if (strcasecmp(algname, "HMAC-SHA384") == 0) { - options |= DST_TYPE_KEY; - alg = DST_ALG_HMACSHA384; - } else if (strcasecmp(algname, "HMAC-SHA512") == 0) { - options |= DST_TYPE_KEY; - alg = DST_ALG_HMACSHA512; - } else { - r.base = algname; - r.length = strlen(algname); - ret = dns_secalg_fromtext(&alg, &r); + if (predecessor == NULL) { + if (prepub == -1) + prepub = 0; + + if (argc < isc_commandline_index + 1) + fatal("the key name was not specified"); + if (argc > isc_commandline_index + 1) + fatal("extraneous arguments"); + + dns_fixedname_init(&fname); + name = dns_fixedname_name(&fname); + isc_buffer_init(&buf, argv[isc_commandline_index], + strlen(argv[isc_commandline_index])); + isc_buffer_add(&buf, strlen(argv[isc_commandline_index])); + ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); if (ret != ISC_R_SUCCESS) - fatal("unknown algorithm %s", algname); - if (alg == DST_ALG_DH) - options |= DST_TYPE_KEY; - } + fatal("invalid key name %s: %s", + argv[isc_commandline_index], + isc_result_totext(ret)); + + if (algname == NULL) { + use_default = ISC_TRUE; + if (use_nsec3) + algname = strdup(DEFAULT_NSEC3_ALGORITHM); + else + algname = strdup(DEFAULT_ALGORITHM); + if (verbose > 0) + fprintf(stderr, "no algorithm specified; " + "defaulting to %s\n", algname); + } - if (type != NULL && (options & DST_TYPE_KEY) != 0) { - if (strcasecmp(type, "NOAUTH") == 0) - flags |= DNS_KEYTYPE_NOAUTH; - else if (strcasecmp(type, "NOCONF") == 0) - flags |= DNS_KEYTYPE_NOCONF; - else if (strcasecmp(type, "NOAUTHCONF") == 0) { - flags |= (DNS_KEYTYPE_NOAUTH | DNS_KEYTYPE_NOCONF); - if (size < 0) - size = 0; + if (strcasecmp(algname, "RSA") == 0) { + fprintf(stderr, "The use of RSA (RSAMD5) is not " + "recommended.\nIf you still wish to " + "use RSA (RSAMD5) please specify " + "\"-a RSAMD5\"\n"); + return (1); + } else if (strcasecmp(algname, "HMAC-MD5") == 0) + alg = DST_ALG_HMACMD5; + else if (strcasecmp(algname, "HMAC-SHA1") == 0) + alg = DST_ALG_HMACSHA1; + else if (strcasecmp(algname, "HMAC-SHA224") == 0) + alg = DST_ALG_HMACSHA224; + else if (strcasecmp(algname, "HMAC-SHA256") == 0) + alg = DST_ALG_HMACSHA256; + else if (strcasecmp(algname, "HMAC-SHA384") == 0) + alg = DST_ALG_HMACSHA384; + else if (strcasecmp(algname, "HMAC-SHA512") == 0) + alg = DST_ALG_HMACSHA512; + else { + r.base = algname; + r.length = strlen(algname); + ret = dns_secalg_fromtext(&alg, &r); + if (ret != ISC_R_SUCCESS) + fatal("unknown algorithm %s", algname); + if (alg == DST_ALG_DH) + options |= DST_TYPE_KEY; } - else if (strcasecmp(type, "AUTHCONF") == 0) - /* nothing */; - else - fatal("invalid type %s", type); - } - if (size < 0) - fatal("key size not specified (-b option)"); + if (use_nsec3 && + alg != DST_ALG_NSEC3DSA && alg != DST_ALG_NSEC3RSASHA1 && + alg != DST_ALG_RSASHA256 && alg!= DST_ALG_RSASHA512 && + alg != DST_ALG_ECCGOST) { + fatal("%s is incompatible with NSEC3; " + "do not use the -3 option", algname); + } + + if (type != NULL && (options & DST_TYPE_KEY) != 0) { + if (strcasecmp(type, "NOAUTH") == 0) + flags |= DNS_KEYTYPE_NOAUTH; + else if (strcasecmp(type, "NOCONF") == 0) + flags |= DNS_KEYTYPE_NOCONF; + else if (strcasecmp(type, "NOAUTHCONF") == 0) { + flags |= (DNS_KEYTYPE_NOAUTH | + DNS_KEYTYPE_NOCONF); + if (size < 0) + size = 0; + } + else if (strcasecmp(type, "AUTHCONF") == 0) + /* nothing */; + else + fatal("invalid type %s", type); + } + + if (size < 0) { + if (use_default) { + if ((kskflag & DNS_KEYFLAG_KSK) != 0) + size = 2048; + else + size = 1024; + if (verbose > 0) + fprintf(stderr, "key size not " + "specified; defaulting " + "to %d\n", size); + } else if (alg != DST_ALG_ECCGOST) + fatal("key size not specified (-b option)"); + } + + if (!oldstyle && prepub > 0) { + if (setpub && setact && (activate - prepub) < publish) + fatal("Activation and publication dates " + "are closer together than the\n\t" + "prepublication interval."); + + if (!setpub && !setact) { + setpub = setact = ISC_TRUE; + publish = now; + activate = now + prepub; + } else if (setpub && !setact) { + setact = ISC_TRUE; + activate = publish + prepub; + } else if (setact && !setpub) { + setpub = ISC_TRUE; + publish = activate - prepub; + } + + if ((activate - prepub) < now) + fatal("Time until activation is shorter " + "than the\n\tprepublication interval."); + } + } else { + char keystr[DST_KEY_FORMATSIZE]; + isc_stdtime_t when; + int major, minor; + + if (prepub == -1) + prepub = (30 * 86400); + + if (algname != NULL) + fatal("-S and -a cannot be used together"); + if (size >= 0) + fatal("-S and -b cannot be used together"); + if (nametype != NULL) + fatal("-S and -n cannot be used together"); + if (type != NULL) + fatal("-S and -t cannot be used together"); + if (setpub || unsetpub) + fatal("-S and -P cannot be used together"); + if (setact || unsetact) + fatal("-S and -A cannot be used together"); + if (use_nsec3) + fatal("-S and -3 cannot be used together"); + if (oldstyle) + fatal("-S and -C cannot be used together"); + if (genonly) + fatal("-S and -G cannot be used together"); + + ret = dst_key_fromnamedfile(predecessor, directory, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, + mctx, &prevkey); + if (ret != ISC_R_SUCCESS) + fatal("Invalid keyfile %s: %s", + filename, isc_result_totext(ret)); + if (!dst_key_isprivate(prevkey)) + fatal("%s is not a private key", filename); + + name = dst_key_name(prevkey); + alg = dst_key_alg(prevkey); + size = dst_key_size(prevkey); + flags = dst_key_flags(prevkey); + + dst_key_format(prevkey, keystr, sizeof(keystr)); + dst_key_getprivateformat(prevkey, &major, &minor); + if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) + fatal("Key %s has incompatible format version %d.%d\n\t" + "It is not possible to generate a successor key.", + keystr, major, minor); + + ret = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &when); + if (ret != ISC_R_SUCCESS) + fatal("Key %s has no activation date.\n\t" + "You must use dnssec-settime -A to set one " + "before generating a successor.", keystr); + + ret = dst_key_gettime(prevkey, DST_TIME_INACTIVE, &activate); + if (ret != ISC_R_SUCCESS) + fatal("Key %s has no inactivation date.\n\t" + "You must use dnssec-settime -I to set one " + "before generating a successor.", keystr); + + publish = activate - prepub; + if (publish < now) + fatal("Key %s becomes inactive\n\t" + "sooner than the prepublication period " + "for the new key ends.\n\t" + "Either change the inactivation date with " + "dnssec-settime -I,\n\t" + "or use the -i option to set a shorter " + "prepublication interval.", keystr); + + ret = dst_key_gettime(prevkey, DST_TIME_DELETE, &when); + if (ret != ISC_R_SUCCESS) + fprintf(stderr, "%s: WARNING: Key %s has no removal " + "date;\n\t it will remain in the zone " + "indefinitely after rollover.\n\t " + "You can use dnssec-settime -D to " + "change this.\n", program, keystr); + + setpub = setact = ISC_TRUE; + } switch (alg) { case DNS_KEYALG_RSAMD5: @@ -326,7 +705,10 @@ main(int argc, char **argv) { if (size != 0 && !dsa_size_ok(size)) fatal("invalid DSS key size: %d", size); break; + case DST_ALG_ECCGOST: + break; case DST_ALG_HMACMD5: + options |= DST_TYPE_KEY; if (size < 1 || size > 512) fatal("HMAC-MD5 key size %d out of range", size); if (dbits != 0 && (dbits < 80 || dbits > 128)) @@ -336,6 +718,7 @@ main(int argc, char **argv) { dbits); break; case DST_ALG_HMACSHA1: + options |= DST_TYPE_KEY; if (size < 1 || size > 160) fatal("HMAC-SHA1 key size %d out of range", size); if (dbits != 0 && (dbits < 80 || dbits > 160)) @@ -345,6 +728,7 @@ main(int argc, char **argv) { dbits); break; case DST_ALG_HMACSHA224: + options |= DST_TYPE_KEY; if (size < 1 || size > 224) fatal("HMAC-SHA224 key size %d out of range", size); if (dbits != 0 && (dbits < 112 || dbits > 224)) @@ -354,6 +738,7 @@ main(int argc, char **argv) { dbits); break; case DST_ALG_HMACSHA256: + options |= DST_TYPE_KEY; if (size < 1 || size > 256) fatal("HMAC-SHA256 key size %d out of range", size); if (dbits != 0 && (dbits < 128 || dbits > 256)) @@ -363,6 +748,7 @@ main(int argc, char **argv) { dbits); break; case DST_ALG_HMACSHA384: + options |= DST_TYPE_KEY; if (size < 1 || size > 384) fatal("HMAC-384 key size %d out of range", size); if (dbits != 0 && (dbits < 192 || dbits > 384)) @@ -372,6 +758,7 @@ main(int argc, char **argv) { dbits); break; case DST_ALG_HMACSHA512: + options |= DST_TYPE_KEY; if (size < 1 || size > 512) fatal("HMAC-SHA512 key size %d out of range", size); if (dbits != 0 && (dbits < 256 || dbits > 512)) @@ -384,7 +771,8 @@ main(int argc, char **argv) { if (!(alg == DNS_KEYALG_RSAMD5 || alg == DNS_KEYALG_RSASHA1 || alg == DNS_KEYALG_NSEC3RSASHA1 || alg == DNS_KEYALG_RSASHA256 || - alg == DNS_KEYALG_RSASHA512) && rsa_exp != 0) + alg == DNS_KEYALG_RSASHA512 || alg == DST_ALG_ECCGOST) && + rsa_exp != 0) fatal("specified RSA exponent for a non-RSA key"); if (alg != DNS_KEYALG_DH && generator != 0) @@ -409,10 +797,15 @@ main(int argc, char **argv) { rdclass = strtoclass(classname); + if (directory == NULL) + directory = "."; + if ((options & DST_TYPE_KEY) != 0) /* KEY / HMAC */ flags |= signatory; - else if ((flags & DNS_KEYOWNER_ZONE) != 0) /* DNSKEY */ - flags |= ksk; + else if ((flags & DNS_KEYOWNER_ZONE) != 0) { /* DNSKEY */ + flags |= kskflag; + flags |= revflag; + } if (protocol == -1) protocol = DNS_KEYPROTO_DNSSEC; @@ -435,16 +828,6 @@ main(int argc, char **argv) { fatal("a key with algorithm '%s' cannot be a zone key", algname); - dns_fixedname_init(&fname); - name = dns_fixedname_name(&fname); - isc_buffer_init(&buf, argv[isc_commandline_index], - strlen(argv[isc_commandline_index])); - isc_buffer_add(&buf, strlen(argv[isc_commandline_index])); - ret = dns_name_fromtext(name, &buf, dns_rootname, ISC_FALSE, NULL); - if (ret != ISC_R_SUCCESS) - fatal("invalid key name %s: %s", argv[isc_commandline_index], - isc_result_totext(ret)); - switch(alg) { case DNS_KEYALG_RSAMD5: case DNS_KEYALG_RSASHA1: @@ -452,12 +835,19 @@ main(int argc, char **argv) { case DNS_KEYALG_RSASHA256: case DNS_KEYALG_RSASHA512: param = rsa_exp; + show_progress = ISC_TRUE; break; + case DNS_KEYALG_DH: param = generator; break; + case DNS_KEYALG_DSA: case DNS_KEYALG_NSEC3DSA: + case DST_ALG_ECCGOST: + show_progress = ISC_TRUE; + /* fall through */ + case DST_ALG_HMACMD5: case DST_ALG_HMACSHA1: case DST_ALG_HMACSHA224: @@ -475,62 +865,136 @@ main(int argc, char **argv) { do { conflict = ISC_FALSE; - oldkey = NULL; - /* generate the key */ - ret = dst_key_generate(name, alg, size, param, flags, protocol, - rdclass, mctx, &key); + if (!quiet && show_progress) { + fprintf(stderr, "Generating key pair."); + ret = dst_key_generate2(name, alg, size, param, flags, + protocol, rdclass, mctx, &key, + &progress); + putc('\n', stderr); + fflush(stderr); + } else { + ret = dst_key_generate2(name, alg, size, param, flags, + protocol, rdclass, mctx, &key, + NULL); + } + isc_entropy_stopcallbacksources(ectx); if (ret != ISC_R_SUCCESS) { char namestr[DNS_NAME_FORMATSIZE]; - char algstr[ALG_FORMATSIZE]; + char algstr[DNS_SECALG_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); - alg_format(alg, algstr, sizeof(algstr)); + dns_secalg_format(alg, algstr, sizeof(algstr)); fatal("failed to generate key %s/%s: %s\n", namestr, algstr, isc_result_totext(ret)); + /* NOTREACHED */ exit(-1); } dst_key_setbits(key, dbits); /* - * Try to read a key with the same name, alg and id from disk. - * If there is one we must continue generating a new one - * unless we were asked to generate a null key, in which - * case we return failure. + * Set key timing metadata (unless using -C) + * + * Creation date is always set to "now". + * + * For a new key without an explicit predecessor, publish + * and activation dates are set to "now" by default, but + * can both be overridden. + * + * For a successor key, activation is set to match the + * predecessor's inactivation date. Publish is set to 30 + * days earlier than that (XXX: this should be configurable). + * If either of the resulting dates are in the past, that's + * an error; the inactivation date of the predecessor key + * must be updated before a successor key can be created. */ - ret = dst_key_fromfile(name, dst_key_id(key), alg, - DST_TYPE_PRIVATE, NULL, mctx, &oldkey); - /* do not overwrite an existing key */ - if (ret == ISC_R_SUCCESS) { - dst_key_free(&oldkey); + if (!oldstyle) { + dst_key_settime(key, DST_TIME_CREATED, now); + + if (genonly && (setpub || setact)) + fatal("cannot use -G together with " + "-P or -A options"); + + if (setpub) + dst_key_settime(key, DST_TIME_PUBLISH, publish); + else if (setact) + dst_key_settime(key, DST_TIME_PUBLISH, + activate); + else if (!genonly && !unsetpub) + dst_key_settime(key, DST_TIME_PUBLISH, now); + + if (setact) + dst_key_settime(key, DST_TIME_ACTIVATE, + activate); + else if (!genonly && !unsetact) + dst_key_settime(key, DST_TIME_ACTIVATE, now); + + if (setrev) { + if (kskflag == 0) + fprintf(stderr, "%s: warning: Key is " + "not flagged as a KSK, but -R " + "was used. Revoking a ZSK is " + "legal, but undefined.\n", + program); + dst_key_settime(key, DST_TIME_REVOKE, revoke); + } + + if (setinact) + dst_key_settime(key, DST_TIME_INACTIVE, + inactive); + + if (setdel) + dst_key_settime(key, DST_TIME_DELETE, delete); + } else { + if (setpub || setact || setrev || setinact || + setdel || unsetpub || unsetact || + unsetrev || unsetinact || unsetdel || genonly) + fatal("cannot use -C together with " + "-P, -A, -R, -I, -D, or -G options"); + /* + * Compatibility mode: Private-key-format + * should be set to 1.2. + */ + dst_key_setprivateformat(key, 1, 2); + } + + /* + * Do not overwrite an existing key, or create a key + * if there is a risk of ID collision due to this key + * or another key being revoked. + */ + if (key_collision(dst_key_id(key), name, directory, + alg, mctx, NULL)) { conflict = ISC_TRUE; - if (null_key) + if (null_key) { + dst_key_free(&key); break; - } - if (conflict == ISC_TRUE) { + } + if (verbose > 0) { isc_buffer_clear(&buf); - ret = dst_key_buildfilename(key, 0, NULL, &buf); + dst_key_buildfilename(key, 0, directory, &buf); fprintf(stderr, - "%s: %s already exists, " - "generating a new key\n", + "%s: %s already exists, or might " + "collide with another key upon " + "revokation. Generating a new key\n", program, filename); } + dst_key_free(&key); } - } while (conflict == ISC_TRUE); if (conflict) - fatal("cannot generate a null key when a key with id 0 " - "already exists"); + fatal("cannot generate a null key due to possible key ID " + "collision"); - ret = dst_key_tofile(key, options, NULL); + ret = dst_key_tofile(key, options, directory); if (ret != ISC_R_SUCCESS) { - char keystr[KEY_FORMATSIZE]; - key_format(key, keystr, sizeof(keystr)); + char keystr[DST_KEY_FORMATSIZE]; + dst_key_format(key, keystr, sizeof(keystr)); fatal("failed to write key %s: %s\n", keystr, isc_result_totext(ret)); } @@ -539,6 +1003,8 @@ main(int argc, char **argv) { ret = dst_key_buildfilename(key, 0, NULL, &buf); printf("%s\n", filename); dst_key_free(&key); + if (prevkey != NULL) + dst_key_free(&prevkey); cleanup_logging(&log); cleanup_entropy(&ectx); diff --git a/bin/dnssec/dnssec-keygen.docbook b/bin/dnssec/dnssec-keygen.docbook index 5c7d164..dc140eb 100644 --- a/bin/dnssec/dnssec-keygen.docbook +++ b/bin/dnssec/dnssec-keygen.docbook @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + June 30, 2000 @@ -57,20 +57,34 @@ dnssec-keygen - -a algorithm - -b keysize - -n nametype + + + + + + + + + + + + + + + + + name @@ -80,7 +94,8 @@ dnssec-keygen generates keys for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034. It can also generate keys for use with - TSIG (Transaction Signatures), as defined in RFC 2845. + TSIG (Transaction Signatures) as defined in RFC 2845, or TKEY + (Transaction Key) as defined in RFC 2930. The of the key is specified on the command @@ -99,19 +114,27 @@ Selects the cryptographic algorithm. For DNSSEC keys, the value of must be one of RSAMD5, RSASHA1, - DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256 or RSASHA512. - For TSIG/TKEY, the value must + DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512 or ECCGOST. + For TSIG/TKEY, the value must be DH (Diffie Hellman), HMAC-MD5, HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, HMAC-SHA384, or HMAC-SHA512. These values are case insensitive. + If no algorithm is specified, then RSASHA1 will be used by + default, unless the option is specified, + in which case NSEC3RSASHA1 will be used instead. (If + is used and an algorithm is specified, + that algorithm will be checked for compatibility with NSEC3.) + + Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement algorithm, and DSA is recommended. For TSIG, HMAC-MD5 is mandatory. - Note 2: HMAC-MD5 and DH automatically set the -k flag. + Note 2: DH, HMAC-MD5, and HMAC-SHA1 through HMAC-SHA512 + automatically set the -T KEY option.
    @@ -127,6 +150,15 @@ bits and an exact multiple of 64. HMAC keys must be between 1 and 512 bits. + + The key size does not need to be specified if using a default + algorithm. The default key size is 1024 bits for zone signing + keys (ZSK's) and 2048 bits for key signing keys (KSK's, + generated with ). However, if an + algorithm is explicitly specified with the , + then there is no default key size, and the + must be used. + @@ -146,6 +178,34 @@ + -3 + + + Use an NSEC3-capable algorithm to generate a DNSSEC key. + If this option is used and no algorithm is explicitly + set on the command line, NSEC3RSASHA1 will be used by + default. Note that RSASHA256, RSASHA512 and ECCGOST algorithms + are NSEC3-capable. + + + + + + -C + + + Compatibility mode: generates an old-style key, without + any metadata. By default, dnssec-keygen + will include the key's creation date in the metadata stored + with the private key, and other dates may be set there as well + (publication date, activation date, etc). Keys that include + this data may be incompatible with older versions of BIND; the + option suppresses them. + + + + + -c class @@ -156,6 +216,18 @@ + -E engine + + + Uses a crypto hardware (OpenSSL engine) for random number + and, when supported, key generation. When compiled with PKCS#11 + support it defaults to pkcs11; the empty name resets it to + no engine. + + + + + -e @@ -169,7 +241,17 @@ Set the specified flag in the flag field of the KEY/DNSKEY record. - The only recognized flag is KSK (Key Signing Key) DNSKEY. + The only recognized flags are KSK (Key Signing Key) and REVOKE. + + + + + + -G + + + Generate a key, but do not publish it or sign with it. This + option is incompatible with -P and -A. @@ -197,10 +279,19 @@ + -K directory + + + Sets the directory in which the key files are to be written. + + + + + -k - Generate KEY records rather than DNSKEY records. + Deprecated in favor of -T KEY. @@ -218,6 +309,25 @@ + -q + + + Quiet mode: Suppresses unnecessary output, including + progress indication. Without this option, when + dnssec-keygen is run interactively + to generate an RSA or DSA key pair, it will print a string + of symbols to stderr indicating the + progress of the key generation. A '.' indicates that a + random number has been found which passed an initial + sieve test; '+' means a number has passed a single + round of the Miller-Rabin primality test; a space + means that the number has passed all the tests and is + a satisfactory key. + + + + + -r randomdev @@ -235,6 +345,21 @@ + -S key + + + Create a new key which is an explicit successor to an + existing key. The name, algorithm, size, and type of the + key will be set to match the existing key. The activation + date of the new key will be set to the inactivation date of + the existing one. The publication date will be set to the + activation date minus the prepublication interval, which + defaults to 30 days. + + + + + -s strength @@ -246,6 +371,22 @@ + -T rrtype + + + Specifies the resource record type to use for the key. + must be either DNSKEY or KEY. The + default is DNSKEY when using a DNSSEC algorithm, but it can be + overridden to KEY for use with SIG(0). + + + Using any TSIG algorithm (HMAC-* or DH) forces this option + to KEY. + + + + + -t type @@ -270,6 +411,109 @@ + TIMING OPTIONS + + + Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. + If the argument begins with a '+' or '-', it is interpreted as + an offset from the present time. For convenience, if such an offset + is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', + then the offset is computed in years (defined as 365 24-hour days, + ignoring leap years), months (defined as 30 24-hour days), weeks, + days, hours, or minutes, respectively. Without a suffix, the offset + is computed in seconds. + + + + + -P date/offset + + + Sets the date on which a key is to be published to the zone. + After that date, the key will be included in the zone but will + not be used to sign it. If not set, and if the -G option has + not been used, the default is "now". + + + + + + -A date/offset + + + Sets the date on which the key is to be activated. After that + date, the key will be included in the zone and used to sign + it. If not set, and if the -G option has not been used, the + default is "now". + + + + + + -R date/offset + + + Sets the date on which the key is to be revoked. After that + date, the key will be flagged as revoked. It will be included + in the zone and will be used to sign it. + + + + + + -I date/offset + + + Sets the date on which the key is to be retired. After that + date, the key will still be included in the zone, but it + will not be used to sign it. + + + + + + -D date/offset + + + Sets the date on which the key is to be deleted. After that + date, the key will no longer be included in the zone. (It + may remain in the key repository, however.) + + + + + + -i interval + + + Sets the prepublication interval for a key. If set, then + the publication and activation dates must be separated by at least + this much time. If the activation date is specified but the + publication date isn't, then the publication date will default + to this much time before the activation date; conversely, if + the publication date is specified but activation date isn't, + then activation will be set to this much time after publication. + + + If the key is being created as an explicit successor to another + key, then the default prepublication interval is 30 days; + otherwise it is zero. + + + As with date offsets, if the argument is followed by one of + the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the + interval is measured in years, months, weeks, days, hours, + or minutes, respectively. Without a suffix, the interval is + measured in seconds. + + + + + + + + + GENERATED KEYS When dnssec-keygen completes diff --git a/bin/dnssec/dnssec-keygen.html b/bin/dnssec/dnssec-keygen.html index 7ca7d57..2f3a69b 100644 --- a/bin/dnssec/dnssec-keygen.html +++ b/bin/dnssec/dnssec-keygen.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -29,14 +29,15 @@

    Synopsis

    -

    dnssec-keygen {-a algorithm} {-b keysize} {-n nametype} [-c class] [-e] [-f flag] [-g generator] [-h] [-k] [-p protocol] [-r randomdev] [-s strength] [-t type] [-v level] {name}

    +

    dnssec-keygen [-a algorithm] [-b keysize] [-n nametype] [-3] [-A date/offset] [-C] [-c class] [-D date/offset] [-E engine] [-e] [-f flag] [-G] [-g generator] [-h] [-I date/offset] [-i interval] [-K directory] [-k] [-P date/offset] [-p protocol] [-q] [-R date/offset] [-r randomdev] [-S key] [-s strength] [-t type] [-v level] [-z] {name}

    -

    DESCRIPTION

    +

    DESCRIPTION

    dnssec-keygen generates keys for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034. It can also generate keys for use with - TSIG (Transaction Signatures), as defined in RFC 2845. + TSIG (Transaction Signatures) as defined in RFC 2845, or TKEY + (Transaction Key) as defined in RFC 2930.

    The name of the key is specified on the command @@ -45,37 +46,56 @@

    -

    OPTIONS

    +

    OPTIONS

    -a algorithm

    Selects the cryptographic algorithm. For DNSSEC keys, the value of algorithm must be one of RSAMD5, RSASHA1, - DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256 or RSASHA512. - For TSIG/TKEY, the value must + DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512 or ECCGOST. + For TSIG/TKEY, the value must be DH (Diffie Hellman), HMAC-MD5, HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, HMAC-SHA384, or HMAC-SHA512. These values are case insensitive.

    + If no algorithm is specified, then RSASHA1 will be used by + default, unless the -3 option is specified, + in which case NSEC3RSASHA1 will be used instead. (If + -3 is used and an algorithm is specified, + that algorithm will be checked for compatibility with NSEC3.) +

    +

    Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement algorithm, and DSA is recommended. For TSIG, HMAC-MD5 is mandatory.

    - Note 2: HMAC-MD5 and DH automatically set the -k flag. + Note 2: DH, HMAC-MD5, and HMAC-SHA1 through HMAC-SHA512 + automatically set the -T KEY option.

    -b keysize
    -

    +

    +

    Specifies the number of bits in the key. The choice of key size depends on the algorithm used. RSA keys must be between 512 and 2048 bits. Diffie Hellman keys must be between 128 and 4096 bits. DSA keys must be between 512 and 1024 bits and an exact multiple of 64. HMAC keys must be between 1 and 512 bits. -

    +

    +

    + The key size does not need to be specified if using a default + algorithm. The default key size is 1024 bits for zone signing + keys (ZSK's) and 2048 bits for key signing keys (KSK's, + generated with -f KSK). However, if an + algorithm is explicitly specified with the -a, + then there is no default key size, and the -b + must be used. +

    +
    -n nametype

    Specifies the owner type of the key. The value of @@ -86,11 +106,36 @@ These values are case insensitive. Defaults to ZONE for DNSKEY generation.

    +
    -3
    +

    + Use an NSEC3-capable algorithm to generate a DNSSEC key. + If this option is used and no algorithm is explicitly + set on the command line, NSEC3RSASHA1 will be used by + default. Note that RSASHA256, RSASHA512 and ECCGOST algorithms + are NSEC3-capable. +

    +
    -C
    +

    + Compatibility mode: generates an old-style key, without + any metadata. By default, dnssec-keygen + will include the key's creation date in the metadata stored + with the private key, and other dates may be set there as well + (publication date, activation date, etc). Keys that include + this data may be incompatible with older versions of BIND; the + -C option suppresses them. +

    -c class

    Indicates that the DNS record containing the key should have the specified class. If not specified, class IN is used.

    +
    -E engine
    +

    + Uses a crypto hardware (OpenSSL engine) for random number + and, when supported, key generation. When compiled with PKCS#11 + support it defaults to pkcs11; the empty name resets it to + no engine. +

    -e

    If generating an RSAMD5/RSASHA1 key, use a large exponent. @@ -98,7 +143,12 @@

    -f flag

    Set the specified flag in the flag field of the KEY/DNSKEY record. - The only recognized flag is KSK (Key Signing Key) DNSKEY. + The only recognized flags are KSK (Key Signing Key) and REVOKE. +

    +
    -G
    +

    + Generate a key, but do not publish it or sign with it. This + option is incompatible with -P and -A.

    -g generator

    @@ -112,9 +162,13 @@ Prints a short summary of the options and arguments to dnssec-keygen.

    +
    -K directory
    +

    + Sets the directory in which the key files are to be written. +

    -k

    - Generate KEY records rather than DNSKEY records. + Deprecated in favor of -T KEY.

    -p protocol

    @@ -123,6 +177,20 @@ Other possible values for this argument are listed in RFC 2535 and its successors.

    +
    -q
    +

    + Quiet mode: Suppresses unnecessary output, including + progress indication. Without this option, when + dnssec-keygen is run interactively + to generate an RSA or DSA key pair, it will print a string + of symbols to stderr indicating the + progress of the key generation. A '.' indicates that a + random number has been found which passed an initial + sieve test; '+' means a number has passed a single + round of the Miller-Rabin primality test; a space + means that the number has passed all the tests and is + a satisfactory key. +

    -r randomdev

    Specifies the source of randomness. If the operating @@ -135,12 +203,37 @@ keyboard indicates that keyboard input should be used.

    +
    -S key
    +

    + Create a new key which is an explicit successor to an + existing key. The name, algorithm, size, and type of the + key will be set to match the existing key. The activation + date of the new key will be set to the inactivation date of + the existing one. The publication date will be set to the + activation date minus the prepublication interval, which + defaults to 30 days. +

    -s strength

    Specifies the strength value of the key. The strength is a number between 0 and 15, and currently has no defined purpose in DNSSEC.

    +
    -T rrtype
    +
    +

    + Specifies the resource record type to use for the key. + rrtype must be either DNSKEY or KEY. The + default is DNSKEY when using a DNSSEC algorithm, but it can be + overridden to KEY for use with SIG(0). +

    +

    +

    +

    + Using any TSIG algorithm (HMAC-* or DH) forces this option + to KEY. +

    +
    -t type

    Indicates the use of the key. type must be @@ -155,7 +248,78 @@

    -

    GENERATED KEYS

    +

    TIMING OPTIONS

    +

    + Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. + If the argument begins with a '+' or '-', it is interpreted as + an offset from the present time. For convenience, if such an offset + is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', + then the offset is computed in years (defined as 365 24-hour days, + ignoring leap years), months (defined as 30 24-hour days), weeks, + days, hours, or minutes, respectively. Without a suffix, the offset + is computed in seconds. +

    +
    +
    -P date/offset
    +

    + Sets the date on which a key is to be published to the zone. + After that date, the key will be included in the zone but will + not be used to sign it. If not set, and if the -G option has + not been used, the default is "now". +

    +
    -A date/offset
    +

    + Sets the date on which the key is to be activated. After that + date, the key will be included in the zone and used to sign + it. If not set, and if the -G option has not been used, the + default is "now". +

    +
    -R date/offset
    +

    + Sets the date on which the key is to be revoked. After that + date, the key will be flagged as revoked. It will be included + in the zone and will be used to sign it. +

    +
    -I date/offset
    +

    + Sets the date on which the key is to be retired. After that + date, the key will still be included in the zone, but it + will not be used to sign it. +

    +
    -D date/offset
    +

    + Sets the date on which the key is to be deleted. After that + date, the key will no longer be included in the zone. (It + may remain in the key repository, however.) +

    +
    -i interval
    +
    +

    + Sets the prepublication interval for a key. If set, then + the publication and activation dates must be separated by at least + this much time. If the activation date is specified but the + publication date isn't, then the publication date will default + to this much time before the activation date; conversely, if + the publication date is specified but activation date isn't, + then activation will be set to this much time after publication. +

    +

    + If the key is being created as an explicit successor to another + key, then the default prepublication interval is 30 days; + otherwise it is zero. +

    +

    + As with date offsets, if the argument is followed by one of + the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the + interval is measured in years, months, weeks, days, hours, + or minutes, respectively. Without a suffix, the interval is + measured in seconds. +

    +
    +
    +
    +
    +

    GENERATED KEYS

    When dnssec-keygen completes successfully, @@ -201,7 +365,7 @@

    -

    EXAMPLE

    +

    EXAMPLE

    To generate a 768-bit DSA key for the domain example.com, the following command would be @@ -222,7 +386,7 @@

    -

    SEE ALSO

    +

    SEE ALSO

    dnssec-signzone(8), BIND 9 Administrator Reference Manual, RFC 2539, @@ -231,7 +395,7 @@

    -

    AUTHOR

    +

    AUTHOR

    Internet Systems Consortium

    diff --git a/bin/dnssec/dnssec-revoke.8 b/bin/dnssec/dnssec-revoke.8 new file mode 100644 index 0000000..d57b6aa --- /dev/null +++ b/bin/dnssec/dnssec-revoke.8 @@ -0,0 +1,83 @@ +.\" Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +.\" +.\" 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 ISC DISCLAIMS ALL WARRANTIES WITH +.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +.\" AND FITNESS. IN NO EVENT SHALL ISC 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. +.\" +.\" $Id: dnssec-revoke.8,v 1.9 2010-05-19 01:14:14 tbox Exp $ +.\" +.hy 0 +.ad l +.\" Title: dnssec\-revoke +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.71.1 +.\" Date: June 1, 2009 +.\" Manual: BIND9 +.\" Source: BIND9 +.\" +.TH "DNSSEC\-REVOKE" "8" "June 1, 2009" "BIND9" "BIND9" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +dnssec\-revoke \- Set the REVOKED bit on a DNSSEC key +.SH "SYNOPSIS" +.HP 14 +\fBdnssec\-revoke\fR [\fB\-hr\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-f\fR] {keyfile} +.SH "DESCRIPTION" +.PP +\fBdnssec\-revoke\fR +reads a DNSSEC key file, sets the REVOKED bit on the key as defined in RFC 5011, and creates a new pair of key files containing the now\-revoked key. +.SH "OPTIONS" +.PP +\-h +.RS 4 +Emit usage message and exit. +.RE +.PP +\-K \fIdirectory\fR +.RS 4 +Sets the directory in which the key files are to reside. +.RE +.PP +\-r +.RS 4 +After writing the new keyset files remove the original keyset files. +.RE +.PP +\-v \fIlevel\fR +.RS 4 +Sets the debugging level. +.RE +.PP +\-E \fIengine\fR +.RS 4 +Use the given OpenSSL engine. When compiled with PKCS#11 support it defaults to pkcs11; the empty name resets it to no engine. +.RE +.PP +\-f +.RS 4 +Force overwrite: Causes +\fBdnssec\-revoke\fR +to write the new key pair even if a file already exists matching the algorithm and key ID of the revoked key. +.RE +.SH "SEE ALSO" +.PP +\fBdnssec\-keygen\fR(8), +BIND 9 Administrator Reference Manual, +RFC 5011. +.SH "AUTHOR" +.PP +Internet Systems Consortium +.SH "COPYRIGHT" +Copyright \(co 2009 Internet Systems Consortium, Inc. ("ISC") +.br diff --git a/bin/dnssec/dnssec-revoke.c b/bin/dnssec/dnssec-revoke.c new file mode 100644 index 0000000..90e905c --- /dev/null +++ b/bin/dnssec/dnssec-revoke.c @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: dnssec-revoke.c,v 1.22 2010-05-06 23:50:56 tbox Exp $ */ + +/*! \file */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "dnssectool.h" + +const char *program = "dnssec-revoke"; +int verbose; + +static isc_mem_t *mctx = NULL; + +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + +static void +usage(void) { + fprintf(stderr, "Usage:\n"); + fprintf(stderr, " %s [options] keyfile\n\n", program); + fprintf(stderr, "Version: %s\n", VERSION); +#ifdef USE_PKCS11 + fprintf(stderr, " -E engine: specify OpenSSL engine " + "(default \"pkcs11\")\n"); +#else + fprintf(stderr, " -E engine: specify OpenSSL engine\n"); +#endif + fprintf(stderr, " -f: force overwrite\n"); + fprintf(stderr, " -K directory: use directory for key files\n"); + fprintf(stderr, " -h: help\n"); + fprintf(stderr, " -r: remove old keyfiles after " + "creating revoked version\n"); + fprintf(stderr, " -v level: set level of verbosity\n"); + fprintf(stderr, "Output:\n"); + fprintf(stderr, " K++.key, " + "K++.private\n"); + + exit (-1); +} + +int +main(int argc, char **argv) { + isc_result_t result; +#ifdef USE_PKCS11 + const char *engine = "pkcs11"; +#else + const char *engine = NULL; +#endif + char *filename = NULL, *dir = NULL; + char newname[1024], oldname[1024]; + char keystr[DST_KEY_FORMATSIZE]; + char *endp; + int ch; + isc_entropy_t *ectx = NULL; + dst_key_t *key = NULL; + isc_uint32_t flags; + isc_buffer_t buf; + isc_boolean_t force = ISC_FALSE; + isc_boolean_t remove = ISC_FALSE; + + if (argc == 1) + usage(); + + result = isc_mem_create(0, 0, &mctx); + if (result != ISC_R_SUCCESS) + fatal("Out of memory"); + + dns_result_register(); + + isc_commandline_errprint = ISC_FALSE; + + while ((ch = isc_commandline_parse(argc, argv, "E:fK:rhv:")) != -1) { + switch (ch) { + case 'E': + engine = isc_commandline_argument; + break; + case 'f': + force = ISC_TRUE; + break; + case 'K': + /* + * We don't have to copy it here, but do it to + * simplify cleanup later + */ + dir = isc_mem_strdup(mctx, isc_commandline_argument); + if (dir == NULL) { + fatal("Failed to allocate memory for " + "directory"); + } + break; + case 'r': + remove = ISC_TRUE; + break; + case 'v': + verbose = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0') + fatal("-v must be followed by a number"); + break; + case '?': + if (isc_commandline_option != '?') + fprintf(stderr, "%s: invalid argument -%c\n", + program, isc_commandline_option); + /* Falls into */ + case 'h': + usage(); + + default: + fprintf(stderr, "%s: unhandled option -%c\n", + program, isc_commandline_option); + exit(1); + } + } + + if (argc < isc_commandline_index + 1 || + argv[isc_commandline_index] == NULL) + fatal("The key file name was not specified"); + if (argc > isc_commandline_index + 1) + fatal("Extraneous arguments"); + + if (dir != NULL) { + filename = argv[isc_commandline_index]; + } else { + result = isc_file_splitpath(mctx, argv[isc_commandline_index], + &dir, &filename); + if (result != ISC_R_SUCCESS) + fatal("cannot process filename %s: %s", + argv[isc_commandline_index], + isc_result_totext(result)); + if (strcmp(dir, ".") == 0) { + isc_mem_free(mctx, dir); + dir = NULL; + } + } + + if (ectx == NULL) + setup_entropy(mctx, NULL, &ectx); + result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); + if (result != ISC_R_SUCCESS) + fatal("Could not initialize hash"); + result = dst_lib_init2(mctx, ectx, engine, + ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); + if (result != ISC_R_SUCCESS) + fatal("Could not initialize dst: %s", + isc_result_totext(result)); + isc_entropy_stopcallbacksources(ectx); + + result = dst_key_fromnamedfile(filename, dir, + DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, + mctx, &key); + if (result != ISC_R_SUCCESS) + fatal("Invalid keyfile name %s: %s", + filename, isc_result_totext(result)); + + dst_key_format(key, keystr, sizeof(keystr)); + + if (verbose > 2) + fprintf(stderr, "%s: %s\n", program, keystr); + + if (force) + set_keyversion(key); + else + check_keyversion(key, keystr); + + + flags = dst_key_flags(key); + if ((flags & DNS_KEYFLAG_REVOKE) == 0) { + isc_stdtime_t now; + + if ((flags & DNS_KEYFLAG_KSK) == 0) + fprintf(stderr, "%s: warning: Key is not flagged " + "as a KSK. Revoking a ZSK is " + "legal, but undefined.\n", + program); + + isc_stdtime_get(&now); + dst_key_settime(key, DST_TIME_REVOKE, now); + + dst_key_setflags(key, flags | DNS_KEYFLAG_REVOKE); + + isc_buffer_init(&buf, newname, sizeof(newname)); + dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf); + + if (access(newname, F_OK) == 0 && !force) { + fatal("Key file %s already exists; " + "use -f to force overwrite", newname); + } + + result = dst_key_tofile(key, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, + dir); + if (result != ISC_R_SUCCESS) { + dst_key_format(key, keystr, sizeof(keystr)); + fatal("Failed to write key %s: %s", keystr, + isc_result_totext(result)); + } + + isc_buffer_clear(&buf); + dst_key_buildfilename(key, 0, dir, &buf); + printf("%s\n", newname); + + /* + * Remove old key file, if told to (and if + * it isn't the same as the new file) + */ + if (remove && dst_key_alg(key) != DST_ALG_RSAMD5) { + isc_buffer_init(&buf, oldname, sizeof(oldname)); + dst_key_setflags(key, flags & ~DNS_KEYFLAG_REVOKE); + dst_key_buildfilename(key, DST_TYPE_PRIVATE, dir, &buf); + if (strcmp(oldname, newname) == 0) + goto cleanup; + if (access(oldname, F_OK) == 0) + unlink(oldname); + isc_buffer_clear(&buf); + dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf); + if (access(oldname, F_OK) == 0) + unlink(oldname); + } + } else { + dst_key_format(key, keystr, sizeof(keystr)); + fatal("Key %s is already revoked", keystr); + } + +cleanup: + dst_key_free(&key); + dst_lib_destroy(); + isc_hash_destroy(); + cleanup_entropy(&ectx); + if (verbose > 10) + isc_mem_stats(mctx, stdout); + if (dir != NULL) + isc_mem_free(mctx, dir); + isc_mem_destroy(&mctx); + + return (0); +} diff --git a/bin/dnssec/dnssec-revoke.docbook b/bin/dnssec/dnssec-revoke.docbook new file mode 100644 index 0000000..b7b5620 --- /dev/null +++ b/bin/dnssec/dnssec-revoke.docbook @@ -0,0 +1,149 @@ +]> + + + + + + June 1, 2009 + + + + dnssec-revoke + 8 + BIND9 + + + + dnssec-revoke + Set the REVOKED bit on a DNSSEC key + + + + + 2009 + Internet Systems Consortium, Inc. ("ISC") + + + + + + dnssec-revoke + + + + + + keyfile + + + + + DESCRIPTION + dnssec-revoke + reads a DNSSEC key file, sets the REVOKED bit on the key as defined + in RFC 5011, and creates a new pair of key files containing the + now-revoked key. + + + + + OPTIONS + + + + -h + + + Emit usage message and exit. + + + + + + -K directory + + + Sets the directory in which the key files are to reside. + + + + + + -r + + + After writing the new keyset files remove the original keyset + files. + + + + + + -v level + + + Sets the debugging level. + + + + + + -E engine + + + Use the given OpenSSL engine. When compiled with PKCS#11 support + it defaults to pkcs11; the empty name resets it to no engine. + + + + + + -f + + + Force overwrite: Causes dnssec-revoke to + write the new key pair even if a file already exists matching + the algorithm and key ID of the revoked key. + + + + + + + + SEE ALSO + + dnssec-keygen8 + , + BIND 9 Administrator Reference Manual, + RFC 5011. + + + + + AUTHOR + Internet Systems Consortium + + + + diff --git a/bin/dnssec/dnssec-revoke.html b/bin/dnssec/dnssec-revoke.html new file mode 100644 index 0000000..fad9ac5 --- /dev/null +++ b/bin/dnssec/dnssec-revoke.html @@ -0,0 +1,87 @@ + + + + + +dnssec-revoke + + +
    +
    +
    +

    Name

    +

    dnssec-revoke — Set the REVOKED bit on a DNSSEC key

    +
    +
    +

    Synopsis

    +

    dnssec-revoke [-hr] [-v level] [-K directory] [-E engine] [-f] {keyfile}

    +
    +
    +

    DESCRIPTION

    +

    dnssec-revoke + reads a DNSSEC key file, sets the REVOKED bit on the key as defined + in RFC 5011, and creates a new pair of key files containing the + now-revoked key. +

    +
    +
    +

    OPTIONS

    +
    +
    -h
    +

    + Emit usage message and exit. +

    +
    -K directory
    +

    + Sets the directory in which the key files are to reside. +

    +
    -r
    +

    + After writing the new keyset files remove the original keyset + files. +

    +
    -v level
    +

    + Sets the debugging level. +

    +
    -E engine
    +

    + Use the given OpenSSL engine. When compiled with PKCS#11 support + it defaults to pkcs11; the empty name resets it to no engine. +

    +
    -f
    +

    + Force overwrite: Causes dnssec-revoke to + write the new key pair even if a file already exists matching + the algorithm and key ID of the revoked key. +

    +
    +
    +
    +

    SEE ALSO

    +

    dnssec-keygen(8), + BIND 9 Administrator Reference Manual, + RFC 5011. +

    +
    +
    +

    AUTHOR

    +

    Internet Systems Consortium +

    +
    +
    + diff --git a/bin/dnssec/dnssec-settime.8 b/bin/dnssec/dnssec-settime.8 new file mode 100644 index 0000000..4390494 --- /dev/null +++ b/bin/dnssec/dnssec-settime.8 @@ -0,0 +1,166 @@ +.\" Copyright (C) 2009, 2010 Internet Systems Consortium, Inc. ("ISC") +.\" +.\" 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 ISC DISCLAIMS ALL WARRANTIES WITH +.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +.\" AND FITNESS. IN NO EVENT SHALL ISC 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. +.\" +.\" $Id: dnssec-settime.8,v 1.14 2010-08-17 01:15:26 tbox Exp $ +.\" +.hy 0 +.ad l +.\" Title: dnssec\-settime +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.71.1 +.\" Date: July 15, 2009 +.\" Manual: BIND9 +.\" Source: BIND9 +.\" +.TH "DNSSEC\-SETTIME" "8" "July 15, 2009" "BIND9" "BIND9" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +dnssec\-settime \- Set the key timing metadata for a DNSSEC key +.SH "SYNOPSIS" +.HP 15 +\fBdnssec\-settime\fR [\fB\-f\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-P\ \fR\fB\fIdate/offset\fR\fR] [\fB\-A\ \fR\fB\fIdate/offset\fR\fR] [\fB\-R\ \fR\fB\fIdate/offset\fR\fR] [\fB\-I\ \fR\fB\fIdate/offset\fR\fR] [\fB\-D\ \fR\fB\fIdate/offset\fR\fR] [\fB\-h\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] {keyfile} +.SH "DESCRIPTION" +.PP +\fBdnssec\-settime\fR +reads a DNSSEC private key file and sets the key timing metadata as specified by the +\fB\-P\fR, +\fB\-A\fR, +\fB\-R\fR, +\fB\-I\fR, and +\fB\-D\fR +options. The metadata can then be used by +\fBdnssec\-signzone\fR +or other signing software to determine when a key is to be published, whether it should be used for signing a zone, etc. +.PP +If none of these options is set on the command line, then +\fBdnssec\-settime\fR +simply prints the key timing metadata already stored in the key. +.PP +When key metadata fields are changed, both files of a key pair (\fIKnnnn.+aaa+iiiii.key\fR +and +\fIKnnnn.+aaa+iiiii.private\fR) are regenerated. Metadata fields are stored in the private file. A human\-readable description of the metadata is also placed in comments in the key file. +.SH "OPTIONS" +.PP +\-f +.RS 4 +Force an update of an old\-format key with no metadata fields. Without this option, +\fBdnssec\-settime\fR +will fail when attempting to update a legacy key. With this option, the key will be recreated in the new format, but with the original key data retained. The key's creation date will be set to the present time. +.RE +.PP +\-K \fIdirectory\fR +.RS 4 +Sets the directory in which the key files are to reside. +.RE +.PP +\-h +.RS 4 +Emit usage message and exit. +.RE +.PP +\-v \fIlevel\fR +.RS 4 +Sets the debugging level. +.RE +.PP +\-E \fIengine\fR +.RS 4 +Use the given OpenSSL engine. When compiled with PKCS#11 support it defaults to pkcs11; the empty name resets it to no engine. +.RE +.SH "TIMING OPTIONS" +.PP +Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the argument begins with a '+' or '\-', it is interpreted as an offset from the present time. For convenience, if such an offset is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the offset is computed in years (defined as 365 24\-hour days, ignoring leap years), months (defined as 30 24\-hour days), weeks, days, hours, or minutes, respectively. Without a suffix, the offset is computed in seconds. To unset a date, use 'none'. +.PP +\-P \fIdate/offset\fR +.RS 4 +Sets the date on which a key is to be published to the zone. After that date, the key will be included in the zone but will not be used to sign it. +.RE +.PP +\-A \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be activated. After that date, the key will be included in the zone and used to sign it. +.RE +.PP +\-R \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be revoked. After that date, the key will be flagged as revoked. It will be included in the zone and will be used to sign it. +.RE +.PP +\-I \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be retired. After that date, the key will still be included in the zone, but it will not be used to sign it. +.RE +.PP +\-D \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be deleted. After that date, the key will no longer be included in the zone. (It may remain in the key repository, however.) +.RE +.PP +\-S \fIpredecessor key\fR +.RS 4 +Select a key for which the key being modified will be an explicit successor. The name, algorithm, size, and type of the predecessor key must exactly match those of the key being modified. The activation date of the successor key will be set to the inactivation date of the predecessor. The publication date will be set to the activation date minus the prepublication interval, which defaults to 30 days. +.RE +.PP +\-i \fIinterval\fR +.RS 4 +Sets the prepublication interval for a key. If set, then the publication and activation dates must be separated by at least this much time. If the activation date is specified but the publication date isn't, then the publication date will default to this much time before the activation date; conversely, if the publication date is specified but activation date isn't, then activation will be set to this much time after publication. +.sp +If the key is being set to be an explicit successor to another key, then the default prepublication interval is 30 days; otherwise it is zero. +.sp +As with date offsets, if the argument is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the interval is measured in years, months, weeks, days, hours, or minutes, respectively. Without a suffix, the interval is measured in seconds. +.RE +.SH "PRINTING OPTIONS" +.PP +\fBdnssec\-settime\fR +can also be used to print the timing metadata associated with a key. +.PP +\-u +.RS 4 +Print times in UNIX epoch format. +.RE +.PP +\-p \fIC/P/A/R/I/D/all\fR +.RS 4 +Print a specific metadata value or set of metadata values. The +\fB\-p\fR +option may be followed by one or more of the following letters to indicate which value or values to print: +\fBC\fR +for the creation date, +\fBP\fR +for the publication date, +\fBA\fR +for the activation date, +\fBR\fR +for the revocation date, +\fBI\fR +for the inactivation date, or +\fBD\fR +for the deletion date. To print all of the metadata, use +\fB\-p all\fR. +.RE +.SH "SEE ALSO" +.PP +\fBdnssec\-keygen\fR(8), +\fBdnssec\-signzone\fR(8), +BIND 9 Administrator Reference Manual, +RFC 5011. +.SH "AUTHOR" +.PP +Internet Systems Consortium +.SH "COPYRIGHT" +Copyright \(co 2009, 2010 Internet Systems Consortium, Inc. ("ISC") +.br diff --git a/bin/dnssec/dnssec-settime.c b/bin/dnssec/dnssec-settime.c new file mode 100644 index 0000000..364e2ab --- /dev/null +++ b/bin/dnssec/dnssec-settime.c @@ -0,0 +1,576 @@ +/* + * Copyright (C) 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: dnssec-settime.c,v 1.28 2010-12-19 07:29:36 each Exp $ */ + +/*! \file */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "dnssectool.h" + +const char *program = "dnssec-settime"; +int verbose; + +static isc_mem_t *mctx = NULL; + +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + +static void +usage(void) { + fprintf(stderr, "Usage:\n"); + fprintf(stderr, " %s [options] keyfile\n\n", program); + fprintf(stderr, "Version: %s\n", VERSION); + fprintf(stderr, "General options:\n"); +#ifdef USE_PKCS11 + fprintf(stderr, " -E engine: specify OpenSSL engine " + "(default \"pkcs11\")\n"); +#else + fprintf(stderr, " -E engine: specify OpenSSL engine\n"); +#endif + fprintf(stderr, " -f: force update of old-style " + "keys\n"); + fprintf(stderr, " -K directory: set key file location\n"); + fprintf(stderr, " -v level: set level of verbosity\n"); + fprintf(stderr, " -h: help\n"); + fprintf(stderr, "Timing options:\n"); + fprintf(stderr, " -P date/[+-]offset/none: set/unset key " + "publication date\n"); + fprintf(stderr, " -A date/[+-]offset/none: set/unset key " + "activation date\n"); + fprintf(stderr, " -R date/[+-]offset/none: set/unset key " + "revocation date\n"); + fprintf(stderr, " -I date/[+-]offset/none: set/unset key " + "inactivation date\n"); + fprintf(stderr, " -D date/[+-]offset/none: set/unset key " + "deletion date\n"); + fprintf(stderr, "Printing options:\n"); + fprintf(stderr, " -p C/P/A/R/I/D/all: print a particular time " + "value or values " + "[default: all]\n"); + fprintf(stderr, " -u: print times in unix epoch " + "format\n"); + fprintf(stderr, "Output:\n"); + fprintf(stderr, " K++.key, " + "K++.private\n"); + + exit (-1); +} + +static void +printtime(dst_key_t *key, int type, const char *tag, isc_boolean_t epoch, + FILE *stream) +{ + isc_result_t result; + const char *output = NULL; + isc_stdtime_t when; + + if (tag != NULL) + fprintf(stream, "%s: ", tag); + + result = dst_key_gettime(key, type, &when); + if (result == ISC_R_NOTFOUND) { + fprintf(stream, "UNSET\n"); + } else if (epoch) { + fprintf(stream, "%d\n", (int) when); + } else { + time_t time = when; + output = ctime(&time); + fprintf(stream, "%s", output); + } +} + +int +main(int argc, char **argv) { + isc_result_t result; +#ifdef USE_PKCS11 + const char *engine = "pkcs11"; +#else + const char *engine = NULL; +#endif + char *filename = NULL, *directory = NULL; + char newname[1024]; + char keystr[DST_KEY_FORMATSIZE]; + char *endp, *p; + int ch; + isc_entropy_t *ectx = NULL; + const char *predecessor = NULL; + dst_key_t *prevkey = NULL; + dst_key_t *key = NULL; + isc_buffer_t buf; + dns_name_t *name = NULL; + dns_secalg_t alg = 0; + unsigned int size = 0; + isc_uint16_t flags = 0; + int prepub = -1; + isc_stdtime_t now; + isc_stdtime_t pub = 0, act = 0, rev = 0, inact = 0, del = 0; + isc_boolean_t setpub = ISC_FALSE, setact = ISC_FALSE; + isc_boolean_t setrev = ISC_FALSE, setinact = ISC_FALSE; + isc_boolean_t setdel = ISC_FALSE; + isc_boolean_t unsetpub = ISC_FALSE, unsetact = ISC_FALSE; + isc_boolean_t unsetrev = ISC_FALSE, unsetinact = ISC_FALSE; + isc_boolean_t unsetdel = ISC_FALSE; + isc_boolean_t printcreate = ISC_FALSE, printpub = ISC_FALSE; + isc_boolean_t printact = ISC_FALSE, printrev = ISC_FALSE; + isc_boolean_t printinact = ISC_FALSE, printdel = ISC_FALSE; + isc_boolean_t force = ISC_FALSE; + isc_boolean_t epoch = ISC_FALSE; + isc_boolean_t changed = ISC_FALSE; + + if (argc == 1) + usage(); + + result = isc_mem_create(0, 0, &mctx); + if (result != ISC_R_SUCCESS) + fatal("Out of memory"); + + dns_result_register(); + + isc_commandline_errprint = ISC_FALSE; + + isc_stdtime_get(&now); + +#define CMDLINE_FLAGS "A:D:E:fhI:i:K:P:p:R:S:uv:" + while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { + switch (ch) { + case 'E': + engine = isc_commandline_argument; + break; + case 'f': + force = ISC_TRUE; + break; + case 'p': + p = isc_commandline_argument; + if (!strcasecmp(p, "all")) { + printcreate = ISC_TRUE; + printpub = ISC_TRUE; + printact = ISC_TRUE; + printrev = ISC_TRUE; + printinact = ISC_TRUE; + printdel = ISC_TRUE; + break; + } + + do { + switch (*p++) { + case 'C': + printcreate = ISC_TRUE; + break; + case 'P': + printpub = ISC_TRUE; + break; + case 'A': + printact = ISC_TRUE; + break; + case 'R': + printrev = ISC_TRUE; + break; + case 'I': + printinact = ISC_TRUE; + break; + case 'D': + printdel = ISC_TRUE; + break; + case ' ': + break; + default: + usage(); + break; + } + } while (*p != '\0'); + break; + case 'u': + epoch = ISC_TRUE; + break; + case 'K': + /* + * We don't have to copy it here, but do it to + * simplify cleanup later + */ + directory = isc_mem_strdup(mctx, + isc_commandline_argument); + if (directory == NULL) { + fatal("Failed to allocate memory for " + "directory"); + } + break; + case 'v': + verbose = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0') + fatal("-v must be followed by a number"); + break; + case 'P': + if (setpub || unsetpub) + fatal("-P specified more than once"); + + changed = ISC_TRUE; + if (!strcasecmp(isc_commandline_argument, "none")) { + unsetpub = ISC_TRUE; + } else { + setpub = ISC_TRUE; + pub = strtotime(isc_commandline_argument, + now, now); + } + break; + case 'A': + if (setact || unsetact) + fatal("-A specified more than once"); + + changed = ISC_TRUE; + if (!strcasecmp(isc_commandline_argument, "none")) { + unsetact = ISC_TRUE; + } else { + setact = ISC_TRUE; + act = strtotime(isc_commandline_argument, + now, now); + } + break; + case 'R': + if (setrev || unsetrev) + fatal("-R specified more than once"); + + changed = ISC_TRUE; + if (!strcasecmp(isc_commandline_argument, "none")) { + unsetrev = ISC_TRUE; + } else { + setrev = ISC_TRUE; + rev = strtotime(isc_commandline_argument, + now, now); + } + break; + case 'I': + if (setinact || unsetinact) + fatal("-I specified more than once"); + + changed = ISC_TRUE; + if (!strcasecmp(isc_commandline_argument, "none")) { + unsetinact = ISC_TRUE; + } else { + setinact = ISC_TRUE; + inact = strtotime(isc_commandline_argument, + now, now); + } + break; + case 'D': + if (setdel || unsetdel) + fatal("-D specified more than once"); + + changed = ISC_TRUE; + if (!strcasecmp(isc_commandline_argument, "none")) { + unsetdel = ISC_TRUE; + } else { + setdel = ISC_TRUE; + del = strtotime(isc_commandline_argument, + now, now); + } + break; + case 'S': + predecessor = isc_commandline_argument; + break; + case 'i': + prepub = strtottl(isc_commandline_argument); + break; + case '?': + if (isc_commandline_option != '?') + fprintf(stderr, "%s: invalid argument -%c\n", + program, isc_commandline_option); + /* Falls into */ + case 'h': + usage(); + + default: + fprintf(stderr, "%s: unhandled option -%c\n", + program, isc_commandline_option); + exit(1); + } + } + + if (argc < isc_commandline_index + 1 || + argv[isc_commandline_index] == NULL) + fatal("The key file name was not specified"); + if (argc > isc_commandline_index + 1) + fatal("Extraneous arguments"); + + if (ectx == NULL) + setup_entropy(mctx, NULL, &ectx); + result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); + if (result != ISC_R_SUCCESS) + fatal("Could not initialize hash"); + result = dst_lib_init2(mctx, ectx, engine, + ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); + if (result != ISC_R_SUCCESS) + fatal("Could not initialize dst: %s", + isc_result_totext(result)); + isc_entropy_stopcallbacksources(ectx); + + if (predecessor != NULL) { + char keystr[DST_KEY_FORMATSIZE]; + isc_stdtime_t when; + int major, minor; + + if (prepub == -1) + prepub = (30 * 86400); + + if (setpub || unsetpub) + fatal("-S and -P cannot be used together"); + if (setact || unsetact) + fatal("-S and -A cannot be used together"); + + result = dst_key_fromnamedfile(predecessor, directory, + DST_TYPE_PUBLIC | + DST_TYPE_PRIVATE, + mctx, &prevkey); + if (result != ISC_R_SUCCESS) + fatal("Invalid keyfile %s: %s", + filename, isc_result_totext(result)); + if (!dst_key_isprivate(prevkey)) + fatal("%s is not a private key", filename); + + name = dst_key_name(prevkey); + alg = dst_key_alg(prevkey); + size = dst_key_size(prevkey); + flags = dst_key_flags(prevkey); + + dst_key_format(prevkey, keystr, sizeof(keystr)); + dst_key_getprivateformat(prevkey, &major, &minor); + if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) + fatal("Predecessor has incompatible format " + "version %d.%d\n\t", major, minor); + + result = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &when); + if (result != ISC_R_SUCCESS) + fatal("Predecessor has no activation date. " + "You must set one before\n\t" + "generating a successor."); + + result = dst_key_gettime(prevkey, DST_TIME_INACTIVE, &act); + if (result != ISC_R_SUCCESS) + fatal("Predecessor has no inactivation date. " + "You must set one before\n\t" + "generating a successor."); + + pub = act - prepub; + if (pub < now && prepub != 0) + fatal("Predecessor will become inactive before the\n\t" + "prepublication period ends. Either change " + "its inactivation date,\n\t" + "or use the -i option to set a shorter " + "prepublication interval."); + + result = dst_key_gettime(prevkey, DST_TIME_DELETE, &when); + if (result != ISC_R_SUCCESS) + fprintf(stderr, "%s: WARNING: Predecessor has no " + "removal date;\n\t" + "it will remain in the zone " + "indefinitely after rollover.\n", + program); + + changed = setpub = setact = ISC_TRUE; + dst_key_free(&prevkey); + } else { + if (prepub < 0) + prepub = 0; + + if (prepub > 0) { + if (setpub && setact && (act - prepub) < pub) + fatal("Activation and publication dates " + "are closer together than the\n\t" + "prepublication interval."); + + if (setpub && !setact) { + setact = ISC_TRUE; + act = pub + prepub; + } else if (setact && !setpub) { + setpub = ISC_TRUE; + pub = act - prepub; + } + + if ((act - prepub) < now) + fatal("Time until activation is shorter " + "than the\n\tprepublication interval."); + } + } + + if (directory != NULL) { + filename = argv[isc_commandline_index]; + } else { + result = isc_file_splitpath(mctx, argv[isc_commandline_index], + &directory, &filename); + if (result != ISC_R_SUCCESS) + fatal("cannot process filename %s: %s", + argv[isc_commandline_index], + isc_result_totext(result)); + } + + result = dst_key_fromnamedfile(filename, directory, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, + mctx, &key); + if (result != ISC_R_SUCCESS) + fatal("Invalid keyfile %s: %s", + filename, isc_result_totext(result)); + + if (!dst_key_isprivate(key)) + fatal("%s is not a private key", filename); + + dst_key_format(key, keystr, sizeof(keystr)); + + if (predecessor != NULL) { + if (!dns_name_equal(name, dst_key_name(key))) + fatal("Key name mismatch"); + if (alg != dst_key_alg(key)) + fatal("Key algorithm mismatch"); + if (size != dst_key_size(key)) + fatal("Key size mismatch"); + if (flags != dst_key_flags(key)) + fatal("Key flags mismatch"); + } + + if (force) + set_keyversion(key); + else + check_keyversion(key, keystr); + + if (verbose > 2) + fprintf(stderr, "%s: %s\n", program, keystr); + + /* + * Set time values. + */ + if (setpub) + dst_key_settime(key, DST_TIME_PUBLISH, pub); + else if (unsetpub) + dst_key_unsettime(key, DST_TIME_PUBLISH); + + if (setact) + dst_key_settime(key, DST_TIME_ACTIVATE, act); + else if (unsetact) + dst_key_unsettime(key, DST_TIME_ACTIVATE); + + if (setrev) { + if ((dst_key_flags(key) & DNS_KEYFLAG_REVOKE) != 0) + fprintf(stderr, "%s: warning: Key %s is already " + "revoked; changing the revocation date " + "will not affect this.\n", + program, keystr); + if ((dst_key_flags(key) & DNS_KEYFLAG_KSK) == 0) + fprintf(stderr, "%s: warning: Key %s is not flagged as " + "a KSK, but -R was used. Revoking a " + "ZSK is legal, but undefined.\n", + program, keystr); + dst_key_settime(key, DST_TIME_REVOKE, rev); + } else if (unsetrev) { + if ((dst_key_flags(key) & DNS_KEYFLAG_REVOKE) != 0) + fprintf(stderr, "%s: warning: Key %s is already " + "revoked; removing the revocation date " + "will not affect this.\n", + program, keystr); + dst_key_unsettime(key, DST_TIME_REVOKE); + } + + if (setinact) + dst_key_settime(key, DST_TIME_INACTIVE, inact); + else if (unsetinact) + dst_key_unsettime(key, DST_TIME_INACTIVE); + + if (setdel) + dst_key_settime(key, DST_TIME_DELETE, del); + else if (unsetdel) + dst_key_unsettime(key, DST_TIME_DELETE); + + /* + * Print out time values, if -p was used. + */ + if (printcreate) + printtime(key, DST_TIME_CREATED, "Created", epoch, stdout); + + if (printpub) + printtime(key, DST_TIME_PUBLISH, "Publish", epoch, stdout); + + if (printact) + printtime(key, DST_TIME_ACTIVATE, "Activate", epoch, stdout); + + if (printrev) + printtime(key, DST_TIME_REVOKE, "Revoke", epoch, stdout); + + if (printinact) + printtime(key, DST_TIME_INACTIVE, "Inactive", epoch, stdout); + + if (printdel) + printtime(key, DST_TIME_DELETE, "Delete", epoch, stdout); + + if (changed) { + isc_buffer_init(&buf, newname, sizeof(newname)); + result = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, + &buf); + if (result != ISC_R_SUCCESS) { + fatal("Failed to build public key filename: %s", + isc_result_totext(result)); + } + + result = dst_key_tofile(key, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, + directory); + if (result != ISC_R_SUCCESS) { + dst_key_format(key, keystr, sizeof(keystr)); + fatal("Failed to write key %s: %s", keystr, + isc_result_totext(result)); + } + + printf("%s\n", newname); + + isc_buffer_clear(&buf); + result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, directory, + &buf); + if (result != ISC_R_SUCCESS) { + fatal("Failed to build private key filename: %s", + isc_result_totext(result)); + } + printf("%s\n", newname); + } + + dst_key_free(&key); + dst_lib_destroy(); + isc_hash_destroy(); + cleanup_entropy(&ectx); + if (verbose > 10) + isc_mem_stats(mctx, stdout); + isc_mem_free(mctx, directory); + isc_mem_destroy(&mctx); + + return (0); +} diff --git a/bin/dnssec/dnssec-settime.docbook b/bin/dnssec/dnssec-settime.docbook new file mode 100644 index 0000000..1096cb7 --- /dev/null +++ b/bin/dnssec/dnssec-settime.docbook @@ -0,0 +1,319 @@ +]> + + + + + + July 15, 2009 + + + + dnssec-settime + 8 + BIND9 + + + + dnssec-settime + Set the key timing metadata for a DNSSEC key + + + + + 2009 + 2010 + Internet Systems Consortium, Inc. ("ISC") + + + + + + dnssec-settime + + + + + + + + + + + keyfile + + + + + DESCRIPTION + dnssec-settime + reads a DNSSEC private key file and sets the key timing metadata + as specified by the , , + , , and + options. The metadata can then be used by + dnssec-signzone or other signing software to + determine when a key is to be published, whether it should be + used for signing a zone, etc. + + + If none of these options is set on the command line, + then dnssec-settime simply prints the key timing + metadata already stored in the key. + + + When key metadata fields are changed, both files of a key + pair (Knnnn.+aaa+iiiii.key and + Knnnn.+aaa+iiiii.private) are regenerated. + Metadata fields are stored in the private file. A human-readable + description of the metadata is also placed in comments in the key + file. + + + + + OPTIONS + + + + -f + + + Force an update of an old-format key with no metadata fields. + Without this option, dnssec-settime will + fail when attempting to update a legacy key. With this option, + the key will be recreated in the new format, but with the + original key data retained. The key's creation date will be + set to the present time. + + + + + + -K directory + + + Sets the directory in which the key files are to reside. + + + + + + -h + + + Emit usage message and exit. + + + + + + -v level + + + Sets the debugging level. + + + + + + -E engine + + + Use the given OpenSSL engine. When compiled with PKCS#11 support + it defaults to pkcs11; the empty name resets it to no engine. + + + + + + + + TIMING OPTIONS + + Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. + If the argument begins with a '+' or '-', it is interpreted as + an offset from the present time. For convenience, if such an offset + is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', + then the offset is computed in years (defined as 365 24-hour days, + ignoring leap years), months (defined as 30 24-hour days), weeks, + days, hours, or minutes, respectively. Without a suffix, the offset + is computed in seconds. To unset a date, use 'none'. + + + + + -P date/offset + + + Sets the date on which a key is to be published to the zone. + After that date, the key will be included in the zone but will + not be used to sign it. + + + + + + -A date/offset + + + Sets the date on which the key is to be activated. After that + date, the key will be included in the zone and used to sign + it. + + + + + + -R date/offset + + + Sets the date on which the key is to be revoked. After that + date, the key will be flagged as revoked. It will be included + in the zone and will be used to sign it. + + + + + + -I date/offset + + + Sets the date on which the key is to be retired. After that + date, the key will still be included in the zone, but it + will not be used to sign it. + + + + + + -D date/offset + + + Sets the date on which the key is to be deleted. After that + date, the key will no longer be included in the zone. (It + may remain in the key repository, however.) + + + + + + -S predecessor key + + + Select a key for which the key being modified will be an + explicit successor. The name, algorithm, size, and type of the + predecessor key must exactly match those of the key being + modified. The activation date of the successor key will be set + to the inactivation date of the predecessor. The publication + date will be set to the activation date minus the prepublication + interval, which defaults to 30 days. + + + + + + -i interval + + + Sets the prepublication interval for a key. If set, then + the publication and activation dates must be separated by at least + this much time. If the activation date is specified but the + publication date isn't, then the publication date will default + to this much time before the activation date; conversely, if + the publication date is specified but activation date isn't, + then activation will be set to this much time after publication. + + + If the key is being set to be an explicit successor to another + key, then the default prepublication interval is 30 days; + otherwise it is zero. + + + As with date offsets, if the argument is followed by one of + the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the + interval is measured in years, months, weeks, days, hours, + or minutes, respectively. Without a suffix, the interval is + measured in seconds. + + + + + + + + PRINTING OPTIONS + + dnssec-settime can also be used to print the + timing metadata associated with a key. + + + + + -u + + + Print times in UNIX epoch format. + + + + + + -p C/P/A/R/I/D/all + + + Print a specific metadata value or set of metadata values. + The option may be followed by one or more + of the following letters to indicate which value or values to print: + for the creation date, + for the publication date, + for the activation date, + for the revocation date, + for the inactivation date, or + for the deletion date. + To print all of the metadata, use . + + + + + + + + + SEE ALSO + + dnssec-keygen8 + , + + dnssec-signzone8 + , + BIND 9 Administrator Reference Manual, + RFC 5011. + + + + + AUTHOR + Internet Systems Consortium + + + + diff --git a/bin/dnssec/dnssec-settime.html b/bin/dnssec/dnssec-settime.html new file mode 100644 index 0000000..84c8dde --- /dev/null +++ b/bin/dnssec/dnssec-settime.html @@ -0,0 +1,208 @@ + + + + + +dnssec-settime + + +
    +
    +
    +

    Name

    +

    dnssec-settime — Set the key timing metadata for a DNSSEC key

    +
    +
    +

    Synopsis

    +

    dnssec-settime [-f] [-K directory] [-P date/offset] [-A date/offset] [-R date/offset] [-I date/offset] [-D date/offset] [-h] [-v level] [-E engine] {keyfile}

    +
    +
    +

    DESCRIPTION

    +

    dnssec-settime + reads a DNSSEC private key file and sets the key timing metadata + as specified by the -P, -A, + -R, -I, and -D + options. The metadata can then be used by + dnssec-signzone or other signing software to + determine when a key is to be published, whether it should be + used for signing a zone, etc. +

    +

    + If none of these options is set on the command line, + then dnssec-settime simply prints the key timing + metadata already stored in the key. +

    +

    + When key metadata fields are changed, both files of a key + pair (Knnnn.+aaa+iiiii.key and + Knnnn.+aaa+iiiii.private) are regenerated. + Metadata fields are stored in the private file. A human-readable + description of the metadata is also placed in comments in the key + file. +

    +
    +
    +

    OPTIONS

    +
    +
    -f
    +

    + Force an update of an old-format key with no metadata fields. + Without this option, dnssec-settime will + fail when attempting to update a legacy key. With this option, + the key will be recreated in the new format, but with the + original key data retained. The key's creation date will be + set to the present time. +

    +
    -K directory
    +

    + Sets the directory in which the key files are to reside. +

    +
    -h
    +

    + Emit usage message and exit. +

    +
    -v level
    +

    + Sets the debugging level. +

    +
    -E engine
    +

    + Use the given OpenSSL engine. When compiled with PKCS#11 support + it defaults to pkcs11; the empty name resets it to no engine. +

    +
    +
    +
    +

    TIMING OPTIONS

    +

    + Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. + If the argument begins with a '+' or '-', it is interpreted as + an offset from the present time. For convenience, if such an offset + is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', + then the offset is computed in years (defined as 365 24-hour days, + ignoring leap years), months (defined as 30 24-hour days), weeks, + days, hours, or minutes, respectively. Without a suffix, the offset + is computed in seconds. To unset a date, use 'none'. +

    +
    +
    -P date/offset
    +

    + Sets the date on which a key is to be published to the zone. + After that date, the key will be included in the zone but will + not be used to sign it. +

    +
    -A date/offset
    +

    + Sets the date on which the key is to be activated. After that + date, the key will be included in the zone and used to sign + it. +

    +
    -R date/offset
    +

    + Sets the date on which the key is to be revoked. After that + date, the key will be flagged as revoked. It will be included + in the zone and will be used to sign it. +

    +
    -I date/offset
    +

    + Sets the date on which the key is to be retired. After that + date, the key will still be included in the zone, but it + will not be used to sign it. +

    +
    -D date/offset
    +

    + Sets the date on which the key is to be deleted. After that + date, the key will no longer be included in the zone. (It + may remain in the key repository, however.) +

    +
    -S predecessor key
    +

    + Select a key for which the key being modified will be an + explicit successor. The name, algorithm, size, and type of the + predecessor key must exactly match those of the key being + modified. The activation date of the successor key will be set + to the inactivation date of the predecessor. The publication + date will be set to the activation date minus the prepublication + interval, which defaults to 30 days. +

    +
    -i interval
    +
    +

    + Sets the prepublication interval for a key. If set, then + the publication and activation dates must be separated by at least + this much time. If the activation date is specified but the + publication date isn't, then the publication date will default + to this much time before the activation date; conversely, if + the publication date is specified but activation date isn't, + then activation will be set to this much time after publication. +

    +

    + If the key is being set to be an explicit successor to another + key, then the default prepublication interval is 30 days; + otherwise it is zero. +

    +

    + As with date offsets, if the argument is followed by one of + the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the + interval is measured in years, months, weeks, days, hours, + or minutes, respectively. Without a suffix, the interval is + measured in seconds. +

    +
    +
    +
    +
    +

    PRINTING OPTIONS

    +

    + dnssec-settime can also be used to print the + timing metadata associated with a key. +

    +
    +
    -u
    +

    + Print times in UNIX epoch format. +

    +
    -p C/P/A/R/I/D/all
    +

    + Print a specific metadata value or set of metadata values. + The -p option may be followed by one or more + of the following letters to indicate which value or values to print: + C for the creation date, + P for the publication date, + A for the activation date, + R for the revocation date, + I for the inactivation date, or + D for the deletion date. + To print all of the metadata, use -p all. +

    +
    +
    +
    +

    SEE ALSO

    +

    dnssec-keygen(8), + dnssec-signzone(8), + BIND 9 Administrator Reference Manual, + RFC 5011. +

    +
    +
    +

    AUTHOR

    +

    Internet Systems Consortium +

    +
    +
    + diff --git a/bin/dnssec/dnssec-signzone.8 b/bin/dnssec/dnssec-signzone.8 index bfe7a20..9822883 100644 --- a/bin/dnssec/dnssec-signzone.8 +++ b/bin/dnssec/dnssec-signzone.8 @@ -13,18 +13,18 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: dnssec-signzone.8,v 1.47.44.8 2009-11-07 01:56:11 tbox Exp $ +.\" $Id: dnssec-signzone.8,v 1.59 2009-12-04 01:13:44 tbox Exp $ .\" .hy 0 .ad l .\" Title: dnssec\-signzone .\" Author: .\" Generator: DocBook XSL Stylesheets v1.71.1 -.\" Date: June 08, 2009 +.\" Date: June 05, 2009 .\" Manual: BIND9 .\" Source: BIND9 .\" -.TH "DNSSEC\-SIGNZONE" "8" "June 08, 2009" "BIND9" "BIND9" +.TH "DNSSEC\-SIGNZONE" "8" "June 05, 2009" "BIND9" "BIND9" .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) @@ -33,15 +33,13 @@ dnssec\-signzone \- DNSSEC zone signing tool .SH "SYNOPSIS" .HP 16 -\fBdnssec\-signzone\fR [\fB\-a\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-d\ \fR\fB\fIdirectory\fR\fR] [\fB\-e\ \fR\fB\fIend\-time\fR\fR] [\fB\-f\ \fR\fB\fIoutput\-file\fR\fR] [\fB\-g\fR] [\fB\-h\fR] [\fB\-k\ \fR\fB\fIkey\fR\fR] [\fB\-l\ \fR\fB\fIdomain\fR\fR] [\fB\-i\ \fR\fB\fIinterval\fR\fR] [\fB\-I\ \fR\fB\fIinput\-format\fR\fR] [\fB\-j\ \fR\fB\fIjitter\fR\fR] [\fB\-N\ \fR\fB\fIsoa\-serial\-format\fR\fR] [\fB\-o\ \fR\fB\fIorigin\fR\fR] [\fB\-O\ \fR\fB\fIoutput\-format\fR\fR] [\fB\-p\fR] [\fB\-P\fR] [\fB\-r\ \fR\fB\fIrandomdev\fR\fR] [\fB\-s\ \fR\fB\fIstart\-time\fR\fR] [\fB\-t\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-z\fR] [\fB\-3\ \fR\fB\fIsalt\fR\fR] [\fB\-H\ \fR\fB\fIiterations\fR\fR] [\fB\-A\fR] {zonefile} [key...] +\fBdnssec\-signzone\fR [\fB\-a\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-d\ \fR\fB\fIdirectory\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-e\ \fR\fB\fIend\-time\fR\fR] [\fB\-f\ \fR\fB\fIoutput\-file\fR\fR] [\fB\-g\fR] [\fB\-h\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-k\ \fR\fB\fIkey\fR\fR] [\fB\-l\ \fR\fB\fIdomain\fR\fR] [\fB\-i\ \fR\fB\fIinterval\fR\fR] [\fB\-I\ \fR\fB\fIinput\-format\fR\fR] [\fB\-j\ \fR\fB\fIjitter\fR\fR] [\fB\-N\ \fR\fB\fIsoa\-serial\-format\fR\fR] [\fB\-o\ \fR\fB\fIorigin\fR\fR] [\fB\-O\ \fR\fB\fIoutput\-format\fR\fR] [\fB\-p\fR] [\fB\-P\fR] [\fB\-r\ \fR\fB\fIrandomdev\fR\fR] [\fB\-S\fR] [\fB\-s\ \fR\fB\fIstart\-time\fR\fR] [\fB\-T\ \fR\fB\fIttl\fR\fR] [\fB\-t\fR] [\fB\-u\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-x\fR] [\fB\-z\fR] [\fB\-3\ \fR\fB\fIsalt\fR\fR] [\fB\-H\ \fR\fB\fIiterations\fR\fR] [\fB\-A\fR] {zonefile} [key...] .SH "DESCRIPTION" .PP \fBdnssec\-signzone\fR -signs a zone. It generates NSEC and RRSIG records and produces a signed version of the zone. It also generates a -\fIkeyset\-\fR -file containing the key\-signing keys for the zone, and if signing a zone which contains delegations, it can optionally generate DS records for the child zones from their -\fIkeyset\-\fR -files. +signs a zone. It generates NSEC and RRSIG records and produces a signed version of the zone. The security status of delegations from the signed zone (that is, whether the child zones are secure or not) is determined by the presence or absence of a +\fIkeyset\fR +file for each child zone. .SH "OPTIONS" .PP \-a @@ -54,30 +52,53 @@ Verify all generated signatures. Specifies the DNS class of the zone. .RE .PP -\-k \fIkey\fR -.RS 4 -Treat specified key as a key signing key ignoring any key flags. This option may be specified multiple times. -.RE -.PP -\-l \fIdomain\fR +\-C .RS 4 -Generate a DLV set in addition to the key (DNSKEY) and DS sets. The domain is appended to the name of the records. +Compatibility mode: Generate a +\fIkeyset\-\fR\fI\fIzonename\fR\fR +file in addition to +\fIdsset\-\fR\fI\fIzonename\fR\fR +when signing a zone, for use by older versions of +\fBdnssec\-signzone\fR. .RE .PP \-d \fIdirectory\fR .RS 4 Look for -\fIkeyset\fR +\fIdsset\-\fR +or +\fIkeyset\-\fR files in -\fBdirectory\fR -as the directory +\fBdirectory\fR. +.RE +.PP +\-E \fIengine\fR +.RS 4 +Uses a crypto hardware (OpenSSL engine) for the crypto operations it supports, for instance signing with private keys from a secure key store. When compiled with PKCS#11 support it defaults to pkcs11; the empty name resets it to no engine. .RE .PP \-g .RS 4 -If the zone contains any delegations, and there are +Generate DS records for child zones from +\fIdsset\-\fR +or \fIkeyset\-\fR -files for any of the child zones, then DS records for the child zones will be generated from the keys in those files. Existing DS records will be removed. +file. Existing DS records will be removed. +.RE +.PP +\-K \fIdirectory\fR +.RS 4 +Key repository: Specify a directory to search for DNSSEC keys. If not specified, defaults to the current directory. +.RE +.PP +\-k \fIkey\fR +.RS 4 +Treat specified key as a key signing key ignoring any key flags. This option may be specified multiple times. +.RE +.PP +\-l \fIdomain\fR +.RS 4 +Generate a DLV set in addition to the key (DNSKEY) and DS sets. The domain is appended to the name of the records. .RE .PP \-s \fIstart\-time\fR @@ -93,6 +114,9 @@ Specify the date and time when the generated RRSIG records expire. As with \fBstart\-time\fR, an absolute time is indicated in YYYYMMDDHHMMSS notation. A time relative to the start time is indicated with +N, which is N seconds from the start time. A time relative to the current time is indicated with now+N. If no \fBend\-time\fR is specified, 30 days from the start time is used as a default. +\fBend\-time\fR +must be later than +\fBstart\-time\fR. .RE .PP \-f \fIoutput\-file\fR @@ -208,34 +232,94 @@ specifies the name of a character device or file containing random data to be us indicates that keyboard input should be used. .RE .PP +\-S +.RS 4 +Smart signing: Instructs +\fBdnssec\-signzone\fR +to search the key repository for keys that match the zone being signed, and to include them in the zone if appropriate. +.sp +When a key is found, its timing metadata is examined to determine how it should be used, according to the following rules. Each successive rule takes priority over the prior ones: +.RS 4 +.PP +.RS 4 +If no timing metadata has been set for the key, the key is published in the zone and used to sign the zone. +.RE +.PP +.RS 4 +If the key's publication date is set and is in the past, the key is published in the zone. +.RE +.PP +.RS 4 +If the key's activation date is set and in the past, the key is published (regardless of publication date) and used to sign the zone. +.RE +.PP +.RS 4 +If the key's revocation date is set and in the past, and the key is published, then the key is revoked, and the revoked key is used to sign the zone. +.RE +.PP +.RS 4 +If either of the key's unpublication or deletion dates are set and in the past, the key is NOT published or used to sign the zone, regardless of any other metadata. +.RE +.RE +.RE +.PP +\-T \fIttl\fR +.RS 4 +Specifies the TTL to be used for new DNSKEY records imported into the zone from the key repository. If not specified, the default is the minimum TTL value from the zone's SOA record. This option is ignored when signing without +\fB\-S\fR, since DNSKEY records are not imported from the key repository in that case. It is also ignored if there are any pre\-existing DNSKEY records at the zone apex, in which case new records' TTL values will be set to match them. +.RE +.PP \-t .RS 4 Print statistics at completion. .RE .PP +\-u +.RS 4 +Update NSEC/NSEC3 chain when re\-signing a previously signed zone. With this option, a zone signed with NSEC can be switched to NSEC3, or a zone signed with NSEC3 can be switch to NSEC or to NSEC3 with different parameters. Without this option, +\fBdnssec\-signzone\fR +will retain the existing chain when re\-signing. +.RE +.PP \-v \fIlevel\fR .RS 4 Sets the debugging level. .RE .PP +\-x +.RS 4 +Only sign the DNSKEY RRset with key\-signing keys, and omit signatures from zone\-signing keys. (This is similar to the +\fBdnssec\-dnskey\-kskonly yes;\fR +zone option in +\fBnamed\fR.) +.RE +.PP \-z .RS 4 -Ignore KSK flag on key when determining what to sign. +Ignore KSK flag on key when determining what to sign. This causes KSK\-flagged keys to sign all records, not just the DNSKEY RRset. (This is similar to the +\fBupdate\-check\-ksk no;\fR +zone option in +\fBnamed\fR.) .RE .PP \-3 \fIsalt\fR .RS 4 -Generate a NSEC3 chain with the given hex encoded salt. A dash (\fIsalt\fR) can be used to indicate that no salt is to be used when generating the NSEC3 chain. +Generate an NSEC3 chain with the given hex encoded salt. A dash (\fIsalt\fR) can be used to indicate that no salt is to be used when generating the NSEC3 chain. .RE .PP \-H \fIiterations\fR .RS 4 -When generating a NSEC3 chain use this many interations. The default is 100. +When generating an NSEC3 chain, use this many interations. The default is 10. .RE .PP \-A .RS 4 -When generating a NSEC3 chain set the OPTOUT flag on all NSEC3 records and do not generate NSEC3 records for insecure delegations. +When generating an NSEC3 chain set the OPTOUT flag on all NSEC3 records and do not generate NSEC3 records for insecure delegations. +.sp +Using this option twice (i.e., +\fB\-AA\fR) turns the OPTOUT flag off for all records. This is useful when using the +\fB\-u\fR +option to modify an NSEC3 chain which previously had OPTOUT set. .RE .PP zonefile @@ -253,9 +337,11 @@ The following command signs the \fBexample.com\fR zone with the DSA key generated by \fBdnssec\-keygen\fR -(Kexample.com.+003+17247). The zone's keys must be in the master file (\fIdb.example.com\fR). This invocation looks for -\fIkeyset\fR -files, in the current directory, so that DS records can be generated from them (\fB\-g\fR). +(Kexample.com.+003+17247). Because the +\fB\-S\fR +option is not being used, the zone's keys must be in the master file (\fIdb.example.com\fR). This invocation looks for +\fIdsset\fR +files, in the current directory, so that DS records can be imported from them (\fB\-g\fR). .sp .RS 4 .nf @@ -283,18 +369,6 @@ db.example.com.signed % .fi .RE -.SH "KNOWN BUGS" -.PP -\fBdnssec\-signzone\fR -was designed so that it could sign a zone partially, using only a subset of the DNSSEC keys needed to produce a fully\-signed zone. This permits a zone administrator, for example, to sign a zone with one key on one machine, move the resulting partially\-signed zone to a second machine, and sign it again with a second key. -.PP -An unfortunate side\-effect of this flexibility is that -\fBdnssec\-signzone\fR -does not check to make sure it's signing a zone with any valid keys at all. An attempt to sign a zone without any keys will appear to succeed, producing a "signed" zone with no signatures. There is no warning issued when a zone is not fully signed. -.PP -This will be corrected in a future release. In the meantime, ISC recommends examining the output of -\fBdnssec\-signzone\fR -to confirm that the zone is properly signed by all keys before using it. .SH "SEE ALSO" .PP \fBdnssec\-keygen\fR(8), diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c index b8f4d66..3997a13 100644 --- a/bin/dnssec/dnssec-signzone.c +++ b/bin/dnssec/dnssec-signzone.c @@ -29,7 +29,7 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-signzone.c,v 1.209.12.20 2010-06-03 23:47:48 tbox Exp $ */ +/* $Id: dnssec-signzone.c,v 1.262 2010-06-03 23:51:04 tbox Exp $ */ /*! \file */ @@ -87,6 +87,10 @@ #include "dnssectool.h" +#ifndef PATH_MAX +#define PATH_MAX 1024 /* AIX, WIN32, and others don't define this. */ +#endif + const char *program = "dnssec-signzone"; int verbose; @@ -97,22 +101,11 @@ static int nsec_datatype = dns_rdatatype_nsec; #define IS_NSEC3 (nsec_datatype == dns_rdatatype_nsec3) #define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0) +#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0) + #define BUFSIZE 2048 #define MAXDSKEYS 8 -typedef struct signer_key_struct signer_key_t; - -struct signer_key_struct { - dst_key_t *key; - isc_boolean_t issigningkey; - isc_boolean_t isdsk; - isc_boolean_t isksk; - isc_boolean_t wasused; - isc_boolean_t commandline; - unsigned int position; - ISC_LINK(signer_key_t) link; -}; - #define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453) #define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0) #define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1) @@ -128,7 +121,7 @@ struct signer_event { dns_dbnode_t *node; }; -static ISC_LIST(signer_key_t) keylist; +static dns_dnsseckeylist_t keylist; static unsigned int keycount = 0; isc_rwlock_t keylist_lock; static isc_stdtime_t starttime = 0, endtime = 0, now; @@ -138,7 +131,8 @@ static isc_boolean_t tryverify = ISC_FALSE; static isc_boolean_t printstats = ISC_FALSE; static isc_mem_t *mctx = NULL; static isc_entropy_t *ectx = NULL; -static dns_ttl_t zonettl; +static dns_ttl_t zone_soa_min_ttl; +static dns_ttl_t soa_ttl; static FILE *fp; static char *tempfile = NULL; static const dns_master_style_t *masterstyle; @@ -146,7 +140,7 @@ static dns_masterformat_t inputformat = dns_masterformat_text; static dns_masterformat_t outputformat = dns_masterformat_text; static unsigned int nsigned = 0, nretained = 0, ndropped = 0; static unsigned int nverified = 0, nverifyfailed = 0; -static const char *directory; +static const char *directory = NULL, *dsdir = NULL; static isc_mutex_t namelock, statslock; static isc_taskmgr_t *taskmgr = NULL; static dns_db_t *gdb; /* The database */ @@ -155,13 +149,18 @@ static dns_dbiterator_t *gdbiter; /* The database iterator */ static dns_rdataclass_t gclass; /* The class */ static dns_name_t *gorigin; /* The database origin */ static int nsec3flags = 0; +static dns_iterations_t nsec3iter = 10U; +static unsigned char saltbuf[255]; +static unsigned char *salt = saltbuf; +static size_t salt_length = 0; static isc_task_t *master = NULL; static unsigned int ntasks = 0; static isc_boolean_t shuttingdown = ISC_FALSE, finished = ISC_FALSE; static isc_boolean_t nokeys = ISC_FALSE; static isc_boolean_t removefile = ISC_FALSE; static isc_boolean_t generateds = ISC_FALSE; -static isc_boolean_t ignoreksk = ISC_FALSE; +static isc_boolean_t ignore_kskflag = ISC_FALSE; +static isc_boolean_t keyset_kskonly = ISC_FALSE; static dns_name_t *dlv = NULL; static dns_fixedname_t dlv_fixed; static dns_master_style_t *dsstyle = NULL; @@ -169,6 +168,9 @@ static unsigned int serialformat = SOA_SERIAL_KEEP; static unsigned int hash_length = 0; static isc_boolean_t unknownalg = ISC_FALSE; static isc_boolean_t disable_zone_check = ISC_FALSE; +static isc_boolean_t update_chain = ISC_FALSE; +static isc_boolean_t set_keyttl = ISC_FALSE; +static dns_ttl_t keyttl; #define INCSTAT(counter) \ if (printstats) { \ @@ -195,48 +197,23 @@ dumpnode(dns_name_t *name, dns_dbnode_t *node) { check_result(result, "dns_master_dumpnodetostream"); } -static signer_key_t * -newkeystruct(dst_key_t *dstkey, isc_boolean_t signwithkey) { - signer_key_t *key; - - key = isc_mem_get(mctx, sizeof(signer_key_t)); - if (key == NULL) - fatal("out of memory"); - key->key = dstkey; - if ((dst_key_flags(dstkey) & DNS_KEYFLAG_KSK) != 0) { - key->issigningkey = signwithkey; - key->isksk = ISC_TRUE; - key->isdsk = ISC_FALSE; - } else { - key->issigningkey = signwithkey; - key->isksk = ISC_FALSE; - key->isdsk = ISC_TRUE; - } - key->wasused = ISC_FALSE; - key->commandline = ISC_FALSE; - key->position = keycount++; - ISC_LINK_INIT(key, link); - return (key); -} - /*% * Sign the given RRset with given key, and add the signature record to the * given tuple. */ - static void signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key, dns_ttl_t ttl, dns_diff_t *add, const char *logmsg) { isc_result_t result; isc_stdtime_t jendtime; - char keystr[KEY_FORMATSIZE]; + char keystr[DST_KEY_FORMATSIZE]; dns_rdata_t trdata = DNS_RDATA_INIT; unsigned char array[BUFSIZE]; isc_buffer_t b; dns_difftuple_t *tuple; - key_format(key, keystr, sizeof(keystr)); + dst_key_format(key, keystr, sizeof(keystr)); vbprintf(1, "\t%s %s\n", logmsg, keystr); jendtime = (jitter != 0) ? isc_random_jitter(endtime, jitter) : endtime; @@ -245,8 +222,8 @@ signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key, mctx, &b, &trdata); isc_entropy_stopcallbacksources(ectx); if (result != ISC_R_SUCCESS) { - char keystr[KEY_FORMATSIZE]; - key_format(key, keystr, sizeof(keystr)); + char keystr[DST_KEY_FORMATSIZE]; + dst_key_format(key, keystr, sizeof(keystr)); fatal("dnskey '%s' failed to sign data: %s", keystr, isc_result_totext(result)); } @@ -272,31 +249,43 @@ signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key, } static inline isc_boolean_t -issigningkey(signer_key_t *key) { - return (key->issigningkey); +issigningkey(dns_dnsseckey_t *key) { + return (key->force_sign || key->hint_sign); } static inline isc_boolean_t -iszonekey(signer_key_t *key) { +iszonekey(dns_dnsseckey_t *key) { return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) && dst_key_iszonekey(key->key))); } +static inline isc_boolean_t +isksk(dns_dnsseckey_t *key) { + return (key->ksk); +} + +static inline isc_boolean_t +iszsk(dns_dnsseckey_t *key) { + return (ignore_kskflag || !key->ksk); +} + /*% - * Find the key if it is in our list. If it is, return it, otherwise null. + * Find the key that generated an RRSIG, if it is in the key list. If + * so, return a pointer to it, otherwise return NULL. + * * No locking is performed here, this must be done by the caller. */ -static signer_key_t * +static dns_dnsseckey_t * keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) { - signer_key_t *key; + dns_dnsseckey_t *key; - key = ISC_LIST_HEAD(keylist); - while (key != NULL) { + for (key = ISC_LIST_HEAD(keylist); + key != NULL; + key = ISC_LIST_NEXT(key, link)) { if (rrsig->keyid == dst_key_id(key->key) && rrsig->algorithm == dst_key_alg(key->key) && dns_name_equal(&rrsig->signer, dst_key_name(key->key))) return (key); - key = ISC_LIST_NEXT(key, link); } return (NULL); } @@ -305,11 +294,11 @@ keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) { * Finds the key that generated a RRSIG, if possible. First look at the keys * that we've loaded already, and then see if there's a key on disk. */ -static signer_key_t * +static dns_dnsseckey_t * keythatsigned(dns_rdata_rrsig_t *rrsig) { isc_result_t result; dst_key_t *pubkey = NULL, *privkey = NULL; - signer_key_t *key; + dns_dnsseckey_t *key = NULL; isc_rwlock_lock(&keylist_lock, isc_rwlocktype_read); key = keythatsigned_unlocked(rrsig); @@ -325,7 +314,6 @@ keythatsigned(dns_rdata_rrsig_t *rrsig) { * after all. */ isc_rwlock_lock(&keylist_lock, isc_rwlocktype_write); - key = keythatsigned_unlocked(rrsig); if (key != NULL) { isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write); @@ -334,7 +322,7 @@ keythatsigned(dns_rdata_rrsig_t *rrsig) { result = dst_key_fromfile(&rrsig->signer, rrsig->keyid, rrsig->algorithm, DST_TYPE_PUBLIC, - NULL, mctx, &pubkey); + directory, mctx, &pubkey); if (result != ISC_R_SUCCESS) { isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write); return (NULL); @@ -343,12 +331,15 @@ keythatsigned(dns_rdata_rrsig_t *rrsig) { result = dst_key_fromfile(&rrsig->signer, rrsig->keyid, rrsig->algorithm, DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, - NULL, mctx, &privkey); + directory, mctx, &privkey); if (result == ISC_R_SUCCESS) { dst_key_free(&pubkey); - key = newkeystruct(privkey, ISC_FALSE); - } else - key = newkeystruct(pubkey, ISC_FALSE); + dns_dnsseckey_create(mctx, &privkey, &key); + } else { + dns_dnsseckey_create(mctx, &pubkey, &key); + } + key->force_publish = ISC_TRUE; + key->force_sign = ISC_FALSE; ISC_LIST_APPEND(keylist, key, link); isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write); @@ -383,15 +374,16 @@ expecttofindkey(dns_name_t *name) { dns_name_format(name, namestr, sizeof(namestr)); fatal("failure looking for '%s DNSKEY' in database: %s", namestr, isc_result_totext(result)); + /* NOTREACHED */ return (ISC_FALSE); /* removes a warning */ } static inline isc_boolean_t -setverifies(dns_name_t *name, dns_rdataset_t *set, signer_key_t *key, +setverifies(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, dns_rdata_t *rrsig) { isc_result_t result; - result = dns_dnssec_verify(name, set, key->key, ISC_FALSE, mctx, rrsig); + result = dns_dnssec_verify(name, set, key, ISC_FALSE, mctx, rrsig); if (result == ISC_R_SUCCESS) { INCSTAT(nverified); return (ISC_TRUE); @@ -413,7 +405,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name, dns_rdataset_t sigset; dns_rdata_t sigrdata = DNS_RDATA_INIT; dns_rdata_rrsig_t rrsig; - signer_key_t *key; + dns_dnsseckey_t *key; isc_result_t result; isc_boolean_t nosigs = ISC_FALSE; isc_boolean_t *wassignedby, *nowsignedby; @@ -483,8 +475,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name, "invalid validity period\n", sigstr); } else if (key == NULL && !future && - expecttofindkey(&rrsig.signer)) - { + expecttofindkey(&rrsig.signer)) { /* rrsig is dropped and not replaced */ vbprintf(2, "\trrsig by %s dropped - " "private dnskey not found\n", @@ -495,35 +486,33 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name, if (!expired) keep = ISC_TRUE; } else if (issigningkey(key)) { - if (!expired && setverifies(name, set, key, &sigrdata)) - { + if (!expired && setverifies(name, set, key->key, + &sigrdata)) { vbprintf(2, "\trrsig by %s retained\n", sigstr); keep = ISC_TRUE; - wassignedby[key->position] = ISC_TRUE; - nowsignedby[key->position] = ISC_TRUE; - key->wasused = ISC_TRUE; + wassignedby[key->index] = ISC_TRUE; + nowsignedby[key->index] = ISC_TRUE; } else { vbprintf(2, "\trrsig by %s dropped - %s\n", sigstr, expired ? "expired" : "failed to verify"); - wassignedby[key->position] = ISC_TRUE; + wassignedby[key->index] = ISC_TRUE; resign = ISC_TRUE; } } else if (iszonekey(key)) { - if (!expired && setverifies(name, set, key, &sigrdata)) - { + if (!expired && setverifies(name, set, key->key, + &sigrdata)) { vbprintf(2, "\trrsig by %s retained\n", sigstr); keep = ISC_TRUE; - wassignedby[key->position] = ISC_TRUE; - nowsignedby[key->position] = ISC_TRUE; - key->wasused = ISC_TRUE; + wassignedby[key->index] = ISC_TRUE; + nowsignedby[key->index] = ISC_TRUE; } else { vbprintf(2, "\trrsig by %s dropped - %s\n", sigstr, expired ? "expired" : "failed to verify"); - wassignedby[key->position] = ISC_TRUE; + wassignedby[key->index] = ISC_TRUE; } } else if (!expired) { vbprintf(2, "\trrsig by %s retained\n", sigstr); @@ -533,7 +522,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name, } if (keep) { - nowsignedby[key->position] = ISC_TRUE; + nowsignedby[key->index] = ISC_TRUE; INCSTAT(nretained); if (sigset.ttl != ttl) { vbprintf(2, "\tfixing ttl %s\n", sigstr); @@ -568,8 +557,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name, signwithkey(name, set, key->key, ttl, add, "resigning with dnskey"); - nowsignedby[key->position] = ISC_TRUE; - key->wasused = ISC_TRUE; + nowsignedby[key->index] = ISC_TRUE; } dns_rdata_reset(&sigrdata); @@ -587,20 +575,37 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name, key != NULL; key = ISC_LIST_NEXT(key, link)) { - if (nowsignedby[key->position]) + if (nowsignedby[key->index]) continue; - if (!key->issigningkey) - continue; - if (!(ignoreksk || key->isdsk || - (key->isksk && - set->type == dns_rdatatype_dnskey && - dns_name_equal(name, gorigin)))) + if (!issigningkey(key)) continue; - signwithkey(name, set, key->key, ttl, add, - "signing with dnskey"); - key->wasused = ISC_TRUE; + if (set->type == dns_rdatatype_dnskey && + dns_name_equal(name, gorigin)) { + isc_boolean_t have_ksk; + dns_dnsseckey_t *tmpkey; + + have_ksk = isksk(key); + for (tmpkey = ISC_LIST_HEAD(keylist); + tmpkey != NULL; + tmpkey = ISC_LIST_NEXT(tmpkey, link)) { + if (dst_key_alg(key->key) != + dst_key_alg(tmpkey->key)) + continue; + if (REVOKE(tmpkey->key)) + continue; + if (isksk(tmpkey)) + have_ksk = ISC_TRUE; + } + if (isksk(key) || !have_ksk || + (iszsk(key) && !keyset_kskonly)) + signwithkey(name, set, key->key, ttl, add, + "signing with dnskey"); + } else if (iszsk(key)) { + signwithkey(name, set, key->key, ttl, add, + "signing with dnskey"); + } } isc_mem_put(mctx, wassignedby, arraysize * sizeof(isc_boolean_t)); @@ -774,16 +779,21 @@ static void opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass, dns_db_t **dbp) { - char filename[256]; + char filename[PATH_MAX]; isc_buffer_t b; isc_result_t result; isc_buffer_init(&b, filename, sizeof(filename)); - if (directory != NULL) { - isc_buffer_putstr(&b, directory); - if (directory[strlen(directory) - 1] != '/') + if (dsdir != NULL) { + /* allow room for a trailing slash */ + if (strlen(dsdir) >= isc_buffer_availablelength(&b)) + fatal("path '%s' is too long", dsdir); + isc_buffer_putstr(&b, dsdir); + if (dsdir[strlen(dsdir) - 1] != '/') isc_buffer_putstr(&b, "/"); } + if (strlen(prefix) > isc_buffer_availablelength(&b)) + fatal("path '%s' is too long", dsdir); isc_buffer_putstr(&b, prefix); result = dns_name_tofilenametext(name, ISC_FALSE, &b); check_result(result, "dns_name_tofilenametext()"); @@ -798,13 +808,15 @@ opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass, rdclass, 0, NULL, dbp); check_result(result, "dns_db_create()"); - result = dns_db_load(*dbp, filename); + result = dns_db_load3(*dbp, filename, inputformat, DNS_MASTER_HINT); if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) dns_db_detach(dbp); } /*% - * Loads the key set for a child zone, if there is one, and builds DS records. + * Load the DS set for a child zone, if a dsset-* file can be found. + * If not, try to find a keyset-* file from an earlier version of + * dnssec-signzone, and build DS records from that. */ static isc_result_t loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) { @@ -818,29 +830,49 @@ loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) { dns_diff_t diff; dns_difftuple_t *tuple = NULL; + opendb("dsset-", name, gclass, &db); + if (db != NULL) { + result = dns_db_findnode(db, name, ISC_FALSE, &node); + if (result == ISC_R_SUCCESS) { + dns_rdataset_init(dsset); + result = dns_db_findrdataset(db, node, NULL, + dns_rdatatype_ds, 0, 0, + dsset, NULL); + dns_db_detachnode(db, &node); + if (result == ISC_R_SUCCESS) { + vbprintf(2, "found DS records\n"); + dsset->ttl = ttl; + dns_db_detach(&db); + return (result); + } + } + dns_db_detach(&db); + } + + /* No DS records found; try again, looking for DNSKEY records */ opendb("keyset-", name, gclass, &db); - if (db == NULL) + if (db == NULL) { return (ISC_R_NOTFOUND); + } result = dns_db_findnode(db, name, ISC_FALSE, &node); if (result != ISC_R_SUCCESS) { dns_db_detach(&db); - return (DNS_R_BADDB); + return (result); } + dns_rdataset_init(&keyset); - result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, - 0, &keyset, NULL); + result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0, + &keyset, NULL); if (result != ISC_R_SUCCESS) { dns_db_detachnode(db, &node); dns_db_detach(&db); return (result); } - vbprintf(2, "found DNSKEY records\n"); result = dns_db_newversion(db, &ver); check_result(result, "dns_db_newversion"); - dns_diff_init(mctx, &diff); for (result = dns_rdataset_first(&keyset); @@ -869,6 +901,7 @@ loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) { check_result(result, "dns_difftuple_create"); dns_diff_append(&diff, &tuple); } + result = dns_diff_apply(&diff, db, ver); check_result(result, "dns_diff_apply"); dns_diff_clear(&diff); @@ -1112,17 +1145,15 @@ active_node(dns_dbnode_t *node) { } /*% - * Extracts the TTL from the SOA. + * Extracts the minimum TTL from the SOA record, and the SOA record's TTL. */ -static dns_ttl_t -soattl(void) { +static void +get_soa_ttls(void) { dns_rdataset_t soaset; dns_fixedname_t fname; dns_name_t *name; isc_result_t result; - dns_ttl_t ttl; dns_rdata_t rdata = DNS_RDATA_INIT; - dns_rdata_soa_t soa; dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); @@ -1136,11 +1167,9 @@ soattl(void) { result = dns_rdataset_first(&soaset); check_result(result, "dns_rdataset_first"); dns_rdataset_current(&soaset, &rdata); - result = dns_rdata_tostruct(&rdata, &soa, NULL); - check_result(result, "dns_rdata_tostruct"); - ttl = soa.minimum; + zone_soa_min_ttl = dns_soa_getminimum(&rdata); + soa_ttl = soaset.ttl; dns_rdataset_disassociate(&soaset); - return (ttl); } /*% @@ -1371,7 +1400,7 @@ verifyset(dns_rdataset_t *rdataset, dns_name_t *name, dns_dbnode_t *node, for (i = 0; i < 256; i++) if ((ksk_algorithms[i] != 0) && (set_algorithms[i] == 0)) { - alg_format(i, algbuf, sizeof(algbuf)); + dns_secalg_format(i, algbuf, sizeof(algbuf)); fprintf(stderr, "Missing %s signature for " "%s %s\n", algbuf, namebuf, typebuf); bad_algorithms[i] = 1; @@ -1414,8 +1443,8 @@ verifynode(dns_name_t *name, dns_dbnode_t *node, isc_boolean_t delegation, /*% * Verify that certain things are sane: * - * The apex has a DNSKEY record with at least one KSK and at least - * one ZSK. + * The apex has a DNSKEY record with at least one KSK, and at least + * one ZSK if the -x flag was not used. * * The DNSKEY record was signed with at least one of the KSKs in this * set. @@ -1440,8 +1469,10 @@ verifyzone(void) { isc_boolean_t goodksk = ISC_FALSE; isc_boolean_t goodzsk = ISC_FALSE; isc_result_t result; - unsigned char revoked[256]; - unsigned char standby[256]; + unsigned char revoked_ksk[256]; + unsigned char revoked_zsk[256]; + unsigned char standby_ksk[256]; + unsigned char standby_zsk[256]; unsigned char ksk_algorithms[256]; unsigned char zsk_algorithms[256]; unsigned char bad_algorithms[256]; @@ -1470,8 +1501,10 @@ verifyzone(void) { if (!dns_rdataset_isassociated(&sigrdataset)) fatal("cannot find DNSKEY RRSIGs\n"); - memset(revoked, 0, sizeof(revoked)); - memset(standby, 0, sizeof(revoked)); + memset(revoked_ksk, 0, sizeof(revoked_ksk)); + memset(revoked_zsk, 0, sizeof(revoked_zsk)); + memset(standby_ksk, 0, sizeof(standby_ksk)); + memset(standby_zsk, 0, sizeof(standby_zsk)); memset(ksk_algorithms, 0, sizeof(ksk_algorithms)); memset(zsk_algorithms, 0, sizeof(zsk_algorithms)); memset(bad_algorithms, 0, sizeof(bad_algorithms)); @@ -1480,8 +1513,9 @@ verifyzone(void) { #endif /* - * Check that the DNSKEY RR has at least one self signing KSK and - * one ZSK per algorithm in it. + * Check that the DNSKEY RR has at least one self signing KSK + * and one ZSK per algorithm in it (or, if -x was used, one + * self-signing KSK). */ for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; @@ -1511,8 +1545,11 @@ verifyzone(void) { (int)isc_buffer_usedlength(&buf), buffer); } if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 && - revoked[dnskey.algorithm] != 255) - revoked[dnskey.algorithm]++; + revoked_ksk[dnskey.algorithm] != 255) + revoked_ksk[dnskey.algorithm]++; + else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 && + revoked_zsk[dnskey.algorithm] != 255) + revoked_zsk[dnskey.algorithm]++; } else if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) { if (dns_dnssec_selfsigns(&rdata, gorigin, &rdataset, &sigrdataset, ISC_FALSE, mctx)) { @@ -1520,8 +1557,8 @@ verifyzone(void) { ksk_algorithms[dnskey.algorithm]++; goodksk = ISC_TRUE; } else { - if (standby[dnskey.algorithm] != 255) - standby[dnskey.algorithm]++; + if (standby_ksk[dnskey.algorithm] != 255) + standby_ksk[dnskey.algorithm]++; } } else if (dns_dnssec_selfsigns(&rdata, gorigin, &rdataset, &sigrdataset, ISC_FALSE, @@ -1534,8 +1571,8 @@ verifyzone(void) { zsk_algorithms[dnskey.algorithm]++; goodzsk = ISC_TRUE; } else { - if (zsk_algorithms[dnskey.algorithm] != 255) - zsk_algorithms[dnskey.algorithm]++; + if (standby_zsk[dnskey.algorithm] != 255) + standby_zsk[dnskey.algorithm]++; #ifdef ALLOW_KSKLESS_ZONES allzsksigned = ISC_FALSE; #endif @@ -1545,42 +1582,54 @@ verifyzone(void) { } dns_rdataset_disassociate(&sigrdataset); - if (!goodksk) { #ifdef ALLOW_KSKLESS_ZONES - if (!goodzsk) - fatal("no self signing keys found"); - fprintf(stderr, "No self signing KSK found. Using self signed " - "ZSK's for active algorithm list.\n"); + if (!goodksk) { + if (!ignore_kskflag) + fprintf(stderr, "No self signing KSK found. Using " + "self signed ZSK's for active " + "algorithm list.\n"); memcpy(ksk_algorithms, self_algorithms, sizeof(ksk_algorithms)); if (!allzsksigned) fprintf(stderr, "warning: not all ZSK's are self " "signed.\n"); + } #else + if (!goodksk) { fatal("no self signed KSK's found"); -#endif } +#endif fprintf(stderr, "Verifying the zone using the following algorithms:"); for (i = 0; i < 256; i++) { - if (ksk_algorithms[i] != 0) { - alg_format(i, algbuf, sizeof(algbuf)); +#ifdef ALLOW_KSKLESS_ZONES + if (ksk_algorithms[i] != 0 || zsk_algorithms[i] != 0) +#else + if (ksk_algorithms[i] != 0) +#endif + { + dns_secalg_format(i, algbuf, sizeof(algbuf)); fprintf(stderr, " %s", algbuf); } } fprintf(stderr, ".\n"); - for (i = 0; i < 256; i++) { - /* - * The counts should both be zero or both be non-zero. - * Mark the algorithm as bad if this is not met. - */ - if ((ksk_algorithms[i] != 0) == (zsk_algorithms[i] != 0)) - continue; - alg_format(i, algbuf, sizeof(algbuf)); - fprintf(stderr, "Missing %s for algorithm %s\n", - (ksk_algorithms[i] != 0) ? "ZSK" : "self signing KSK", - algbuf); - bad_algorithms[i] = 1; + if (!ignore_kskflag && !keyset_kskonly) { + for (i = 0; i < 256; i++) { + /* + * The counts should both be zero or both be non-zero. + * Mark the algorithm as bad if this is not met. + */ + if ((ksk_algorithms[i] != 0) == + (zsk_algorithms[i] != 0)) + continue; + dns_secalg_format(i, algbuf, sizeof(algbuf)); + fprintf(stderr, "Missing %s for algorithm %s\n", + (ksk_algorithms[i] != 0) + ? "ZSK" + : "self signing KSK", + algbuf); + bad_algorithms[i] = 1; + } } /* @@ -1674,7 +1723,7 @@ verifyzone(void) { if (first) fprintf(stderr, "The zone is not fully signed " "for the following algorithms:"); - alg_format(i, algbuf, sizeof(algbuf)); + dns_secalg_format(i, algbuf, sizeof(algbuf)); fprintf(stderr, " %s", algbuf); first = ISC_FALSE; } @@ -1684,21 +1733,30 @@ verifyzone(void) { fatal("DNSSEC completeness test failed."); } - if (goodksk) { + if (goodksk || ignore_kskflag) { /* * Print the success summary. */ fprintf(stderr, "Zone signing complete:\n"); for (i = 0; i < 256; i++) { - if ((zsk_algorithms[i] != 0) || - (ksk_algorithms[i] != 0) || - (revoked[i] != 0) || (standby[i] != 0)) { - alg_format(i, algbuf, sizeof(algbuf)); - fprintf(stderr, "Algorithm: %s: ZSKs: %u, " - "KSKs: %u active, %u revoked, %u " - "stand-by\n", algbuf, - zsk_algorithms[i], ksk_algorithms[i], - revoked[i], standby[i]); + if ((ksk_algorithms[i] != 0) || + (standby_ksk[i] != 0) || + (revoked_zsk[i] != 0) || + (zsk_algorithms[i] != 0) || + (standby_zsk[i] != 0) || + (revoked_zsk[i] != 0)) { + dns_secalg_format(i, algbuf, sizeof(algbuf)); + fprintf(stderr, "Algorithm: %s: KSKs: " + "%u active, %u stand-by, %u revoked\n", + algbuf, ksk_algorithms[i], + standby_ksk[i], revoked_ksk[i]); + fprintf(stderr, "%*sZSKs: " + "%u active, %u %s, %u revoked\n", + (int) strlen(algbuf) + 13, "", + zsk_algorithms[i], + standby_zsk[i], + keyset_kskonly ? "present" : "stand-by", + revoked_zsk[i]); } } } @@ -1923,6 +1981,7 @@ add_ds(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t nsttl) { dns_rdatatype_ds, 0); check_result(result, "dns_db_deleterdataset"); } + result = loadds(name, nsttl, &dsset); if (result == ISC_R_SUCCESS) { result = dns_db_addrdataset(gdb, node, gversion, 0, @@ -1953,7 +2012,7 @@ remove_records(dns_dbnode_t *node, dns_rdatatype_t which) { dns_rdataset_init(&rdataset); /* - * Delete any NSEC records at the apex. + * Delete any records of the given type at the apex. */ result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter); check_result(result, "dns_db_allrdatasets()"); @@ -1965,6 +2024,12 @@ remove_records(dns_dbnode_t *node, dns_rdatatype_t which) { covers = rdataset.covers; dns_rdataset_disassociate(&rdataset); if (type == which || covers == which) { + if (which == dns_rdatatype_nsec && !update_chain) + fatal("Zone contains NSEC records. Use -u " + "to update to NSEC3."); + if (which == dns_rdatatype_nsec3param && !update_chain) + fatal("Zone contains NSEC3 chains. Use -u " + "to update to NSEC."); result = dns_db_deleterdataset(gdb, node, gversion, type, covers); check_result(result, "dns_db_deleterdataset()"); @@ -2088,8 +2153,9 @@ nsecify(void) { } else if (result != ISC_R_SUCCESS) fatal("iterating through the database failed: %s", isc_result_totext(result)); + dns_dbiterator_pause(dbiter); result = dns_nsec_build(gdb, gversion, node, nextname, - zonettl); + zone_soa_min_ttl); check_result(result, "dns_nsec_build()"); dns_db_detachnode(gdb, &node); } @@ -2320,6 +2386,97 @@ nsec3clean(dns_name_t *name, dns_dbnode_t *node, check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))"); } +static void +rrset_remove_duplicates(dns_name_t *name, dns_rdataset_t *rdataset, + dns_diff_t *diff) +{ + dns_difftuple_t *tuple = NULL; + isc_result_t result; + unsigned int count1 = 0; + dns_rdataset_t tmprdataset; + + dns_rdataset_init(&tmprdataset); + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + dns_rdata_t rdata1 = DNS_RDATA_INIT; + unsigned int count2 = 0; + + count1++; + dns_rdataset_current(rdataset, &rdata1); + dns_rdataset_clone(rdataset, &tmprdataset); + for (result = dns_rdataset_first(&tmprdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&tmprdataset)) { + dns_rdata_t rdata2 = DNS_RDATA_INIT; + count2++; + if (count1 >= count2) + continue; + dns_rdataset_current(&tmprdataset, &rdata2); + if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) { + result = dns_difftuple_create(mctx, + DNS_DIFFOP_DEL, + name, + rdataset->ttl, + &rdata2, &tuple); + check_result(result, "dns_difftuple_create"); + dns_diff_append(diff, &tuple); + } + } + dns_rdataset_disassociate(&tmprdataset); + } +} + +static void +remove_duplicates(void) { + isc_result_t result; + dns_dbiterator_t *dbiter = NULL; + dns_rdatasetiter_t *rdsiter = NULL; + dns_diff_t diff; + dns_dbnode_t *node = NULL; + dns_rdataset_t rdataset; + dns_fixedname_t fname; + dns_name_t *name; + + dns_diff_init(mctx, &diff); + dns_fixedname_init(&fname); + name = dns_fixedname_name(&fname); + dns_rdataset_init(&rdataset); + + result = dns_db_createiterator(gdb, 0, &dbiter); + check_result(result, "dns_db_createiterator()"); + + for (result = dns_dbiterator_first(dbiter); + result == ISC_R_SUCCESS; + result = dns_dbiterator_next(dbiter)) { + + result = dns_dbiterator_current(dbiter, &node, name); + check_dns_dbiterator_current(result); + result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter); + check_result(result, "dns_db_allrdatasets()"); + for (result = dns_rdatasetiter_first(rdsiter); + result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(rdsiter)) { + dns_rdatasetiter_current(rdsiter, &rdataset); + rrset_remove_duplicates(name, &rdataset, &diff); + dns_rdataset_disassociate(&rdataset); + } + if (result != ISC_R_NOMORE) + fatal("rdatasets iteration failed."); + dns_rdatasetiter_destroy(&rdsiter); + dns_db_detachnode(gdb, &node); + } + if (result != ISC_R_NOMORE) + fatal("zone iteration failed."); + + if (!ISC_LIST_EMPTY(diff.tuples)) { + result = dns_diff_applysilently(&diff, gdb, gversion); + check_result(result, "dns_diff_applysilently"); + } + dns_diff_clear(&diff); + dns_dbiterator_destroy(&dbiter); +} + /* * Generate NSEC3 records for the zone. */ @@ -2546,7 +2703,7 @@ nsec3ify(unsigned int hashalg, unsigned int iterations, */ dns_dbiterator_pause(dbiter); addnsec3(name, node, salt, salt_length, iterations, - hashlist, zonettl); + hashlist, zone_soa_min_ttl); dns_db_detachnode(gdb, &node); /* * Add NSEC3's for empty nodes. Use closest encloser logic. @@ -2557,7 +2714,7 @@ nsec3ify(unsigned int hashalg, unsigned int iterations, count--; dns_name_split(nextname, count, NULL, nextname); addnsec3(nextname, NULL, salt, salt_length, - iterations, hashlist, zonettl); + iterations, hashlist, zone_soa_min_ttl); } } dns_dbiterator_destroy(&dbiter); @@ -2580,7 +2737,7 @@ loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) { dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); - result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) fatal("failed converting name '%s' to dns format: %s", origin, isc_result_totext(result)); @@ -2600,90 +2757,169 @@ loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) { * private keys from disk. */ static void -loadzonekeys(dns_db_t *db) { +loadzonekeys(isc_boolean_t preserve_keys, isc_boolean_t load_public) { dns_dbnode_t *node; - dns_dbversion_t *currentversion; + dns_dbversion_t *currentversion = NULL; isc_result_t result; - dst_key_t *keys[20]; - unsigned int nkeys, i; - - currentversion = NULL; - dns_db_currentversion(db, ¤tversion); + dns_rdataset_t rdataset, keysigs, soasigs; node = NULL; - result = dns_db_findnode(db, gorigin, ISC_FALSE, &node); + result = dns_db_findnode(gdb, gorigin, ISC_FALSE, &node); if (result != ISC_R_SUCCESS) fatal("failed to find the zone's origin: %s", isc_result_totext(result)); - result = dns_dnssec_findzonekeys(db, currentversion, node, gorigin, - mctx, 20, keys, &nkeys); - if (result == ISC_R_NOTFOUND) - result = ISC_R_SUCCESS; + dns_db_currentversion(gdb, ¤tversion); + + dns_rdataset_init(&rdataset); + dns_rdataset_init(&soasigs); + dns_rdataset_init(&keysigs); + + /* Make note of the keys which signed the SOA, if any */ + result = dns_db_findrdataset(gdb, node, currentversion, + dns_rdatatype_soa, 0, 0, + &rdataset, &soasigs); + if (result != ISC_R_SUCCESS) + goto cleanup; + + /* Preserve the TTL of the DNSKEY RRset, if any */ + dns_rdataset_disassociate(&rdataset); + result = dns_db_findrdataset(gdb, node, currentversion, + dns_rdatatype_dnskey, 0, 0, + &rdataset, &keysigs); + if (result != ISC_R_SUCCESS) - fatal("failed to find the zone keys: %s", + goto cleanup; + + if (set_keyttl && keyttl != rdataset.ttl) { + fprintf(stderr, "User-specified TTL (%d) conflicts " + "with existing DNSKEY RRset TTL.\n", + keyttl); + fprintf(stderr, "Imported keys will use the RRSet " + "TTL (%d) instead.\n", + rdataset.ttl); + } + keyttl = rdataset.ttl; + + /* Load keys corresponding to the existing DNSKEY RRset */ + result = dns_dnssec_keylistfromrdataset(gorigin, directory, mctx, + &rdataset, &keysigs, &soasigs, + preserve_keys, load_public, + &keylist); + if (result != ISC_R_SUCCESS) + fatal("failed to load the zone keys: %s", isc_result_totext(result)); - for (i = 0; i < nkeys; i++) { - signer_key_t *key; + cleanup: + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); + if (dns_rdataset_isassociated(&keysigs)) + dns_rdataset_disassociate(&keysigs); + if (dns_rdataset_isassociated(&soasigs)) + dns_rdataset_disassociate(&soasigs); + dns_db_detachnode(gdb, &node); + dns_db_closeversion(gdb, ¤tversion, ISC_FALSE); +} + +static void +loadexplicitkeys(char *keyfiles[], int n, isc_boolean_t setksk) { + isc_result_t result; + int i; + + for (i = 0; i < n; i++) { + dns_dnsseckey_t *key = NULL; + dst_key_t *newkey = NULL; + + result = dst_key_fromnamedfile(keyfiles[i], directory, + DST_TYPE_PUBLIC | + DST_TYPE_PRIVATE, + mctx, &newkey); + if (result != ISC_R_SUCCESS) + fatal("cannot load dnskey %s: %s", keyfiles[i], + isc_result_totext(result)); + + if (!dns_name_equal(gorigin, dst_key_name(newkey))) + fatal("key %s not at origin\n", keyfiles[i]); + + if (!dst_key_isprivate(newkey)) + fatal("cannot sign zone with non-private dnskey %s", + keyfiles[i]); + + /* Skip any duplicates */ + for (key = ISC_LIST_HEAD(keylist); + key != NULL; + key = ISC_LIST_NEXT(key, link)) { + if (dst_key_id(key->key) == dst_key_id(newkey) && + dst_key_alg(key->key) == dst_key_alg(newkey)) + break; + } + + if (key == NULL) { + /* We haven't seen this key before */ + dns_dnsseckey_create(mctx, &newkey, &key); + ISC_LIST_APPEND(keylist, key, link); + key->source = dns_keysource_user; + } else { + dst_key_free(&key->key); + key->key = newkey; + } + + key->force_publish = ISC_TRUE; + key->force_sign = ISC_TRUE; - key = newkeystruct(keys[i], dst_key_isprivate(keys[i])); - ISC_LIST_APPEND(keylist, key, link); + if (setksk) + key->ksk = ISC_TRUE; } - dns_db_detachnode(db, &node); - dns_db_closeversion(db, ¤tversion, ISC_FALSE); } -/*% - * Finds all public zone keys in the zone. - */ static void -loadzonepubkeys(dns_db_t *db) { - dns_dbversion_t *currentversion = NULL; - dns_dbnode_t *node = NULL; - dns_rdataset_t rdataset; - dns_rdata_t rdata = DNS_RDATA_INIT; - dst_key_t *pubkey; - signer_key_t *key; +report(const char *format, ...) { + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + putc('\n', stderr); +} + +static void +build_final_keylist() { isc_result_t result; + dns_dbversion_t *ver = NULL; + dns_diff_t diff; + dns_dnsseckeylist_t matchkeys; + char name[DNS_NAME_FORMATSIZE]; - dns_db_currentversion(db, ¤tversion); + /* + * Find keys that match this zone in the key repository. + */ + ISC_LIST_INIT(matchkeys); + result = dns_dnssec_findmatchingkeys(gorigin, directory, + mctx, &matchkeys); + if (result == ISC_R_NOTFOUND) + result = ISC_R_SUCCESS; + check_result(result, "dns_dnssec_findmatchingkeys"); - result = dns_db_findnode(db, gorigin, ISC_FALSE, &node); - if (result != ISC_R_SUCCESS) - fatal("failed to find the zone's origin: %s", - isc_result_totext(result)); + result = dns_db_newversion(gdb, &ver); + check_result(result, "dns_db_newversion"); - dns_rdataset_init(&rdataset); - result = dns_db_findrdataset(db, node, currentversion, - dns_rdatatype_dnskey, 0, 0, &rdataset, - NULL); + dns_diff_init(mctx, &diff); + + /* + * Update keylist with information from from the key repository. + */ + dns_dnssec_updatekeys(&keylist, &matchkeys, NULL, gorigin, keyttl, + &diff, ignore_kskflag, mctx, report); + + dns_name_format(gorigin, name, sizeof(name)); + + result = dns_diff_applysilently(&diff, gdb, ver); if (result != ISC_R_SUCCESS) - fatal("failed to find keys at the zone apex: %s", - isc_result_totext(result)); - result = dns_rdataset_first(&rdataset); - check_result(result, "dns_rdataset_first"); - while (result == ISC_R_SUCCESS) { - pubkey = NULL; - dns_rdata_reset(&rdata); - dns_rdataset_current(&rdataset, &rdata); - result = dns_dnssec_keyfromrdata(gorigin, &rdata, mctx, - &pubkey); - if (result != ISC_R_SUCCESS) - goto next; - if (!dst_key_iszonekey(pubkey)) { - dst_key_free(&pubkey); - goto next; - } + fatal("failed to update DNSKEY RRset at node '%s': %s", + name, isc_result_totext(result)); - key = newkeystruct(pubkey, ISC_FALSE); - ISC_LIST_APPEND(keylist, key, link); - next: - result = dns_rdataset_next(&rdataset); - } - dns_rdataset_disassociate(&rdataset); - dns_db_detachnode(db, &node); - dns_db_closeversion(db, ¤tversion, ISC_FALSE); + dns_db_closeversion(gdb, &ver, ISC_TRUE); + + dns_diff_clear(&diff); } static void @@ -2727,18 +2963,112 @@ warnifallksk(dns_db_t *db) { dns_rdataset_disassociate(&rdataset); dns_db_detachnode(db, &node); dns_db_closeversion(db, ¤tversion, ISC_FALSE); - if (!have_non_ksk && !ignoreksk) { + if (!have_non_ksk && !ignore_kskflag) { if (disable_zone_check) - fprintf(stderr, "%s: warning: No non-KSK dnskey found. " - "Supply non-KSK dnskey or use '-z'.\n", + fprintf(stderr, "%s: warning: No non-KSK DNSKEY found; " + "supply a ZSK or use '-z'.\n", program); else - fatal("No non-KSK dnskey found. " - "Supply non-KSK dnskey or use '-z'."); + fatal("No non-KSK DNSKEY found; " + "supply a ZSK or use '-z'."); } } static void +set_nsec3params(isc_boolean_t update_chain, isc_boolean_t set_salt, + isc_boolean_t set_optout, isc_boolean_t set_iter) +{ + isc_result_t result; + dns_dbversion_t *ver = NULL; + dns_dbnode_t *node = NULL; + dns_rdataset_t rdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_nsec3_t nsec3; + dns_fixedname_t fname; + dns_name_t *hashname; + unsigned char orig_salt[256]; + size_t orig_saltlen; + dns_hash_t orig_hash; + isc_uint16_t orig_iter; + + dns_db_currentversion(gdb, &ver); + dns_rdataset_init(&rdataset); + + orig_saltlen = sizeof(orig_salt); + result = dns_db_getnsec3parameters(gdb, ver, &orig_hash, NULL, + &orig_iter, orig_salt, + &orig_saltlen); + if (result != ISC_R_SUCCESS) + goto cleanup; + + nsec_datatype = dns_rdatatype_nsec3; + + if (!update_chain && set_salt) { + if (salt_length != orig_saltlen || + memcmp(saltbuf, orig_salt, salt_length) != 0) + fatal("An NSEC3 chain exists with a different salt. " + "Use -u to update it."); + } else if (!set_salt) { + salt_length = orig_saltlen; + memcpy(saltbuf, orig_salt, orig_saltlen); + salt = saltbuf; + } + + if (!update_chain && set_iter) { + if (nsec3iter != orig_iter) + fatal("An NSEC3 chain exists with different " + "iterations. Use -u to update it."); + } else if (!set_iter) + nsec3iter = orig_iter; + + /* + * Find an NSEC3 record to get the current OPTOUT value. + * (This assumes all NSEC3 records agree.) + */ + + dns_fixedname_init(&fname); + hashname = dns_fixedname_name(&fname); + result = dns_nsec3_hashname(&fname, NULL, NULL, + gorigin, gorigin, dns_hash_sha1, + orig_iter, orig_salt, orig_saltlen); + check_result(result, "dns_nsec3_hashname"); + + result = dns_db_findnsec3node(gdb, hashname, ISC_FALSE, &node); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_nsec3, + 0, 0, &rdataset, NULL); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = dns_rdataset_first(&rdataset); + check_result(result, "dns_rdataset_first"); + dns_rdataset_current(&rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &nsec3, NULL); + check_result(result, "dns_rdata_tostruct"); + + if (!update_chain && set_optout) { + if (nsec3flags != nsec3.flags) + fatal("An NSEC3 chain exists with%s OPTOUT. " + "Use -u -%s to %s it.", + OPTOUT(nsec3.flags) ? "" : "out", + OPTOUT(nsec3.flags) ? "AA" : "A", + OPTOUT(nsec3.flags) ? "clear" : "set"); + } else if (!set_optout) + nsec3flags = nsec3.flags; + + dns_rdata_freestruct(&nsec3); + + cleanup: + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); + if (node != NULL) + dns_db_detachnode(gdb, &node); + dns_db_closeversion(gdb, &ver, ISC_FALSE); +} + +static void writeset(const char *prefix, dns_rdatatype_t type) { char *filename; char namestr[DNS_NAME_FORMATSIZE]; @@ -2755,7 +3085,7 @@ writeset(const char *prefix, dns_rdatatype_t type) { isc_buffer_t namebuf; isc_region_t r; isc_result_t result; - signer_key_t *key; + dns_dnsseckey_t *key, *tmpkey; unsigned char dsbuf[DNS_DS_BUFFERSIZE]; unsigned char keybuf[DST_KEY_MAXSIZE]; unsigned int filenamelen; @@ -2767,13 +3097,13 @@ writeset(const char *prefix, dns_rdatatype_t type) { check_result(result, "dns_name_tofilenametext"); isc_buffer_putuint8(&namebuf, 0); filenamelen = strlen(prefix) + strlen(namestr); - if (directory != NULL) - filenamelen += strlen(directory) + 1; + if (dsdir != NULL) + filenamelen += strlen(dsdir) + 1; filename = isc_mem_get(mctx, filenamelen + 1); if (filename == NULL) fatal("out of memory"); - if (directory != NULL) - sprintf(filename, "%s/", directory); + if (dsdir != NULL) + sprintf(filename, "%s/", dsdir); else filename[0] = 0; strcat(filename, prefix); @@ -2781,22 +3111,6 @@ writeset(const char *prefix, dns_rdatatype_t type) { dns_diff_init(mctx, &diff); - for (key = ISC_LIST_HEAD(keylist); - key != NULL; - key = ISC_LIST_NEXT(key, link)) - if (!key->isksk) { - have_non_ksk = ISC_TRUE; - break; - } - - for (key = ISC_LIST_HEAD(keylist); - key != NULL; - key = ISC_LIST_NEXT(key, link)) - if (key->isksk) { - have_ksk = ISC_TRUE; - break; - } - if (type == dns_rdatatype_dlv) { dns_name_t tname; unsigned int labels; @@ -2815,7 +3129,28 @@ writeset(const char *prefix, dns_rdatatype_t type) { key != NULL; key = ISC_LIST_NEXT(key, link)) { - if (have_ksk && have_non_ksk && !key->isksk) + if (REVOKE(key->key)) + continue; + if (isksk(key)) { + have_ksk = ISC_TRUE; + have_non_ksk = ISC_FALSE; + } else { + have_ksk = ISC_FALSE; + have_non_ksk = ISC_TRUE; + } + for (tmpkey = ISC_LIST_HEAD(keylist); + tmpkey != NULL; + tmpkey = ISC_LIST_NEXT(tmpkey, link)) { + if (dst_key_alg(key->key) != dst_key_alg(tmpkey->key)) + continue; + if (REVOKE(tmpkey->key)) + continue; + if (isksk(tmpkey)) + have_ksk = ISC_TRUE; + else + have_non_ksk = ISC_TRUE; + } + if (have_ksk && have_non_ksk && !isksk(key)) continue; dns_rdata_init(&rdata); dns_rdata_init(&ds); @@ -2848,7 +3183,7 @@ writeset(const char *prefix, dns_rdatatype_t type) { } else result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, - gorigin, zonettl, + gorigin, zone_soa_min_ttl, &rdata, &tuple); check_result(result, "dns_difftuple_create"); dns_diff_append(&diff, &tuple); @@ -2893,6 +3228,9 @@ print_version(FILE *fp) { fprintf(fp, "; dnssec_signzone version " VERSION "\n"); } +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + static void usage(void) { fprintf(stderr, "Usage:\n"); @@ -2903,14 +3241,18 @@ usage(void) { fprintf(stderr, "Version: %s\n", VERSION); fprintf(stderr, "Options: (default value in parenthesis) \n"); - fprintf(stderr, "\t-c class (IN)\n"); - fprintf(stderr, "\t-d directory\n"); - fprintf(stderr, "\t\tdirectory to find keyset files (.)\n"); + fprintf(stderr, "\t-S:\tsmart signing: automatically finds key files\n" + "\t\tfor the zone and determines how they are to " + "be used\n"); + fprintf(stderr, "\t-K directory:\n"); + fprintf(stderr, "\t\tdirectory to find key files (.)\n"); + fprintf(stderr, "\t-d directory:\n"); + fprintf(stderr, "\t\tdirectory to find dsset-* files (.)\n"); fprintf(stderr, "\t-g:\t"); - fprintf(stderr, "generate DS records from keyset files\n"); + fprintf(stderr, "update DS records based on child zones' " + "dsset-* files\n"); fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n"); - fprintf(stderr, "\t\tRRSIG start time - absolute|offset " - "(now - 1 hour)\n"); + fprintf(stderr, "\t\tRRSIG start time - absolute|offset (now - 1 hour)\n"); fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n"); fprintf(stderr, "\t\tRRSIG end time - absolute|from start|from now " "(now + 30 days)\n"); @@ -2918,8 +3260,7 @@ usage(void) { fprintf(stderr, "\t\tcycle interval - resign " "if < interval from end ( (end-start)/4 )\n"); fprintf(stderr, "\t-j jitter:\n"); - fprintf(stderr, "\t\trandomize signature end time up to jitter " - "seconds\n"); + fprintf(stderr, "\t\trandomize signature end time up to jitter seconds\n"); fprintf(stderr, "\t-v debuglevel (0)\n"); fprintf(stderr, "\t-o origin:\n"); fprintf(stderr, "\t\tzone origin (name of zonefile)\n"); @@ -2936,20 +3277,33 @@ usage(void) { fprintf(stderr, "\t\ta file containing random data\n"); fprintf(stderr, "\t-a:\t"); fprintf(stderr, "verify generated signatures\n"); + fprintf(stderr, "\t-c class (IN)\n"); + fprintf(stderr, "\t-E engine:\n"); +#ifdef USE_PKCS11 + fprintf(stderr, "\t\tname of an OpenSSL engine to use " + "(default is \"pkcs11\")\n"); +#else + fprintf(stderr, "\t\tname of an OpenSSL engine to use\n"); +#endif fprintf(stderr, "\t-p:\t"); fprintf(stderr, "use pseudorandom data (faster but less secure)\n"); fprintf(stderr, "\t-P:\t"); fprintf(stderr, "disable post-sign verification\n"); + fprintf(stderr, "\t-T TTL:\tTTL for newly added DNSKEYs\n"); fprintf(stderr, "\t-t:\t"); fprintf(stderr, "print statistics\n"); + fprintf(stderr, "\t-u:\t"); + fprintf(stderr, "update or replace an existing NSEC/NSEC3 chain\n"); + fprintf(stderr, "\t-x:\tsign DNSKEY record with KSKs only, not ZSKs\n"); + fprintf(stderr, "\t-z:\tsign all records with KSKs\n"); + fprintf(stderr, "\t-C:\tgenerate a keyset file, for compatibility\n" + "\t\twith older versions of dnssec-signzone -g\n"); fprintf(stderr, "\t-n ncpus (number of cpus present)\n"); fprintf(stderr, "\t-k key_signing_key\n"); fprintf(stderr, "\t-l lookasidezone\n"); - fprintf(stderr, "\t-3 salt (NSEC3 salt)\n"); - fprintf(stderr, "\t-H iterations (NSEC3 iterations)\n"); - fprintf(stderr, "\t-A (NSEC3 optout)\n"); - fprintf(stderr, "\t-z:\t"); - fprintf(stderr, "ignore KSK flag in DNSKEYs"); + fprintf(stderr, "\t-3 NSEC3 salt\n"); + fprintf(stderr, "\t-H NSEC3 iterations (10)\n"); + fprintf(stderr, "\t-A NSEC3 optout\n"); fprintf(stderr, "\n"); @@ -3001,10 +3355,15 @@ main(int argc, char *argv[]) { int ndskeys = 0; char *endp; isc_time_t timer_start, timer_finish; - signer_key_t *key; + dns_dnsseckey_t *key; isc_result_t result; isc_log_t *log = NULL; isc_boolean_t pseudorandom = ISC_FALSE; +#ifdef USE_PKCS11 + const char *engine = "pkcs11"; +#else + const char *engine = NULL; +#endif unsigned int eflags; isc_boolean_t free_output = ISC_FALSE; int tempfilelen; @@ -3012,13 +3371,15 @@ main(int argc, char *argv[]) { isc_task_t **tasks = NULL; isc_buffer_t b; int len; - unsigned int iterations = 100U; - const unsigned char *salt = NULL; - size_t salt_length = 0; - unsigned char saltbuf[255]; hashlist_t hashlist; + isc_boolean_t smartsign = ISC_FALSE; + isc_boolean_t make_keyset = ISC_FALSE; + isc_boolean_t set_salt = ISC_FALSE; + isc_boolean_t set_optout = ISC_FALSE; + isc_boolean_t set_iter = ISC_FALSE; -#define CMDLINE_FLAGS "3:aAc:d:e:f:FghH:i:I:j:k:l:m:n:N:o:O:pPr:s:StUv:z" +#define CMDLINE_FLAGS \ + "3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:l:m:n:N:o:O:pPr:s:ST:tuUv:xz" /* * Process memory debugging argument first. @@ -3058,7 +3419,9 @@ main(int argc, char *argv[]) { while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { switch (ch) { case '3': - if (strcmp(isc_commandline_argument, "-")) { + set_salt = ISC_TRUE; + nsec_datatype = dns_rdatatype_nsec3; + if (strcmp(isc_commandline_argument, "-") != 0) { isc_buffer_t target; char *sarg; @@ -3068,29 +3431,42 @@ main(int argc, char *argv[]) { result = isc_hex_decodestring(sarg, &target); check_result(result, "isc_hex_decodestring(salt)"); - salt = saltbuf; salt_length = isc_buffer_usedlength(&target); - } else { - salt = saltbuf; - salt_length = 0; } - nsec_datatype = dns_rdatatype_nsec3; break; case 'A': - nsec3flags |= DNS_NSEC3FLAG_OPTOUT; + set_optout = ISC_TRUE; + if (OPTOUT(nsec3flags)) + nsec3flags &= ~DNS_NSEC3FLAG_OPTOUT; + else + nsec3flags |= DNS_NSEC3FLAG_OPTOUT; break; case 'a': tryverify = ISC_TRUE; break; + case 'C': + make_keyset = ISC_TRUE; + break; + case 'c': classname = isc_commandline_argument; break; case 'd': - directory = isc_commandline_argument; + dsdir = isc_commandline_argument; + if (strlen(dsdir) == 0U) + fatal("DS directory must be non-empty string"); + result = try_dir(dsdir); + if (result != ISC_R_SUCCESS) + fatal("cannot open directory %s: %s", + dsdir, isc_result_totext(result)); + break; + + case 'E': + engine = isc_commandline_argument; break; case 'e': @@ -3106,11 +3482,11 @@ main(int argc, char *argv[]) { break; case 'H': - iterations = strtoul(isc_commandline_argument, - &endp, 0); + set_iter = ISC_TRUE; + nsec3iter = strtoul(isc_commandline_argument, &endp, 0); if (*endp != '\0') fatal("iterations must be numeric"); - if (iterations > 0xffffU) + if (nsec3iter > 0xffffU) fatal("iterations too big"); break; @@ -3118,6 +3494,10 @@ main(int argc, char *argv[]) { usage(); break; + case 'I': + inputformatstr = isc_commandline_argument; + break; + case 'i': endp = NULL; cycle = strtol(isc_commandline_argument, &endp, 0); @@ -3126,10 +3506,6 @@ main(int argc, char *argv[]) { "positive"); break; - case 'I': - inputformatstr = isc_commandline_argument; - break; - case 'j': endp = NULL; jitter = strtol(isc_commandline_argument, &endp, 0); @@ -3137,6 +3513,10 @@ main(int argc, char *argv[]) { fatal("jitter must be numeric and positive"); break; + case 'K': + directory = isc_commandline_argument; + break; + case 'k': if (ndskeys == MAXDSKEYS) fatal("too many key-signing keys specified"); @@ -3150,14 +3530,18 @@ main(int argc, char *argv[]) { dns_fixedname_init(&dlv_fixed); dlv = dns_fixedname_name(&dlv_fixed); - result = dns_name_fromtext(dlv, &b, dns_rootname, - ISC_FALSE, NULL); + result = dns_name_fromtext(dlv, &b, dns_rootname, 0, + NULL); check_result(result, "dns_name_fromtext(dlv)"); break; case 'm': break; + case 'N': + serialformatstr = isc_commandline_argument; + break; + case 'n': endp = NULL; ntasks = strtol(isc_commandline_argument, &endp, 0); @@ -3165,38 +3549,38 @@ main(int argc, char *argv[]) { fatal("number of cpus must be numeric"); break; - case 'N': - serialformatstr = isc_commandline_argument; + case 'O': + outputformatstr = isc_commandline_argument; break; case 'o': origin = isc_commandline_argument; break; - case 'O': - outputformatstr = isc_commandline_argument; + case 'P': + disable_zone_check = ISC_TRUE; break; case 'p': pseudorandom = ISC_TRUE; break; - case 'P': - disable_zone_check = ISC_TRUE; - break; - case 'r': setup_entropy(mctx, isc_commandline_argument, &ectx); break; + case 'S': + smartsign = ISC_TRUE; + break; + case 's': startstr = isc_commandline_argument; break; - case 'S': - /* This is intentionally undocumented */ - /* -S: simple output style */ - masterstyle = &dns_master_style_simple; + case 'T': + endp = NULL; + set_keyttl = ISC_TRUE; + keyttl = strtottl(isc_commandline_argument); break; case 't': @@ -3207,6 +3591,10 @@ main(int argc, char *argv[]) { unknownalg = ISC_TRUE; break; + case 'u': + update_chain = ISC_TRUE; + break; + case 'v': endp = NULL; verbose = strtol(isc_commandline_argument, &endp, 0); @@ -3214,8 +3602,12 @@ main(int argc, char *argv[]) { fatal("verbose level must be numeric"); break; + case 'x': + keyset_kskonly = ISC_TRUE; + break; + case 'z': - ignoreksk = ISC_TRUE; + ignore_kskflag = ISC_TRUE; break; case 'F': @@ -3245,20 +3637,21 @@ main(int argc, char *argv[]) { if (result != ISC_R_SUCCESS) fatal("could not create hash context"); - result = dst_lib_init(mctx, ectx, eflags); + result = dst_lib_init2(mctx, ectx, engine, eflags); if (result != ISC_R_SUCCESS) - fatal("could not initialize dst"); + fatal("could not initialize dst: %s", + isc_result_totext(result)); isc_stdtime_get(&now); - if (startstr != NULL) + if (startstr != NULL) { starttime = strtotime(startstr, now, now); - else + } else starttime = now - 3600; /* Allow for some clock skew. */ - if (endstr != NULL) + if (endstr != NULL) { endtime = strtotime(endstr, now, starttime); - else + } else endtime = starttime + (30 * 24 * 60 * 60); if (cycle == -1) @@ -3270,6 +3663,9 @@ main(int argc, char *argv[]) { rdclass = strtoclass(classname); + if (directory == NULL) + directory = "."; + setup_logging(verbose, mctx, &log); argc -= isc_commandline_index; @@ -3335,7 +3731,19 @@ main(int argc, char *argv[]) { loadzone(file, origin, rdclass, &gdb); gorigin = dns_db_origin(gdb); gclass = dns_db_class(gdb); - zonettl = soattl(); + get_soa_ttls(); + + if (!set_keyttl) + keyttl = soa_ttl; + + /* + * Check for any existing NSEC3 parameters in the zone, + * and use them as defaults if -u was not specified. + */ + if (update_chain && !set_optout && !set_iter && !set_salt) + nsec_datatype = dns_rdatatype_nsec; + else + set_nsec3params(update_chain, set_salt, set_optout, set_iter); if (IS_NSEC3) { isc_boolean_t answer; @@ -3356,95 +3764,42 @@ main(int argc, char *argv[]) { ISC_LIST_INIT(keylist); isc_rwlock_init(&keylist_lock, 0, 0); - if (argc == 0) { - loadzonekeys(gdb); - } else { - for (i = 0; i < argc; i++) { - dst_key_t *newkey = NULL; - - result = dst_key_fromnamedfile(argv[i], - DST_TYPE_PUBLIC | - DST_TYPE_PRIVATE, - mctx, &newkey); - if (result != ISC_R_SUCCESS) - fatal("cannot load dnskey %s: %s", argv[i], - isc_result_totext(result)); - - if (!dns_name_equal(gorigin, dst_key_name(newkey))) - fatal("key %s not at origin\n", argv[i]); - - key = ISC_LIST_HEAD(keylist); - while (key != NULL) { - dst_key_t *dkey = key->key; - if (dst_key_id(dkey) == dst_key_id(newkey) && - dst_key_alg(dkey) == dst_key_alg(newkey) && - dns_name_equal(dst_key_name(dkey), - dst_key_name(newkey))) - { - if (!dst_key_isprivate(dkey)) - fatal("cannot sign zone with " - "non-private dnskey %s", - argv[i]); - break; - } - key = ISC_LIST_NEXT(key, link); - } - if (key == NULL) { - key = newkeystruct(newkey, ISC_TRUE); - key->commandline = ISC_TRUE; - ISC_LIST_APPEND(keylist, key, link); - } else - dst_key_free(&newkey); - } - - loadzonepubkeys(gdb); - } - - for (i = 0; i < ndskeys; i++) { - dst_key_t *newkey = NULL; - - result = dst_key_fromnamedfile(dskeyfile[i], - DST_TYPE_PUBLIC | - DST_TYPE_PRIVATE, - mctx, &newkey); - if (result != ISC_R_SUCCESS) - fatal("cannot load dnskey %s: %s", dskeyfile[i], - isc_result_totext(result)); + /* + * Fill keylist with: + * 1) Keys listed in the DNSKEY set that have + * private keys associated, *if* no keys were + * set on the command line. + * 2) ZSKs set on the command line + * 3) KSKs set on the command line + * 4) Any keys remaining in the DNSKEY set which + * do not have private keys associated and were + * not specified on the command line. + */ + if (argc == 0 || smartsign) + loadzonekeys(!smartsign, ISC_FALSE); + loadexplicitkeys(argv, argc, ISC_FALSE); + loadexplicitkeys(dskeyfile, ndskeys, ISC_TRUE); + loadzonekeys(!smartsign, ISC_TRUE); - if (!dns_name_equal(gorigin, dst_key_name(newkey))) - fatal("key %s not at origin\n", dskeyfile[i]); + /* + * If we're doing smart signing, look in the key repository for + * key files with metadata, and merge them with the keylist + * we have now. + */ + if (smartsign) + build_final_keylist(); - key = ISC_LIST_HEAD(keylist); - while (key != NULL) { - dst_key_t *dkey = key->key; - if (dst_key_id(dkey) == dst_key_id(newkey) && - dst_key_alg(dkey) == dst_key_alg(newkey) && - dns_name_equal(dst_key_name(dkey), - dst_key_name(newkey))) - { - /* Override key flags. */ - key->issigningkey = ISC_TRUE; - key->isksk = ISC_TRUE; - key->isdsk = ISC_FALSE; - dst_key_free(&dkey); - key->key = newkey; - break; - } - key = ISC_LIST_NEXT(key, link); - } - if (key == NULL) { - /* Override dnskey flags. */ - key = newkeystruct(newkey, ISC_TRUE); - key->isksk = ISC_TRUE; - key->isdsk = ISC_FALSE; - ISC_LIST_APPEND(keylist, key, link); - } + /* Now enumerate the key list */ + for (key = ISC_LIST_HEAD(keylist); + key != NULL; + key = ISC_LIST_NEXT(key, link)) { + key->index = keycount++; } - if (ISC_LIST_EMPTY(keylist)) { + if (keycount == 0) { if (disable_zone_check) fprintf(stderr, "%s: warning: No keys specified " - "or found\n", program); + "or found\n", program); else fatal("No signing keys specified or found."); nokeys = ISC_TRUE; @@ -3454,7 +3809,7 @@ main(int argc, char *argv[]) { unsigned int max; result = dns_nsec3_maxiterations(gdb, NULL, mctx, &max); check_result(result, "dns_nsec3_maxiterations()"); - if (iterations > max) + if (nsec3iter > max) fatal("NSEC3 iterations too big for weakest DNSKEY " "strength. Maximum iterations allowed %u.", max); } @@ -3478,15 +3833,18 @@ main(int argc, char *argv[]) { break; } + remove_duplicates(); + if (IS_NSEC3) - nsec3ify(dns_hash_sha1, iterations, salt, salt_length, + nsec3ify(dns_hash_sha1, nsec3iter, salt, salt_length, &hashlist); else nsecify(); if (!nokeys) { - writeset("keyset-", dns_rdatatype_dnskey); writeset("dsset-", dns_rdatatype_ds); + if (make_keyset) + writeset("keyset-", dns_rdatatype_dnskey); if (dlv != NULL) { writeset("dlvset-", dns_rdatatype_dlv); } @@ -3591,8 +3949,7 @@ main(int argc, char *argv[]) { while (!ISC_LIST_EMPTY(keylist)) { key = ISC_LIST_HEAD(keylist); ISC_LIST_UNLINK(keylist, key, link); - dst_key_free(&key->key); - isc_mem_put(mctx, key, sizeof(signer_key_t)); + dns_dnsseckey_destroy(mctx, &key); } isc_mem_put(mctx, tempfile, tempfilelen); diff --git a/bin/dnssec/dnssec-signzone.docbook b/bin/dnssec/dnssec-signzone.docbook index 87a801e..51a1496 100644 --- a/bin/dnssec/dnssec-signzone.docbook +++ b/bin/dnssec/dnssec-signzone.docbook @@ -18,10 +18,10 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + - June 08, 2009 + June 05, 2009 @@ -60,10 +60,12 @@ + + @@ -75,9 +77,13 @@ + + + + @@ -92,10 +98,10 @@ dnssec-signzone signs a zone. It generates NSEC and RRSIG records and produces a signed version of the - zone. It also generates a keyset- file containing - the key-signing keys for the zone, and if signing a zone which - contains delegations, it can optionally generate DS records for - the child zones from their keyset- files. + zone. The security status of delegations from the signed zone + (that is, whether the child zones are secure or not) is + determined by the presence or absence of a + keyset file for each child zone.
    @@ -122,31 +128,37 @@
    - -k key + -C - Treat specified key as a key signing key ignoring any - key flags. This option may be specified multiple times. + Compatibility mode: Generate a + keyset-zonename + file in addition to + dsset-zonename + when signing a zone, for use by older versions of + dnssec-signzone. - -l domain + -d directory - Generate a DLV set in addition to the key (DNSKEY) and DS sets. - The domain is appended to the name of the records. + Look for dsset- or + keyset- files in . - -d directory + -E engine - Look for keyset files in - as the directory + Uses a crypto hardware (OpenSSL engine) for the crypto operations + it supports, for instance signing with private keys from + a secure key store. When compiled with PKCS#11 support + it defaults to pkcs11; the empty name resets it to no engine. @@ -155,10 +167,39 @@ -g - If the zone contains any delegations, and there are - keyset- files for any of the child zones, - then DS records for the child zones will be generated from the - keys in those files. Existing DS records will be removed. + Generate DS records for child zones from + dsset- or keyset- + file. Existing DS records will be removed. + + + + + + -K directory + + + Key repository: Specify a directory to search for DNSSEC keys. + If not specified, defaults to the current directory. + + + + + + -k key + + + Treat specified key as a key signing key ignoring any + key flags. This option may be specified multiple times. + + + + + + -l domain + + + Generate a DLV set in addition to the key (DNSKEY) and DS sets. + The domain is appended to the name of the records. @@ -190,6 +231,8 @@ the start time. A time relative to the current time is indicated with now+N. If no is specified, 30 days from the start time is used as a default. + must be later than + . @@ -396,6 +439,89 @@ + -S + + + Smart signing: Instructs dnssec-signzone to + search the key repository for keys that match the zone being + signed, and to include them in the zone if appropriate. + + + When a key is found, its timing metadata is examined to + determine how it should be used, according to the following + rules. Each successive rule takes priority over the prior + ones: + + + + + + If no timing metadata has been set for the key, the key is + published in the zone and used to sign the zone. + + + + + + + + If the key's publication date is set and is in the past, the + key is published in the zone. + + + + + + + + If the key's activation date is set and in the past, the + key is published (regardless of publication date) and + used to sign the zone. + + + + + + + + If the key's revocation date is set and in the past, and the + key is published, then the key is revoked, and the revoked key + is used to sign the zone. + + + + + + + + If either of the key's unpublication or deletion dates are set + and in the past, the key is NOT published or used to sign the + zone, regardless of any other metadata. + + + + + + + + + -T ttl + + + Specifies the TTL to be used for new DNSKEY records imported + into the zone from the key repository. If not specified, + the default is the minimum TTL value from the zone's SOA + record. This option is ignored when signing without + , since DNSKEY records are not imported + from the key repository in that case. It is also ignored if + there are any pre-existing DNSKEY records at the zone apex, + in which case new records' TTL values will be set to match + them. + + + + + -t @@ -405,6 +531,20 @@ + -u + + + Update NSEC/NSEC3 chain when re-signing a previously signed + zone. With this option, a zone signed with NSEC can be + switched to NSEC3, or a zone signed with NSEC3 can + be switch to NSEC or to NSEC3 with different parameters. + Without this option, dnssec-signzone will + retain the existing chain when re-signing. + + + + + -v level @@ -414,10 +554,26 @@ + -x + + + Only sign the DNSKEY RRset with key-signing keys, and omit + signatures from zone-signing keys. (This is similar to the + dnssec-dnskey-kskonly yes; zone option in + named.) + + + + + -z - Ignore KSK flag on key when determining what to sign. + Ignore KSK flag on key when determining what to sign. This + causes KSK-flagged keys to sign all records, not just the + DNSKEY RRset. (This is similar to the + update-check-ksk no; zone option in + named.) @@ -426,7 +582,7 @@ -3 salt - Generate a NSEC3 chain with the given hex encoded salt. + Generate an NSEC3 chain with the given hex encoded salt. A dash (salt) can be used to indicate that no salt is to be used when generating the NSEC3 chain. @@ -437,8 +593,8 @@ -H iterations - When generating a NSEC3 chain use this many interations. The - default is 100. + When generating an NSEC3 chain, use this many interations. The + default is 10. @@ -447,10 +603,16 @@ -A - When generating a NSEC3 chain set the OPTOUT flag on all + When generating an NSEC3 chain set the OPTOUT flag on all NSEC3 records and do not generate NSEC3 records for insecure delegations. + + Using this option twice (i.e., ) + turns the OPTOUT flag off for all records. This is useful + when using the option to modify an NSEC3 + chain which previously had OPTOUT set. + @@ -484,10 +646,11 @@ The following command signs the example.com zone with the DSA key generated by dnssec-keygen - (Kexample.com.+003+17247). The zone's keys must be in the master - file (db.example.com). This invocation looks - for keyset files, in the current directory, - so that DS records can be generated from them (-g). + (Kexample.com.+003+17247). Because the -S option + is not being used, the zone's keys must be in the master file + (db.example.com). This invocation looks + for dsset files, in the current directory, + so that DS records can be imported from them (-g). % dnssec-signzone -g -o example.com db.example.com \ Kexample.com.+003+17247 @@ -510,33 +673,6 @@ db.example.com.signed - KNOWN BUGS - - dnssec-signzone was designed so that it could - sign a zone partially, using only a subset of the DNSSEC keys - needed to produce a fully-signed zone. This permits a zone - administrator, for example, to sign a zone with one key on one - machine, move the resulting partially-signed zone to a second - machine, and sign it again with a second key. - - - An unfortunate side-effect of this flexibility is that - dnssec-signzone does not check to make sure - it's signing a zone with any valid keys at all. An attempt to - sign a zone without any keys will appear to succeed, producing - a "signed" zone with no signatures. There is no warning issued - when a zone is not fully signed. - - - - This will be corrected in a future release. In the meantime, ISC - recommends examining the output of dnssec-signzone - to confirm that the zone is properly signed by all keys before - using it. - - - - SEE ALSO dnssec-keygen8 diff --git a/bin/dnssec/dnssec-signzone.html b/bin/dnssec/dnssec-signzone.html index 1d4ecff..28e7158 100644 --- a/bin/dnssec/dnssec-signzone.html +++ b/bin/dnssec/dnssec-signzone.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -29,21 +29,21 @@

    Synopsis

    -

    dnssec-signzone [-a] [-c class] [-d directory] [-e end-time] [-f output-file] [-g] [-h] [-k key] [-l domain] [-i interval] [-I input-format] [-j jitter] [-N soa-serial-format] [-o origin] [-O output-format] [-p] [-P] [-r randomdev] [-s start-time] [-t] [-v level] [-z] [-3 salt] [-H iterations] [-A] {zonefile} [key...]

    +

    dnssec-signzone [-a] [-c class] [-d directory] [-E engine] [-e end-time] [-f output-file] [-g] [-h] [-K directory] [-k key] [-l domain] [-i interval] [-I input-format] [-j jitter] [-N soa-serial-format] [-o origin] [-O output-format] [-p] [-P] [-r randomdev] [-S] [-s start-time] [-T ttl] [-t] [-u] [-v level] [-x] [-z] [-3 salt] [-H iterations] [-A] {zonefile} [key...]

    -

    DESCRIPTION

    +

    DESCRIPTION

    dnssec-signzone signs a zone. It generates NSEC and RRSIG records and produces a signed version of the - zone. It also generates a keyset- file containing - the key-signing keys for the zone, and if signing a zone which - contains delegations, it can optionally generate DS records for - the child zones from their keyset- files. + zone. The security status of delegations from the signed zone + (that is, whether the child zones are secure or not) is + determined by the presence or absence of a + keyset file for each child zone.

    -

    OPTIONS

    +

    OPTIONS

    -a

    @@ -53,6 +53,38 @@

    Specifies the DNS class of the zone.

    +
    -C
    +

    + Compatibility mode: Generate a + keyset-zonename + file in addition to + dsset-zonename + when signing a zone, for use by older versions of + dnssec-signzone. +

    +
    -d directory
    +

    + Look for dsset- or + keyset- files in directory. +

    +
    -E engine
    +

    + Uses a crypto hardware (OpenSSL engine) for the crypto operations + it supports, for instance signing with private keys from + a secure key store. When compiled with PKCS#11 support + it defaults to pkcs11; the empty name resets it to no engine. +

    +
    -g
    +

    + Generate DS records for child zones from + dsset- or keyset- + file. Existing DS records will be removed. +

    +
    -K directory
    +

    + Key repository: Specify a directory to search for DNSSEC keys. + If not specified, defaults to the current directory. +

    -k key

    Treat specified key as a key signing key ignoring any @@ -63,18 +95,6 @@ Generate a DLV set in addition to the key (DNSKEY) and DS sets. The domain is appended to the name of the records.

    -
    -d directory
    -

    - Look for keyset files in - directory as the directory -

    -
    -g
    -

    - If the zone contains any delegations, and there are - keyset- files for any of the child zones, - then DS records for the child zones will be generated from the - keys in those files. Existing DS records will be removed. -

    -s start-time

    Specify the date and time when the generated RRSIG records @@ -95,6 +115,8 @@ the start time. A time relative to the current time is indicated with now+N. If no end-time is specified, 30 days from the start time is used as a default. + end-time must be later than + start-time.

    -f output-file

    @@ -229,35 +251,119 @@ keyboard indicates that keyboard input should be used.

    +
    -S
    +
    +

    + Smart signing: Instructs dnssec-signzone to + search the key repository for keys that match the zone being + signed, and to include them in the zone if appropriate. +

    +

    + When a key is found, its timing metadata is examined to + determine how it should be used, according to the following + rules. Each successive rule takes priority over the prior + ones: +

    +
    +
    +

    + If no timing metadata has been set for the key, the key is + published in the zone and used to sign the zone. +

    +
    +

    + If the key's publication date is set and is in the past, the + key is published in the zone. +

    +
    +

    + If the key's activation date is set and in the past, the + key is published (regardless of publication date) and + used to sign the zone. +

    +
    +

    + If the key's revocation date is set and in the past, and the + key is published, then the key is revoked, and the revoked key + is used to sign the zone. +

    +
    +

    + If either of the key's unpublication or deletion dates are set + and in the past, the key is NOT published or used to sign the + zone, regardless of any other metadata. +

    +
    +
    +
    -T ttl
    +

    + Specifies the TTL to be used for new DNSKEY records imported + into the zone from the key repository. If not specified, + the default is the minimum TTL value from the zone's SOA + record. This option is ignored when signing without + -S, since DNSKEY records are not imported + from the key repository in that case. It is also ignored if + there are any pre-existing DNSKEY records at the zone apex, + in which case new records' TTL values will be set to match + them. +

    -t

    Print statistics at completion.

    +
    -u
    +

    + Update NSEC/NSEC3 chain when re-signing a previously signed + zone. With this option, a zone signed with NSEC can be + switched to NSEC3, or a zone signed with NSEC3 can + be switch to NSEC or to NSEC3 with different parameters. + Without this option, dnssec-signzone will + retain the existing chain when re-signing. +

    -v level

    Sets the debugging level.

    +
    -x
    +

    + Only sign the DNSKEY RRset with key-signing keys, and omit + signatures from zone-signing keys. (This is similar to the + dnssec-dnskey-kskonly yes; zone option in + named.) +

    -z

    - Ignore KSK flag on key when determining what to sign. + Ignore KSK flag on key when determining what to sign. This + causes KSK-flagged keys to sign all records, not just the + DNSKEY RRset. (This is similar to the + update-check-ksk no; zone option in + named.)

    -3 salt

    - Generate a NSEC3 chain with the given hex encoded salt. + Generate an NSEC3 chain with the given hex encoded salt. A dash (salt) can be used to indicate that no salt is to be used when generating the NSEC3 chain.

    -H iterations

    - When generating a NSEC3 chain use this many interations. The - default is 100. + When generating an NSEC3 chain, use this many interations. The + default is 10.

    -A
    -

    - When generating a NSEC3 chain set the OPTOUT flag on all +

    +

    + When generating an NSEC3 chain set the OPTOUT flag on all NSEC3 records and do not generate NSEC3 records for insecure delegations. -

    +

    +

    + Using this option twice (i.e., -AA) + turns the OPTOUT flag off for all records. This is useful + when using the -u option to modify an NSEC3 + chain which previously had OPTOUT set. +

    +
    zonefile

    The file containing the zone to be signed. @@ -273,14 +379,15 @@

    -

    EXAMPLE

    +

    EXAMPLE

    The following command signs the example.com zone with the DSA key generated by dnssec-keygen - (Kexample.com.+003+17247). The zone's keys must be in the master - file (db.example.com). This invocation looks - for keyset files, in the current directory, - so that DS records can be generated from them (-g). + (Kexample.com.+003+17247). Because the -S option + is not being used, the zone's keys must be in the master file + (db.example.com). This invocation looks + for dsset files, in the current directory, + so that DS records can be imported from them (-g).

    % dnssec-signzone -g -o example.com db.example.com \
     Kexample.com.+003+17247
    @@ -302,39 +409,14 @@ db.example.com.signed
     %
    -

    KNOWN BUGS

    -

    - dnssec-signzone was designed so that it could - sign a zone partially, using only a subset of the DNSSEC keys - needed to produce a fully-signed zone. This permits a zone - administrator, for example, to sign a zone with one key on one - machine, move the resulting partially-signed zone to a second - machine, and sign it again with a second key. -

    -

    - An unfortunate side-effect of this flexibility is that - dnssec-signzone does not check to make sure - it's signing a zone with any valid keys at all. An attempt to - sign a zone without any keys will appear to succeed, producing - a "signed" zone with no signatures. There is no warning issued - when a zone is not fully signed. -

    -

    - This will be corrected in a future release. In the meantime, ISC - recommends examining the output of dnssec-signzone - to confirm that the zone is properly signed by all keys before - using it. -

    -
    -
    -

    SEE ALSO

    +

    SEE ALSO

    dnssec-keygen(8), BIND 9 Administrator Reference Manual, RFC 4033.

    -

    AUTHOR

    +

    AUTHOR

    Internet Systems Consortium

    diff --git a/bin/dnssec/dnssectool.c b/bin/dnssec/dnssectool.c index 81120e3..da6b0b2 100644 --- a/bin/dnssec/dnssectool.c +++ b/bin/dnssec/dnssectool.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssectool.c,v 1.45.334.5 2009-06-22 05:05:00 marka Exp $ */ +/* $Id: dnssectool.c,v 1.60 2010-01-19 23:48:56 tbox Exp $ */ /*! \file */ @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -36,6 +37,8 @@ #include #include +#include +#include #include #include #include @@ -111,39 +114,16 @@ type_format(const dns_rdatatype_t type, char *cp, unsigned int size) { } void -alg_format(const dns_secalg_t alg, char *cp, unsigned int size) { - isc_buffer_t b; - isc_region_t r; - isc_result_t result; - - isc_buffer_init(&b, cp, size - 1); - result = dns_secalg_totext(alg, &b); - check_result(result, "dns_secalg_totext()"); - isc_buffer_usedregion(&b, &r); - r.base[r.length] = 0; -} - -void sig_format(dns_rdata_rrsig_t *sig, char *cp, unsigned int size) { char namestr[DNS_NAME_FORMATSIZE]; char algstr[DNS_NAME_FORMATSIZE]; dns_name_format(&sig->signer, namestr, sizeof(namestr)); - alg_format(sig->algorithm, algstr, sizeof(algstr)); + dns_secalg_format(sig->algorithm, algstr, sizeof(algstr)); snprintf(cp, size, "%s/%s/%d", namestr, algstr, sig->keyid); } void -key_format(const dst_key_t *key, char *cp, unsigned int size) { - char namestr[DNS_NAME_FORMATSIZE]; - char algstr[DNS_NAME_FORMATSIZE]; - - dns_name_format(dst_key_name(key), namestr, sizeof(namestr)); - alg_format((dns_secalg_t) dst_key_alg(key), algstr, sizeof(algstr)); - snprintf(cp, size, "%s/%s/%d", namestr, algstr, dst_key_id(key)); -} - -void setup_logging(int verbose, isc_mem_t *mctx, isc_log_t **logp) { isc_result_t result; isc_logdestination_t destination; @@ -265,32 +245,92 @@ cleanup_entropy(isc_entropy_t **ectx) { isc_entropy_detach(ectx); } +static isc_stdtime_t +time_units(isc_stdtime_t offset, char *suffix, const char *str) { + switch (suffix[0]) { + case 'Y': case 'y': + return (offset * (365 * 24 * 3600)); + case 'M': case 'm': + switch (suffix[1]) { + case 'O': case 'o': + return (offset * (30 * 24 * 3600)); + case 'I': case 'i': + return (offset * 60); + case '\0': + fatal("'%s' ambiguous: use 'mi' for minutes " + "or 'mo' for months", str); + default: + fatal("time value %s is invalid", str); + } + /* NOTREACHED */ + break; + case 'W': case 'w': + return (offset * (7 * 24 * 3600)); + case 'D': case 'd': + return (offset * (24 * 3600)); + case 'H': case 'h': + return (offset * 3600); + case 'S': case 's': case '\0': + return (offset); + default: + fatal("time value %s is invalid", str); + } + /* NOTREACHED */ + return(0); /* silence compiler warning */ +} + +dns_ttl_t +strtottl(const char *str) { + const char *orig = str; + dns_ttl_t ttl; + char *endp; + + ttl = strtol(str, &endp, 0); + if (ttl == 0 && endp == str) + fatal("TTL must be numeric"); + ttl = time_units(ttl, endp, orig); + return (ttl); +} + isc_stdtime_t strtotime(const char *str, isc_int64_t now, isc_int64_t base) { isc_int64_t val, offset; isc_result_t result; + const char *orig = str; char *endp; - if (str[0] == '+') { + if ((str[0] == '0' || str[0] == '-') && str[1] == '\0') + return ((isc_stdtime_t) 0); + + if (strncmp(str, "now", 3) == 0) { + base = now; + str += 3; + } + + if (str[0] == '\0') + return ((isc_stdtime_t) base); + else if (str[0] == '+') { offset = strtol(str + 1, &endp, 0); - if (*endp != '\0') - fatal("time value %s is invalid", str); + offset = time_units((isc_stdtime_t) offset, endp, orig); val = base + offset; - } else if (strncmp(str, "now+", 4) == 0) { - offset = strtol(str + 4, &endp, 0); - if (*endp != '\0') - fatal("time value %s is invalid", str); - val = now + offset; + } else if (str[0] == '-') { + offset = strtol(str + 1, &endp, 0); + offset = time_units((isc_stdtime_t) offset, endp, orig); + val = base - offset; } else if (strlen(str) == 8U) { char timestr[15]; sprintf(timestr, "%s000000", str); result = dns_time64_fromtext(timestr, &val); if (result != ISC_R_SUCCESS) - fatal("time value %s is invalid", str); + fatal("time value %s is invalid: %s", orig, + isc_result_totext(result)); + } else if (strlen(str) > 14U) { + fatal("time value %s is invalid", orig); } else { result = dns_time64_fromtext(str, &val); if (result != ISC_R_SUCCESS) - fatal("time value %s is invalid", str); + fatal("time value %s is invalid: %s", orig, + isc_result_totext(result)); } return ((isc_stdtime_t) val); @@ -311,3 +351,114 @@ strtoclass(const char *str) { fatal("unknown class %s", str); return (rdclass); } + +isc_result_t +try_dir(const char *dirname) { + isc_result_t result; + isc_dir_t d; + + isc_dir_init(&d); + result = isc_dir_open(&d, dirname); + if (result == ISC_R_SUCCESS) { + isc_dir_close(&d); + } + return (result); +} + +/* + * Check private key version compatibility. + */ +void +check_keyversion(dst_key_t *key, char *keystr) { + int major, minor; + dst_key_getprivateformat(key, &major, &minor); + INSIST(major <= DST_MAJOR_VERSION); /* invalid private key */ + + if (major < DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) + fatal("Key %s has incompatible format version %d.%d, " + "use -f to force upgrade to new version.", + keystr, major, minor); + if (minor > DST_MINOR_VERSION) + fatal("Key %s has incompatible format version %d.%d, " + "use -f to force downgrade to current version.", + keystr, major, minor); +} + +void +set_keyversion(dst_key_t *key) { + int major, minor; + dst_key_getprivateformat(key, &major, &minor); + INSIST(major <= DST_MAJOR_VERSION); + + if (major != DST_MAJOR_VERSION || minor != DST_MINOR_VERSION) + dst_key_setprivateformat(key, DST_MAJOR_VERSION, + DST_MINOR_VERSION); + + /* + * If the key is from a version older than 1.3, set + * set the creation date + */ + if (major < 1 || (major == 1 && minor <= 2)) { + isc_stdtime_t now; + isc_stdtime_get(&now); + dst_key_settime(key, DST_TIME_CREATED, now); + } +} + +isc_boolean_t +key_collision(isc_uint16_t id, dns_name_t *name, const char *dir, + dns_secalg_t alg, isc_mem_t *mctx, isc_boolean_t *exact) +{ + isc_result_t result; + isc_boolean_t conflict = ISC_FALSE; + dns_dnsseckeylist_t matchkeys; + dns_dnsseckey_t *key = NULL; + isc_uint16_t oldid, diff; + isc_uint16_t bits = DNS_KEYFLAG_REVOKE; /* flag bits to look for */ + + if (exact != NULL) + *exact = ISC_FALSE; + + ISC_LIST_INIT(matchkeys); + result = dns_dnssec_findmatchingkeys(name, dir, mctx, &matchkeys); + if (result == ISC_R_NOTFOUND) + return (ISC_FALSE); + + while (!ISC_LIST_EMPTY(matchkeys) && !conflict) { + key = ISC_LIST_HEAD(matchkeys); + if (dst_key_alg(key->key) != alg) + goto next; + + oldid = dst_key_id(key->key); + diff = (oldid > id) ? (oldid - id) : (id - oldid); + if ((diff & ~bits) == 0) { + conflict = ISC_TRUE; + if (diff != 0) { + if (verbose > 1) + fprintf(stderr, "Key ID %d could " + "collide with %d\n", + id, oldid); + } else { + if (exact != NULL) + *exact = ISC_TRUE; + if (verbose > 1) + fprintf(stderr, "Key ID %d exists\n", + id); + } + } + + next: + ISC_LIST_UNLINK(matchkeys, key, link); + dns_dnsseckey_destroy(mctx, &key); + } + + /* Finish freeing the list */ + while (!ISC_LIST_EMPTY(matchkeys)) { + key = ISC_LIST_HEAD(matchkeys); + ISC_LIST_UNLINK(matchkeys, key, link); + dns_dnsseckey_destroy(mctx, &key); + } + + return (conflict); +} + diff --git a/bin/dnssec/dnssectool.h b/bin/dnssec/dnssectool.h index 8cc133d..b52bc13 100644 --- a/bin/dnssec/dnssectool.h +++ b/bin/dnssec/dnssectool.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssectool.h,v 1.22.48.2 2009-09-04 23:46:58 tbox Exp $ */ +/* $Id: dnssectool.h,v 1.31 2010-01-19 23:48:56 tbox Exp $ */ #ifndef DNSSECTOOL_H #define DNSSECTOOL_H 1 @@ -27,8 +27,9 @@ typedef void (fatalcallback_t)(void); -void -fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); +ISC_PLATFORM_NORETURN_PRE void +fatal(const char *format, ...) +ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; void setfatalcallback(fatalcallback_t *callback); @@ -44,16 +45,8 @@ type_format(const dns_rdatatype_t type, char *cp, unsigned int size); #define TYPE_FORMATSIZE 20 void -alg_format(const dns_secalg_t alg, char *cp, unsigned int size); -#define ALG_FORMATSIZE 20 - -void sig_format(dns_rdata_rrsig_t *sig, char *cp, unsigned int size); -#define SIG_FORMATSIZE (DNS_NAME_FORMATSIZE + ALG_FORMATSIZE + sizeof("65535")) - -void -key_format(const dst_key_t *key, char *cp, unsigned int size); -#define KEY_FORMATSIZE (DNS_NAME_FORMATSIZE + ALG_FORMATSIZE + sizeof("65535")) +#define SIG_FORMATSIZE (DNS_NAME_FORMATSIZE + DNS_SECALG_FORMATSIZE + sizeof("65535")) void setup_logging(int verbose, isc_mem_t *mctx, isc_log_t **logp); @@ -67,10 +60,24 @@ setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx); void cleanup_entropy(isc_entropy_t **ectx); +dns_ttl_t strtottl(const char *str); + isc_stdtime_t strtotime(const char *str, isc_int64_t now, isc_int64_t base); dns_rdataclass_t strtoclass(const char *str); +isc_result_t +try_dir(const char *dirname); + +void +check_keyversion(dst_key_t *key, char *keystr); + +void +set_keyversion(dst_key_t *key); + +isc_boolean_t +key_collision(isc_uint16_t id, dns_name_t *name, const char *dir, + dns_secalg_t alg, isc_mem_t *mctx, isc_boolean_t *exact); #endif /* DNSSEC_DNSSECTOOL_H */ diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in index ee76134..a3dbb38 100644 --- a/bin/named/Makefile.in +++ b/bin/named/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 1998-2002 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.101 2008-09-23 17:25:47 jinmei Exp $ +# $Id: Makefile.in,v 1.114 2010-12-22 09:00:40 marka Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -43,9 +43,9 @@ DLZDRIVER_LIBS = @DLZ_DRIVER_LIBS@ CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include -I. \ ${LWRES_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} \ ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \ - ${DLZDRIVER_INCLUDES} ${DBDRIVER_INCLUDES} + ${DLZDRIVER_INCLUDES} ${DBDRIVER_INCLUDES} @DST_OPENSSL_INC@ -CDEFINES = @USE_DLZ@ +CDEFINES = @USE_DLZ@ @USE_PKCS11@ @USE_OPENSSL@ CWARNINGS = @@ -53,6 +53,7 @@ DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ ISCCCLIBS = ../../lib/isccc/libisccc.@A@ ISCLIBS = ../../lib/isc/libisc.@A@ +ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ LWRESLIBS = ../../lib/lwres/liblwres.@A@ BIND9LIBS = ../../lib/bind9/libbind9.@A@ @@ -70,6 +71,10 @@ LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \ ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCLIBS} \ ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@ +NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \ + ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCNOSYMLIBS} \ + ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@ + SUBDIRS = unix TARGETS = named@EXEEXT@ lwresd@EXEEXT@ @@ -86,10 +91,12 @@ OBJS = builtin.@O@ client.@O@ config.@O@ control.@O@ \ UOBJS = unix/os.@O@ +SYMOBJS = symtbl.@O@ + SRCS = builtin.c client.c config.c control.c \ controlconf.c interfacemgr.c \ listenlist.c log.c logconf.c main.c notify.c \ - query.c server.c sortlist.c statschannel.c \ + query.c server.c sortlist.c statschannel.c symtbl.c symtbl-empty.c \ tkeyconf.c tsigconf.c update.c xfrout.c \ zoneconf.c \ lwaddr.c lwresd.c lwdclient.c lwderror.c lwdgabn.c \ @@ -111,15 +118,20 @@ main.@O@: main.c -DNS_LOCALSTATEDIR=\"${localstatedir}\" \ -DNS_SYSCONFDIR=\"${sysconfdir}\" -c ${srcdir}/main.c -config.@O@: config.c +bind.keys.h: ${top_srcdir}/bind.keys ${srcdir}/bindkeys.pl + ${PERL} ${srcdir}/bindkeys.pl < ${top_srcdir}/bind.keys > $@ + +config.@O@: config.c bind.keys.h ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ -DVERSION=\"${VERSION}\" \ -DNS_LOCALSTATEDIR=\"${localstatedir}\" \ + -DNS_SYSCONFDIR=\"${sysconfdir}\" \ -c ${srcdir}/config.c named@EXEEXT@: ${OBJS} ${UOBJS} ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - ${OBJS} ${UOBJS} ${LIBS} + export MAKE_SYMTABLE="yes"; \ + export BASEOBJS="${OBJS} ${UOBJS}"; \ + ${FINALBUILDCMD} lwresd@EXEEXT@: named@EXEEXT@ rm -f lwresd@EXEEXT@ @@ -133,7 +145,10 @@ docclean manclean maintainer-clean:: clean distclean maintainer-clean:: rm -f ${TARGETS} ${OBJS} -bind9.xsl.h: bind9.xsl convertxsl.pl +maintainer-clean:: + rm -f bind.keys.h + +bind9.xsl.h: bind9.xsl ${srcdir}/convertxsl.pl ${PERL} ${srcdir}/convertxsl.pl < ${srcdir}/bind9.xsl > bind9.xsl.h depend: bind9.xsl.h diff --git a/bin/named/bind.keys.h b/bin/named/bind.keys.h new file mode 100644 index 0000000..0177214 --- /dev/null +++ b/bin/named/bind.keys.h @@ -0,0 +1,99 @@ +/* + * Generated by bindkeys.pl 1.7 2011-01-04 23:47:13 tbox Exp + * From bind.keys 1.7 2011-01-03 23:45:07 each Exp + */ +#define TRUSTED_KEYS "\ +# The bind.keys file is used to override the built-in DNSSEC trust anchors\n\ +# which are included as part of BIND 9. As of the current release, the only\n\ +# trust anchors it contains are those for the DNS root zone (\".\"), and for\n\ +# the ISC DNSSEC Lookaside Validation zone (\"dlv.isc.org\"). Trust anchors\n\ +# for any other zones MUST be configured elsewhere; if they are configured\n\ +# here, they will not be recognized or used by named.\n\ +#\n\ +# The built-in trust anchors are provided for convenience of configuration.\n\ +# They are not activated within named.conf unless specifically switched on.\n\ +# To use the built-in root key, set \"dnssec-validation auto;\" in\n\ +# named.conf options. To use the built-in DLV key, set\n\ +# \"dnssec-lookaside auto;\". Without these options being set,\n\ +# the keys in this file are ignored.\n\ +#\n\ +# This file is NOT expected to be user-configured.\n\ +#\n\ +# These keys are current as of January 2011. If any key fails to\n\ +# initialize correctly, it may have expired. In that event you should\n\ +# replace this file with a current version. The latest version of\n\ +# bind.keys can always be obtained from ISC at https://www.isc.org/bind-keys.\n\ +\n\ +trusted-keys {\n\ + # ISC DLV: See https://www.isc.org/solutions/dlv for details.\n\ + # NOTE: This key is activated by setting \"dnssec-lookaside auto;\"\n\ + # in named.conf.\n\ + dlv.isc.org. 257 3 5 \"BEAAAAPHMu/5onzrEE7z1egmhg/WPO0+juoZrW3euWEn4MxDCE1+lLy2\n\ + brhQv5rN32RKtMzX6Mj70jdzeND4XknW58dnJNPCxn8+jAGl2FZLK8t+\n\ + 1uq4W+nnA3qO2+DL+k6BD4mewMLbIYFwe0PG73Te9fZ2kJb56dhgMde5\n\ + ymX4BI/oQ+cAK50/xvJv00Frf8kw6ucMTwFlgPe+jnGxPPEmHAte/URk\n\ + Y62ZfkLoBAADLHQ9IrS2tryAe7mbBZVcOwIeU/Rw/mRx/vwwMCTgNboM\n\ + QKtUdvNXDrYJDSHZws3xiRXF1Rf+al9UmZfSav/4NWLKjHzpT59k/VSt\n\ + TDN0YUuWrBNh\";\n\ +\n\ + # ROOT KEY: See https://data.iana.org/root-anchors/root-anchors.xml\n\ + # for current trust anchor information.\n\ + # NOTE: This key is activated by setting \"dnssec-validation auto;\"\n\ + # in named.conf.\n\ + . 257 3 8 \"AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF\n\ + FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX\n\ + bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD\n\ + X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz\n\ + W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS\n\ + Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq\n\ + QxA+Uk1ihz0=\";\n\ +};\n\ +" + +#define MANAGED_KEYS "\ +# The bind.keys file is used to override the built-in DNSSEC trust anchors\n\ +# which are included as part of BIND 9. As of the current release, the only\n\ +# trust anchors it contains are those for the DNS root zone (\".\"), and for\n\ +# the ISC DNSSEC Lookaside Validation zone (\"dlv.isc.org\"). Trust anchors\n\ +# for any other zones MUST be configured elsewhere; if they are configured\n\ +# here, they will not be recognized or used by named.\n\ +#\n\ +# The built-in trust anchors are provided for convenience of configuration.\n\ +# They are not activated within named.conf unless specifically switched on.\n\ +# To use the built-in root key, set \"dnssec-validation auto;\" in\n\ +# named.conf options. To use the built-in DLV key, set\n\ +# \"dnssec-lookaside auto;\". Without these options being set,\n\ +# the keys in this file are ignored.\n\ +#\n\ +# This file is NOT expected to be user-configured.\n\ +#\n\ +# These keys are current as of January 2011. If any key fails to\n\ +# initialize correctly, it may have expired. In that event you should\n\ +# replace this file with a current version. The latest version of\n\ +# bind.keys can always be obtained from ISC at https://www.isc.org/bind-keys.\n\ +\n\ +managed-keys {\n\ + # ISC DLV: See https://www.isc.org/solutions/dlv for details.\n\ + # NOTE: This key is activated by setting \"dnssec-lookaside auto;\"\n\ + # in named.conf.\n\ + dlv.isc.org. initial-key 257 3 5 \"BEAAAAPHMu/5onzrEE7z1egmhg/WPO0+juoZrW3euWEn4MxDCE1+lLy2\n\ + brhQv5rN32RKtMzX6Mj70jdzeND4XknW58dnJNPCxn8+jAGl2FZLK8t+\n\ + 1uq4W+nnA3qO2+DL+k6BD4mewMLbIYFwe0PG73Te9fZ2kJb56dhgMde5\n\ + ymX4BI/oQ+cAK50/xvJv00Frf8kw6ucMTwFlgPe+jnGxPPEmHAte/URk\n\ + Y62ZfkLoBAADLHQ9IrS2tryAe7mbBZVcOwIeU/Rw/mRx/vwwMCTgNboM\n\ + QKtUdvNXDrYJDSHZws3xiRXF1Rf+al9UmZfSav/4NWLKjHzpT59k/VSt\n\ + TDN0YUuWrBNh\";\n\ +\n\ + # ROOT KEY: See https://data.iana.org/root-anchors/root-anchors.xml\n\ + # for current trust anchor information.\n\ + # NOTE: This key is activated by setting \"dnssec-validation auto;\"\n\ + # in named.conf.\n\ + . initial-key 257 3 8 \"AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF\n\ + FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX\n\ + bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD\n\ + X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz\n\ + W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS\n\ + Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq\n\ + QxA+Uk1ihz0=\";\n\ +};\n\ +" diff --git a/bin/named/bind9.xsl b/bin/named/bind9.xsl index 71d2eba..5913c1c 100644 --- a/bin/named/bind9.xsl +++ b/bin/named/bind9.xsl @@ -15,7 +15,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + \n" @@ -20,7 +20,7 @@ static char xslmsg[] = " - PERFORMANCE OF THIS SOFTWARE.\n" "-->\n" "\n" - "\n" + "\n" "\n" " 71U || zlen < 8U || (nlen % 2) != 1U) + return (ISC_R_NOTFOUND); + + /* + * We assume the zone name is well formed. + */ + + /* + * XXXMPA We could check the dns64 suffix here if we need to. + */ + /* + * Check that name is a series of nibbles. + * Compute the byte values that correspond to the nibbles as we go. + * + * Shift the final result 4 bits, by setting 'i' to 1, if we if we + * have a odd number of nibbles so that "must be zero" tests below + * are byte aligned and we correctly return ISC_R_NOTFOUND or + * ISC_R_SUCCESS. We will not generate a CNAME in this case. + */ + i = (nlen % 4) == 1U ? 1 : 0; + j = nlen; + memset(v, 0, sizeof(v)); + while (j >= 1U) { + INSIST((i/2) < sizeof(v)); + if (j > 1U && name[1] != '.') + return (ISC_R_NOTFOUND); + v[i/2] >>= 4; + if ((s = strchr(hex, name[0])) != NULL) + v[i/2] |= (s - hex) << 4; + else if ((s = strchr(HEX, name[0])) != NULL) + v[i/2] |= (s - HEX) << 4; + else + return (ISC_R_NOTFOUND); + if (j > 1U) + j -= 2; + else + j -= 1; + name += 2; + i++; + } + + /* + * If we get here then we know name only consisted of nibbles. + * Now we need to determine if the name exists or not and whether + * it corresponds to a empty node in the zone or there should be + * a CNAME. + */ + switch (zlen) { + case 24: /* prefix len 32 */ + /* + * If the total length is not 71 then this is a empty node + * so return success. + */ + if (nlen + zlen != 71U) + return (ISC_R_SUCCESS); + snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.", + v[8], v[9], v[10], v[11]); + break; + case 28: /* prefix len 40 */ + /* + * The nibbles that map to this byte must be zero for 'name' + * to exist in the zone. + */ + if (nlen > 11U && v[nlen/4 - 3] != 0) + return (ISC_R_NOTFOUND); + /* + * If the total length is not 71 then this is a empty node + * so return success. + */ + if (nlen + zlen != 71U) + return (ISC_R_SUCCESS); + snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.", + v[6], v[8], v[9], v[10]); + break; + case 32: /* prefix len 48 */ + /* + * The nibbles that map to this byte must be zero for 'name' + * to exist in the zone. + */ + if (nlen > 7U && v[nlen/4 - 2] != 0) + return (ISC_R_NOTFOUND); + /* + * If the total length is not 71 then this is a empty node + * so return success. + */ + if (nlen + zlen != 71U) + return (ISC_R_SUCCESS); + snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.", + v[5], v[6], v[8], v[9]); + break; + case 36: /* prefix len 56 */ + /* + * The nibbles that map to this byte must be zero for 'name' + * to exist in the zone. + */ + if (nlen > 3U && v[nlen/4 - 1] != 0) + return (ISC_R_NOTFOUND); + /* + * If the total length is not 71 then this is a empty node + * so return success. + */ + if (nlen + zlen != 71U) + return (ISC_R_SUCCESS); + snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.", + v[4], v[5], v[6], v[8]); + break; + case 40: /* prefix len 64 */ + /* + * The nibbles that map to this byte must be zero for 'name' + * to exist in the zone. + */ + if (v[nlen/4] != 0) + return (ISC_R_NOTFOUND); + /* + * If the total length is not 71 then this is a empty node + * so return success. + */ + if (nlen + zlen != 71U) + return (ISC_R_SUCCESS); + snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.", + v[3], v[4], v[5], v[6]); + break; + case 56: /* prefix len 96 */ + /* + * If the total length is not 71 then this is a empty node + * so return success. + */ + if (nlen + zlen != 71U) + return (ISC_R_SUCCESS); + snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.", + v[0], v[1], v[2], v[3]); + break; + default: + /* + * This should never be reached unless someone adds a + * zone declaration with this internal type to named.conf. + */ + return (ISC_R_NOTFOUND); + } + return (dns_sdb_putrr(lookup, "CNAME", 600, reverse)); +} + static isc_result_t builtin_lookup(const char *zone, const char *name, void *dbdata, dns_sdblookup_t *lookup) @@ -78,6 +249,8 @@ builtin_lookup(const char *zone, const char *name, void *dbdata, if (strcmp(name, "@") == 0) return (b->do_lookup(lookup)); + else if (b->do_lookup == do_dns64_lookup) + return (dns64_cname(zone, name, lookup)); else return (ISC_R_NOTFOUND); } @@ -132,11 +305,13 @@ do_authors_lookup(dns_sdblookup_t *lookup) { "Michael Graff", "Andreas Gustafsson", "Bob Halley", + "Evan Hunt", "JINMEI Tatuya", "David Lawrence", "Danny Mayer", "Damien Neil", "Matt Nelson", + "Jeremy C. Reed", "Michael Sawyer", "Brian Wellington", NULL @@ -174,6 +349,12 @@ do_id_lookup(dns_sdblookup_t *lookup) { } static isc_result_t +do_dns64_lookup(dns_sdblookup_t *lookup) { + UNUSED(lookup); + return (ISC_R_SUCCESS); +} + +static isc_result_t do_empty_lookup(dns_sdblookup_t *lookup) { UNUSED(lookup); @@ -220,7 +401,7 @@ builtin_create(const char *zone, int argc, char **argv, UNUSED(zone); UNUSED(driverdata); - if (strcmp(argv[0], "empty") == 0) { + if (strcmp(argv[0], "empty") == 0 || strcmp(argv[0], "dns64") == 0) { if (argc != 3) return (DNS_R_SYNTAX); } else if (argc != 1) @@ -234,7 +415,8 @@ builtin_create(const char *zone, int argc, char **argv, *dbdata = &authors_builtin; else if (strcmp(argv[0], "id") == 0) *dbdata = &id_builtin; - else if (strcmp(argv[0], "empty") == 0) { + else if (strcmp(argv[0], "empty") == 0 || + strcmp(argv[0], "dns64") == 0) { builtin_t *empty; char *server; char *contact; @@ -246,7 +428,10 @@ builtin_create(const char *zone, int argc, char **argv, server = isc_mem_strdup(ns_g_mctx, argv[1]); contact = isc_mem_strdup(ns_g_mctx, argv[2]); if (empty == NULL || server == NULL || contact == NULL) { - *dbdata = &empty_builtin; + if (strcmp(argv[0], "empty") == 0) + *dbdata = &empty_builtin; + else + *dbdata = &dns64_builtin; if (server != NULL) isc_mem_free(ns_g_mctx, server); if (contact != NULL) @@ -254,7 +439,12 @@ builtin_create(const char *zone, int argc, char **argv, if (empty != NULL) isc_mem_put(ns_g_mctx, empty, sizeof (*empty)); } else { - memcpy(empty, &empty_builtin, sizeof (empty_builtin)); + if (strcmp(argv[0], "empty") == 0) + memcpy(empty, &empty_builtin, + sizeof (empty_builtin)); + else + memcpy(empty, &dns64_builtin, + sizeof (empty_builtin)); empty->server = server; empty->contact = contact; *dbdata = empty; @@ -276,7 +466,7 @@ builtin_destroy(const char *zone, void *driverdata, void **dbdata) { */ if (*dbdata == &version_builtin || *dbdata == &hostname_builtin || *dbdata == &authors_builtin || *dbdata == &id_builtin || - *dbdata == &empty_builtin) + *dbdata == &empty_builtin || *dbdata == &dns64_builtin) return; isc_mem_free(ns_g_mctx, b->server); @@ -306,3 +496,4 @@ void ns_builtin_deinit(void) { dns_sdb_unregister(&builtin_impl); } + diff --git a/bin/named/client.c b/bin/named/client.c index 6236d27..bc9cc87 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: client.c,v 1.259.12.5 2010-09-24 08:30:27 tbox Exp $ */ +/* $Id: client.c,v 1.271 2011-01-11 23:47:12 tbox Exp $ */ #include @@ -918,7 +918,7 @@ ns_client_send(ns_client_t *client) { dns_compress_t cctx; isc_boolean_t cleanup_cctx = ISC_FALSE; unsigned char sendbuf[SEND_BUFFER_SIZE]; - unsigned int dnssec_opts; + unsigned int render_opts; unsigned int preferred_glue; isc_boolean_t opt_included = ISC_FALSE; @@ -930,10 +930,21 @@ ns_client_send(ns_client_t *client) { client->message->flags |= DNS_MESSAGEFLAG_RA; if ((client->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0) - dnssec_opts = 0; + render_opts = 0; else - dnssec_opts = DNS_MESSAGERENDER_OMITDNSSEC; - + render_opts = DNS_MESSAGERENDER_OMITDNSSEC; +#ifdef ALLOW_FILTER_AAAA_ON_V4 + /* + * filter-aaaa-on-v4 yes or break-dnssec option to suppress + * AAAA records + * We already know that request came via IPv4, + * that we have both AAAA and A records, + * and that we either have no signatures that the client wants + * or we are supposed to break DNSSEC. + */ + if ((client->attributes & NS_CLIENTATTR_FILTER_AAAA) != 0) + render_opts |= DNS_MESSAGERENDER_FILTER_AAAA; +#endif preferred_glue = 0; if (client->view != NULL) { if (client->view->preferred_glue == dns_rdatatype_a) @@ -977,7 +988,7 @@ ns_client_send(ns_client_t *client) { result = dns_message_rendersection(client->message, DNS_SECTION_ANSWER, DNS_MESSAGERENDER_PARTIAL | - dnssec_opts); + render_opts); if (result == ISC_R_NOSPACE) { client->message->flags |= DNS_MESSAGEFLAG_TC; goto renderend; @@ -987,7 +998,7 @@ ns_client_send(ns_client_t *client) { result = dns_message_rendersection(client->message, DNS_SECTION_AUTHORITY, DNS_MESSAGERENDER_PARTIAL | - dnssec_opts); + render_opts); if (result == ISC_R_NOSPACE) { client->message->flags |= DNS_MESSAGEFLAG_TC; goto renderend; @@ -996,7 +1007,7 @@ ns_client_send(ns_client_t *client) { goto done; result = dns_message_rendersection(client->message, DNS_SECTION_ADDITIONAL, - preferred_glue | dnssec_opts); + preferred_glue | render_opts); if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE) goto done; renderend: @@ -1355,7 +1366,6 @@ client_request(isc_task_t *task, isc_event_t *event) { dns_name_t *signame; isc_boolean_t ra; /* Recursion available. */ isc_netaddr_t netaddr; - isc_netaddr_t destaddr; int match; dns_messageid_t id; unsigned int flags; @@ -1473,7 +1483,7 @@ client_request(isc_task_t *task, isc_event_t *event) { /* * Silently drop multicast requests for the present. - * XXXMPA look at when/if mDNS spec stabilizes. + * XXXMPA revisit this as mDNS spec was published. */ if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0) { ns_client_log(client, NS_LOGCATEGORY_CLIENT, @@ -1647,24 +1657,20 @@ client_request(isc_task_t *task, isc_event_t *event) { * etc), we regard this as an error for safety. */ if ((client->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0) - isc_netaddr_fromsockaddr(&destaddr, &client->interface->addr); + isc_netaddr_fromsockaddr(&client->destaddr, + &client->interface->addr); else { + isc_sockaddr_t sockaddr; result = ISC_R_FAILURE; - if (TCP_CLIENT(client)) { - isc_sockaddr_t destsockaddr; - + if (TCP_CLIENT(client)) result = isc_socket_getsockname(client->tcpsocket, - &destsockaddr); - if (result == ISC_R_SUCCESS) - isc_netaddr_fromsockaddr(&destaddr, - &destsockaddr); - } + &sockaddr); + if (result == ISC_R_SUCCESS) + isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr); if (result != ISC_R_SUCCESS && client->interface->addr.type.sa.sa_family == AF_INET6 && (client->attributes & NS_CLIENTATTR_PKTINFO) != 0) { - isc_uint32_t zone = 0; - /* * XXXJT technically, we should convert the receiving * interface ID to a proper scope zone ID. However, @@ -1673,12 +1679,11 @@ client_request(isc_task_t *task, isc_event_t *event) { * interface index as link ID. Despite the assumption, * it should cover most typical cases. */ - if (IN6_IS_ADDR_LINKLOCAL(&client->pktinfo.ipi6_addr)) - zone = (isc_uint32_t)client->pktinfo.ipi6_ifindex; - - isc_netaddr_fromin6(&destaddr, + isc_netaddr_fromin6(&client->destaddr, &client->pktinfo.ipi6_addr); - isc_netaddr_setzone(&destaddr, zone); + if (IN6_IS_ADDR_LINKLOCAL(&client->pktinfo.ipi6_addr)) + isc_netaddr_setzone(&client->destaddr, + client->pktinfo.ipi6_ifindex); result = ISC_R_SUCCESS; } if (result != ISC_R_SUCCESS) { @@ -1708,7 +1713,8 @@ client_request(isc_task_t *task, isc_event_t *event) { tsig = dns_tsigkey_identity(client->message->tsigkey); if (allowed(&netaddr, tsig, view->matchclients) && - allowed(&destaddr, tsig, view->matchdestinations) && + allowed(&client->destaddr, tsig, + view->matchdestinations) && !((client->message->flags & DNS_MESSAGEFLAG_RD) == 0 && view->matchrecursiveonly)) { @@ -1771,9 +1777,11 @@ client_request(isc_task_t *task, isc_event_t *event) { } if (result == ISC_R_SUCCESS) { + char namebuf[DNS_NAME_FORMATSIZE]; + dns_name_format(&client->signername, namebuf, sizeof(namebuf)); ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), - "request has valid signature"); + "request has valid signature: %s", namebuf); client->signer = &client->signername; } else if (result == ISC_R_NOTFOUND) { ns_client_log(client, DNS_LOGCATEGORY_SECURITY, @@ -1861,10 +1869,10 @@ client_request(isc_task_t *task, isc_event_t *event) { ns_client_checkaclsilent(client, NULL, client->view->cacheacl, ISC_TRUE) == ISC_R_SUCCESS && - ns_client_checkaclsilent(client, &client->interface->addr, + ns_client_checkaclsilent(client, &client->destaddr, client->view->recursiononacl, ISC_TRUE) == ISC_R_SUCCESS && - ns_client_checkaclsilent(client, &client->interface->addr, + ns_client_checkaclsilent(client, &client->destaddr, client->view->cacheonacl, ISC_TRUE) == ISC_R_SUCCESS) ra = ISC_TRUE; @@ -2600,12 +2608,12 @@ ns_client_getsockaddr(ns_client_t *client) { } isc_result_t -ns_client_checkaclsilent(ns_client_t *client, isc_sockaddr_t *sockaddr, +ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr, dns_acl_t *acl, isc_boolean_t default_allow) { isc_result_t result; + isc_netaddr_t tmpnetaddr; int match; - isc_netaddr_t netaddr; if (acl == NULL) { if (default_allow) @@ -2614,15 +2622,13 @@ ns_client_checkaclsilent(ns_client_t *client, isc_sockaddr_t *sockaddr, goto deny; } + if (netaddr == NULL) { + isc_netaddr_fromsockaddr(&tmpnetaddr, &client->peeraddr); + netaddr = &tmpnetaddr; + } - if (sockaddr == NULL) - isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); - else - isc_netaddr_fromsockaddr(&netaddr, sockaddr); - - result = dns_acl_match(&netaddr, client->signer, acl, - &ns_g_server->aclenv, - &match, NULL); + result = dns_acl_match(netaddr, client->signer, acl, + &ns_g_server->aclenv, &match, NULL); if (result != ISC_R_SUCCESS) goto deny; /* Internal error, already logged. */ @@ -2642,8 +2648,14 @@ ns_client_checkacl(ns_client_t *client, isc_sockaddr_t *sockaddr, const char *opname, dns_acl_t *acl, isc_boolean_t default_allow, int log_level) { - isc_result_t result = - ns_client_checkaclsilent(client, sockaddr, acl, default_allow); + isc_result_t result; + isc_netaddr_t netaddr; + + if (sockaddr != NULL) + isc_netaddr_fromsockaddr(&netaddr, sockaddr); + + result = ns_client_checkaclsilent(client, sockaddr ? &netaddr : NULL, + acl, default_allow); if (result == ISC_R_SUCCESS) ns_client_log(client, DNS_LOGCATEGORY_SECURITY, @@ -2753,9 +2765,14 @@ void ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) { ns_client_t *client; char namebuf[DNS_NAME_FORMATSIZE]; + char original[DNS_NAME_FORMATSIZE]; char peerbuf[ISC_SOCKADDR_FORMATSIZE]; + char typebuf[DNS_RDATATYPE_FORMATSIZE]; + char classbuf[DNS_RDATACLASS_FORMATSIZE]; const char *name; const char *sep; + const char *origfor; + dns_rdataset_t *rdataset; REQUIRE(VALID_MANAGER(manager)); @@ -2773,8 +2790,31 @@ ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) { sep = ""; } dns_name_format(client->query.qname, namebuf, sizeof(namebuf)); - fprintf(f, "; client %s%s%s: '%s' requesttime %d\n", - peerbuf, sep, name, namebuf, client->requesttime); + if (client->query.qname != client->query.origqname && + client->query.origqname != NULL) { + origfor = " for "; + dns_name_format(client->query.origqname, original, + sizeof(original)); + } else { + origfor = ""; + original[0] = '\0'; + } + rdataset = ISC_LIST_HEAD(client->query.qname->list); + if (rdataset == NULL && client->query.origqname != NULL) + rdataset = ISC_LIST_HEAD(client->query.origqname->list); + if (rdataset != NULL) { + dns_rdatatype_format(rdataset->type, typebuf, + sizeof(typebuf)); + dns_rdataclass_format(rdataset->rdclass, classbuf, + sizeof(classbuf)); + } else { + strcpy(typebuf, "-"); + strcpy(classbuf, "-"); + } + fprintf(f, "; client %s%s%s: id %u '%s/%s/%s'%s%s " + "requesttime %d\n", peerbuf, sep, name, + client->message->id, namebuf, typebuf, classbuf, + origfor, original, client->requesttime); client = ISC_LIST_NEXT(client, link); } UNLOCK(&manager->lock); diff --git a/bin/named/config.c b/bin/named/config.c index 43d0e52..704d7ecc 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2001-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: config.c,v 1.93.14.2 2009-03-17 23:47:28 tbox Exp $ */ +/* $Id: config.c,v 1.113.16.1.2.1 2011-06-02 23:47:28 tbox Exp $ */ /*! \file */ @@ -42,9 +42,13 @@ #include #include +#include + #include #include +#include "bind.keys.h" + /*% default configuration */ static char defaultconf[] = "\ options {\n\ @@ -55,7 +59,10 @@ options {\n\ files unlimited;\n\ stacksize default;\n" #endif -" deallocate-on-exit true;\n\ +"# session-keyfile \"" NS_LOCALSTATEDIR "/run/named/session.key\";\n\ + session-keyname local-ddns;\n\ + session-keyalg hmac-sha256;\n\ + deallocate-on-exit true;\n\ # directory \n\ dump-file \"named_dump.db\";\n\ fake-iquery no;\n\ @@ -70,8 +77,10 @@ options {\n\ multiple-cnames no;\n\ # named-xfer ;\n\ # pid-file \"" NS_LOCALSTATEDIR "/run/named/named.pid\"; /* or /lwresd.pid */\n\ + bindkeys-file \"" NS_SYSCONFDIR "/bind.keys\";\n\ port 53;\n\ recursing-file \"named.recursing\";\n\ + secroots-file \"named.secroots\";\n\ " #ifdef PATH_RANDOMDEV "\ @@ -80,6 +89,7 @@ options {\n\ #endif "\ recursive-clients 1000;\n\ + resolver-query-timeout 30;\n\ rrset-order {type NS order random; order cyclic; };\n\ serial-queries 20;\n\ serial-query-rate 20;\n\ @@ -102,6 +112,9 @@ options {\n\ request-nsid false;\n\ reserved-sockets 512;\n\ \n\ + /* DLV */\n\ + dnssec-lookaside . trust-anchor dlv.isc.org;\n\ +\n\ /* view */\n\ allow-notify {none;};\n\ allow-update-forwarding {none;};\n\ @@ -135,6 +148,7 @@ options {\n\ check-names master fail;\n\ check-names slave warn;\n\ check-names response ignore;\n\ + check-dup-records warn;\n\ check-mx warn;\n\ acache-enable no;\n\ acache-cleaning-interval 60;\n\ @@ -146,7 +160,13 @@ options {\n\ max-clients-per-query 100;\n\ zero-no-soa-ttl-cache no;\n\ nsec3-test-zone no;\n\ + allow-new-zones no;\n\ +" +#ifdef ALLOW_FILTER_AAAA_ON_V4 +" filter-aaaa-on-v4 no;\n\ + filter-aaaa { any; };\n\ " +#endif " /* zone */\n\ allow-query {any;};\n\ @@ -174,6 +194,7 @@ options {\n\ max-refresh-time 2419200; /* 4 weeks */\n\ min-refresh-time 300;\n\ multi-master no;\n\ + dnssec-secure-to-insecure no;\n\ sig-validity-interval 30; /* days */\n\ sig-signing-nodes 100;\n\ sig-signing-signatures 10;\n\ @@ -188,6 +209,7 @@ options {\n\ check-srv-cname warn;\n\ zero-no-soa-ttl yes;\n\ update-check-ksk yes;\n\ + dnssec-dnskey-kskonly no;\n\ try-tcp-refresh yes; /* BIND 8 compat */\n\ };\n\ " @@ -198,6 +220,7 @@ options {\n\ view \"_bind\" chaos {\n\ recursion no;\n\ notify no;\n\ + allow-new-zones no;\n\ \n\ zone \"version.bind\" chaos {\n\ type master;\n\ @@ -213,11 +236,24 @@ view \"_bind\" chaos {\n\ type master;\n\ database \"_builtin authors\";\n\ };\n\ +\n\ zone \"id.server\" chaos {\n\ type master;\n\ database \"_builtin id\";\n\ };\n\ };\n\ +" +"#\n\ +# Default trusted key(s) for builtin DLV support\n\ +# (used if \"dnssec-lookaside auto;\" is set and\n\ +# sysconfdir/bind.keys doesn't exist).\n\ +#\n\ +# BEGIN MANAGED KEYS\n" + +/* Imported from bind.keys.h: */ +MANAGED_KEYS + +"# END MANAGED KEYS\n\ "; isc_result_t @@ -339,6 +375,8 @@ ns_config_getzonetype(const cfg_obj_t *zonetypeobj) { ztype = dns_zone_slave; else if (strcasecmp(str, "stub") == 0) ztype = dns_zone_stub; + else if (strcasecmp(str, "static-stub") == 0) + ztype = dns_zone_staticstub; else INSIST(0); return (ztype); @@ -615,7 +653,7 @@ ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list, isc_buffer_add(&b, strlen(keystr)); dns_fixedname_init(&fname); result = dns_name_fromtext(dns_fixedname_name(&fname), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_name_dup(dns_fixedname_name(&fname), mctx, @@ -747,23 +785,31 @@ struct keyalgorithms { const char *str; enum { hmacnone, hmacmd5, hmacsha1, hmacsha224, hmacsha256, hmacsha384, hmacsha512 } hmac; + unsigned int type; isc_uint16_t size; } algorithms[] = { - { "hmac-md5", hmacmd5, 128 }, - { "hmac-md5.sig-alg.reg.int", hmacmd5, 0 }, - { "hmac-md5.sig-alg.reg.int.", hmacmd5, 0 }, - { "hmac-sha1", hmacsha1, 160 }, - { "hmac-sha224", hmacsha224, 224 }, - { "hmac-sha256", hmacsha256, 256 }, - { "hmac-sha384", hmacsha384, 384 }, - { "hmac-sha512", hmacsha512, 512 }, - { NULL, hmacnone, 0 } + { "hmac-md5", hmacmd5, DST_ALG_HMACMD5, 128 }, + { "hmac-md5.sig-alg.reg.int", hmacmd5, DST_ALG_HMACMD5, 0 }, + { "hmac-md5.sig-alg.reg.int.", hmacmd5, DST_ALG_HMACMD5, 0 }, + { "hmac-sha1", hmacsha1, DST_ALG_HMACSHA1, 160 }, + { "hmac-sha224", hmacsha224, DST_ALG_HMACSHA224, 224 }, + { "hmac-sha256", hmacsha256, DST_ALG_HMACSHA256, 256 }, + { "hmac-sha384", hmacsha384, DST_ALG_HMACSHA384, 384 }, + { "hmac-sha512", hmacsha512, DST_ALG_HMACSHA512, 512 }, + { NULL, hmacnone, DST_ALG_UNKNOWN, 0 } }; isc_result_t ns_config_getkeyalgorithm(const char *str, dns_name_t **name, isc_uint16_t *digestbits) { + return (ns_config_getkeyalgorithm2(str, name, NULL, digestbits)); +} + +isc_result_t +ns_config_getkeyalgorithm2(const char *str, dns_name_t **name, + unsigned int *typep, isc_uint16_t *digestbits) +{ int i; size_t len = 0; isc_uint16_t bits; @@ -801,6 +847,8 @@ ns_config_getkeyalgorithm(const char *str, dns_name_t **name, INSIST(0); } } + if (typep != NULL) + *typep = algorithms[i].type; if (digestbits != NULL) *digestbits = bits; return (ISC_R_SUCCESS); diff --git a/bin/named/control.c b/bin/named/control.c index 38115d6..3fc7bd3 100644 --- a/bin/named/control.c +++ b/bin/named/control.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: control.c,v 1.33.266.4 2010-12-03 23:45:46 tbox Exp $ */ +/* $Id: control.c,v 1.41 2010-12-03 22:05:19 each Exp $ */ /*! \file */ @@ -158,6 +158,8 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) { } else if (command_compare(command, NS_COMMAND_DUMPDB)) { ns_server_dumpdb(ns_g_server, command); result = ISC_R_SUCCESS; + } else if (command_compare(command, NS_COMMAND_SECROOTS)) { + result = ns_server_dumpsecroots(ns_g_server, command); } else if (command_compare(command, NS_COMMAND_TRACE)) { result = ns_server_setdebuglevel(ns_g_server, command); } else if (command_compare(command, NS_COMMAND_NOTRACE)) { @@ -192,6 +194,13 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) { result = ns_server_notifycommand(ns_g_server, command, text); } else if (command_compare(command, NS_COMMAND_VALIDATION)) { result = ns_server_validation(ns_g_server, command); + } else if (command_compare(command, NS_COMMAND_SIGN) || + command_compare(command, NS_COMMAND_LOADKEYS)) { + result = ns_server_rekey(ns_g_server, command); + } else if (command_compare(command, NS_COMMAND_ADDZONE)) { + result = ns_server_add_zone(ns_g_server, command); + } else if (command_compare(command, NS_COMMAND_DELZONE)) { + result = ns_server_del_zone(ns_g_server, command); } else { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_WARNING, diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h index 5ad9c6b..33f124d 100644 --- a/bin/named/include/named/client.h +++ b/bin/named/include/named/client.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: client.h,v 1.86.120.2 2009-01-18 23:47:34 tbox Exp $ */ +/* $Id: client.h,v 1.91 2009-10-26 23:14:53 each Exp $ */ #ifndef NAMED_CLIENT_H #define NAMED_CLIENT_H 1 @@ -138,6 +138,7 @@ struct ns_client { ns_interface_t *interface; isc_sockaddr_t peeraddr; isc_boolean_t peeraddr_valid; + isc_netaddr_t destaddr; struct in6_pktinfo pktinfo; isc_event_t ctlevent; /*% @@ -167,6 +168,10 @@ struct ns_client { #define NS_CLIENTATTR_MULTICAST 0x08 /*%< recv'd from multicast */ #define NS_CLIENTATTR_WANTDNSSEC 0x10 /*%< include dnssec records */ #define NS_CLIENTATTR_WANTNSID 0x20 /*%< include nameserver ID */ +#ifdef ALLOW_FILTER_AAAA_ON_V4 +#define NS_CLIENTATTR_FILTER_AAAA 0x40 /*%< suppress AAAAs */ +#define NS_CLIENTATTR_FILTER_AAAA_RC 0x80 /*%< recursing for A against AAAA */ +#endif extern unsigned int ns_client_requests; @@ -274,10 +279,8 @@ ns_client_getsockaddr(ns_client_t *client); */ isc_result_t -ns_client_checkaclsilent(ns_client_t *client, - isc_sockaddr_t *sockaddr, - dns_acl_t *acl, - isc_boolean_t default_allow); +ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr, + dns_acl_t *acl, isc_boolean_t default_allow); /*% * Convenience function for client request ACL checking. @@ -296,12 +299,12 @@ ns_client_checkaclsilent(ns_client_t *client, * * Requires: *\li 'client' points to a valid client. - *\li 'sockaddr' points to a valid address, or is NULL. + *\li 'netaddr' points to a valid address, or is NULL. *\li 'acl' points to a valid ACL, or is NULL. * * Returns: *\li ISC_R_SUCCESS if the request should be allowed - * \li ISC_R_REFUSED if the request should be denied + * \li DNS_R_REFUSED if the request should be denied *\li No other return values are possible. */ diff --git a/bin/named/include/named/config.h b/bin/named/include/named/config.h index fa96d32..d1570b0 100644 --- a/bin/named/include/named/config.h +++ b/bin/named/include/named/config.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2001, 2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: config.h,v 1.14 2007-06-19 23:46:59 tbox Exp $ */ +/* $Id: config.h,v 1.16 2009-06-11 23:47:55 tbox Exp $ */ #ifndef NAMED_CONFIG_H #define NAMED_CONFIG_H 1 @@ -75,5 +75,8 @@ ns_config_getport(const cfg_obj_t *config, in_port_t *portp); isc_result_t ns_config_getkeyalgorithm(const char *str, dns_name_t **name, isc_uint16_t *digestbits); +isc_result_t +ns_config_getkeyalgorithm2(const char *str, dns_name_t **name, + unsigned int *typep, isc_uint16_t *digestbits); #endif /* NAMED_CONFIG_H */ diff --git a/bin/named/include/named/control.h b/bin/named/include/named/control.h index 436fb19..e699892 100644 --- a/bin/named/include/named/control.h +++ b/bin/named/include/named/control.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2001-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: control.h,v 1.25 2007-06-19 23:46:59 tbox Exp $ */ +/* $Id: control.h,v 1.31 2010-08-16 22:21:06 marka Exp $ */ #ifndef NAMED_CONTROL_H #define NAMED_CONTROL_H 1 @@ -42,6 +42,7 @@ #define NS_COMMAND_DUMPSTATS "stats" #define NS_COMMAND_QUERYLOG "querylog" #define NS_COMMAND_DUMPDB "dumpdb" +#define NS_COMMAND_SECROOTS "secroots" #define NS_COMMAND_TRACE "trace" #define NS_COMMAND_NOTRACE "notrace" #define NS_COMMAND_FLUSH "flush" @@ -57,6 +58,10 @@ #define NS_COMMAND_NULL "null" #define NS_COMMAND_NOTIFY "notify" #define NS_COMMAND_VALIDATION "validation" +#define NS_COMMAND_SIGN "sign" +#define NS_COMMAND_LOADKEYS "loadkeys" +#define NS_COMMAND_ADDZONE "addzone" +#define NS_COMMAND_DELZONE "delzone" isc_result_t ns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp); diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h index 1d57a18..f155c7f 100644 --- a/bin/named/include/named/globals.h +++ b/bin/named/include/named/globals.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: globals.h,v 1.80.12.3 2010-09-15 12:16:50 marka Exp $ */ +/* $Id: globals.h,v 1.89 2010-09-15 12:07:55 marka Exp $ */ #ifndef NAMED_GLOBALS_H #define NAMED_GLOBALS_H 1 @@ -30,6 +30,8 @@ #include +#include + #include #undef EXTERN @@ -86,8 +88,13 @@ EXTERN cfg_obj_t * ns_g_config INIT(NULL); EXTERN const cfg_obj_t * ns_g_defaults INIT(NULL); EXTERN const char * ns_g_conffile INIT(NS_SYSCONFDIR "/named.conf"); +EXTERN cfg_obj_t * ns_g_bindkeys INIT(NULL); EXTERN const char * ns_g_keyfile INIT(NS_SYSCONFDIR "/rndc.key"); + +EXTERN dns_tsigkey_t * ns_g_sessionkey INIT(NULL); +EXTERN dns_name_t ns_g_sessionkeyname; + EXTERN const char * lwresd_g_conffile INIT(NS_SYSCONFDIR "/lwresd.conf"); EXTERN const char * lwresd_g_resolvconffile INIT("/etc" @@ -112,6 +119,10 @@ EXTERN const char * ns_g_chrootdir INIT(NULL); EXTERN isc_boolean_t ns_g_foreground INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_logstderr INIT(ISC_FALSE); +EXTERN const char * ns_g_defaultsessionkeyfile + INIT(NS_LOCALSTATEDIR "/run/named/" + "session.key"); + #if NS_RUN_PID_DIR EXTERN const char * ns_g_defaultpidfile INIT(NS_LOCALSTATEDIR "/run/named/" @@ -128,6 +139,12 @@ EXTERN const char * lwresd_g_defaultpidfile INIT(NS_LOCALSTATEDIR EXTERN const char * ns_g_username INIT(NULL); +#ifdef USE_PKCS11 +EXTERN const char * ns_g_engine INIT("pkcs11"); +#else +EXTERN const char * ns_g_engine INIT(NULL); +#endif + EXTERN int ns_g_listen INIT(3); EXTERN isc_time_t ns_g_boottime; EXTERN isc_boolean_t ns_g_memstatistics INIT(ISC_FALSE); diff --git a/bin/named/include/named/log.h b/bin/named/include/named/log.h index 0cfbee9..1ce680f 100644 --- a/bin/named/include/named/log.h +++ b/bin/named/include/named/log.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: log.h,v 1.25.332.2 2009-01-07 23:47:16 tbox Exp $ */ +/* $Id: log.h,v 1.27 2009-01-07 23:47:46 tbox Exp $ */ #ifndef NAMED_LOG_H #define NAMED_LOG_H 1 diff --git a/bin/named/include/named/lwdclient.h b/bin/named/include/named/lwdclient.h index 44e1fa6..5451b73 100644 --- a/bin/named/include/named/lwdclient.h +++ b/bin/named/include/named/lwdclient.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lwdclient.h,v 1.18.332.2 2009-01-18 23:47:34 tbox Exp $ */ +/* $Id: lwdclient.h,v 1.20 2009-01-17 23:47:42 tbox Exp $ */ #ifndef NAMED_LWDCLIENT_H #define NAMED_LWDCLIENT_H 1 diff --git a/bin/named/include/named/main.h b/bin/named/include/named/main.h index 96fb23e..6116add 100644 --- a/bin/named/include/named/main.h +++ b/bin/named/include/named/main.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,15 +15,16 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: main.h,v 1.15 2007-06-19 23:46:59 tbox Exp $ */ +/* $Id: main.h,v 1.17 2009-09-29 23:48:03 tbox Exp $ */ #ifndef NAMED_MAIN_H #define NAMED_MAIN_H 1 /*! \file */ -void -ns_main_earlyfatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); +ISC_PLATFORM_NORETURN_PRE void +ns_main_earlyfatal(const char *format, ...) +ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; void ns_main_earlywarning(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); diff --git a/bin/named/include/named/notify.h b/bin/named/include/named/notify.h index ac7fe2d..34fabcd 100644 --- a/bin/named/include/named/notify.h +++ b/bin/named/include/named/notify.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: notify.h,v 1.14.332.2 2009-01-18 23:47:34 tbox Exp $ */ +/* $Id: notify.h,v 1.16 2009-01-17 23:47:42 tbox Exp $ */ #ifndef NAMED_NOTIFY_H #define NAMED_NOTIFY_H 1 diff --git a/bin/named/include/named/query.h b/bin/named/include/named/query.h index 2f00f1e..37f771b 100644 --- a/bin/named/include/named/query.h +++ b/bin/named/include/named/query.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2010, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: query.h,v 1.40.332.2 2010-09-24 08:30:28 tbox Exp $ */ +/* $Id: query.h,v 1.45 2011-01-13 04:59:24 tbox Exp $ */ #ifndef NAMED_QUERY_H #define NAMED_QUERY_H 1 @@ -26,6 +26,8 @@ #include #include +#include +#include #include #include @@ -34,6 +36,7 @@ typedef struct ns_dbversion { dns_db_t *db; dns_dbversion_t *version; + isc_boolean_t acl_checked; isc_boolean_t queryok; ISC_LINK(struct ns_dbversion) link; } ns_dbversion_t; @@ -54,9 +57,16 @@ struct ns_query { isc_boolean_t isreferral; isc_mutex_t fetchlock; dns_fetch_t * fetch; + dns_rpz_st_t * rpz_st; isc_bufferlist_t namebufs; ISC_LIST(ns_dbversion_t) activeversions; ISC_LIST(ns_dbversion_t) freeversions; + dns_rdataset_t * dns64_aaaa; + dns_rdataset_t * dns64_sigaaaa; + isc_boolean_t * dns64_aaaaok; + unsigned int dns64_aaaaoklen; + unsigned int dns64_options; + unsigned int dns64_ttl; }; #define NS_QUERYATTR_RECURSIONOK 0x0001 @@ -73,6 +83,9 @@ struct ns_query { #define NS_QUERYATTR_NOADDITIONAL 0x0800 #define NS_QUERYATTR_CACHEACLOKVALID 0x1000 #define NS_QUERYATTR_CACHEACLOK 0x2000 +#define NS_QUERYATTR_DNS64 0x4000 +#define NS_QUERYATTR_DNS64EXCLUDE 0x8000 + isc_result_t ns_query_init(ns_client_t *client); diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h index 3a4c5f7..3c6426e 100644 --- a/bin/named/include/named/server.h +++ b/bin/named/include/named/server.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.h,v 1.93.120.3 2009-07-11 04:23:53 marka Exp $ */ +/* $Id: server.h,v 1.110 2010-08-16 23:46:52 tbox Exp $ */ #ifndef NAMED_SERVER_H #define NAMED_SERVER_H 1 @@ -54,6 +54,8 @@ struct ns_server { dns_acl_t *blackholeacl; char * statsfile; /*%< Statistics file name */ char * dumpfile; /*%< Dump file name */ + char * secrootsfile; /*%< Secroots file name */ + char * bindkeysfile; /*%< bind.keys file name */ char * recfile; /*%< Recursive file name */ isc_boolean_t version_set; /*%< User has set version */ char * version; /*%< User-specified version */ @@ -91,13 +93,14 @@ struct ns_server { isc_boolean_t flushonshutdown; isc_boolean_t log_queries; /*%< For BIND 8 compatibility */ - isc_stats_t * nsstats; /*%< Server statistics */ - dns_stats_t * rcvquerystats; /*% Incoming query statistics */ - dns_stats_t * opcodestats; /*%< Incoming message statistics */ - isc_stats_t * zonestats; /*% Zone management statistics */ - isc_stats_t * resolverstats; /*% Resolver statistics */ + ns_cachelist_t cachelist; /*%< Possibly shared caches */ + isc_stats_t * nsstats; /*%< Server stats */ + dns_stats_t * rcvquerystats; /*% Incoming query stats */ + dns_stats_t * opcodestats; /*%< Incoming message stats */ + isc_stats_t * zonestats; /*% Zone management stats */ + isc_stats_t * resolverstats; /*% Resolver stats */ + isc_stats_t * sockstats; /*%< Socket stats */ - isc_stats_t * sockstats; /*%< Socket statistics */ ns_controls_t * controls; /*%< Control channels */ unsigned int dispatchgen; ns_dispatchlist_t dispatches; @@ -105,6 +108,12 @@ struct ns_server { dns_acache_t *acache; ns_statschannellist_t statschannels; + + dns_tsigkey_t *sessionkey; + char *session_keyfile; + dns_name_t *session_keyname; + unsigned int session_keyalg; + isc_uint16_t session_keybits; }; #define NS_SERVER_MAGIC ISC_MAGIC('S','V','E','R') @@ -237,6 +246,12 @@ isc_result_t ns_server_dumpdb(ns_server_t *server, char *args); /*% + * Dump the current security roots to the secroots file. + */ +isc_result_t +ns_server_dumpsecroots(ns_server_t *server, char *args); + +/*% * Change or increment the server debug level. */ isc_result_t @@ -280,6 +295,16 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, isc_buffer_t *text); /*% + * Update a zone's DNSKEY set from the key repository. If + * the command that triggered the call to this function was "sign", + * then force a full signing of the zone. If it was "loadkeys", + * then don't sign the zone; any needed changes to signatures can + * take place incrementally. + */ +isc_result_t +ns_server_rekey(ns_server_t *server, char *args); + +/*% * Dump the current recursive queries. */ isc_result_t @@ -297,4 +322,16 @@ ns_add_reserved_dispatch(ns_server_t *server, const isc_sockaddr_t *addr); isc_result_t ns_server_validation(ns_server_t *server, char *args); +/*% + * Add a zone to a running process + */ +isc_result_t +ns_server_add_zone(ns_server_t *server, char *args); + +/*% + * Deletes a zone from a running process + */ +isc_result_t +ns_server_del_zone(ns_server_t *server, char *args); + #endif /* NAMED_SERVER_H */ diff --git a/bin/named/include/named/tsigconf.h b/bin/named/include/named/tsigconf.h index a4841ba..4a59ec2 100644 --- a/bin/named/include/named/tsigconf.h +++ b/bin/named/include/named/tsigconf.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: tsigconf.h,v 1.16 2007-06-19 23:46:59 tbox Exp $ */ +/* $Id: tsigconf.h,v 1.18 2009-06-11 23:47:55 tbox Exp $ */ #ifndef NS_TSIGCONF_H #define NS_TSIGCONF_H 1 @@ -36,8 +36,9 @@ ns_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig, * * Requires: * \li 'config' is not NULL. + * \li 'vconfig' is not NULL. * \li 'mctx' is not NULL - * \li 'ring' is not NULL, and '*ring' is NULL + * \li 'ringp' is not NULL, and '*ringp' is NULL * * Returns: * \li ISC_R_SUCCESS diff --git a/bin/named/include/named/types.h b/bin/named/include/named/types.h index b0729a7..96c4c01 100644 --- a/bin/named/include/named/types.h +++ b/bin/named/include/named/types.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: types.h,v 1.29 2008-01-17 23:46:59 tbox Exp $ */ +/* $Id: types.h,v 1.31 2009-01-09 23:47:45 tbox Exp $ */ #ifndef NAMED_TYPES_H #define NAMED_TYPES_H 1 @@ -24,6 +24,8 @@ #include +typedef struct ns_cache ns_cache_t; +typedef ISC_LIST(ns_cache_t) ns_cachelist_t; typedef struct ns_client ns_client_t; typedef struct ns_clientmgr ns_clientmgr_t; typedef struct ns_query ns_query_t; diff --git a/bin/named/include/named/zoneconf.h b/bin/named/include/named/zoneconf.h index ab84c84..65cf72f 100644 --- a/bin/named/include/named/zoneconf.h +++ b/bin/named/include/named/zoneconf.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zoneconf.h,v 1.26 2007-06-19 23:46:59 tbox Exp $ */ +/* $Id: zoneconf.h,v 1.28 2010-12-20 23:47:20 tbox Exp $ */ #ifndef NS_ZONECONF_H #define NS_ZONECONF_H 1 @@ -58,6 +58,21 @@ ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig); * and recreated, return ISC_FALSE. */ + +isc_result_t +ns_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone, + dns_rdataclass_t rdclass, dns_name_t *name); +/*%> + * configure a DLZ zone, setting up the database methods and calling + * postload to load the origin values + * + * Require: + * \li 'dlzdatabase' to be a valid dlz database + * \li 'zone' to be initialized. + * \li 'rdclass' to be a valid rdataclass + * \li 'name' to be a valid zone origin name + */ + ISC_LANG_ENDDECLS #endif /* NS_ZONECONF_H */ diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c index fad3213..e99d3b9 100644 --- a/bin/named/interfacemgr.c +++ b/bin/named/interfacemgr.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: interfacemgr.c,v 1.93.70.2 2009-01-18 23:47:34 tbox Exp $ */ +/* $Id: interfacemgr.c,v 1.95 2009-01-17 23:47:42 tbox Exp $ */ /*! \file */ diff --git a/bin/named/log.c b/bin/named/log.c index 867ad56..5d1c942 100644 --- a/bin/named/log.c +++ b/bin/named/log.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: log.c,v 1.46.334.3 2009-01-07 01:50:14 jinmei Exp $ */ +/* $Id: log.c,v 1.49 2009-01-07 01:46:40 jinmei Exp $ */ /*! \file */ diff --git a/bin/named/lwdgabn.c b/bin/named/lwdgabn.c index 66d7246..6a609c9 100644 --- a/bin/named/lwdgabn.c +++ b/bin/named/lwdgabn.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lwdgabn.c,v 1.22 2007-06-19 23:46:59 tbox Exp $ */ +/* $Id: lwdgabn.c,v 1.24 2009-09-02 23:48:01 tbox Exp $ */ /*! \file */ @@ -619,7 +619,7 @@ ns_lwdclient_processgabn(ns_lwdclient_t *client, lwres_buffer_t *b) { dns_fixedname_init(&client->target_name); dns_fixedname_init(&client->query_name); result = dns_name_fromtext(dns_fixedname_name(&client->query_name), - &namebuf, NULL, ISC_FALSE, NULL); + &namebuf, NULL, 0, NULL); if (result != ISC_R_SUCCESS) goto out; ns_lwsearchctx_init(&client->searchctx, diff --git a/bin/named/lwdgrbn.c b/bin/named/lwdgrbn.c index bf29a48..22b62c6 100644 --- a/bin/named/lwdgrbn.c +++ b/bin/named/lwdgrbn.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lwdgrbn.c,v 1.20 2007-06-19 23:46:59 tbox Exp $ */ +/* $Id: lwdgrbn.c,v 1.22 2009-09-02 23:48:01 tbox Exp $ */ /*! \file */ @@ -472,7 +472,7 @@ ns_lwdclient_processgrbn(ns_lwdclient_t *client, lwres_buffer_t *b) { dns_fixedname_init(&client->query_name); result = dns_name_fromtext(dns_fixedname_name(&client->query_name), - &namebuf, NULL, ISC_FALSE, NULL); + &namebuf, NULL, 0, NULL); if (result != ISC_R_SUCCESS) goto out; ns_lwsearchctx_init(&client->searchctx, diff --git a/bin/named/lwresd.8 b/bin/named/lwresd.8 index d1e760d..30dfbd5 100644 --- a/bin/named/lwresd.8 +++ b/bin/named/lwresd.8 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: lwresd.8,v 1.29.14.2 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: lwresd.8,v 1.31 2009-07-11 01:12:45 tbox Exp $ .\" .hy 0 .ad l diff --git a/bin/named/lwresd.c b/bin/named/lwresd.c index b7dc0af..ad36709 100644 --- a/bin/named/lwresd.c +++ b/bin/named/lwresd.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lwresd.c,v 1.58 2008-07-23 23:27:54 marka Exp $ */ +/* $Id: lwresd.c,v 1.60 2009-09-02 23:48:01 tbox Exp $ */ /*! \file * \brief @@ -372,8 +372,7 @@ ns_lwdmanager_create(isc_mem_t *mctx, const cfg_obj_t *lwres, strlen(searchstr)); isc_buffer_add(&namebuf, strlen(searchstr)); result = dns_name_fromtext(name, &namebuf, - dns_rootname, ISC_FALSE, - NULL); + dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, diff --git a/bin/named/lwresd.docbook b/bin/named/lwresd.docbook index f8e1500..934b5da 100644 --- a/bin/named/lwresd.docbook +++ b/bin/named/lwresd.docbook @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + June 30, 2000 diff --git a/bin/named/lwresd.html b/bin/named/lwresd.html index dec47ca..223b1c2 100644 --- a/bin/named/lwresd.html +++ b/bin/named/lwresd.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + diff --git a/bin/named/main.c b/bin/named/main.c index a1d94ff..84d86b1 100644 --- a/bin/named/main.c +++ b/bin/named/main.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: main.c,v 1.166.34.7 2010-09-15 12:16:49 marka Exp $ */ +/* $Id: main.c,v 1.180 2010-12-22 03:59:02 marka Exp $ */ /*! \file */ @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -69,6 +70,12 @@ #include #endif +#ifdef OPENSSL +#include +#endif +#ifdef HAVE_LIBXML2 +#include +#endif /* * Include header files for database drivers here. */ @@ -81,12 +88,20 @@ #include #endif +/* + * The maximum number of stack frames to dump on assertion failure. + */ +#ifndef BACKTRACE_MAXFRAME +#define BACKTRACE_MAXFRAME 128 +#endif + static isc_boolean_t want_stats = ISC_FALSE; static char program_name[ISC_DIR_NAMEMAX] = "named"; static char absolute_conffile[ISC_DIR_PATHMAX]; static char saved_command_line[512]; static char version[512]; static unsigned int maxsocks = 0; +static int maxudp = 0; void ns_main_earlywarning(const char *format, ...) { @@ -129,10 +144,20 @@ ns_main_earlyfatal(const char *format, ...) { exit(1); } +ISC_PLATFORM_NORETURN_PRE static void +assertion_failed(const char *file, int line, isc_assertiontype_t type, + const char *cond) ISC_PLATFORM_NORETURN_POST; + static void assertion_failed(const char *file, int line, isc_assertiontype_t type, const char *cond) { + void *tracebuf[BACKTRACE_MAXFRAME]; + int i, nframes; + isc_result_t result; + const char *logsuffix = ""; + const char *fname; + /* * Handle assertion failures. */ @@ -144,10 +169,40 @@ assertion_failed(const char *file, int line, isc_assertiontype_t type, */ isc_assertion_setcallback(NULL); + result = isc_backtrace_gettrace(tracebuf, BACKTRACE_MAXFRAME, + &nframes); + if (result == ISC_R_SUCCESS && nframes > 0) + logsuffix = ", back trace"; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL, - "%s:%d: %s(%s) failed", file, line, - isc_assertion_typetotext(type), cond); + "%s:%d: %s(%s) failed%s", file, line, + isc_assertion_typetotext(type), cond, logsuffix); + if (result == ISC_R_SUCCESS) { + for (i = 0; i < nframes; i++) { + unsigned long offset; + + fname = NULL; + result = isc_backtrace_getsymbol(tracebuf[i], + &fname, + &offset); + if (result == ISC_R_SUCCESS) { + isc_log_write(ns_g_lctx, + NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_MAIN, + ISC_LOG_CRITICAL, + "#%d %p in %s()+0x%lx", i, + tracebuf[i], fname, + offset); + } else { + isc_log_write(ns_g_lctx, + NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_MAIN, + ISC_LOG_CRITICAL, + "#%d %p in ??", i, + tracebuf[i]); + } + } + } isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL, "exiting (due to assertion failure)"); @@ -162,9 +217,10 @@ assertion_failed(const char *file, int line, isc_assertiontype_t type, exit(1); } -static void +ISC_PLATFORM_NORETURN_PRE static void library_fatal_error(const char *file, int line, const char *format, - va_list args) ISC_FORMAT_PRINTF(3, 0); + va_list args) +ISC_FORMAT_PRINTF(3, 0) ISC_PLATFORM_NORETURN_POST; static void library_fatal_error(const char *file, int line, const char *format, @@ -248,8 +304,9 @@ usage(void) { } fprintf(stderr, "usage: named [-4|-6] [-c conffile] [-d debuglevel] " - "[-f|-g] [-n number_of_cpus]\n" - " [-p port] [-s] [-t chrootdir] [-u username]\n" + "[-E engine] [-f|-g]\n" + " [-n number_of_cpus] [-p port] [-s] " + "[-t chrootdir] [-u username]\n" " [-m {usage|trace|record|size|mctx}]\n"); } @@ -358,7 +415,7 @@ parse_command_line(int argc, char *argv[]) { isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, - "46c:C:d:fgi:lm:n:N:p:P:" + "46c:C:d:E:fFgi:lm:n:N:p:P:" "sS:t:T:u:vVx:")) != -1) { switch (ch) { case '4': @@ -394,6 +451,9 @@ parse_command_line(int argc, char *argv[]) { ns_g_debuglevel = parse_int(isc_commandline_argument, "debug level"); break; + case 'E': + ns_g_engine = isc_commandline_argument; + break; case 'f': ns_g_foreground = ISC_TRUE; break; @@ -451,12 +511,16 @@ parse_command_line(int argc, char *argv[]) { * clienttest: make clients single shot with their * own memory context. */ - if (strcmp(isc_commandline_argument, "clienttest") == 0) + if (!strcmp(isc_commandline_argument, "clienttest")) ns_g_clienttest = ISC_TRUE; else if (!strcmp(isc_commandline_argument, "nosoa")) ns_g_nosoa = ISC_TRUE; else if (!strcmp(isc_commandline_argument, "noaa")) ns_g_noaa = ISC_TRUE; + else if (!strcmp(isc_commandline_argument, "maxudp512")) + maxudp = 512; + else if (!strcmp(isc_commandline_argument, "maxudp1460")) + maxudp = 1460; else fprintf(stderr, "unknown -T flag '%s\n", isc_commandline_argument); @@ -470,13 +534,25 @@ parse_command_line(int argc, char *argv[]) { case 'V': printf("BIND %s built with %s\n", ns_g_version, ns_g_configargs); +#ifdef OPENSSL + printf("using OpenSSL version: %s\n", + OPENSSL_VERSION_TEXT); +#endif +#ifdef HAVE_LIBXML2 + printf("using libxml2 version: %s\n", + LIBXML_DOTTED_VERSION); +#endif exit(0); + case 'F': + /* Reserved for FIPS mode */ + /* FALLTHROUGH */ case '?': usage(); if (isc_commandline_option == '?') exit(0); ns_main_earlyfatal("unknown option '-%c'", isc_commandline_option); + /* FALLTHROUGH */ default: ns_main_earlyfatal("parsing options returned %d", ch); } @@ -529,6 +605,7 @@ create_managers(void) { isc_result_totext(result)); return (ISC_R_UNEXPECTED); } + isc__socketmgr_maxudp(ns_g_socketmgr, maxudp); result = isc_socketmgr_getmaxsockets(ns_g_socketmgr, &socks); if (result == ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, @@ -579,6 +656,34 @@ destroy_managers(void) { } static void +dump_symboltable() { + int i; + isc_result_t result; + const char *fname; + const void *addr; + + if (isc__backtrace_nsymbols == 0) + return; + + if (!isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(99))) + return; + + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, + ISC_LOG_DEBUG(99), "Symbol table:"); + + for (i = 0, result = ISC_R_SUCCESS; result == ISC_R_SUCCESS; i++) { + addr = NULL; + fname = NULL; + result = isc_backtrace_getsymbolfromindex(i, &addr, &fname); + if (result == ISC_R_SUCCESS) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_MAIN, ISC_LOG_DEBUG(99), + "[%d] %p %s", i, addr, fname); + } + } +} + +static void setup(void) { isc_result_t result; isc_resourcevalue_t old_openfiles; @@ -685,6 +790,8 @@ setup(void) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "built with %s", ns_g_configargs); + dump_symboltable(); + /* * Get the initial resource limits. */ @@ -723,8 +830,8 @@ setup(void) { absolute_conffile, sizeof(absolute_conffile)); if (result != ISC_R_SUCCESS) - ns_main_earlyfatal("could not construct absolute path of " - "configuration file: %s", + ns_main_earlyfatal("could not construct absolute path " + "of configuration file: %s", isc_result_totext(result)); ns_g_conffile = absolute_conffile; } @@ -896,6 +1003,9 @@ main(int argc, char *argv[]) { if (strcmp(program_name, "lwresd") == 0) ns_g_lwresdonly = ISC_TRUE; + if (result != ISC_R_SUCCESS) + ns_main_earlyfatal("failed to build internal symbol table"); + isc_assertion_setcallback(assertion_failed); isc_error_setfatal(library_fatal_error); isc_error_setunexpected(library_unexpected_error); diff --git a/bin/named/named.8 b/bin/named/named.8 index 90782ed..23805b0 100644 --- a/bin/named/named.8 +++ b/bin/named/named.8 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: named.8,v 1.38.14.2 2009-12-03 05:06:38 tbox Exp $ +.\" $Id: named.8,v 1.41 2009-10-06 01:14:41 tbox Exp $ .\" .hy 0 .ad l @@ -33,7 +33,7 @@ named \- Internet domain name server .SH "SYNOPSIS" .HP 6 -\fBnamed\fR [\fB\-4\fR] [\fB\-6\fR] [\fB\-c\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-d\ \fR\fB\fIdebug\-level\fR\fR] [\fB\-f\fR] [\fB\-g\fR] [\fB\-m\ \fR\fB\fIflag\fR\fR] [\fB\-n\ \fR\fB\fI#cpus\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-s\fR] [\fB\-S\ \fR\fB\fI#max\-socks\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [\fB\-V\fR] [\fB\-x\ \fR\fB\fIcache\-file\fR\fR] +\fBnamed\fR [\fB\-4\fR] [\fB\-6\fR] [\fB\-c\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-d\ \fR\fB\fIdebug\-level\fR\fR] [\fB\-E\ \fR\fB\fIengine\-name\fR\fR] [\fB\-f\fR] [\fB\-g\fR] [\fB\-m\ \fR\fB\fIflag\fR\fR] [\fB\-n\ \fR\fB\fI#cpus\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-s\fR] [\fB\-S\ \fR\fB\fI#max\-socks\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [\fB\-V\fR] [\fB\-x\ \fR\fB\fIcache\-file\fR\fR] .SH "DESCRIPTION" .PP \fBnamed\fR @@ -83,6 +83,13 @@ Set the daemon's debug level to become more verbose as the debug level increases. .RE .PP +\-E \fIengine\-name\fR +.RS 4 +Use a crypto hardware (OpenSSL engine) for the crypto operations it supports, for instance re\-signing with private keys from a secure key store. When compiled with PKCS#11 support +\fIengine\-name\fR +defaults to pkcs11, the empty name resets it to no engine. +.RE +.PP \-f .RS 4 Run the server in the foreground (i.e. do not daemonize). diff --git a/bin/named/named.conf.5 b/bin/named/named.conf.5 index cd0d4ad..9dc7002b 100644 --- a/bin/named/named.conf.5 +++ b/bin/named/named.conf.5 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") .\" .\" Permission to use, copy, modify, and/or distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above @@ -12,7 +12,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: named.conf.5,v 1.36.48.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: named.conf.5,v 1.44.12.1 2011-02-03 12:29:12 tbox Exp $ .\" .hy 0 .ad l @@ -102,6 +102,15 @@ trusted\-keys { }; .fi .RE +.SH "MANAGED\-KEYS" +.sp +.RS 4 +.nf +managed\-keys { + \fIdomain_name\fR \fBinitial\-key\fR \fIflags\fR \fIprotocol\fR \fIalgorithm\fR \fIkey\fR; ... +}; +.fi +.RE .SH "CONTROLS" .sp .RS 4 @@ -186,6 +195,7 @@ options { tcp\-listen\-queue \fIinteger\fR; tkey\-dhkey \fIquoted_string\fR \fIinteger\fR; tkey\-gssapi\-credential \fIquoted_string\fR; + tkey\-gssapi\-keytab \fIquoted_string\fR; tkey\-domain \fIquoted_string\fR; transfers\-per\-ns \fIinteger\fR; transfers\-in \fIinteger\fR; @@ -214,6 +224,7 @@ options { queryport\-pool\-ports \fIinteger\fR; queryport\-pool\-updateinterval \fIinteger\fR; cleaning\-interval \fIinteger\fR; + resolver\-query\-timeout \fIinteger\fR; min\-roots \fIinteger\fR; // not implemented lame\-ttl \fIinteger\fR; max\-ncache\-ttl \fIinteger\fR; @@ -244,8 +255,19 @@ options { dnssec\-enable \fIboolean\fR; dnssec\-validation \fIboolean\fR; dnssec\-lookaside \fIstring\fR trust\-anchor \fIstring\fR; + dnssec\-lookaside ( \fIauto\fR | \fIdomain\fR trust\-anchor \fIdomain\fR ); dnssec\-must\-be\-secure \fIstring\fR \fIboolean\fR; dnssec\-accept\-expired \fIboolean\fR; + dns64\-server \fIstring\fR; + dns64\-contact \fIstring\fR; + dns64 \fIprefix\fR { + clients { acl; }; + exclude { acl; }; + mapped { acl; }; + break\-dnssec \fIboolean\fR; + recursive\-only \fIboolean\fR; + suffix \fIipv6_address\fR; + }; empty\-server \fIstring\fR; empty\-contact \fIstring\fR; empty\-zones\-enable \fIboolean\fR; @@ -260,6 +282,7 @@ options { allow\-update { \fIaddress_match_element\fR; ... }; allow\-update\-forwarding { \fIaddress_match_element\fR; ... }; update\-check\-ksk \fIboolean\fR; + dnssec\-dnskey\-kskonly \fIboolean\fR; masterfile\-format ( text | raw ); notify \fInotifytype\fR; notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ]; @@ -299,9 +322,18 @@ options { use\-alt\-transfer\-source \fIboolean\fR; zone\-statistics \fIboolean\fR; key\-directory \fIquoted_string\fR; + managed\-keys\-directory \fIquoted_string\fR; + auto\-dnssec \fBallow\fR|\fBmaintain\fR|\fBcreate\fR|\fBoff\fR; try\-tcp\-refresh \fIboolean\fR; zero\-no\-soa\-ttl \fIboolean\fR; zero\-no\-soa\-ttl\-cache \fIboolean\fR; + dnssec\-secure\-to\-insecure \fIboolean\fR; + deny\-answer\-addresses { + \fIaddress_match_list\fR + } [ except\-from { \fInamelist\fR } ]; + deny\-answer\-aliases { + \fInamelist\fR + } [ except\-from { \fInamelist\fR } ]; nsec3\-test\-zone \fIboolean\fR; // testing only allow\-v6\-synthesis { \fIaddress_match_element\fR; ... }; // obsolete deallocate\-on\-exit \fIboolean\fR; // obsolete @@ -337,7 +369,8 @@ view \fIstring\fR \fIoptional_class\fR { ... }; trusted\-keys { - \fIstring\fR \fIinteger\fR \fIinteger\fR \fIinteger\fR \fIquoted_string\fR; ... + \fIstring\fR \fIinteger\fR \fIinteger\fR \fIinteger\fR \fIquoted_string\fR; + [...] }; allow\-recursion { \fIaddress_match_element\fR; ... }; allow\-recursion\-on { \fIaddress_match_element\fR; ... }; @@ -361,6 +394,7 @@ view \fIstring\fR \fIoptional_class\fR { queryport\-pool\-ports \fIinteger\fR; queryport\-pool\-updateinterval \fIinteger\fR; cleaning\-interval \fIinteger\fR; + resolver\-query\-timeout \fIinteger\fR; min\-roots \fIinteger\fR; // not implemented lame\-ttl \fIinteger\fR; max\-ncache\-ttl \fIinteger\fR; @@ -393,6 +427,16 @@ view \fIstring\fR \fIoptional_class\fR { dnssec\-lookaside \fIstring\fR trust\-anchor \fIstring\fR; dnssec\-must\-be\-secure \fIstring\fR \fIboolean\fR; dnssec\-accept\-expired \fIboolean\fR; + dns64\-server \fIstring\fR; + dns64\-contact \fIstring\fR; + dns64 \fIprefix\fR { + clients { acl; }; + exclude { acl; }; + mapped { acl; }; + break\-dnssec \fIboolean\fR; + recursive\-only \fIboolean\fR; + suffix \fIipv6_address\fR; + }; empty\-server \fIstring\fR; empty\-contact \fIstring\fR; empty\-zones\-enable \fIboolean\fR; @@ -407,6 +451,7 @@ view \fIstring\fR \fIoptional_class\fR { allow\-update { \fIaddress_match_element\fR; ... }; allow\-update\-forwarding { \fIaddress_match_element\fR; ... }; update\-check\-ksk \fIboolean\fR; + dnssec\-dnskey\-kskonly \fIboolean\fR; masterfile\-format ( text | raw ); notify \fInotifytype\fR; notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ]; @@ -445,6 +490,7 @@ view \fIstring\fR \fIoptional_class\fR { key\-directory \fIquoted_string\fR; zero\-no\-soa\-ttl \fIboolean\fR; zero\-no\-soa\-ttl\-cache \fIboolean\fR; + dnssec\-secure\-to\-insecure \fIboolean\fR; allow\-v6\-synthesis { \fIaddress_match_element\fR; ... }; // obsolete fetch\-glue \fIboolean\fR; // obsolete maintain\-ixfr\-base \fIboolean\fR; // obsolete @@ -476,19 +522,22 @@ zone \fIstring\fR \fIoptional_class\fR { ixfr\-from\-differences \fIboolean\fR; journal \fIquoted_string\fR; zero\-no\-soa\-ttl \fIboolean\fR; + dnssec\-secure\-to\-insecure \fIboolean\fR; allow\-query { \fIaddress_match_element\fR; ... }; allow\-query\-on { \fIaddress_match_element\fR; ... }; allow\-transfer { \fIaddress_match_element\fR; ... }; allow\-update { \fIaddress_match_element\fR; ... }; allow\-update\-forwarding { \fIaddress_match_element\fR; ... }; - update\-policy { - ( grant | deny ) \fIstring\fR + update\-policy \fIlocal\fR | \fI { + ( grant | deny ) \fR\fI\fIstring\fR\fR\fI ( name | subdomain | wildcard | self | selfsub | selfwild | krb5\-self | ms\-self | krb5\-subdomain | ms\-subdomain | - tcp\-self | 6to4\-self ) \fIstring\fR - \fIrrtypelist\fR; ... - }; + tcp\-self | zonesub | 6to4\-self ) \fR\fI\fIstring\fR\fR\fI + \fR\fI\fIrrtypelist\fR\fR\fI; + \fR\fI[...]\fR\fI + }\fR; update\-check\-ksk \fIboolean\fR; + dnssec\-dnskey\-kskonly \fIboolean\fR; masterfile\-format ( text | raw ); notify \fInotifytype\fR; notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ]; @@ -544,5 +593,5 @@ zone \fIstring\fR \fIoptional_class\fR { \fBrndc\fR(8), BIND 9 Administrator Reference Manual. .SH "COPYRIGHT" -Copyright \(co 2004\-2008 Internet Systems Consortium, Inc. ("ISC") +Copyright \(co 2004\-2011 Internet Systems Consortium, Inc. ("ISC") .br diff --git a/bin/named/named.conf.docbook b/bin/named/named.conf.docbook index d98e289..962eaaa 100644 --- a/bin/named/named.conf.docbook +++ b/bin/named/named.conf.docbook @@ -2,7 +2,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" []> - + Aug 13, 2004 @@ -41,6 +41,9 @@ 2006 2007 2008 + 2009 + 2010 + 2011 Internet Systems Consortium, Inc. ("ISC")
    @@ -132,6 +135,15 @@ trusted-keys { + MANAGED-KEYS + +managed-keys { + domain_name initial-key flags protocol algorithm key; ... +}; + + + + CONTROLS controls { @@ -214,6 +226,7 @@ options { tcp-listen-queue integer; tkey-dhkey quoted_string integer; tkey-gssapi-credential quoted_string; + tkey-gssapi-keytab quoted_string; tkey-domain quoted_string; transfers-per-ns integer; transfers-in integer; @@ -242,6 +255,7 @@ options { queryport-pool-ports integer; queryport-pool-updateinterval integer; cleaning-interval integer; + resolver-query-timeout integer; min-roots integer; // not implemented lame-ttl integer; max-ncache-ttl integer; @@ -272,9 +286,21 @@ options { dnssec-enable boolean; dnssec-validation boolean; dnssec-lookaside string trust-anchor string; + dnssec-lookaside ( auto | domain trust-anchor domain ); dnssec-must-be-secure string boolean; dnssec-accept-expired boolean; + dns64-server string; + dns64-contact string; + dns64 prefix { + clients { acl; }; + exclude { acl; }; + mapped { acl; }; + break-dnssec boolean; + recursive-only boolean; + suffix ipv6_address; + }; + empty-server string; empty-contact string; empty-zones-enable boolean; @@ -291,6 +317,7 @@ options { allow-update { address_match_element; ... }; allow-update-forwarding { address_match_element; ... }; update-check-ksk boolean; + dnssec-dnskey-kskonly boolean; masterfile-format ( text | raw ); notify notifytype; @@ -337,9 +364,18 @@ options { zone-statistics boolean; key-directory quoted_string; + managed-keys-directory quoted_string; + auto-dnssec allow|maintain|create|off; try-tcp-refresh boolean; zero-no-soa-ttl boolean; zero-no-soa-ttl-cache boolean; + dnssec-secure-to-insecure boolean; + deny-answer-addresses { + address_match_list + } except-from { namelist } ; + deny-answer-aliases { + namelist + } except-from { namelist } ; nsec3-test-zone boolean; // testing only @@ -381,7 +417,8 @@ view string optional_class }; trusted-keys { - string integer integer integer quoted_string; ... + string integer integer integer quoted_string; + ... }; allow-recursion { address_match_element; ... }; @@ -406,6 +443,7 @@ view string optional_class queryport-pool-ports integer; queryport-pool-updateinterval integer; cleaning-interval integer; + resolver-query-timeout integer; min-roots integer; // not implemented lame-ttl integer; max-ncache-ttl integer; @@ -439,6 +477,17 @@ view string optional_class dnssec-must-be-secure string boolean; dnssec-accept-expired boolean; + dns64-server string; + dns64-contact string; + dns64 prefix { + clients { acl; }; + exclude { acl; }; + mapped { acl; }; + break-dnssec boolean; + recursive-only boolean; + suffix ipv6_address; + }; + empty-server string; empty-contact string; empty-zones-enable boolean; @@ -455,6 +504,7 @@ view string optional_class allow-update { address_match_element; ... }; allow-update-forwarding { address_match_element; ... }; update-check-ksk boolean; + dnssec-dnskey-kskonly boolean; masterfile-format ( text | raw ); notify notifytype; @@ -499,6 +549,7 @@ view string optional_class key-directory quoted_string; zero-no-soa-ttl boolean; zero-no-soa-ttl-cache boolean; + dnssec-secure-to-insecure boolean; allow-v6-synthesis { address_match_element; ... }; // obsolete fetch-glue boolean; // obsolete @@ -533,20 +584,23 @@ zone string optional_class ixfr-from-differences boolean; journal quoted_string; zero-no-soa-ttl boolean; + dnssec-secure-to-insecure boolean; allow-query { address_match_element; ... }; allow-query-on { address_match_element; ... }; allow-transfer { address_match_element; ... }; allow-update { address_match_element; ... }; allow-update-forwarding { address_match_element; ... }; - update-policy { + update-policy local | { ( grant | deny ) string ( name | subdomain | wildcard | self | selfsub | selfwild | krb5-self | ms-self | krb5-subdomain | ms-subdomain | - tcp-self | 6to4-self ) string - rrtypelist; ... - }; + tcp-self | zonesub | 6to4-self ) string + rrtypelist; + ... + }; update-check-ksk boolean; + dnssec-dnskey-kskonly boolean; masterfile-format ( text | raw ); notify notifytype; diff --git a/bin/named/named.conf.html b/bin/named/named.conf.html index fccad18..f20e411 100644 --- a/bin/named/named.conf.html +++ b/bin/named/named.conf.html @@ -1,5 +1,5 @@ - + @@ -31,7 +31,7 @@

    named.conf

    -

    DESCRIPTION

    +

    DESCRIPTION

    named.conf is the configuration file for named. Statements are enclosed @@ -50,14 +50,14 @@

    -

    ACL

    +

    ACL


    acl string { address_match_element; ... };

    -

    KEY

    +

    KEY


    key domain_name {
    algorithm string;
    @@ -66,7 +66,7 @@ key

    -

    MASTERS

    +

    MASTERS


    masters string [ port integer ] {
    masters | ipv4_address [port integer] |
    @@ -75,7 +75,7 @@ masters

    -

    SERVER

    +

    SERVER


    server ( ipv4_address[/prefixlen] | ipv6_address[/prefixlen] ) {
    bogus boolean;
    @@ -97,7 +97,7 @@ server

    -

    TRUSTED-KEYS

    +

    TRUSTED-KEYS


    trusted-keys {
    domain_name flags protocol algorithm key; ... 
    @@ -105,7 +105,15 @@ trusted-keys

    -

    CONTROLS

    +

    MANAGED-KEYS

    +


    +managed-keys {
    + domain_name initial-key flags protocol algorithm key; ... 
    +};
    +

    +
    +
    +

    CONTROLS


    controls {
    inet ( ipv4_address | ipv6_address | * )
    @@ -117,7 +125,7 @@ controls

    -

    LOGGING

    +

    LOGGING


    logging {
    channel string {
    @@ -135,7 +143,7 @@ logging

    -

    LWRES

    +

    LWRES


    lwres {
    listen-on [ port integer ] {
    @@ -148,7 +156,7 @@ lwres

    -

    OPTIONS

    +

    OPTIONS


    options {
    avoid-v4-udp-ports { port; ... };
    @@ -184,6 +192,7 @@ options tcp-listen-queue integer;
    tkey-dhkey quoted_string integer;
    tkey-gssapi-credential quoted_string;
    + tkey-gssapi-keytab quoted_string;
    tkey-domain quoted_string;
    transfers-per-ns integer;
    transfers-in integer;
    @@ -212,6 +221,7 @@ options queryport-pool-ports integer;
    queryport-pool-updateinterval integer;
    cleaning-interval integer;
    + resolver-query-timeout integer;
    min-roots integer; // not implemented
    lame-ttl integer;
    max-ncache-ttl integer;
    @@ -242,9 +252,21 @@ options dnssec-enable boolean;
    dnssec-validation boolean;
    dnssec-lookaside string trust-anchor string;
    + dnssec-lookaside ( auto | domain trust-anchor domain );
    dnssec-must-be-secure string boolean;
    dnssec-accept-expired boolean;

    + dns64-server string;
    + dns64-contact string;
    + dns64 prefix {
    + clients { <replacable>acl</replacable>; };
    + exclude { <replacable>acl</replacable>; };
    + mapped { <replacable>acl</replacable>; };
    + break-dnssec boolean;
    + recursive-only boolean;
    + suffix ipv6_address;
    + };
    +
    empty-server string;
    empty-contact string;
    empty-zones-enable boolean;
    @@ -261,6 +283,7 @@ options allow-update { address_match_element; ... };
    allow-update-forwarding { address_match_element; ... };
    update-check-ksk boolean;
    + dnssec-dnskey-kskonly boolean;

    masterfile-format ( text | raw );
    notify notifytype;
    @@ -307,9 +330,18 @@ options
    zone-statistics boolean;
    key-directory quoted_string;
    + managed-keys-directory quoted_string;
    + auto-dnssec allow|maintain|create|off;
    try-tcp-refresh boolean;
    zero-no-soa-ttl boolean;
    zero-no-soa-ttl-cache boolean;
    + dnssec-secure-to-insecure boolean;
    + deny-answer-addresses {
    + address_match_list
    + } [ except-from { namelist } ];
    + deny-answer-aliases {
    + namelist
    + } [ except-from { namelist } ];

    nsec3-test-zone boolean;  // testing only

    @@ -329,7 +361,7 @@ options

    -

    VIEW

    +

    VIEW


    view string optional_class {
    match-clients { address_match_element; ... };
    @@ -350,7 +382,8 @@ view };

    trusted-keys {
    - string integer integer integer quoted_string; ...
    + string integer integer integer quoted_string;
    + [...]
    };

    allow-recursion { address_match_element; ... };
    @@ -375,6 +408,7 @@ view queryport-pool-ports integer;
    queryport-pool-updateinterval integer;
    cleaning-interval integer;
    + resolver-query-timeout integer;
    min-roots integer; // not implemented
    lame-ttl integer;
    max-ncache-ttl integer;
    @@ -408,6 +442,17 @@ view dnssec-must-be-secure string boolean;
    dnssec-accept-expired boolean;

    + dns64-server string;
    + dns64-contact string;
    + dns64 prefix {
    + clients { <replacable>acl</replacable>; };
    + exclude { <replacable>acl</replacable>; };
    + mapped { <replacable>acl</replacable>; };
    + break-dnssec boolean;
    + recursive-only boolean;
    + suffix ipv6_address;
    + };
    +
    empty-server string;
    empty-contact string;
    empty-zones-enable boolean;
    @@ -424,6 +469,7 @@ view allow-update { address_match_element; ... };
    allow-update-forwarding { address_match_element; ... };
    update-check-ksk boolean;
    + dnssec-dnskey-kskonly boolean;

    masterfile-format ( text | raw );
    notify notifytype;
    @@ -468,6 +514,7 @@ view key-directory quoted_string;
    zero-no-soa-ttl boolean;
    zero-no-soa-ttl-cache boolean;
    + dnssec-secure-to-insecure boolean;

    allow-v6-synthesis { address_match_element; ... }; // obsolete
    fetch-glue boolean; // obsolete
    @@ -477,7 +524,7 @@ view

    -

    ZONE

    +

    ZONE


    zone string optional_class {
    type ( master | slave | stub | hint |
    @@ -501,20 +548,23 @@ zone ixfr-from-differences boolean;
    journal quoted_string;
    zero-no-soa-ttl boolean;
    + dnssec-secure-to-insecure boolean;

    allow-query { address_match_element; ... };
    allow-query-on { address_match_element; ... };
    allow-transfer { address_match_element; ... };
    allow-update { address_match_element; ... };
    allow-update-forwarding { address_match_element; ... };
    - update-policy {
    + update-policy local |  {
    ( grant | deny ) string
    ( name | subdomain | wildcard | self | selfsub | selfwild |
                      krb5-self | ms-self | krb5-subdomain | ms-subdomain |
    -   tcp-self | 6to4-self ) string
    - rrtypelist; ...
    - };
    +   tcp-self | zonesub | 6to4-self ) string
    + rrtypelist;
    + [...]
    + }
    ;
    update-check-ksk boolean;
    + dnssec-dnskey-kskonly boolean;

    masterfile-format ( text | raw );
    notify notifytype;
    @@ -569,12 +619,12 @@ zone

    -

    FILES

    +

    FILES

    /etc/named.conf

    -

    SEE ALSO

    +

    SEE ALSO

    named(8), named-checkconf(8), rndc(8), diff --git a/bin/named/named.docbook b/bin/named/named.docbook index 808e998..214f8ac 100644 --- a/bin/named/named.docbook +++ b/bin/named/named.docbook @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + May 21, 2009 @@ -60,6 +60,7 @@ + @@ -116,6 +117,7 @@ + -c config-file @@ -145,6 +147,19 @@ + -E engine-name + + + Use a crypto hardware (OpenSSL engine) for the crypto operations + it supports, for instance re-signing with private keys from + a secure key store. When compiled with PKCS#11 support + engine-name + defaults to pkcs11, the empty name resets it to no engine. + + + + + -f diff --git a/bin/named/named.html b/bin/named/named.html index 031b492..fa869c4 100644 --- a/bin/named/named.html +++ b/bin/named/named.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -29,10 +29,10 @@

    Synopsis

    -

    named [-4] [-6] [-c config-file] [-d debug-level] [-f] [-g] [-m flag] [-n #cpus] [-p port] [-s] [-S #max-socks] [-t directory] [-u user] [-v] [-V] [-x cache-file]

    +

    named [-4] [-6] [-c config-file] [-d debug-level] [-E engine-name] [-f] [-g] [-m flag] [-n #cpus] [-p port] [-s] [-S #max-socks] [-t directory] [-u user] [-v] [-V] [-x cache-file]

    -

    DESCRIPTION

    +

    DESCRIPTION

    named is a Domain Name System (DNS) server, part of the BIND 9 distribution from ISC. For more @@ -47,7 +47,7 @@

    -

    OPTIONS

    +

    OPTIONS

    -4

    @@ -79,6 +79,14 @@ Debugging traces from named become more verbose as the debug level increases.

    +
    -E engine-name
    +

    + Use a crypto hardware (OpenSSL engine) for the crypto operations + it supports, for instance re-signing with private keys from + a secure key store. When compiled with PKCS#11 support + engine-name + defaults to pkcs11, the empty name resets it to no engine. +

    -f

    Run the server in the foreground (i.e. do not daemonize). @@ -220,7 +228,7 @@

    -

    SIGNALS

    +

    SIGNALS

    In routine operation, signals should not be used to control the nameserver; rndc should be used @@ -241,7 +249,7 @@

    -

    CONFIGURATION

    +

    CONFIGURATION

    The named configuration file is too complex to describe in detail here. A complete description is provided @@ -258,7 +266,7 @@

    -

    FILES

    +

    FILES

    /etc/named.conf

    @@ -271,7 +279,7 @@

    -

    SEE ALSO

    +

    SEE ALSO

    RFC 1033, RFC 1034, RFC 1035, @@ -284,7 +292,7 @@

    -

    AUTHOR

    +

    AUTHOR

    Internet Systems Consortium

    diff --git a/bin/named/query.c b/bin/named/query.c index fa34da6..1950257 100644 --- a/bin/named/query.c +++ b/bin/named/query.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: query.c,v 1.313.20.24 2010-09-24 08:09:07 marka Exp $ */ +/* $Id: query.c,v 1.353.8.2.2.5 2011-06-09 03:17:10 marka Exp $ */ /*! \file */ @@ -34,6 +34,7 @@ #ifdef DLZ #include #endif +#include #include #include #include @@ -62,6 +63,17 @@ #include #include +#if 0 +/* + * It has been recommended that DNS64 be changed to return excluded + * AAAA addresses if DNS64 synthesis does not occur. This minimises + * the impact on the lookup results. While most DNS AAAA lookups are + * done to send IP packets to a host, not all of them are and filtering + * excluded addresses has a negative impact on those uses. + */ +#define dns64_bis_return_excluded_addresses 1 +#endif + /*% Partial answer? */ #define PARTIALANSWER(c) (((c)->query.attributes & \ NS_QUERYATTR_PARTIALANSWER) != 0) @@ -92,6 +104,12 @@ /*% Secure? */ #define SECURE(c) (((c)->query.attributes & \ NS_QUERYATTR_SECURE) != 0) +/*% DNS64 A lookup? */ +#define DNS64(c) (((c)->query.attributes & \ + NS_QUERYATTR_DNS64) != 0) + +#define DNS64EXCLUDE(c) (((c)->query.attributes & \ + NS_QUERYATTR_DNS64EXCLUDE) != 0) /*% No QNAME Proof? */ #define NOQNAME(r) (((r)->attributes & \ @@ -116,6 +134,7 @@ #define DNS_GETDB_NOEXACT 0x01U #define DNS_GETDB_NOLOG 0x02U #define DNS_GETDB_PARTIAL 0x04U +#define DNS_GETDB_IGNOREACL 0x08U #define PENDINGOK(x) (((x) & DNS_DBFIND_PENDINGOK) != 0) @@ -141,6 +160,9 @@ query_findclosestnsec3(dns_name_t *qname, dns_db_t *db, static inline void log_queryerror(ns_client_t *client, isc_result_t result, int line, int level); +static void +rpz_st_clear(ns_client_t *client); + /*% * Increment query statistics counters. */ @@ -252,6 +274,19 @@ ns_query_cancel(ns_client_t *client) { } static inline void +query_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) { + dns_rdataset_t *rdataset = *rdatasetp; + + CTRACE("query_putrdataset"); + if (rdataset != NULL) { + if (dns_rdataset_isassociated(rdataset)) + dns_rdataset_disassociate(rdataset); + dns_message_puttemprdataset(client->message, rdatasetp); + } + CTRACE("query_putrdataset: done"); +} + +static inline void query_reset(ns_client_t *client, isc_boolean_t everything) { isc_buffer_t *dbuf, *dbuf_next; ns_dbversion_t *dbversion, *dbversion_next; @@ -285,6 +320,18 @@ query_reset(ns_client_t *client, isc_boolean_t everything) { if (client->query.authzone != NULL) dns_zone_detach(&client->query.authzone); + if (client->query.dns64_aaaa != NULL) + query_putrdataset(client, &client->query.dns64_aaaa); + if (client->query.dns64_sigaaaa != NULL) + query_putrdataset(client, &client->query.dns64_sigaaaa); + if (client->query.dns64_aaaaok != NULL) { + isc_mem_put(client->mctx, client->query.dns64_aaaaok, + client->query.dns64_aaaaoklen * + sizeof(isc_boolean_t)); + client->query.dns64_aaaaok = NULL; + client->query.dns64_aaaaoklen = 0; + } + query_freefreeversions(client, everything); for (dbuf = ISC_LIST_HEAD(client->query.namebufs); @@ -310,13 +357,22 @@ query_reset(ns_client_t *client, isc_boolean_t everything) { NS_QUERYATTR_SECURE); client->query.restarts = 0; client->query.timerset = ISC_FALSE; + if (client->query.rpz_st != NULL) { + rpz_st_clear(client); + if (everything) { + isc_mem_put(client->mctx, client->query.rpz_st, + sizeof(*client->query.rpz_st)); + client->query.rpz_st = NULL; + } + } client->query.origqname = NULL; - client->query.qname = NULL; client->query.dboptions = 0; client->query.fetchoptions = 0; client->query.gluedb = NULL; client->query.authdbset = ISC_FALSE; client->query.isreferral = ISC_FALSE; + client->query.dns64_options = 0; + client->query.dns64_ttl = ISC_UINT32_MAX; } static void @@ -473,20 +529,6 @@ query_newrdataset(ns_client_t *client) { return (rdataset); } -static inline void -query_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) { - dns_rdataset_t *rdataset = *rdatasetp; - - CTRACE("query_putrdataset"); - if (rdataset != NULL) { - if (dns_rdataset_isassociated(rdataset)) - dns_rdataset_disassociate(rdataset); - dns_message_puttemprdataset(client->message, rdatasetp); - } - CTRACE("query_putrdataset: done"); -} - - static inline isc_result_t query_newdbversion(ns_client_t *client, unsigned int n) { unsigned int i; @@ -540,6 +582,7 @@ ns_query_init(ns_client_t *client) { ISC_LIST_INIT(client->query.freeversions); client->query.restarts = 0; client->query.timerset = ISC_FALSE; + client->query.rpz_st = NULL; client->query.qname = NULL; result = isc_mutex_init(&client->query.fetchlock); if (result != ISC_R_SUCCESS) @@ -549,6 +592,10 @@ ns_query_init(ns_client_t *client) { client->query.authzone = NULL; client->query.authdbset = ISC_FALSE; client->query.isreferral = ISC_FALSE; + client->query.dns64_aaaa = NULL; + client->query.dns64_sigaaaa = NULL; + client->query.dns64_aaaaok = NULL; + client->query.dns64_aaaaoklen = 0; query_reset(client, ISC_FALSE); result = query_newdbversion(client, 3); if (result != ISC_R_SUCCESS) { @@ -563,8 +610,7 @@ ns_query_init(ns_client_t *client) { } static inline ns_dbversion_t * -query_findversion(ns_client_t *client, dns_db_t *db, - isc_boolean_t *newzonep) +query_findversion(ns_client_t *client, dns_db_t *db) { ns_dbversion_t *dbversion; @@ -590,12 +636,11 @@ query_findversion(ns_client_t *client, dns_db_t *db, return (NULL); dns_db_attach(db, &dbversion->db); dns_db_currentversion(db, &dbversion->version); + dbversion->acl_checked = ISC_FALSE; dbversion->queryok = ISC_FALSE; ISC_LIST_APPEND(client->query.activeversions, dbversion, link); - *newzonep = ISC_TRUE; - } else - *newzonep = ISC_FALSE; + } return (dbversion); } @@ -607,7 +652,6 @@ query_validatezonedb(ns_client_t *client, dns_name_t *name, dns_dbversion_t **versionp) { isc_result_t result; - isc_boolean_t check_acl, new_zone; dns_acl_t *queryacl; ns_dbversion_t *dbversion; @@ -623,7 +667,17 @@ query_validatezonedb(ns_client_t *client, dns_name_t *name, if (!client->view->additionalfromauth && client->query.authdbset && db != client->query.authdb) - goto refuse; + return (DNS_R_REFUSED); + + /* + * Non recursive query to a static-stub zone is prohibited; its + * zone content is not public data, but a part of local configuration + * and should not be disclosed. + */ + if (dns_zone_gettype(zone) == dns_zone_staticstub && + !RECURSIONOK(client)) { + return (DNS_R_REFUSED); + } /* * If the zone has an ACL, we'll check it, otherwise @@ -633,23 +687,19 @@ query_validatezonedb(ns_client_t *client, dns_name_t *name, * Also, get the database version to use. */ - check_acl = ISC_TRUE; /* Keep compiler happy. */ - queryacl = NULL; - /* * Get the current version of this database. */ - dbversion = query_findversion(client, db, &new_zone); - if (dbversion == NULL) { - result = DNS_R_SERVFAIL; - goto fail; - } - if (new_zone) { - check_acl = ISC_TRUE; - } else if (!dbversion->queryok) { - goto refuse; - } else { - check_acl = ISC_FALSE; + dbversion = query_findversion(client, db); + if (dbversion == NULL) + return (DNS_R_SERVFAIL); + + if ((options & DNS_GETDB_IGNOREACL) != 0) + goto approved; + if (dbversion->acl_checked) { + if (!dbversion->queryok) + return (DNS_R_REFUSED); + goto approved; } queryacl = dns_zone_getqueryacl(zone); @@ -663,88 +713,69 @@ query_validatezonedb(ns_client_t *client, dns_name_t *name, * allowed to make queries, otherwise the query should * be refused. */ - check_acl = ISC_FALSE; + dbversion->acl_checked = ISC_TRUE; if ((client->query.attributes & - NS_QUERYATTR_QUERYOK) == 0) - goto refuse; - } else { - /* - * We haven't evaluated the view's queryacl yet. - */ - check_acl = ISC_TRUE; + NS_QUERYATTR_QUERYOK) == 0) { + dbversion->queryok = ISC_FALSE; + return (DNS_R_REFUSED); + } + dbversion->queryok = ISC_TRUE; + goto approved; } } - if (check_acl) { - isc_boolean_t log = ISC_TF((options & DNS_GETDB_NOLOG) == 0); - - result = ns_client_checkaclsilent(client, NULL, queryacl, - ISC_TRUE); - if (log) { - char msg[NS_CLIENT_ACLMSGSIZE("query")]; - if (result == ISC_R_SUCCESS) { - if (isc_log_wouldlog(ns_g_lctx, - ISC_LOG_DEBUG(3))) - { - ns_client_aclmsg("query", name, qtype, - client->view->rdclass, - msg, sizeof(msg)); - ns_client_log(client, - DNS_LOGCATEGORY_SECURITY, - NS_LOGMODULE_QUERY, - ISC_LOG_DEBUG(3), - "%s approved", msg); - } - } else { + result = ns_client_checkaclsilent(client, NULL, queryacl, ISC_TRUE); + if ((options & DNS_GETDB_NOLOG) == 0) { + char msg[NS_CLIENT_ACLMSGSIZE("query")]; + if (result == ISC_R_SUCCESS) { + if (isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(3))) { ns_client_aclmsg("query", name, qtype, client->view->rdclass, msg, sizeof(msg)); - ns_client_log(client, DNS_LOGCATEGORY_SECURITY, - NS_LOGMODULE_QUERY, ISC_LOG_INFO, - "%s denied", msg); + ns_client_log(client, + DNS_LOGCATEGORY_SECURITY, + NS_LOGMODULE_QUERY, + ISC_LOG_DEBUG(3), + "%s approved", msg); } + } else { + ns_client_aclmsg("query", name, qtype, + client->view->rdclass, + msg, sizeof(msg)); + ns_client_log(client, DNS_LOGCATEGORY_SECURITY, + NS_LOGMODULE_QUERY, ISC_LOG_INFO, + "%s denied", msg); } + } - if (queryacl == client->view->queryacl) { - if (result == ISC_R_SUCCESS) { - /* - * We were allowed by the default - * "allow-query" ACL. Remember this so we - * don't have to check again. - */ - client->query.attributes |= - NS_QUERYATTR_QUERYOK; - } + if (queryacl == client->view->queryacl) { + if (result == ISC_R_SUCCESS) { /* - * We've now evaluated the view's query ACL, and - * the NS_QUERYATTR_QUERYOK attribute is now valid. + * We were allowed by the default + * "allow-query" ACL. Remember this so we + * don't have to check again. */ - client->query.attributes |= NS_QUERYATTR_QUERYOKVALID; + client->query.attributes |= NS_QUERYATTR_QUERYOK; } - - if (result != ISC_R_SUCCESS) - goto refuse; + /* + * We've now evaluated the view's query ACL, and + * the NS_QUERYATTR_QUERYOK attribute is now valid. + */ + client->query.attributes |= NS_QUERYATTR_QUERYOKVALID; } - /* Approved. */ - - /* - * Remember the result of the ACL check so we - * don't have to check again. - */ + dbversion->acl_checked = ISC_TRUE; + if (result != ISC_R_SUCCESS) { + dbversion->queryok = ISC_FALSE; + return (DNS_R_REFUSED); + } dbversion->queryok = ISC_TRUE; + approved: /* Transfer ownership, if necessary. */ if (versionp != NULL) *versionp = dbversion->version; - return (ISC_R_SUCCESS); - - refuse: - return (DNS_R_REFUSED); - - fail: - return (result); } static inline isc_result_t @@ -800,6 +831,97 @@ query_getzonedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype, return (result); } +static void +rpz_log(ns_client_t *client) { + char namebuf1[DNS_NAME_FORMATSIZE]; + char namebuf2[DNS_NAME_FORMATSIZE]; + dns_rpz_st_t *st; + const char *pat; + + if (!ns_g_server->log_queries || + !isc_log_wouldlog(ns_g_lctx, DNS_RPZ_INFO_LEVEL)) + return; + + st = client->query.rpz_st; + dns_name_format(client->query.qname, namebuf1, sizeof(namebuf1)); + dns_name_format(st->qname, namebuf2, sizeof(namebuf2)); + + switch (st->m.policy) { + case DNS_RPZ_POLICY_NO_OP: + pat ="response policy %s rewrite %s NO-OP using %s"; + break; + case DNS_RPZ_POLICY_NXDOMAIN: + pat = "response policy %s rewrite %s to NXDOMAIN using %s"; + break; + case DNS_RPZ_POLICY_NODATA: + pat = "response policy %s rewrite %s to NODATA using %s"; + break; + case DNS_RPZ_POLICY_RECORD: + case DNS_RPZ_POLICY_CNAME: + pat = "response policy %s rewrite %s using %s"; + break; + default: + INSIST(0); + } + ns_client_log(client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY, + DNS_RPZ_INFO_LEVEL, pat, dns_rpz_type2str(st->m.type), + namebuf1, namebuf2); +} + +static void +rpz_fail_log(ns_client_t *client, int level, dns_rpz_type_t rpz_type, + dns_name_t *name, const char *str, isc_result_t result) +{ + char namebuf1[DNS_NAME_FORMATSIZE]; + char namebuf2[DNS_NAME_FORMATSIZE]; + + if (!ns_g_server->log_queries || !isc_log_wouldlog(ns_g_lctx, level)) + return; + + dns_name_format(client->query.qname, namebuf1, sizeof(namebuf1)); + dns_name_format(name, namebuf2, sizeof(namebuf2)); + ns_client_log(client, NS_LOGCATEGORY_QUERY_EERRORS, + NS_LOGMODULE_QUERY, level, + "response policy %s rewrite %s via %s %sfailed: %s", + dns_rpz_type2str(rpz_type), + namebuf1, namebuf2, str, isc_result_totext(result)); +} + +/* + * Get a policy rewrite zone database. + */ +static isc_result_t +rpz_getdb(ns_client_t *client, dns_rpz_type_t rpz_type, + dns_name_t *rpz_qname, dns_zone_t **zonep, + dns_db_t **dbp, dns_dbversion_t **versionp) +{ + char namebuf1[DNS_NAME_FORMATSIZE]; + char namebuf2[DNS_NAME_FORMATSIZE]; + dns_dbversion_t *rpz_version = NULL; + isc_result_t result; + + result = query_getzonedb(client, rpz_qname, dns_rdatatype_any, + DNS_GETDB_IGNOREACL, zonep, dbp, &rpz_version); + if (result == ISC_R_SUCCESS) { + if (ns_g_server->log_queries && + isc_log_wouldlog(ns_g_lctx, DNS_RPZ_DEBUG_LEVEL2)) { + dns_name_format(client->query.qname, namebuf1, + sizeof(namebuf1)); + dns_name_format(rpz_qname, namebuf2, sizeof(namebuf2)); + ns_client_log(client, NS_LOGCATEGORY_QUERIES, + NS_LOGMODULE_QUERY, DNS_RPZ_DEBUG_LEVEL2, + "try rpz %s rewrite %s via %s", + dns_rpz_type2str(rpz_type), + namebuf1, namebuf2); + } + *versionp = rpz_version; + return (ISC_R_SUCCESS); + } + rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL, rpz_type, rpz_qname, + "query_getzonedb() ", result); + return (result); +} + static inline isc_result_t query_getcachedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype, dns_db_t **dbp, unsigned int options) @@ -1958,14 +2080,24 @@ query_addrdataset(ns_client_t *client, dns_name_t *fname, CTRACE("query_addrdataset: done"); } -static void -query_addrrset(ns_client_t *client, dns_name_t **namep, - dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp, - isc_buffer_t *dbuf, dns_section_t section) +static isc_result_t +query_dns64(ns_client_t *client, dns_name_t **namep, dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset, isc_buffer_t *dbuf, + dns_section_t section) { dns_name_t *name, *mname; - dns_rdataset_t *rdataset, *mrdataset, *sigrdataset; + dns_rdata_t *dns64_rdata; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdatalist_t *dns64_rdatalist; + dns_rdataset_t *dns64_rdataset; + dns_rdataset_t *mrdataset; + isc_buffer_t *buffer; + isc_region_t r; isc_result_t result; + dns_view_t *view = client->view; + isc_netaddr_t netaddr; + dns_dns64_t *dns64; + unsigned int flags = 0; /*% * To the current response for 'client', add the answer RRset @@ -1977,27 +2109,27 @@ query_addrrset(ns_client_t *client, dns_name_t **namep, * stored in 'dbuf'. In this case, query_addrrset() guarantees that * when it returns the name will either have been kept or released. */ - CTRACE("query_addrrset"); + CTRACE("query_dns64"); name = *namep; - rdataset = *rdatasetp; - if (sigrdatasetp != NULL) - sigrdataset = *sigrdatasetp; - else - sigrdataset = NULL; mname = NULL; mrdataset = NULL; + buffer = NULL; + dns64_rdata = NULL; + dns64_rdataset = NULL; + dns64_rdatalist = NULL; result = dns_message_findname(client->message, section, - name, rdataset->type, rdataset->covers, + name, dns_rdatatype_aaaa, + rdataset->covers, &mname, &mrdataset); if (result == ISC_R_SUCCESS) { /* * We've already got an RRset of the given name and type. * There's nothing else to do; */ - CTRACE("query_addrrset: dns_message_findname succeeded: done"); + CTRACE("query_dns64: dns_message_findname succeeded: done"); if (dbuf != NULL) query_releasename(client, namep); - return; + return (ISC_R_SUCCESS); } else if (result == DNS_R_NXDOMAIN) { /* * The name doesn't exist. @@ -2017,83 +2149,390 @@ query_addrrset(ns_client_t *client, dns_name_t **namep, (section == DNS_SECTION_ANSWER || section == DNS_SECTION_AUTHORITY)) client->query.attributes &= ~NS_QUERYATTR_SECURE; - /* - * Note: we only add SIGs if we've added the type they cover, so - * we do not need to check if the SIG rdataset is already in the - * response. - */ - query_addrdataset(client, mname, rdataset); - *rdatasetp = NULL; - if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) { - /* - * We have a signature. Add it to the response. - */ - ISC_LIST_APPEND(mname->list, sigrdataset, link); - *sigrdatasetp = NULL; - } - CTRACE("query_addrrset: done"); -} -static inline isc_result_t -query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version, - isc_boolean_t zero_ttl, isc_boolean_t isassociated) -{ - dns_name_t *name; - dns_dbnode_t *node; - isc_result_t result, eresult; - dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; - dns_rdataset_t **sigrdatasetp = NULL; + isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); - CTRACE("query_addsoa"); - /* - * Initialization. - */ - eresult = ISC_R_SUCCESS; - name = NULL; - rdataset = NULL; - node = NULL; + result = isc_buffer_allocate(client->mctx, &buffer, view->dns64cnt * + 16 * dns_rdataset_count(rdataset)); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = dns_message_gettemprdataset(client->message, &dns64_rdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = dns_message_gettemprdatalist(client->message, + &dns64_rdatalist); + if (result != ISC_R_SUCCESS) + goto cleanup; - /* - * Don't add the SOA record for test which set "-T nosoa". - */ - if (ns_g_nosoa && (!WANTDNSSEC(client) || !isassociated)) - return (ISC_R_SUCCESS); + dns_rdataset_init(dns64_rdataset); + dns_rdatalist_init(dns64_rdatalist); + dns64_rdatalist->rdclass = dns_rdataclass_in; + dns64_rdatalist->type = dns_rdatatype_aaaa; + if (client->query.dns64_ttl != ISC_UINT32_MAX) + dns64_rdatalist->ttl = ISC_MIN(rdataset->ttl, + client->query.dns64_ttl); + else + dns64_rdatalist->ttl = ISC_MIN(rdataset->ttl, 600); + + if (RECURSIONOK(client)) + flags |= DNS_DNS64_RECURSIVE; /* - * Get resources and make 'name' be the database origin. + * We use the signatures from the A lookup to set DNS_DNS64_DNSSEC + * as this provides a easy way to see if the answer was signed. */ - result = dns_message_gettempname(client->message, &name); + if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) + flags |= DNS_DNS64_DNSSEC; + + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + for (dns64 = ISC_LIST_HEAD(client->view->dns64); + dns64 != NULL; dns64 = dns_dns64_next(dns64)) { + + dns_rdataset_current(rdataset, &rdata); + isc__buffer_availableregion(buffer, &r); + INSIST(r.length >= 16); + result = dns_dns64_aaaafroma(dns64, &netaddr, + client->signer, + &ns_g_server->aclenv, + flags, rdata.data, r.base); + if (result != ISC_R_SUCCESS) { + dns_rdata_reset(&rdata); + continue; + } + isc_buffer_add(buffer, 16); + isc_buffer_remainingregion(buffer, &r); + isc_buffer_forward(buffer, 16); + result = dns_message_gettemprdata(client->message, + &dns64_rdata); + if (result != ISC_R_SUCCESS) + goto cleanup; + dns_rdata_init(dns64_rdata); + dns_rdata_fromregion(dns64_rdata, dns_rdataclass_in, + dns_rdatatype_aaaa, &r); + ISC_LIST_APPEND(dns64_rdatalist->rdata, dns64_rdata, + link); + dns64_rdata = NULL; + dns_rdata_reset(&rdata); + } + } + if (result != ISC_R_NOMORE) + goto cleanup; + + if (ISC_LIST_EMPTY(dns64_rdatalist->rdata)) + goto cleanup; + + result = dns_rdatalist_tordataset(dns64_rdatalist, dns64_rdataset); if (result != ISC_R_SUCCESS) - return (result); - dns_name_init(name, NULL); - dns_name_clone(dns_db_origin(db), name); - rdataset = query_newrdataset(client); - if (rdataset == NULL) { - eresult = DNS_R_SERVFAIL; goto cleanup; - } - if (WANTDNSSEC(client) && dns_db_issecure(db)) { - sigrdataset = query_newrdataset(client); - if (sigrdataset == NULL) { - eresult = DNS_R_SERVFAIL; - goto cleanup; + client->query.attributes |= NS_QUERYATTR_NOADDITIONAL; + dns64_rdataset->trust = rdataset->trust; + query_addrdataset(client, mname, dns64_rdataset); + dns64_rdataset = NULL; + dns64_rdatalist = NULL; + dns_message_takebuffer(client->message, &buffer); + result = ISC_R_SUCCESS; + + cleanup: + if (buffer != NULL) + isc_buffer_free(&buffer); + + if (dns64_rdata != NULL) + dns_message_puttemprdata(client->message, &dns64_rdata); + + if (dns64_rdataset != NULL) + dns_message_puttemprdataset(client->message, &dns64_rdataset); + + if (dns64_rdatalist != NULL) { + for (dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata); + dns64_rdata != NULL; + dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata)) + { + ISC_LIST_UNLINK(dns64_rdatalist->rdata, + dns64_rdata, link); + dns_message_puttemprdata(client->message, &dns64_rdata); } + dns_message_puttemprdatalist(client->message, &dns64_rdatalist); } - /* - * Find the SOA. - */ - result = dns_db_getoriginnode(db, &node); - if (result == ISC_R_SUCCESS) { - result = dns_db_findrdataset(db, node, version, - dns_rdatatype_soa, - 0, client->now, rdataset, - sigrdataset); - } else { - dns_fixedname_t foundname; - dns_name_t *fname; + CTRACE("query_dns64: done"); + return (result); +} - dns_fixedname_init(&foundname); +static void +query_filter64(ns_client_t *client, dns_name_t **namep, + dns_rdataset_t *rdataset, isc_buffer_t *dbuf, + dns_section_t section) +{ + dns_name_t *name, *mname; + dns_rdata_t *myrdata; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdatalist_t *myrdatalist; + dns_rdataset_t *myrdataset; + isc_buffer_t *buffer; + isc_region_t r; + isc_result_t result; + unsigned int i; + + CTRACE("query_filter64"); + + INSIST(client->query.dns64_aaaaok != NULL); + INSIST(client->query.dns64_aaaaoklen == dns_rdataset_count(rdataset)); + + name = *namep; + mname = NULL; + buffer = NULL; + myrdata = NULL; + myrdataset = NULL; + myrdatalist = NULL; + result = dns_message_findname(client->message, section, + name, dns_rdatatype_aaaa, + rdataset->covers, + &mname, &myrdataset); + if (result == ISC_R_SUCCESS) { + /* + * We've already got an RRset of the given name and type. + * There's nothing else to do; + */ + CTRACE("query_filter64: dns_message_findname succeeded: done"); + if (dbuf != NULL) + query_releasename(client, namep); + return; + } else if (result == DNS_R_NXDOMAIN) { + mname = name; + *namep = NULL; + } else { + RUNTIME_CHECK(result == DNS_R_NXRRSET); + if (dbuf != NULL) + query_releasename(client, namep); + dbuf = NULL; + } + + if (rdataset->trust != dns_trust_secure && + (section == DNS_SECTION_ANSWER || + section == DNS_SECTION_AUTHORITY)) + client->query.attributes &= ~NS_QUERYATTR_SECURE; + + result = isc_buffer_allocate(client->mctx, &buffer, + 16 * dns_rdataset_count(rdataset)); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = dns_message_gettemprdataset(client->message, &myrdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = dns_message_gettemprdatalist(client->message, &myrdatalist); + if (result != ISC_R_SUCCESS) + goto cleanup; + + dns_rdataset_init(myrdataset); + dns_rdatalist_init(myrdatalist); + myrdatalist->rdclass = dns_rdataclass_in; + myrdatalist->type = dns_rdatatype_aaaa; + myrdatalist->ttl = rdataset->ttl; + + i = 0; + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + if (!client->query.dns64_aaaaok[i++]) + continue; + dns_rdataset_current(rdataset, &rdata); + INSIST(rdata.length == 16); + isc_buffer_putmem(buffer, rdata.data, rdata.length); + isc_buffer_remainingregion(buffer, &r); + isc_buffer_forward(buffer, rdata.length); + result = dns_message_gettemprdata(client->message, &myrdata); + if (result != ISC_R_SUCCESS) + goto cleanup; + dns_rdata_init(myrdata); + dns_rdata_fromregion(myrdata, dns_rdataclass_in, + dns_rdatatype_aaaa, &r); + ISC_LIST_APPEND(myrdatalist->rdata, myrdata, link); + myrdata = NULL; + dns_rdata_reset(&rdata); + } + if (result != ISC_R_NOMORE) + goto cleanup; + + result = dns_rdatalist_tordataset(myrdatalist, myrdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + client->query.attributes |= NS_QUERYATTR_NOADDITIONAL; + if (mname == name) { + if (dbuf != NULL) + query_keepname(client, name, dbuf); + dns_message_addname(client->message, name, section); + dbuf = NULL; + } + myrdataset->trust = rdataset->trust; + query_addrdataset(client, mname, myrdataset); + myrdataset = NULL; + myrdatalist = NULL; + dns_message_takebuffer(client->message, &buffer); + + cleanup: + if (buffer != NULL) + isc_buffer_free(&buffer); + + if (myrdata != NULL) + dns_message_puttemprdata(client->message, &myrdata); + + if (myrdataset != NULL) + dns_message_puttemprdataset(client->message, &myrdataset); + + if (myrdatalist != NULL) { + for (myrdata = ISC_LIST_HEAD(myrdatalist->rdata); + myrdata != NULL; + myrdata = ISC_LIST_HEAD(myrdatalist->rdata)) + { + ISC_LIST_UNLINK(myrdatalist->rdata, myrdata, link); + dns_message_puttemprdata(client->message, &myrdata); + } + dns_message_puttemprdatalist(client->message, &myrdatalist); + } + if (dbuf != NULL) + query_releasename(client, &name); + + CTRACE("query_filter64: done"); +} + +static void +query_addrrset(ns_client_t *client, dns_name_t **namep, + dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp, + isc_buffer_t *dbuf, dns_section_t section) +{ + dns_name_t *name, *mname; + dns_rdataset_t *rdataset, *mrdataset, *sigrdataset; + isc_result_t result; + + /*% + * To the current response for 'client', add the answer RRset + * '*rdatasetp' and an optional signature set '*sigrdatasetp', with + * owner name '*namep', to section 'section', unless they are + * already there. Also add any pertinent additional data. + * + * If 'dbuf' is not NULL, then '*namep' is the name whose data is + * stored in 'dbuf'. In this case, query_addrrset() guarantees that + * when it returns the name will either have been kept or released. + */ + CTRACE("query_addrrset"); + name = *namep; + rdataset = *rdatasetp; + if (sigrdatasetp != NULL) + sigrdataset = *sigrdatasetp; + else + sigrdataset = NULL; + mname = NULL; + mrdataset = NULL; + result = dns_message_findname(client->message, section, + name, rdataset->type, rdataset->covers, + &mname, &mrdataset); + if (result == ISC_R_SUCCESS) { + /* + * We've already got an RRset of the given name and type. + * There's nothing else to do; + */ + CTRACE("query_addrrset: dns_message_findname succeeded: done"); + if (dbuf != NULL) + query_releasename(client, namep); + return; + } else if (result == DNS_R_NXDOMAIN) { + /* + * The name doesn't exist. + */ + if (dbuf != NULL) + query_keepname(client, name, dbuf); + dns_message_addname(client->message, name, section); + *namep = NULL; + mname = name; + } else { + RUNTIME_CHECK(result == DNS_R_NXRRSET); + if (dbuf != NULL) + query_releasename(client, namep); + } + + if (rdataset->trust != dns_trust_secure && + (section == DNS_SECTION_ANSWER || + section == DNS_SECTION_AUTHORITY)) + client->query.attributes &= ~NS_QUERYATTR_SECURE; + /* + * Note: we only add SIGs if we've added the type they cover, so + * we do not need to check if the SIG rdataset is already in the + * response. + */ + query_addrdataset(client, mname, rdataset); + *rdatasetp = NULL; + if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) { + /* + * We have a signature. Add it to the response. + */ + ISC_LIST_APPEND(mname->list, sigrdataset, link); + *sigrdatasetp = NULL; + } + CTRACE("query_addrrset: done"); +} + +static inline isc_result_t +query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version, + unsigned int override_ttl, isc_boolean_t isassociated) +{ + dns_name_t *name; + dns_dbnode_t *node; + isc_result_t result, eresult; + dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; + dns_rdataset_t **sigrdatasetp = NULL; + + CTRACE("query_addsoa"); + /* + * Initialization. + */ + eresult = ISC_R_SUCCESS; + name = NULL; + rdataset = NULL; + node = NULL; + + /* + * Don't add the SOA record for test which set "-T nosoa". + */ + if (ns_g_nosoa && (!WANTDNSSEC(client) || !isassociated)) + return (ISC_R_SUCCESS); + + /* + * Get resources and make 'name' be the database origin. + */ + result = dns_message_gettempname(client->message, &name); + if (result != ISC_R_SUCCESS) + return (result); + dns_name_init(name, NULL); + dns_name_clone(dns_db_origin(db), name); + rdataset = query_newrdataset(client); + if (rdataset == NULL) { + eresult = DNS_R_SERVFAIL; + goto cleanup; + } + if (WANTDNSSEC(client) && dns_db_issecure(db)) { + sigrdataset = query_newrdataset(client); + if (sigrdataset == NULL) { + eresult = DNS_R_SERVFAIL; + goto cleanup; + } + } + + /* + * Find the SOA. + */ + result = dns_db_getoriginnode(db, &node); + if (result == ISC_R_SUCCESS) { + result = dns_db_findrdataset(db, node, version, + dns_rdatatype_soa, + 0, client->now, rdataset, + sigrdataset); + } else { + dns_fixedname_t foundname; + dns_name_t *fname; + + dns_fixedname_init(&foundname); fname = dns_fixedname_name(&foundname); result = dns_db_find(db, name, version, dns_rdatatype_soa, @@ -2119,10 +2558,11 @@ query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version, if (result != ISC_R_SUCCESS) goto cleanup; - if (zero_ttl) { - rdataset->ttl = 0; + if (override_ttl != ISC_UINT32_MAX && + override_ttl < rdataset->ttl) { + rdataset->ttl = override_ttl; if (sigrdataset != NULL) - sigrdataset->ttl = 0; + sigrdataset->ttl = override_ttl; } /* @@ -2246,67 +2686,79 @@ query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) { return (eresult); } -static inline isc_result_t -query_addcnamelike(ns_client_t *client, dns_name_t *qname, dns_name_t *tname, - dns_rdataset_t *dname, dns_name_t **anamep, - dns_rdatatype_t type) +static isc_result_t +query_add_cname(ns_client_t *client, dns_name_t *qname, dns_name_t *tname, + dns_trust_t trust, dns_ttl_t ttl) { dns_rdataset_t *rdataset; dns_rdatalist_t *rdatalist; dns_rdata_t *rdata; - isc_result_t result; isc_region_t r; + dns_name_t *aname; + isc_result_t result; /* * We assume the name data referred to by tname won't go away. */ - REQUIRE(anamep != NULL); + aname = NULL; + result = dns_message_gettempname(client->message, &aname); + if (result != ISC_R_SUCCESS) + return (result); + result = dns_name_dup(qname, client->mctx, aname); + if (result != ISC_R_SUCCESS) { + dns_message_puttempname(client->message, &aname); + return (result); + } rdatalist = NULL; result = dns_message_gettemprdatalist(client->message, &rdatalist); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) { + dns_message_puttempname(client->message, &aname); return (result); + } rdata = NULL; result = dns_message_gettemprdata(client->message, &rdata); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) { + dns_message_puttempname(client->message, &aname); + dns_message_puttemprdatalist(client->message, &rdatalist); return (result); + } rdataset = NULL; result = dns_message_gettemprdataset(client->message, &rdataset); - if (result != ISC_R_SUCCESS) - return (result); - dns_rdataset_init(rdataset); - result = dns_name_dup(qname, client->mctx, *anamep); if (result != ISC_R_SUCCESS) { - dns_message_puttemprdataset(client->message, &rdataset); + dns_message_puttempname(client->message, &aname); + dns_message_puttemprdatalist(client->message, &rdatalist); + dns_message_puttemprdata(client->message, &rdata); return (result); } - - rdatalist->type = type; + dns_rdataset_init(rdataset); + rdatalist->type = dns_rdatatype_cname; rdatalist->covers = 0; rdatalist->rdclass = client->message->rdclass; - rdatalist->ttl = dname->ttl; + rdatalist->ttl = ttl; dns_name_toregion(tname, &r); rdata->data = r.base; rdata->length = r.length; rdata->rdclass = client->message->rdclass; - rdata->type = type; + rdata->type = dns_rdatatype_cname; ISC_LIST_INIT(rdatalist->rdata); ISC_LIST_APPEND(rdatalist->rdata, rdata, link); RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == ISC_R_SUCCESS); - rdataset->trust = dname->trust; + rdataset->trust = trust; - query_addrrset(client, anamep, &rdataset, NULL, NULL, + query_addrrset(client, &aname, &rdataset, NULL, NULL, DNS_SECTION_ANSWER); - if (rdataset != NULL) { if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); dns_message_puttemprdataset(client->message, &rdataset); } + if (aname != NULL) + dns_message_puttempname(client->message, &aname); return (ISC_R_SUCCESS); } @@ -2860,7 +3312,7 @@ query_addwildcardproof(ns_client_t *client, dns_db_t *db, * j.example -> z.i.example NSEC example * owner common example * next common example - * wild *.f.example + * wild *.example */ options = client->query.dboptions | DNS_DBFIND_NOWILD; dns_fixedname_init(&wfixed); @@ -3196,8 +3648,9 @@ query_resume(isc_task_t *task, isc_event_t *event) { } static isc_result_t -query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain, - dns_rdataset_t *nameservers, isc_boolean_t resuming) +query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname, + dns_name_t *qdomain, dns_rdataset_t *nameservers, + isc_boolean_t resuming) { isc_result_t result; dns_rdataset_t *rdataset, *sigrdataset; @@ -3229,7 +3682,11 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain, NS_LOGMODULE_QUERY, ISC_LOG_WARNING, "recursive-clients soft limit " - "exceeded, aborting oldest query"); + "exceeded (%d/%d/%d), " + "aborting oldest query", + client->recursionquota->used, + client->recursionquota->soft, + client->recursionquota->max); } ns_client_killoldestquery(client); result = ISC_R_SUCCESS; @@ -3242,7 +3699,11 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain, ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY, ISC_LOG_WARNING, - "no more recursive clients: %s", + "no more recursive clients " + "(%d/%d/%d): %s", + ns_g_server->recursionquota.used, + ns_g_server->recursionquota.soft, + ns_g_server->recursionquota.max, isc_result_totext(result)); } ns_client_killoldestquery(client); @@ -3289,8 +3750,7 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain, else peeraddr = NULL; result = dns_resolver_createfetch2(client->view->resolver, - client->query.qname, - qtype, qdomain, nameservers, + qname, qtype, qdomain, nameservers, NULL, peeraddr, client->message->id, client->query.fetchoptions, client->task, @@ -3313,24 +3773,714 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain, return (result); } -#define MAX_RESTARTS 16 - -#define QUERY_ERROR(r) \ -do { \ - eresult = r; \ - want_restart = ISC_FALSE; \ - line = __LINE__; \ -} while (0) +static inline void +rpz_clean(dns_zone_t **zonep, dns_db_t **dbp, dns_dbnode_t **nodep, + dns_rdataset_t **rdatasetp) +{ + if (nodep != NULL && *nodep != NULL) { + REQUIRE(dbp != NULL && *dbp != NULL); + dns_db_detachnode(*dbp, nodep); + } + if (dbp != NULL && *dbp != NULL) + dns_db_detach(dbp); + if (zonep != NULL && *zonep != NULL) + dns_zone_detach(zonep); + if (rdatasetp != NULL && *rdatasetp != NULL && + dns_rdataset_isassociated(*rdatasetp)) + dns_rdataset_disassociate(*rdatasetp); +} -#define RECURSE_ERROR(r) \ -do { \ - if ((r) == DNS_R_DUPLICATE || (r) == DNS_R_DROP) \ - QUERY_ERROR(r); \ - else \ - QUERY_ERROR(DNS_R_SERVFAIL); \ -} while (0) +static inline isc_result_t +rpz_ready(ns_client_t *client, dns_zone_t **zonep, dns_db_t **dbp, + dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp) +{ + REQUIRE(rdatasetp != NULL); -/* + rpz_clean(zonep, dbp, nodep, rdatasetp); + if (*rdatasetp == NULL) { + *rdatasetp = query_newrdataset(client); + if (*rdatasetp == NULL) + return (DNS_R_SERVFAIL); + } + return (ISC_R_SUCCESS); +} + +static void +rpz_st_clear(ns_client_t *client) { + dns_rpz_st_t *st = client->query.rpz_st; + + rpz_clean(&st->m.zone, &st->m.db, &st->m.node, NULL); + if (st->m.rdataset != NULL) + query_putrdataset(client, &st->m.rdataset); + + rpz_clean(NULL, &st->ns.db, NULL, NULL); + if (st->ns.ns_rdataset != NULL) + query_putrdataset(client, &st->ns.ns_rdataset); + if (st->ns.r_rdataset != NULL) + query_putrdataset(client, &st->ns.r_rdataset); + + rpz_clean(&st->q.zone, &st->q.db, &st->q.node, NULL); + if (st->q.rdataset != NULL) + query_putrdataset(client, &st->q.rdataset); + if (st->q.sigrdataset != NULL) + query_putrdataset(client, &st->q.sigrdataset); + st->state = 0; +} + +/* + * Get NS, A, or AAAA rrset for rpz nsdname or nsip checking. + */ +static isc_result_t +rpz_ns_find(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type, + dns_db_t **dbp, dns_dbversion_t *version, + dns_rdataset_t **rdatasetp, isc_boolean_t resuming) +{ + dns_rpz_st_t *st; + isc_boolean_t is_zone; + dns_dbnode_t *node; + dns_fixedname_t fixed; + dns_name_t *found; + isc_result_t result; + + st = client->query.rpz_st; + if ((st->state & DNS_RPZ_RECURSING) != 0) { + INSIST(st->ns.r_type == type); + INSIST(dns_name_equal(name, st->r_name)); + INSIST(*rdatasetp == NULL || + !dns_rdataset_isassociated(*rdatasetp)); + st->state &= ~DNS_RPZ_RECURSING; + *dbp = st->ns.db; + st->ns.db = NULL; + if (*rdatasetp != NULL) + query_putrdataset(client, rdatasetp); + *rdatasetp = st->ns.r_rdataset; + st->ns.r_rdataset = NULL; + result = st->ns.r_result; + if (result == DNS_R_DELEGATION) { + rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL, + DNS_RPZ_TYPE_NSIP, name, + "rpz_ns_find() ", result); + st->m.policy = DNS_RPZ_POLICY_ERROR; + result = DNS_R_SERVFAIL; + } + return (result); + } + + result = rpz_ready(client, NULL, NULL, NULL, rdatasetp); + if (result != ISC_R_SUCCESS) { + st->m.policy = DNS_RPZ_POLICY_ERROR; + return (result); + } + if (*dbp != NULL) { + is_zone = ISC_FALSE; + } else { + dns_zone_t *zone; + + version = NULL; + zone = NULL; + result = query_getdb(client, name, type, 0, &zone, dbp, + &version, &is_zone); + if (result != ISC_R_SUCCESS) { + rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL, + DNS_RPZ_TYPE_NSIP, name, "NS getdb() ", + result); + st->m.policy = DNS_RPZ_POLICY_ERROR; + if (zone != NULL) + dns_zone_detach(&zone); + return (result); + } + if (zone != NULL) + dns_zone_detach(&zone); + } + + node = NULL; + dns_fixedname_init(&fixed); + found = dns_fixedname_name(&fixed); + result = dns_db_find(*dbp, name, version, type, 0, client->now, &node, + found, *rdatasetp, NULL); + if (result == DNS_R_DELEGATION && is_zone && USECACHE(client)) { + /* + * Try the cache if we're authoritative for an + * ancestor but not the domain itself. + */ + rpz_clean(NULL, dbp, &node, rdatasetp); + version = NULL; + dns_db_attach(client->view->cachedb, dbp); + result = dns_db_find(*dbp, name, version, dns_rdatatype_ns, + 0, client->now, &node, found, + *rdatasetp, NULL); + } + rpz_clean(NULL, dbp, &node, NULL); + if (result == DNS_R_DELEGATION) { + /* + * Recurse to get NS rrset or A or AAAA rrset for an NS name. + */ + rpz_clean(NULL, NULL, NULL, rdatasetp); + dns_name_copy(name, st->r_name, NULL); + result = query_recurse(client, type, st->r_name, NULL, NULL, + resuming); + if (result == ISC_R_SUCCESS) { + st->state |= DNS_RPZ_RECURSING; + result = DNS_R_DELEGATION; + } + } + return (result); +} + +/* + * Check the IP address in an A or AAAA rdataset against + * the IP or NSIP response policy rules of a view. + */ +static isc_result_t +rpz_rewrite_ip(ns_client_t *client, dns_rdataset_t *rdataset, + dns_rpz_type_t rpz_type) +{ + dns_rpz_st_t *st; + dns_dbversion_t *version; + dns_zone_t *zone; + dns_db_t *db; + dns_rpz_zone_t *new_rpz; + isc_result_t result; + + st = client->query.rpz_st; + if (st->m.rdataset == NULL) { + st->m.rdataset = query_newrdataset(client); + if (st->m.rdataset == NULL) + return (DNS_R_SERVFAIL); + } + zone = NULL; + db = NULL; + for (new_rpz = ISC_LIST_HEAD(client->view->rpz_zones); + new_rpz != NULL; + new_rpz = ISC_LIST_NEXT(new_rpz, link)) { + version = NULL; + + /* + * Find the database for this policy zone to get its + * radix tree. + */ + result = rpz_getdb(client, rpz_type, &new_rpz->origin, + &zone, &db, &version); + if (result != ISC_R_SUCCESS) { + rpz_clean(&zone, &db, NULL, NULL); + continue; + } + /* + * Look for a better (e.g. longer prefix) hit for an IP address + * in this rdataset in this radix tree than than the previous + * hit, if any. Note the domain name and quality of the + * best hit. + */ + result = dns_db_rpz_findips(new_rpz, rpz_type, zone, db, + version, rdataset, st); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + rpz_clean(&zone, &db, NULL, NULL); + } + return (ISC_R_SUCCESS); +} + +static isc_result_t +rpz_rewrite_nsip(ns_client_t *client, dns_rdatatype_t type, dns_name_t *name, + dns_db_t **dbp, dns_dbversion_t *version, + dns_rdataset_t **rdatasetp, isc_boolean_t resuming) +{ + isc_result_t result; + + result = rpz_ns_find(client, name, type, dbp, version, rdatasetp, + resuming); + switch (result) { + case ISC_R_SUCCESS: + result = rpz_rewrite_ip(client, *rdatasetp, DNS_RPZ_TYPE_NSIP); + break; + case DNS_R_EMPTYNAME: + case DNS_R_EMPTYWILD: + case DNS_R_NXDOMAIN: + case DNS_R_NCACHENXDOMAIN: + case DNS_R_NXRRSET: + case DNS_R_NCACHENXRRSET: + result = ISC_R_SUCCESS; + break; + case DNS_R_DELEGATION: + case DNS_R_DUPLICATE: + case DNS_R_DROP: + break; + default: + if (client->query.rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) { + client->query.rpz_st->m.policy = DNS_RPZ_POLICY_ERROR; + rpz_fail_log(client, ISC_LOG_WARNING, DNS_RPZ_TYPE_NSIP, + name, "NS address rewrite nsip ", result); + } + break; + } + return (result); +} + +/* + * Get the rrset from a response policy zone. + */ +static isc_result_t +rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef, + dns_name_t *sname, dns_rpz_type_t rpz_type, dns_zone_t **zonep, + dns_db_t **dbp, dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp, + dns_rpz_policy_t *policyp) +{ + dns_dbversion_t *version; + dns_rpz_policy_t policy; + dns_fixedname_t fixed; + dns_name_t *found; + isc_result_t result; + + result = rpz_ready(client, zonep, dbp, nodep, rdatasetp); + if (result != ISC_R_SUCCESS) { + *policyp = DNS_RPZ_POLICY_ERROR; + return (result); + } + + /* + * Try to get either a CNAME or the type of record demanded by the + * request from the policy zone. + */ + version = NULL; + result = rpz_getdb(client, rpz_type, qnamef, zonep, dbp, &version); + if (result != ISC_R_SUCCESS) { + *policyp = DNS_RPZ_POLICY_MISS; + return (DNS_R_NXDOMAIN); + } + + dns_fixedname_init(&fixed); + found = dns_fixedname_name(&fixed); + result = dns_db_find(*dbp, qnamef, version, dns_rdatatype_any, 0, + client->now, nodep, found, *rdatasetp, NULL); + if (result == ISC_R_SUCCESS) { + dns_rdatasetiter_t *rdsiter; + + rdsiter = NULL; + result = dns_db_allrdatasets(*dbp, *nodep, version, 0, + &rdsiter); + if (result != ISC_R_SUCCESS) { + dns_db_detachnode(*dbp, nodep); + rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL, rpz_type, + qnamef, "allrdatasets()", result); + *policyp = DNS_RPZ_POLICY_ERROR; + return (DNS_R_SERVFAIL); + } + for (result = dns_rdatasetiter_first(rdsiter); + result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(rdsiter)) { + dns_rdatasetiter_current(rdsiter, *rdatasetp); + if ((*rdatasetp)->type == dns_rdatatype_cname || + (*rdatasetp)->type == qtype) + break; + dns_rdataset_disassociate(*rdatasetp); + } + dns_rdatasetiter_destroy(&rdsiter); + if (result != ISC_R_SUCCESS) { + if (result != ISC_R_NOMORE) { + rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL, + rpz_type, qnamef, "rdatasetiter", + result); + *policyp = DNS_RPZ_POLICY_ERROR; + return (DNS_R_SERVFAIL); + } + /* + * Ask again to get the right DNS_R_DNAME/NXRRSET/... + * result if there is neither a CNAME nor target type. + */ + if (dns_rdataset_isassociated(*rdatasetp)) + dns_rdataset_disassociate(*rdatasetp); + dns_db_detachnode(*dbp, nodep); + + if (qtype == dns_rdatatype_rrsig || + qtype == dns_rdatatype_sig) + result = DNS_R_NXRRSET; + else + result = dns_db_find(*dbp, qnamef, version, + qtype, 0, client->now, + nodep, found, *rdatasetp, + NULL); + } + } + switch (result) { + case ISC_R_SUCCESS: + if ((*rdatasetp)->type != dns_rdatatype_cname) { + policy = DNS_RPZ_POLICY_RECORD; + } else { + policy = dns_rpz_decode_cname(*rdatasetp, sname); + if (policy == DNS_RPZ_POLICY_RECORD && + qtype != dns_rdatatype_cname && + qtype != dns_rdatatype_any) + result = DNS_R_CNAME; + } + break; + case DNS_R_DNAME: + /* + * DNAME policy RRs have very few if any uses that are not + * better served with simple wildcards. Making the work would + * require complications to get the number of labels matched + * in the name or the found name itself to the main DNS_R_DNAME + * case in query_find(). So fall through to treat them as NODATA. + */ + case DNS_R_NXRRSET: + policy = DNS_RPZ_POLICY_NODATA; + break; + case DNS_R_NXDOMAIN: + case DNS_R_EMPTYNAME: + /* + * If we don't get a qname hit, + * see if it is worth looking for other types. + */ + dns_db_rpz_enabled(*dbp, client->query.rpz_st); + dns_db_detach(dbp); + dns_zone_detach(zonep); + policy = DNS_RPZ_POLICY_MISS; + break; + default: + dns_db_detach(dbp); + dns_zone_detach(zonep); + rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL, rpz_type, qnamef, + "", result); + policy = DNS_RPZ_POLICY_ERROR; + result = DNS_R_SERVFAIL; + break; + } + + *policyp = policy; + return (result); +} + +/* + * Build and look for a QNAME or NSDNAME owner name in a response policy zone. + */ +static isc_result_t +rpz_rewrite_name(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname, + dns_rpz_type_t rpz_type, dns_rdataset_t **rdatasetp) +{ + dns_rpz_st_t *st; + dns_rpz_zone_t *rpz; + dns_fixedname_t prefixf, rpz_qnamef; + dns_name_t *prefix, *suffix, *rpz_qname; + dns_zone_t *zone; + dns_db_t *db; + dns_dbnode_t *node; + dns_rpz_policy_t policy; + unsigned int labels; + isc_result_t result; + + st = client->query.rpz_st; + zone = NULL; + db = NULL; + node = NULL; + + for (rpz = ISC_LIST_HEAD(client->view->rpz_zones); + rpz != NULL; + rpz = ISC_LIST_NEXT(rpz, link)) { + /* + * Construct the rule's owner name. + */ + dns_fixedname_init(&prefixf); + prefix = dns_fixedname_name(&prefixf); + dns_name_split(qname, 1, prefix, NULL); + if (rpz_type == DNS_RPZ_TYPE_NSDNAME) + suffix = &rpz->nsdname; + else + suffix = &rpz->origin; + dns_fixedname_init(&rpz_qnamef); + rpz_qname = dns_fixedname_name(&rpz_qnamef); + for (;;) { + result = dns_name_concatenate(prefix, suffix, + rpz_qname, NULL); + if (result == ISC_R_SUCCESS) + break; + INSIST(result == DNS_R_NAMETOOLONG); + labels = dns_name_countlabels(prefix); + if (labels < 2) { + rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL, + rpz_type, suffix, + "concatentate() ", result); + return (ISC_R_SUCCESS); + } + if (labels+1 == dns_name_countlabels(qname)) { + rpz_fail_log(client, DNS_RPZ_DEBUG_LEVEL1, + rpz_type, suffix, + "concatentate() ", result); + } + dns_name_split(prefix, labels - 1, NULL, prefix); + } + + /* + * See if the qname rule (or RR) exists. + */ + result = rpz_find(client, qtype, rpz_qname, qname, rpz_type, + &zone, &db, &node, rdatasetp, &policy); + switch (result) { + case DNS_R_NXDOMAIN: + case DNS_R_EMPTYNAME: + break; + case DNS_R_SERVFAIL: + rpz_clean(&zone, &db, &node, rdatasetp); + st->m.policy = DNS_RPZ_POLICY_ERROR; + return (DNS_R_SERVFAIL); + default: + /* + * when more than one name or address hits a rule, + * prefer the first set of names (qname or NS), + * the first policy zone, and the smallest name + */ + if (st->m.type == rpz_type && + rpz->num > st->m.rpz->num && + 0 <= dns_name_compare(rpz_qname, st->qname)) + continue; + rpz_clean(&st->m.zone, &st->m.db, &st->m.node, + &st->m.rdataset); + st->m.rpz = rpz; + st->m.type = rpz_type; + st->m.prefix = 0; + st->m.policy = policy; + st->m.result = result; + dns_name_copy(rpz_qname, st->qname, NULL); + if (dns_rdataset_isassociated(*rdatasetp)) { + dns_rdataset_t *trdataset; + + trdataset = st->m.rdataset; + st->m.rdataset = *rdatasetp; + *rdatasetp = trdataset; + st->m.ttl = st->m.rdataset->ttl; + } else { + st->m.ttl = DNS_RPZ_TTL_DEFAULT; + } + st->m.node = node; + node = NULL; + st->m.db = db; + db = NULL; + st->m.zone = zone; + zone = NULL; + } + } + + rpz_clean(&zone, &db, &node, rdatasetp); + return (ISC_R_SUCCESS); +} + +/* + * Look for response policy zone NSIP and NSDNAME rewriting. + */ +static isc_result_t +rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, + isc_boolean_t resuming) +{ + dns_rpz_st_t *st; + dns_db_t *ipdb; + dns_rdataset_t *rdataset; + dns_fixedname_t nsnamef; + dns_name_t *nsname; + dns_dbversion_t *version; + isc_result_t result; + + ipdb = NULL; + rdataset = NULL; + + st = client->query.rpz_st; + if (st == NULL) { + st = isc_mem_get(client->mctx, sizeof(*st)); + if (st == NULL) + return (ISC_R_NOMEMORY); + st->state = 0; + memset(&st->m, 0, sizeof(st->m)); + memset(&st->ns, 0, sizeof(st->ns)); + memset(&st->q, 0, sizeof(st->q)); + dns_fixedname_init(&st->_qnamef); + dns_fixedname_init(&st->_r_namef); + dns_fixedname_init(&st->_fnamef); + st->qname = dns_fixedname_name(&st->_qnamef); + st->r_name = dns_fixedname_name(&st->_r_namef); + st->fname = dns_fixedname_name(&st->_fnamef); + client->query.rpz_st = st; + } + if ((st->state & DNS_RPZ_DONE_QNAME) == 0) { + st->state = DNS_RPZ_DONE_QNAME; + st->m.type = DNS_RPZ_TYPE_BAD; + st->m.policy = DNS_RPZ_POLICY_MISS; + + /* + * Check rules for the name if this it the first time, + * i.e. we've not been recursing. + */ + result = DNS_R_SERVFAIL; + st->state &= ~(DNS_RPZ_HAVE_IP | DNS_RPZ_HAVE_NSIPv4 | + DNS_RPZ_HAVE_NSIPv6 | DNS_RPZ_HAD_NSDNAME); + result = rpz_rewrite_name(client, qtype, client->query.qname, + DNS_RPZ_TYPE_QNAME, &rdataset); + if (st->m.policy != DNS_RPZ_POLICY_MISS) + goto cleanup; + if ((st->state & (DNS_RPZ_HAVE_NSIPv4 | DNS_RPZ_HAVE_NSIPv6 | + DNS_RPZ_HAD_NSDNAME)) == 0) + goto cleanup; + st->ns.label = dns_name_countlabels(client->query.qname); + } + + dns_fixedname_init(&nsnamef); + dns_name_clone(client->query.qname, dns_fixedname_name(&nsnamef)); + while (st->ns.label > 1 && st->m.policy == DNS_RPZ_POLICY_MISS) { + if (st->ns.label == dns_name_countlabels(client->query.qname)) { + nsname = client->query.qname; + } else { + nsname = dns_fixedname_name(&nsnamef); + dns_name_split(client->query.qname, st->ns.label, + NULL, nsname); + } + if (st->ns.ns_rdataset == NULL || + !dns_rdataset_isassociated(st->ns.ns_rdataset)) { + dns_db_t *db = NULL; + result = rpz_ns_find(client, nsname, dns_rdatatype_ns, + &db, NULL, &st->ns.ns_rdataset, + resuming); + if (db != NULL) + dns_db_detach(&db); + if (result != ISC_R_SUCCESS) { + if (result == DNS_R_DELEGATION) + goto cleanup; + if (result == DNS_R_EMPTYNAME || + result == DNS_R_NXRRSET || + result == DNS_R_EMPTYWILD || + result == DNS_R_NXDOMAIN || + result == DNS_R_NCACHENXDOMAIN || + result == DNS_R_NCACHENXRRSET || + result == DNS_R_CNAME || + result == DNS_R_DNAME) { + rpz_fail_log(client, + DNS_RPZ_DEBUG_LEVEL2, + DNS_RPZ_TYPE_NSIP, nsname, + "NS db_find() ", result); + dns_rdataset_disassociate(st->ns. + ns_rdataset); + st->ns.label--; + continue; + } + if (st->m.policy != DNS_RPZ_POLICY_ERROR) { + rpz_fail_log(client, DNS_RPZ_INFO_LEVEL, + DNS_RPZ_TYPE_NSIP, nsname, + "NS db_find() ", result); + st->m.policy = DNS_RPZ_POLICY_ERROR; + } + goto cleanup; + } + result = dns_rdataset_first(st->ns.ns_rdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + /* + * Check all NS names. + */ + do { + dns_rdata_ns_t ns; + dns_rdata_t nsrdata = DNS_RDATA_INIT; + + dns_rdataset_current(st->ns.ns_rdataset, &nsrdata); + result = dns_rdata_tostruct(&nsrdata, &ns, NULL); + dns_rdata_reset(&nsrdata); + if (result != ISC_R_SUCCESS) { + rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL, + DNS_RPZ_TYPE_NSIP, nsname, + "rdata_tostruct() ", result); + st->m.policy = DNS_RPZ_POLICY_ERROR; + goto cleanup; + } + if ((st->state & DNS_RPZ_HAD_NSDNAME) != 0) { + result = rpz_rewrite_name(client, qtype, + &ns.name, + DNS_RPZ_TYPE_NSDNAME, + &rdataset); + if (result != ISC_R_SUCCESS) { + dns_rdata_freestruct(&ns); + goto cleanup; + } + } + /* + * Check all IP addresses for this NS name, but don't + * bother without NSIP rules or with a NSDNAME hit. + */ + version = NULL; + if ((st->state & DNS_RPZ_HAVE_NSIPv4) != 0 && + st->m.type != DNS_RPZ_TYPE_NSDNAME && + (st->state & DNS_RPZ_DONE_A) == 0) { + result = rpz_rewrite_nsip(client, + dns_rdatatype_a, + &ns.name, &ipdb, + version, &rdataset, + resuming); + if (result == ISC_R_SUCCESS) + st->state |= DNS_RPZ_DONE_A; + } + if (result == ISC_R_SUCCESS && + (st->state & DNS_RPZ_HAVE_NSIPv6) != 0 && + st->m.type != DNS_RPZ_TYPE_NSDNAME) { + result = rpz_rewrite_nsip(client, + dns_rdatatype_aaaa, + &ns.name, &ipdb, version, + &rdataset, resuming); + } + dns_rdata_freestruct(&ns); + if (ipdb != NULL) + dns_db_detach(&ipdb); + if (result != ISC_R_SUCCESS) + goto cleanup; + st->state &= ~DNS_RPZ_DONE_A; + result = dns_rdataset_next(st->ns.ns_rdataset); + } while (result == ISC_R_SUCCESS); + dns_rdataset_disassociate(st->ns.ns_rdataset); + st->ns.label--; + } + + /* + * Use the best, if any, hit. + */ + result = ISC_R_SUCCESS; + +cleanup: + if (st->m.policy != DNS_RPZ_POLICY_MISS && + st->m.policy != DNS_RPZ_POLICY_NO_OP && + st->m.policy != DNS_RPZ_POLICY_ERROR && + st->m.rpz->policy != DNS_RPZ_POLICY_GIVEN) + st->m.policy = st->m.rpz->policy; + if (st->m.policy == DNS_RPZ_POLICY_NO_OP) + rpz_log(client); + if (st->m.policy == DNS_RPZ_POLICY_MISS || + st->m.policy == DNS_RPZ_POLICY_NO_OP || + st->m.policy == DNS_RPZ_POLICY_ERROR) + rpz_clean(&st->m.zone, &st->m.db, &st->m.node, &st->m.rdataset); + if (st->m.policy != DNS_RPZ_POLICY_MISS) + st->state |= DNS_RPZ_REWRITTEN; + if (st->m.policy == DNS_RPZ_POLICY_ERROR) { + st->m.type = DNS_RPZ_TYPE_BAD; + result = DNS_R_SERVFAIL; + } + if (rdataset != NULL) + query_putrdataset(client, &rdataset); + if ((st->state & DNS_RPZ_RECURSING) == 0) { + rpz_clean(NULL, &st->ns.db, NULL, &st->ns.ns_rdataset); + } + + return (result); +} + +#define MAX_RESTARTS 16 + +#define QUERY_ERROR(r) \ +do { \ + eresult = r; \ + want_restart = ISC_FALSE; \ + line = __LINE__; \ +} while (0) + +#define RECURSE_ERROR(r) \ +do { \ + if ((r) == DNS_R_DUPLICATE || (r) == DNS_R_DROP) \ + QUERY_ERROR(r); \ + else \ + QUERY_ERROR(DNS_R_SERVFAIL); \ +} while (0) + +/* * Extract a network address from the RDATA of an A or AAAA * record. * @@ -3658,44 +4808,137 @@ query_findclosestnsec3(dns_name_t *qname, dns_db_t *db, dns_rdatatype_nsec3, dboptions, client->now, NULL, fname, rdataset, sigrdataset); - if (result == DNS_R_NXDOMAIN) { - if (!dns_rdataset_isassociated(rdataset)) { - return; - } - result = dns_rdataset_first(rdataset); - INSIST(result == ISC_R_SUCCESS); - dns_rdataset_current(rdataset, &rdata); - dns_rdata_tostruct(&rdata, &nsec3, NULL); - dns_rdata_reset(&rdata); - optout = ISC_TF((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0); - if (found != NULL && optout && - dns_name_fullcompare(&name, dns_db_origin(db), &order, - &count) == dns_namereln_subdomain) { - dns_rdataset_disassociate(rdataset); - if (dns_rdataset_isassociated(sigrdataset)) - dns_rdataset_disassociate(sigrdataset); - count = dns_name_countlabels(&name) - 1; - dns_name_getlabelsequence(&name, 1, count, &name); - ns_client_log(client, DNS_LOGCATEGORY_DNSSEC, - NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(3), - "looking for closest provable encloser"); - goto again; + if (result == DNS_R_NXDOMAIN) { + if (!dns_rdataset_isassociated(rdataset)) { + return; + } + result = dns_rdataset_first(rdataset); + INSIST(result == ISC_R_SUCCESS); + dns_rdataset_current(rdataset, &rdata); + dns_rdata_tostruct(&rdata, &nsec3, NULL); + dns_rdata_reset(&rdata); + optout = ISC_TF((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0); + if (found != NULL && optout && + dns_name_fullcompare(&name, dns_db_origin(db), &order, + &count) == dns_namereln_subdomain) { + dns_rdataset_disassociate(rdataset); + if (dns_rdataset_isassociated(sigrdataset)) + dns_rdataset_disassociate(sigrdataset); + count = dns_name_countlabels(&name) - 1; + dns_name_getlabelsequence(&name, 1, count, &name); + ns_client_log(client, DNS_LOGCATEGORY_DNSSEC, + NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(3), + "looking for closest provable encloser"); + goto again; + } + if (exact) + ns_client_log(client, DNS_LOGCATEGORY_DNSSEC, + NS_LOGMODULE_QUERY, ISC_LOG_WARNING, + "expected a exact match NSEC3, got " + "a covering record"); + + } else if (result != ISC_R_SUCCESS) { + return; + } else if (!exact) + ns_client_log(client, DNS_LOGCATEGORY_DNSSEC, + NS_LOGMODULE_QUERY, ISC_LOG_WARNING, + "expected covering NSEC3, got an exact match"); + if (found != NULL) + dns_name_copy(&name, found, NULL); + return; +} + +#ifdef ALLOW_FILTER_AAAA_ON_V4 +static isc_boolean_t +is_v4_client(ns_client_t *client) { + if (isc_sockaddr_pf(&client->peeraddr) == AF_INET) + return (ISC_TRUE); + if (isc_sockaddr_pf(&client->peeraddr) == AF_INET6 && + IN6_IS_ADDR_V4MAPPED(&client->peeraddr.type.sin6.sin6_addr)) + return (ISC_TRUE); + return (ISC_FALSE); +} +#endif + +static isc_uint32_t +dns64_ttl(dns_db_t *db, dns_dbversion_t *version) { + dns_dbnode_t *node = NULL; + dns_rdata_soa_t soa; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_t rdataset; + isc_result_t result; + isc_uint32_t ttl = ISC_UINT32_MAX; + + result = dns_db_getoriginnode(db, &node); + if (result != ISC_R_SUCCESS) + goto cleanup; + dns_rdataset_init(&rdataset); + result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa, + 0, 0, &rdataset, NULL); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = dns_rdataset_first(&rdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + + dns_rdataset_current(&rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &soa, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + ttl = ISC_MIN(rdataset.ttl, soa.minimum); + +cleanup: + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); + if (node != NULL) + dns_db_detachnode(db, &node); + return (ttl); +} + +static isc_boolean_t +dns64_aaaaok(ns_client_t *client, dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset) +{ + isc_netaddr_t netaddr; + dns_dns64_t *dns64 = ISC_LIST_HEAD(client->view->dns64); + unsigned int flags = 0; + unsigned int i, count; + isc_boolean_t *aaaaok; + + INSIST(client->query.dns64_aaaaok == NULL); + INSIST(client->query.dns64_aaaaoklen == 0); + INSIST(client->query.dns64_aaaa == NULL); + INSIST(client->query.dns64_sigaaaa == NULL); + + if (dns64 == NULL) + return (ISC_TRUE); + + if (RECURSIONOK(client)) + flags |= DNS_DNS64_RECURSIVE; + + if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) + flags |= DNS_DNS64_DNSSEC; + + count = dns_rdataset_count(rdataset); + aaaaok = isc_mem_get(client->mctx, sizeof(isc_boolean_t) * count); + + isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); + if (dns_dns64_aaaaok(dns64, &netaddr, client->signer, + &ns_g_server->aclenv, flags, rdataset, + aaaaok, count)) { + for (i = 0; i < count; i++) { + if (aaaaok != NULL && !aaaaok[i]) { + client->query.dns64_aaaaok = aaaaok; + client->query.dns64_aaaaoklen = count; + break; + } } - if (exact) - ns_client_log(client, DNS_LOGCATEGORY_DNSSEC, - NS_LOGMODULE_QUERY, ISC_LOG_WARNING, - "expected a exact match NSEC3, got " - "a covering record"); - - } else if (result != ISC_R_SUCCESS) { - return; - } else if (!exact) - ns_client_log(client, DNS_LOGCATEGORY_DNSSEC, - NS_LOGMODULE_QUERY, ISC_LOG_WARNING, - "expected covering NSEC3, got an exact match"); - if (found != NULL) - dns_name_copy(&name, found, NULL); - return; + if (i == count) + isc_mem_put(client->mctx, aaaaok, + sizeof(isc_boolean_t) * count); + return (ISC_TRUE); + } + isc_mem_put(client->mctx, aaaaok, sizeof(isc_boolean_t) * count); + return (ISC_FALSE); } /* @@ -3716,6 +4959,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdatasetiter_t *rdsiter; isc_boolean_t want_restart, authoritative, is_zone, need_wildcardproof; + isc_boolean_t is_staticstub_zone; unsigned int n, nlabels; dns_namereln_t namereln; int order; @@ -3731,8 +4975,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) unsigned int options; isc_boolean_t empty_wild; dns_rdataset_t *noqname; + dns_rpz_st_t *rpz_st; isc_boolean_t resuming; int line = -1; + isc_boolean_t dns64_exclude, dns64; CTRACE("query_find"); @@ -3758,28 +5004,67 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) zone = NULL; need_wildcardproof = ISC_FALSE; empty_wild = ISC_FALSE; + dns64_exclude = dns64 = ISC_FALSE; options = 0; resuming = ISC_FALSE; is_zone = ISC_FALSE; + is_staticstub_zone = ISC_FALSE; if (event != NULL) { /* * We're returning from recursion. Restore the query context * and resume. */ - want_restart = ISC_FALSE; - authoritative = ISC_FALSE; - qtype = event->qtype; + rpz_st = client->query.rpz_st; + if (rpz_st != NULL && + (rpz_st->state & DNS_RPZ_RECURSING) != 0) { + is_zone = rpz_st->q.is_zone; + authoritative = rpz_st->q.authoritative; + zone = rpz_st->q.zone; + rpz_st->q.zone = NULL; + node = rpz_st->q.node; + rpz_st->q.node = NULL; + db = rpz_st->q.db; + rpz_st->q.db = NULL; + rdataset = rpz_st->q.rdataset; + rpz_st->q.rdataset = NULL; + sigrdataset = rpz_st->q.sigrdataset; + rpz_st->q.sigrdataset = NULL; + qtype = rpz_st->q.qtype; + + if (event->node != NULL) + dns_db_detachnode(db, &event->node); + rpz_st->ns.db = event->db; + rpz_st->ns.r_type = event->qtype; + rpz_st->ns.r_rdataset = event->rdataset; + if (event->sigrdataset != NULL && + dns_rdataset_isassociated(event->sigrdataset)) + dns_rdataset_disassociate(event->sigrdataset); + } else { + authoritative = ISC_FALSE; + + qtype = event->qtype; + db = event->db; + node = event->node; + rdataset = event->rdataset; + sigrdataset = event->sigrdataset; + } + if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig) type = dns_rdatatype_any; else type = qtype; - db = event->db; - node = event->node; - rdataset = event->rdataset; - sigrdataset = event->sigrdataset; + + if (DNS64(client)) { + client->query.attributes &= ~NS_QUERYATTR_DNS64; + dns64 = ISC_TRUE; + } + if (DNS64EXCLUDE(client)) { + client->query.attributes &= ~NS_QUERYATTR_DNS64EXCLUDE; + dns64_exclude = ISC_TRUE; + } /* * We'll need some resources... @@ -3794,16 +5079,26 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } - tname = dns_fixedname_name(&event->foundname); + if (rpz_st != NULL && + (rpz_st->state & DNS_RPZ_RECURSING) != 0) { + tname = rpz_st->fname; + } else { + tname = dns_fixedname_name(&event->foundname); + } result = dns_name_copy(tname, fname, NULL); if (result != ISC_R_SUCCESS) { QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } - - result = event->result; + if (rpz_st != NULL && + (rpz_st->state & DNS_RPZ_RECURSING) != 0) { + rpz_st->ns.r_result = event->result; + result = rpz_st->q.result; + isc_event_free(ISC_EVENT_PTR(&event)); + } else { + result = event->result; + } resuming = ISC_TRUE; - goto resume; } @@ -3902,8 +5197,12 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) goto cleanup; } - if (is_zone) + is_staticstub_zone = ISC_FALSE; + if (is_zone && zone != NULL) { authoritative = ISC_TRUE; + if (dns_zone_gettype(zone) == dns_zone_staticstub) + is_staticstub_zone = ISC_TRUE; + } if (event == NULL && client->query.restarts == 0) { if (is_zone) { @@ -3956,6 +5255,119 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) resume: CTRACE("query_find: resume"); + + if (!ISC_LIST_EMPTY(client->view->rpz_zones) && + RECURSIONOK(client) && !RECURSING(client) && + result != DNS_R_DELEGATION && result != ISC_R_NOTFOUND && + (client->query.rpz_st == NULL || + (client->query.rpz_st->state & DNS_RPZ_REWRITTEN) == 0) && + !dns_name_equal(client->query.qname, dns_rootname)) { + isc_result_t rresult; + + rresult = rpz_rewrite(client, qtype, resuming); + rpz_st = client->query.rpz_st; + switch (rresult) { + case ISC_R_SUCCESS: + break; + case DNS_R_DELEGATION: + /* + * recursing for NS names or addresses, + * so save the main query state + */ + rpz_st->q.qtype = qtype; + rpz_st->q.is_zone = is_zone; + rpz_st->q.authoritative = authoritative; + rpz_st->q.zone = zone; + zone = NULL; + rpz_st->q.db = db; + db = NULL; + rpz_st->q.node = node; + node = NULL; + rpz_st->q.rdataset = rdataset; + rdataset = NULL; + rpz_st->q.sigrdataset = sigrdataset; + sigrdataset = NULL; + dns_name_copy(fname, rpz_st->fname, NULL); + rpz_st->q.result = result; + client->query.attributes |= NS_QUERYATTR_RECURSING; + result = ISC_R_SUCCESS; + goto cleanup; + default: + RECURSE_ERROR(rresult); + goto cleanup; + } + if (rpz_st->m.policy != DNS_RPZ_POLICY_MISS && + rpz_st->m.policy != DNS_RPZ_POLICY_NO_OP) { + result = dns_name_copy(client->query.qname, fname, + NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + finish_rewrite: + rpz_clean(&zone, &db, &node, NULL); + if (rpz_st->m.rdataset != NULL) { + if (rdataset != NULL) + query_putrdataset(client, &rdataset); + rdataset = rpz_st->m.rdataset; + rpz_st->m.rdataset = NULL; + } else if (rdataset != NULL && + dns_rdataset_isassociated(rdataset)) { + dns_rdataset_disassociate(rdataset); + } + node = rpz_st->m.node; + rpz_st->m.node = NULL; + db = rpz_st->m.db; + rpz_st->m.db = NULL; + zone = rpz_st->m.zone; + rpz_st->m.zone = NULL; + + result = rpz_st->m.result; + switch (rpz_st->m.policy) { + case DNS_RPZ_POLICY_NXDOMAIN: + result = DNS_R_NXDOMAIN; + break; + case DNS_RPZ_POLICY_NODATA: + result = DNS_R_NXRRSET; + break; + case DNS_RPZ_POLICY_RECORD: + if (type == dns_rdatatype_any && + result != DNS_R_CNAME && + dns_rdataset_isassociated(rdataset)) + dns_rdataset_disassociate(rdataset); + break; + case DNS_RPZ_POLICY_CNAME: + result = dns_name_copy(&rpz_st->m.rpz->cname, + fname, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + query_keepname(client, fname, dbuf); + result = query_add_cname(client, + client->query.qname, + fname, + dns_trust_authanswer, + rpz_st->m.ttl); + if (result != ISC_R_SUCCESS) + goto cleanup; + ns_client_qnamereplace(client, fname); + fname = NULL; + client->attributes &= ~NS_CLIENTATTR_WANTDNSSEC; + rpz_log(client); + want_restart = ISC_TRUE; + goto cleanup; + default: + INSIST(0); + } + + /* + * Turn off DNSSEC because the results of a + * response policy zone cannot verify. + */ + client->attributes &= ~NS_CLIENTATTR_WANTDNSSEC; + if (sigrdataset != NULL && + dns_rdataset_isassociated(sigrdataset)) + dns_rdataset_disassociate(sigrdataset); + is_zone = ISC_TRUE; + rpz_log(client); + } + } + switch (result) { case ISC_R_SUCCESS: /* @@ -4008,11 +5420,18 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) */ if (RECURSIONOK(client)) { result = query_recurse(client, qtype, + client->query.qname, NULL, NULL, resuming); - if (result == ISC_R_SUCCESS) + if (result == ISC_R_SUCCESS) { client->query.attributes |= NS_QUERYATTR_RECURSING; - else + if (dns64) + client->query.attributes |= + NS_QUERYATTR_DNS64; + if (dns64_exclude) + client->query.attributes |= + NS_QUERYATTR_DNS64EXCLUDE; + } else RECURSE_ERROR(result); goto cleanup; } else { @@ -4143,12 +5562,22 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) } } else { if (zfname != NULL && - !dns_name_issubdomain(fname, zfname)) { + (!dns_name_issubdomain(fname, zfname) || + (is_staticstub_zone && + dns_name_equal(fname, zfname)))) { /* - * We've already got a delegation from - * authoritative data, and it is better - * than what we found in the cache. Use - * it instead of the cache delegation. + * In the following cases use "authoritative" + * data instead of the cache delegation: + * 1. We've already got a delegation from + * authoritative data, and it is better + * than what we found in the cache. + * 2. The query name matches the origin name + * of a static-stub zone. This needs to be + * considered for the case where the NS of + * the static-stub zone and the cached NS + * are different. We still need to contact + * the nameservers configured in the + * static-stub zone. */ query_releasename(client, &fname); fname = zfname; @@ -4183,15 +5612,31 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) */ if (dns_rdatatype_atparent(type)) result = query_recurse(client, qtype, - NULL, NULL, - resuming); + client->query.qname, + NULL, NULL, resuming); + else if (dns64) + result = query_recurse(client, + dns_rdatatype_a, + client->query.qname, + NULL, NULL, resuming); else result = query_recurse(client, qtype, - fname, rdataset, - resuming); - if (result == ISC_R_SUCCESS) + client->query.qname, + fname, rdataset, + resuming); + + if (result == ISC_R_SUCCESS) { client->query.attributes |= NS_QUERYATTR_RECURSING; + if (dns64) + client->query.attributes |= + NS_QUERYATTR_DNS64; + if (dns64_exclude) + client->query.attributes |= + NS_QUERYATTR_DNS64EXCLUDE; + } else if (result == DNS_R_DUPLICATE || + result == DNS_R_DROP) + QUERY_ERROR(result); else RECURSE_ERROR(result); } else { @@ -4231,11 +5676,75 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) } } goto cleanup; + case DNS_R_EMPTYNAME: - result = DNS_R_NXRRSET; - /* FALLTHROUGH */ case DNS_R_NXRRSET: + nxrrset: INSIST(is_zone); + +#ifdef dns64_bis_return_excluded_addresses + if (dns64) +#else + if (dns64 && !dns64_exclude) +#endif + { + /* + * Restore the answers from the previous AAAA lookup. + */ + if (rdataset != NULL) + query_putrdataset(client, &rdataset); + if (sigrdataset != NULL) + query_putrdataset(client, &sigrdataset); + rdataset = client->query.dns64_aaaa; + sigrdataset = client->query.dns64_sigaaaa; + if (fname == NULL) { + dbuf = query_getnamebuf(client); + if (dbuf == NULL) { + QUERY_ERROR(DNS_R_SERVFAIL); + goto cleanup; + } + fname = query_newname(client, dbuf, &b); + if (fname == NULL) { + QUERY_ERROR(DNS_R_SERVFAIL); + goto cleanup; + } + } + dns_name_copy(client->query.qname, fname, NULL); + client->query.dns64_aaaa = NULL; + client->query.dns64_sigaaaa = NULL; + dns64 = ISC_FALSE; +#ifdef dns64_bis_return_excluded_addresses + /* + * Resume the diverted processing of the AAAA response? + */ + if (dns64_excluded) + break; +#endif + } else if (result == DNS_R_NXRRSET && + !ISC_LIST_EMPTY(client->view->dns64) && + client->message->rdclass == dns_rdataclass_in && + qtype == dns_rdatatype_aaaa) + { + /* + * Look to see if there are A records for this + * name. + */ + INSIST(client->query.dns64_aaaa == NULL); + INSIST(client->query.dns64_sigaaaa == NULL); + client->query.dns64_aaaa = rdataset; + client->query.dns64_sigaaaa = sigrdataset; + client->query.dns64_ttl = dns64_ttl(db, version); + query_releasename(client, &fname); + dns_db_detachnode(db, &node); + rdataset = NULL; + sigrdataset = NULL; + type = qtype = dns_rdatatype_a; + dns64 = ISC_TRUE; + goto db_find; + } + + result = DNS_R_NXRRSET; + /* * Look for a NSEC3 record if we don't have a NSEC record. */ @@ -4258,10 +5767,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) * instead? If so add the nearest to the * closest provable encloser. */ - if (found && - dns_rdataset_isassociated(rdataset) && - !dns_name_equal(qname, found)) - { + if (dns_rdataset_isassociated(rdataset) && + !dns_name_equal(qname, found)) { unsigned int count; unsigned int skip; @@ -4328,7 +5835,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) /* * Add SOA. */ - result = query_addsoa(client, db, version, ISC_FALSE, + result = query_addsoa(client, db, version, ISC_UINT32_MAX, dns_rdataset_isassociated(rdataset)); if (result != ISC_R_SUCCESS) { QUERY_ERROR(result); @@ -4377,10 +5884,11 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) zone != NULL && #endif dns_zone_getzeronosoattl(zone)) - result = query_addsoa(client, db, version, ISC_TRUE, + result = query_addsoa(client, db, version, 0, dns_rdataset_isassociated(rdataset)); else - result = query_addsoa(client, db, version, ISC_FALSE, + result = query_addsoa(client, db, version, + ISC_UINT32_MAX, dns_rdataset_isassociated(rdataset)); if (result != ISC_R_SUCCESS) { QUERY_ERROR(result); @@ -4411,6 +5919,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) case DNS_R_NCACHENXDOMAIN: case DNS_R_NCACHENXRRSET: + ncache_nxrrset: INSIST(!is_zone); authoritative = ISC_FALSE; /* @@ -4426,6 +5935,74 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) client->message->rdclass == dns_rdataclass_in && dns_name_countlabels(fname) == 7) warn_rfc1918(client, fname, rdataset); + +#ifdef dns64_bis_return_excluded_addresses + if (dns64) +#else + if (dns64 && !dns64_exclude) +#endif + { + /* + * Restore the answers from the previous AAAA lookup. + */ + if (rdataset != NULL) + query_putrdataset(client, &rdataset); + if (sigrdataset != NULL) + query_putrdataset(client, &sigrdataset); + rdataset = client->query.dns64_aaaa; + sigrdataset = client->query.dns64_sigaaaa; + if (fname == NULL) { + dbuf = query_getnamebuf(client); + if (dbuf == NULL) { + QUERY_ERROR(DNS_R_SERVFAIL); + goto cleanup; + } + fname = query_newname(client, dbuf, &b); + if (fname == NULL) { + QUERY_ERROR(DNS_R_SERVFAIL); + goto cleanup; + } + } + dns_name_copy(client->query.qname, fname, NULL); + client->query.dns64_aaaa = NULL; + client->query.dns64_sigaaaa = NULL; + dns64 = ISC_FALSE; +#ifdef dns64_bis_return_excluded_addresses + if (dns64_excluded) + break; +#endif + } else if (result == DNS_R_NCACHENXRRSET && + !ISC_LIST_EMPTY(client->view->dns64) && + client->message->rdclass == dns_rdataclass_in && + qtype == dns_rdatatype_aaaa) + { + /* + * Look to see if there are A records for this + * name. + */ + INSIST(client->query.dns64_aaaa == NULL); + INSIST(client->query.dns64_sigaaaa == NULL); + client->query.dns64_aaaa = rdataset; + client->query.dns64_sigaaaa = sigrdataset; + /* + * If the ttl is zero we need to workout if we have just + * decremented to zero or if there was no negative cache + * ttl in the answer. + */ + if (rdataset->ttl != 0) + client->query.dns64_ttl = rdataset->ttl; + else if (dns_rdataset_first(rdataset) == ISC_R_SUCCESS) + client->query.dns64_ttl = 0; + query_releasename(client, &fname); + dns_db_detachnode(db, &node); + rdataset = NULL; + sigrdataset = NULL; + fname = NULL; + type = qtype = dns_rdatatype_a; + dns64 = ISC_TRUE; + goto db_find; + } + /* * We don't call query_addrrset() because we don't need any * of its extra features (and things would probably break!). @@ -4562,11 +6139,11 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) dns_message_puttempname(client->message, &tname); goto cleanup; } - dns_name_init(tname, NULL); dns_name_clone(&dname.dname, tname); dns_rdata_freestruct(&dname); /* - * Construct the new qname. + * Construct the new qname consisting of + * . */ dns_fixedname_init(&fixed); prefix = dns_fixedname_name(&fixed); @@ -4583,8 +6160,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) goto cleanup; } result = dns_name_concatenate(prefix, tname, fname, NULL); + dns_message_puttempname(client->message, &tname); if (result != ISC_R_SUCCESS) { - dns_message_puttempname(client->message, &tname); if (result == ISC_R_NOSPACE) { /* * RFC2672, section 4.1, subsection 3c says @@ -4597,11 +6174,12 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) } query_keepname(client, fname, dbuf); /* - * Synthesize a CNAME for this DNAME. + * Synthesize a CNAME consisting of + * CNAME + * with * - * We want to synthesize a CNAME since if we don't - * then older software that doesn't understand DNAME - * will not chain like it should. + * Synthesize a CNAME so old old clients that don't understand + * DNAME can chain. * * We do not try to synthesize a signature because we hope * that security aware servers will understand DNAME. Also, @@ -4609,12 +6187,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) * on-the-fly is costly, and not really legitimate anyway * since the synthesized CNAME is NOT in the zone. */ - dns_name_init(tname, NULL); - (void)query_addcnamelike(client, client->query.qname, fname, - trdataset, &tname, - dns_rdatatype_cname); - if (tname != NULL) - dns_message_puttempname(client->message, &tname); + result = query_add_cname(client, client->query.qname, fname, + trdataset->trust, trdataset->ttl); + if (result != ISC_R_SUCCESS) + goto cleanup; /* * Switch to the new qname and restart. */ @@ -4641,6 +6217,28 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) } if (type == dns_rdatatype_any) { +#ifdef ALLOW_FILTER_AAAA_ON_V4 + isc_boolean_t have_aaaa, have_a, have_sig, filter_aaaa; + + /* + * The filter-aaaa-on-v4 option should + * suppress AAAAs for IPv4 clients if there is an A. + * If we are not authoritative, assume there is a A + * even in if it is not in our cache. This assumption could + * be wrong but it is a good bet. + */ + have_aaaa = ISC_FALSE; + have_a = !authoritative; + have_sig = ISC_FALSE; + if (client->view->v4_aaaa != dns_v4_aaaa_ok && + is_v4_client(client) && + ns_client_checkaclsilent(client, NULL, + client->view->v4_aaaa_acl, + ISC_TRUE) == ISC_R_SUCCESS) + filter_aaaa = ISC_TRUE; + else + filter_aaaa = ISC_FALSE; +#endif /* * XXXRTH Need to handle zonecuts with special case * code. @@ -4652,6 +6250,54 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } + + /* + * Check all A and AAAA records in all response policy + * IP address zones + */ + rpz_st = client->query.rpz_st; + if (rpz_st != NULL && + (rpz_st->state & DNS_RPZ_DONE_QNAME) != 0 && + (rpz_st->state & DNS_RPZ_REWRITTEN) == 0 && + RECURSIONOK(client) && !RECURSING(client) && + (rpz_st->state & DNS_RPZ_HAVE_IP) != 0) { + for (result = dns_rdatasetiter_first(rdsiter); + result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(rdsiter)) { + dns_rdatasetiter_current(rdsiter, rdataset); + if (rdataset->type == dns_rdatatype_a || + rdataset->type == dns_rdatatype_aaaa) + result = rpz_rewrite_ip(client, + rdataset, + DNS_RPZ_TYPE_IP); + dns_rdataset_disassociate(rdataset); + if (result != ISC_R_SUCCESS) + break; + } + if (result != ISC_R_NOMORE) { + dns_rdatasetiter_destroy(&rdsiter); + QUERY_ERROR(DNS_R_SERVFAIL); + goto cleanup; + } + switch (rpz_st->m.policy) { + case DNS_RPZ_POLICY_MISS: + break; + case DNS_RPZ_POLICY_NO_OP: + rpz_log(client); + rpz_st->state |= DNS_RPZ_REWRITTEN; + break; + case DNS_RPZ_POLICY_NXDOMAIN: + case DNS_RPZ_POLICY_NODATA: + case DNS_RPZ_POLICY_RECORD: + case DNS_RPZ_POLICY_CNAME: + dns_rdatasetiter_destroy(&rdsiter); + rpz_st->state |= DNS_RPZ_REWRITTEN; + goto finish_rewrite; + default: + INSIST(0); + } + } + /* * Calling query_addrrset() with a non-NULL dbuf is going * to either keep or release the name. We don't want it to @@ -4668,6 +6314,18 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) result = dns_rdatasetiter_first(rdsiter); while (result == ISC_R_SUCCESS) { dns_rdatasetiter_current(rdsiter, rdataset); +#ifdef ALLOW_FILTER_AAAA_ON_V4 + /* + * Notice the presence of A and AAAAs so + * that AAAAs can be hidden from IPv4 clients. + */ + if (filter_aaaa) { + if (rdataset->type == dns_rdatatype_aaaa) + have_aaaa = ISC_TRUE; + else if (rdataset->type == dns_rdatatype_a) + have_a = ISC_TRUE; + } +#endif if (is_zone && qtype == dns_rdatatype_any && !dns_db_issecure(db) && dns_rdatatype_isdnssec(rdataset->type)) { @@ -4679,6 +6337,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) dns_rdataset_disassociate(rdataset); } else if ((qtype == dns_rdatatype_any || rdataset->type == qtype) && rdataset->type != 0) { +#ifdef ALLOW_FILTER_AAAA_ON_V4 + if (dns_rdatatype_isdnssec(rdataset->type)) + have_sig = ISC_TRUE; +#endif if (NOQNAME(rdataset) && WANTDNSSEC(client)) noqname = rdataset; else @@ -4709,6 +6371,16 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) result = dns_rdatasetiter_next(rdsiter); } +#ifdef ALLOW_FILTER_AAAA_ON_V4 + /* + * Filter AAAAs if there is an A and there is no signature + * or we are supposed to break DNSSEC. + */ + if (filter_aaaa && have_aaaa && have_a && + (!have_sig || !WANTDNSSEC(client) || + client->view->v4_aaaa == dns_v4_aaaa_break_dnssec)) + client->attributes |= NS_CLIENTATTR_FILTER_AAAA; +#endif if (fname != NULL) dns_message_puttempname(client->message, &fname); @@ -4742,10 +6414,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) dns_rdatasetiter_destroy(&rdsiter); if (RECURSIONOK(client)) { result = query_recurse(client, - qtype, - NULL, - NULL, - resuming); + qtype, + client->query.qname, + NULL, NULL, + resuming); if (result == ISC_R_SUCCESS) client->query.attributes |= NS_QUERYATTR_RECURSING; @@ -4763,7 +6435,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) * Add SOA. */ result = query_addsoa(client, db, version, - ISC_FALSE, ISC_FALSE); + ISC_UINT32_MAX, + ISC_FALSE); if (result == ISC_R_SUCCESS) result = ISC_R_NOMORE; } else { @@ -4783,6 +6456,162 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) * This is the "normal" case -- an ordinary question to which * we know the answer. */ + + /* + * Check all A and AAAA records in all response policy + * IP address zones + */ + rpz_st = client->query.rpz_st; + if (rpz_st != NULL && + (rpz_st->state & DNS_RPZ_DONE_QNAME) != 0 && + (rpz_st->state & DNS_RPZ_REWRITTEN) == 0 && + RECURSIONOK(client) && !RECURSING(client) && + (rpz_st->state & DNS_RPZ_HAVE_IP) != 0 && + (qtype == dns_rdatatype_aaaa || qtype == dns_rdatatype_a)) { + result = rpz_rewrite_ip(client, rdataset, + DNS_RPZ_TYPE_IP); + if (result != ISC_R_SUCCESS) { + QUERY_ERROR(DNS_R_SERVFAIL); + goto cleanup; + } + /* + * After a hit in the radix tree for the policy domain, + * either stop trying to rewrite (DNS_RPZ_POLICY_NO_OP) + * or restart to ask the ordinary database of the + * policy zone for the DNS record corresponding to the + * record in the radix tree. + */ + switch (rpz_st->m.policy) { + case DNS_RPZ_POLICY_MISS: + break; + case DNS_RPZ_POLICY_NO_OP: + rpz_log(client); + rpz_st->state |= DNS_RPZ_REWRITTEN; + break; + case DNS_RPZ_POLICY_NXDOMAIN: + case DNS_RPZ_POLICY_NODATA: + case DNS_RPZ_POLICY_RECORD: + case DNS_RPZ_POLICY_CNAME: + rpz_st->state |= DNS_RPZ_REWRITTEN; + goto finish_rewrite; + default: + INSIST(0); + } + } + +#ifdef ALLOW_FILTER_AAAA_ON_V4 + /* + * Optionally hide AAAAs from IPv4 clients if there is an A. + * We add the AAAAs now, but might refuse to render them later + * after DNSSEC is figured out. + * This could be more efficient, but the whole idea is + * so fundamentally wrong, unavoidably inaccurate, and + * unneeded that it is best to keep it as short as possible. + */ + if (client->view->v4_aaaa != dns_v4_aaaa_ok && + is_v4_client(client) && + ns_client_checkaclsilent(client, NULL, + client->view->v4_aaaa_acl, + ISC_TRUE) == ISC_R_SUCCESS && + (!WANTDNSSEC(client) || + sigrdataset == NULL || + !dns_rdataset_isassociated(sigrdataset) || + client->view->v4_aaaa == dns_v4_aaaa_break_dnssec)) { + if (qtype == dns_rdatatype_aaaa) { + trdataset = query_newrdataset(client); + result = dns_db_findrdataset(db, node, version, + dns_rdatatype_a, 0, + client->now, + trdataset, NULL); + if (dns_rdataset_isassociated(trdataset)) + dns_rdataset_disassociate(trdataset); + query_putrdataset(client, &trdataset); + + /* + * We have an AAAA but the A is not in our cache. + * Assume any result other than DNS_R_DELEGATION + * or ISC_R_NOTFOUND means there is no A and + * so AAAAs are ok. + * Assume there is no A if we can't recurse + * for this client, although that could be + * the wrong answer. What else can we do? + * Besides, that we have the AAAA and are using + * this mechanism suggests that we care more + * about As than AAAAs and would have cached + * the A if it existed. + */ + if (result == ISC_R_SUCCESS) { + client->attributes |= + NS_CLIENTATTR_FILTER_AAAA; + + } else if (authoritative || + !RECURSIONOK(client) || + (result != DNS_R_DELEGATION && + result != ISC_R_NOTFOUND)) { + client->attributes &= + ~NS_CLIENTATTR_FILTER_AAAA; + } else { + /* + * This is an ugly kludge to recurse + * for the A and discard the result. + * + * Continue to add the AAAA now. + * We'll make a note to not render it + * if the recursion for the A succeeds. + */ + result = query_recurse(client, + dns_rdatatype_a, + client->query.qname, + NULL, NULL, resuming); + if (result == ISC_R_SUCCESS) { + client->attributes |= + NS_CLIENTATTR_FILTER_AAAA_RC; + client->query.attributes |= + NS_QUERYATTR_RECURSING; + } + } + + } else if (qtype == dns_rdatatype_a && + (client->attributes & + NS_CLIENTATTR_FILTER_AAAA_RC) != 0) { + client->attributes &= + ~NS_CLIENTATTR_FILTER_AAAA_RC; + client->attributes |= + NS_CLIENTATTR_FILTER_AAAA; + dns_rdataset_disassociate(rdataset); + if (sigrdataset != NULL && + dns_rdataset_isassociated(sigrdataset)) + dns_rdataset_disassociate(sigrdataset); + goto cleanup; + } + } +#endif + /* + * Check to see if the AAAA RRset has non-excluded addresses + * in it. If not look for a A RRset. + */ + INSIST(client->query.dns64_aaaaok == NULL); + + if (qtype == dns_rdatatype_aaaa && !dns64_exclude && + !ISC_LIST_EMPTY(client->view->dns64) && + client->message->rdclass == dns_rdataclass_in && + !dns64_aaaaok(client, rdataset, sigrdataset)) { + /* + * Look to see if there are A records for this + * name. + */ + client->query.dns64_aaaa = rdataset; + client->query.dns64_sigaaaa = sigrdataset; + client->query.dns64_ttl = rdataset->ttl; + query_releasename(client, &fname); + dns_db_detachnode(db, &node); + rdataset = NULL; + sigrdataset = NULL; + type = qtype = dns_rdatatype_a; + dns64_exclude = dns64 = ISC_TRUE; + goto db_find; + } + if (sigrdataset != NULL) sigrdatasetp = &sigrdataset; else @@ -4798,8 +6627,43 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) dns_name_equal(client->query.qname, dns_rootname)) client->query.attributes &= ~NS_QUERYATTR_NOADDITIONAL; - query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf, - DNS_SECTION_ANSWER); + if (dns64) { + qtype = type = dns_rdatatype_aaaa; + result = query_dns64(client, &fname, rdataset, + sigrdataset, dbuf, + DNS_SECTION_ANSWER); + dns_rdataset_disassociate(rdataset); + dns_message_puttemprdataset(client->message, &rdataset); + if (result == ISC_R_NOMORE) { +#ifndef dns64_bis_return_excluded_addresses + if (dns64_exclude) { + if (!is_zone) + goto cleanup; + /* + * Add a fake SOA record. + */ + result = query_addsoa(client, db, + version, 600, + ISC_FALSE); + goto cleanup; + } +#endif + if (is_zone) + goto nxrrset; + else + goto ncache_nxrrset; + } else if (result != ISC_R_SUCCESS) { + eresult = result; + goto cleanup; + } + } else if (client->query.dns64_aaaaok != NULL) { + query_filter64(client, &fname, rdataset, dbuf, + DNS_SECTION_ANSWER); + query_putrdataset(client, &rdataset); + } else + query_addrrset(client, &fname, &rdataset, + sigrdatasetp, dbuf, DNS_SECTION_ANSWER); + if (noqname != NULL) query_addnoqnameproof(client, noqname); /* @@ -4842,6 +6706,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) /* * General cleanup. */ + rpz_st = client->query.rpz_st; + if (rpz_st != NULL && (rpz_st->state & DNS_RPZ_RECURSING) == 0) + rpz_clean(&rpz_st->m.zone, &rpz_st->m.db, &rpz_st->m.node, + &rpz_st->m.rdataset); if (rdataset != NULL) query_putrdataset(client, &rdataset); if (sigrdataset != NULL) @@ -4949,6 +6817,7 @@ log_query(ns_client_t *client, unsigned int flags, unsigned int extflags) { char namebuf[DNS_NAME_FORMATSIZE]; char typename[DNS_RDATATYPE_FORMATSIZE]; char classname[DNS_RDATACLASS_FORMATSIZE]; + char onbuf[ISC_NETADDR_FORMATSIZE]; dns_rdataset_t *rdataset; int level = ISC_LOG_INFO; @@ -4960,14 +6829,18 @@ log_query(ns_client_t *client, unsigned int flags, unsigned int extflags) { dns_name_format(client->query.qname, namebuf, sizeof(namebuf)); dns_rdataclass_format(rdataset->rdclass, classname, sizeof(classname)); dns_rdatatype_format(rdataset->type, typename, sizeof(typename)); + isc_netaddr_format(&client->destaddr, onbuf, sizeof(onbuf)); ns_client_log(client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY, - level, "query: %s %s %s %s%s%s%s%s", namebuf, classname, - typename, WANTRECURSION(client) ? "+" : "-", + level, "query: %s %s %s %s%s%s%s%s%s (%s)", namebuf, + classname, typename, WANTRECURSION(client) ? "+" : "-", (client->signer != NULL) ? "S": "", (client->opt != NULL) ? "E" : "", + ((client->attributes & NS_CLIENTATTR_TCP) != 0) ? + "T" : "", ((extflags & DNS_MESSAGEEXTFLAG_DO) != 0) ? "D" : "", - ((flags & DNS_MESSAGEFLAG_CD) != 0) ? "C" : ""); + ((flags & DNS_MESSAGEFLAG_CD) != 0) ? "C" : "", + onbuf); } static inline void diff --git a/bin/named/server.c b/bin/named/server.c index bc7fc17..5bbf94b 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.c,v 1.520.12.21 2011-01-14 23:45:49 tbox Exp $ */ +/* $Id: server.c,v 1.599.8.4 2011-02-16 19:46:12 each Exp $ */ /*! \file */ @@ -23,6 +23,10 @@ #include #include +#include +#include +#include +#include #include #include @@ -36,7 +40,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -57,9 +63,11 @@ #ifdef DLZ #include #endif +#include #include #include #include +#include #include #include #include @@ -102,6 +110,10 @@ #include #endif +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + /*% * Check an operation for failure. Assumes that the function * using it has a 'result' variable and a 'cleanup' label. @@ -143,6 +155,14 @@ fatal(msg, result); \ } while (0) \ +/*% + * Maximum ADB size for views that share a cache. Use this limit to suppress + * the total of memory footprint, which should be the main reason for sharing + * a cache. Only effective when a finite max-cache-size is specified. + * This is currently defined to be 8MB. + */ +#define MAX_ADB_SIZE_FOR_CACHESHARE 8388608 + struct ns_dispatch { isc_sockaddr_t addr; unsigned int dispatchgen; @@ -150,6 +170,14 @@ struct ns_dispatch { ISC_LINK(struct ns_dispatch) link; }; +struct ns_cache { + dns_cache_t *cache; + dns_view_t *primaryview; + isc_boolean_t needflush; + isc_boolean_t adbsizeadjusted; + ISC_LINK(ns_cache_t) link; +}; + struct dumpcontext { isc_mem_t *mctx; isc_boolean_t dumpcache; @@ -176,6 +204,17 @@ struct zonelistentry { ISC_LINK(struct zonelistentry) link; }; +/*% + * Configuration context to retain for each view that allows + * new zones to be added at runtime + */ +struct cfg_context { + isc_mem_t * mctx; + cfg_obj_t * config; + cfg_parser_t * parser; + cfg_aclconfctx_t actx; +}; + /* * These zones should not leak onto the Internet. */ @@ -230,8 +269,8 @@ static const struct { { NULL, ISC_FALSE } }; -static void -fatal(const char *msg, isc_result_t result); +ISC_PLATFORM_NORETURN_PRE static void +fatal(const char *msg, isc_result_t result) ISC_PLATFORM_NORETURN_POST; static void ns_server_reload(isc_task_t *task, isc_event_t *event); @@ -256,19 +295,25 @@ configure_alternates(const cfg_obj_t *config, dns_view_t *view, static isc_result_t configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, - cfg_aclconfctx_t *aclconf); + cfg_aclconfctx_t *aclconf, isc_boolean_t added); + +static isc_result_t +add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx); static void end_reserved_dispatches(ns_server_t *server, isc_boolean_t all); +static void +cfgctx_destroy(void **cfgp); + /*% * Configure a single view ACL at '*aclp'. Get its configuration from * 'vconfig' (for per-view configuration) and maybe from 'config' */ static isc_result_t configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config, - const char *aclname, cfg_aclconfctx_t *actx, - isc_mem_t *mctx, dns_acl_t **aclp) + const char *aclname, const char *acltuplename, + cfg_aclconfctx_t *actx, isc_mem_t *mctx, dns_acl_t **aclp) { isc_result_t result; const cfg_obj_t *maps[3]; @@ -294,13 +339,21 @@ configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config, */ return (ISC_R_SUCCESS); + if (acltuplename != NULL) { + /* + * If the ACL is given in an optional tuple, retrieve it. + * The parser should have ensured that a valid object be + * returned. + */ + aclobj = cfg_tuple_get(aclobj, acltuplename); + } + result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx, actx, mctx, 0, aclp); return (result); } - /*% * Configure a sortlist at '*aclp'. Essentially the same as * configure_view_acl() except it calls cfg_acl_fromconfig with a @@ -345,8 +398,88 @@ configure_view_sortlist(const cfg_obj_t *vconfig, const cfg_obj_t *config, } static isc_result_t -configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key, - dns_keytable_t *keytable, isc_mem_t *mctx) +configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config, + const char *confname, const char *conftuplename, + isc_mem_t *mctx, dns_rbt_t **rbtp) +{ + isc_result_t result; + const cfg_obj_t *maps[3]; + const cfg_obj_t *obj = NULL; + const cfg_listelt_t *element; + int i = 0; + dns_fixedname_t fixed; + dns_name_t *name; + isc_buffer_t b; + const char *str; + const cfg_obj_t *nameobj; + + if (*rbtp != NULL) + dns_rbt_destroy(rbtp); + if (vconfig != NULL) + maps[i++] = cfg_tuple_get(vconfig, "options"); + if (config != NULL) { + const cfg_obj_t *options = NULL; + (void)cfg_map_get(config, "options", &options); + if (options != NULL) + maps[i++] = options; + } + maps[i] = NULL; + + (void)ns_config_get(maps, confname, &obj); + if (obj == NULL) + /* + * No value available. *rbtp == NULL. + */ + return (ISC_R_SUCCESS); + + if (conftuplename != NULL) { + obj = cfg_tuple_get(obj, conftuplename); + if (cfg_obj_isvoid(obj)) + return (ISC_R_SUCCESS); + } + + result = dns_rbt_create(mctx, NULL, NULL, rbtp); + if (result != ISC_R_SUCCESS) + return (result); + + dns_fixedname_init(&fixed); + name = dns_fixedname_name(&fixed); + for (element = cfg_list_first(obj); + element != NULL; + element = cfg_list_next(element)) { + nameobj = cfg_listelt_value(element); + str = cfg_obj_asstring(nameobj); + isc_buffer_init(&b, str, strlen(str)); + isc_buffer_add(&b, strlen(str)); + CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); + /* + * We don't need the node data, but need to set dummy data to + * avoid a partial match with an empty node. For example, if + * we have foo.example.com and bar.example.com, we'd get a match + * for baz.example.com, which is not the expected result. + * We simply use (void *)1 as the dummy data. + */ + result = dns_rbt_addname(*rbtp, name, (void *)1); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(nameobj, ns_g_lctx, ISC_LOG_ERROR, + "failed to add %s for %s: %s", + str, confname, isc_result_totext(result)); + goto cleanup; + } + + } + + return (result); + + cleanup: + dns_rbt_destroy(rbtp); + return (result); + +} + +static isc_result_t +dstkey_fromconfig(const cfg_obj_t *vconfig, const cfg_obj_t *key, + isc_boolean_t managed, dst_key_t **target, isc_mem_t *mctx) { dns_rdataclass_t viewclass; dns_rdata_dnskey_t keystruct; @@ -363,12 +496,28 @@ configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key, isc_result_t result; dst_key_t *dstkey = NULL; + INSIST(target != NULL && *target == NULL); + flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags")); proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol")); alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm")); keyname = dns_fixedname_name(&fkeyname); keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); + if (managed) { + const char *initmethod; + initmethod = cfg_obj_asstring(cfg_tuple_get(key, "init")); + + if (strcasecmp(initmethod, "initial-key") != 0) { + cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, + "managed key '%s': " + "invalid initialization method '%s'", + keynamestr, initmethod); + result = ISC_R_FAILURE; + goto cleanup; + } + } + if (vconfig == NULL) viewclass = dns_rdataclass_in; else { @@ -408,7 +557,8 @@ configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key, keystruct.algorithm == DST_ALG_RSAMD5) && r.length > 1 && r.base[0] == 1 && r.base[1] == 3) cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, - "trusted key '%s' has a weak exponent", + "%s key '%s' has a weak exponent", + managed ? "managed" : "trusted", keynamestr); CHECK(dns_rdata_fromstruct(NULL, @@ -418,25 +568,28 @@ configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key, dns_fixedname_init(&fkeyname); isc_buffer_init(&namebuf, keynamestr, strlen(keynamestr)); isc_buffer_add(&namebuf, strlen(keynamestr)); - CHECK(dns_name_fromtext(keyname, &namebuf, - dns_rootname, ISC_FALSE, - NULL)); + CHECK(dns_name_fromtext(keyname, &namebuf, dns_rootname, 0, NULL)); CHECK(dst_key_fromdns(keyname, viewclass, &rrdatabuf, mctx, &dstkey)); - CHECK(dns_keytable_add(keytable, &dstkey)); - INSIST(dstkey == NULL); + *target = dstkey; return (ISC_R_SUCCESS); cleanup: if (result == DST_R_NOCRYPTO) { cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, - "ignoring trusted key for '%s': no crypto support", + "ignoring %s key for '%s': no crypto support", + managed ? "managed" : "trusted", keynamestr); - result = ISC_R_SUCCESS; + } else if (result == DST_R_UNSUPPORTEDALG) { + cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, + "skipping %s key for '%s': %s", + managed ? "managed" : "trusted", + keynamestr, isc_result_totext(result)); } else { cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, - "configuring trusted key for '%s': %s", + "configuring %s key for '%s': %s", + managed ? "managed" : "trusted", keynamestr, isc_result_totext(result)); result = ISC_R_FAILURE; } @@ -447,63 +600,215 @@ configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key, return (result); } +static isc_result_t +load_view_keys(const cfg_obj_t *keys, const cfg_obj_t *vconfig, + dns_view_t *view, isc_boolean_t managed, + dns_name_t *keyname, isc_mem_t *mctx) +{ + const cfg_listelt_t *elt, *elt2; + const cfg_obj_t *key, *keylist; + dst_key_t *dstkey = NULL; + isc_result_t result; + dns_keytable_t *secroots = NULL; + + CHECK(dns_view_getsecroots(view, &secroots)); + + for (elt = cfg_list_first(keys); + elt != NULL; + elt = cfg_list_next(elt)) { + keylist = cfg_listelt_value(elt); + + for (elt2 = cfg_list_first(keylist); + elt2 != NULL; + elt2 = cfg_list_next(elt2)) { + key = cfg_listelt_value(elt2); + result = dstkey_fromconfig(vconfig, key, managed, + &dstkey, mctx); + if (result == DST_R_UNSUPPORTEDALG) { + result = ISC_R_SUCCESS; + continue; + } + if (result != ISC_R_SUCCESS) + goto cleanup; + + /* + * If keyname was specified, we only add that key. + */ + if (keyname != NULL && + !dns_name_equal(keyname, dst_key_name(dstkey))) + { + dst_key_free(&dstkey); + continue; + } + + CHECK(dns_keytable_add(secroots, managed, &dstkey)); + } + } + + cleanup: + if (dstkey != NULL) + dst_key_free(&dstkey); + if (secroots != NULL) + dns_keytable_detach(&secroots); + if (result == DST_R_NOCRYPTO) + result = ISC_R_SUCCESS; + return (result); +} + /*% - * Configure DNSSEC keys for a view. Currently used only for - * the security roots. + * Configure DNSSEC keys for a view. * * The per-view configuration values and the server-global defaults are read - * from 'vconfig' and 'config'. The variable to be configured is '*target'. + * from 'vconfig' and 'config'. */ static isc_result_t -configure_view_dnsseckeys(const cfg_obj_t *vconfig, const cfg_obj_t *config, - isc_mem_t *mctx, dns_keytable_t **target) +configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig, + const cfg_obj_t *config, const cfg_obj_t *bindkeys, + isc_boolean_t auto_dlv, isc_boolean_t auto_root, + isc_mem_t *mctx) { - isc_result_t result; - const cfg_obj_t *keys = NULL; + isc_result_t result = ISC_R_SUCCESS; + const cfg_obj_t *view_keys = NULL; + const cfg_obj_t *global_keys = NULL; + const cfg_obj_t *view_managed_keys = NULL; + const cfg_obj_t *global_managed_keys = NULL; + const cfg_obj_t *maps[4]; const cfg_obj_t *voptions = NULL; - const cfg_listelt_t *element, *element2; - const cfg_obj_t *keylist; - const cfg_obj_t *key; - dns_keytable_t *keytable = NULL; + const cfg_obj_t *options = NULL; + const cfg_obj_t *obj = NULL; + const char *directory; + int i = 0; - CHECK(dns_keytable_create(mctx, &keytable)); + /* We don't need trust anchors for the _bind view */ + if (strcmp(view->name, "_bind") == 0 && + view->rdclass == dns_rdataclass_chaos) { + return (ISC_R_SUCCESS); + } - if (vconfig != NULL) + if (vconfig != NULL) { voptions = cfg_tuple_get(vconfig, "options"); + if (voptions != NULL) { + (void) cfg_map_get(voptions, "trusted-keys", + &view_keys); + (void) cfg_map_get(voptions, "managed-keys", + &view_managed_keys); + maps[i++] = voptions; + } + } - keys = NULL; - if (voptions != NULL) - (void)cfg_map_get(voptions, "trusted-keys", &keys); - if (keys == NULL) - (void)cfg_map_get(config, "trusted-keys", &keys); + if (config != NULL) { + (void)cfg_map_get(config, "trusted-keys", &global_keys); + (void)cfg_map_get(config, "managed-keys", &global_managed_keys); + (void)cfg_map_get(config, "options", &options); + if (options != NULL) { + maps[i++] = options; + } + } - for (element = cfg_list_first(keys); - element != NULL; - element = cfg_list_next(element)) - { - keylist = cfg_listelt_value(element); - for (element2 = cfg_list_first(keylist); - element2 != NULL; - element2 = cfg_list_next(element2)) - { - key = cfg_listelt_value(element2); - CHECK(configure_view_dnsseckey(vconfig, key, - keytable, mctx)); + maps[i++] = ns_g_defaults; + maps[i] = NULL; + + result = dns_view_initsecroots(view, mctx); + if (result != ISC_R_SUCCESS) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "couldn't create keytable"); + return (ISC_R_UNEXPECTED); + } + + if (auto_dlv && view->rdclass == dns_rdataclass_in) { + const cfg_obj_t *builtin_keys = NULL; + const cfg_obj_t *builtin_managed_keys = NULL; + + isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY, + NS_LOGMODULE_SERVER, ISC_LOG_WARNING, + "using built-in DLV key for view %s", + view->name); + + /* + * If bind.keys exists, it overrides the managed-keys + * clause hard-coded in ns_g_config. + */ + if (bindkeys != NULL) { + (void)cfg_map_get(bindkeys, "trusted-keys", + &builtin_keys); + (void)cfg_map_get(bindkeys, "managed-keys", + &builtin_managed_keys); + } else { + (void)cfg_map_get(ns_g_config, "trusted-keys", + &builtin_keys); + (void)cfg_map_get(ns_g_config, "managed-keys", + &builtin_managed_keys); } + + if (builtin_keys != NULL) + CHECK(load_view_keys(builtin_keys, vconfig, view, + ISC_FALSE, view->dlv, mctx)); + if (builtin_managed_keys != NULL) + CHECK(load_view_keys(builtin_managed_keys, vconfig, + view, ISC_TRUE, view->dlv, mctx)); } - dns_keytable_detach(target); - *target = keytable; /* Transfer ownership. */ - keytable = NULL; - result = ISC_R_SUCCESS; + if (auto_root && view->rdclass == dns_rdataclass_in) { + const cfg_obj_t *builtin_keys = NULL; + const cfg_obj_t *builtin_managed_keys = NULL; - cleanup: + isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY, + NS_LOGMODULE_SERVER, ISC_LOG_WARNING, + "using built-in root key for view %s", + view->name); + + /* + * If bind.keys exists, it overrides the managed-keys + * clause hard-coded in ns_g_config. + */ + if (bindkeys != NULL) { + (void)cfg_map_get(bindkeys, "trusted-keys", + &builtin_keys); + (void)cfg_map_get(bindkeys, "managed-keys", + &builtin_managed_keys); + } else { + (void)cfg_map_get(ns_g_config, "trusted-keys", + &builtin_keys); + (void)cfg_map_get(ns_g_config, "managed-keys", + &builtin_managed_keys); + } + + if (builtin_keys != NULL) + CHECK(load_view_keys(builtin_keys, vconfig, view, + ISC_FALSE, dns_rootname, mctx)); + if (builtin_managed_keys != NULL) + CHECK(load_view_keys(builtin_managed_keys, vconfig, + view, ISC_TRUE, dns_rootname, + mctx)); + } + + CHECK(load_view_keys(view_keys, vconfig, view, ISC_FALSE, + NULL, mctx)); + CHECK(load_view_keys(view_managed_keys, vconfig, view, ISC_TRUE, + NULL, mctx)); + + if (view->rdclass == dns_rdataclass_in) { + CHECK(load_view_keys(global_keys, vconfig, view, ISC_FALSE, + NULL, mctx)); + CHECK(load_view_keys(global_managed_keys, vconfig, view, + ISC_TRUE, NULL, mctx)); + } + + /* + * Add key zone for managed-keys. + */ + obj = NULL; + (void)ns_config_get(maps, "managed-keys-directory", &obj); + directory = obj != NULL ? cfg_obj_asstring(obj) : NULL; + CHECK(add_keydata_zone(view, directory, ns_g_mctx)); + + cleanup: return (result); } static isc_result_t -mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) -{ +mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) { const cfg_listelt_t *element; const cfg_obj_t *obj; const char *str; @@ -523,8 +828,7 @@ mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) str = cfg_obj_asstring(cfg_tuple_get(obj, "name")); isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); - CHECK(dns_name_fromtext(name, &b, dns_rootname, - ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); value = cfg_obj_asboolean(cfg_tuple_get(obj, "value")); CHECK(dns_resolver_setmustbesecure(resolver, name, value)); } @@ -684,7 +988,7 @@ configure_order(dns_order_t *order, const cfg_obj_t *ent) { isc_buffer_add(&b, strlen(str)); dns_fixedname_init(&fixed); result = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) return (result); @@ -868,7 +1172,7 @@ disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) { str = cfg_obj_asstring(cfg_tuple_get(disabled, "name")); isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); - CHECK(dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); algorithms = cfg_tuple_get(disabled, "algorithms"); for (element = cfg_list_first(algorithms); @@ -921,7 +1225,7 @@ on_disable_list(const cfg_obj_t *disablelist, dns_name_t *zonename) { isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); result = dns_name_fromtext(name, &b, dns_rootname, - ISC_TRUE, NULL); + 0, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); if (dns_name_equal(name, zonename)) return (ISC_TRUE); @@ -979,6 +1283,20 @@ setquerystats(dns_zone_t *zone, isc_mem_t *mctx, isc_boolean_t on) { return (ISC_R_SUCCESS); } +static ns_cache_t * +cachelist_find(ns_cachelist_t *cachelist, const char *cachename) { + ns_cache_t *nsc; + + for (nsc = ISC_LIST_HEAD(*cachelist); + nsc != NULL; + nsc = ISC_LIST_NEXT(nsc, link)) { + if (strcmp(dns_cache_getname(nsc->cache), cachename) == 0) + return (nsc); + } + + return (NULL); +} + static isc_boolean_t cache_reusable(dns_view_t *originview, dns_view_t *view, isc_boolean_t new_zero_no_soattl) @@ -996,6 +1314,238 @@ cache_reusable(dns_view_t *originview, dns_view_t *view, return (ISC_TRUE); } +static isc_boolean_t +cache_sharable(dns_view_t *originview, dns_view_t *view, + isc_boolean_t new_zero_no_soattl, + unsigned int new_cleaning_interval, + isc_uint32_t new_max_cache_size) +{ + /* + * If the cache cannot even reused for the same view, it cannot be + * shared with other views. + */ + if (!cache_reusable(originview, view, new_zero_no_soattl)) + return (ISC_FALSE); + + /* + * Check other cache related parameters that must be consistent among + * the sharing views. + */ + if (dns_cache_getcleaninginterval(originview->cache) != + new_cleaning_interval || + dns_cache_getcachesize(originview->cache) != new_max_cache_size) { + return (ISC_FALSE); + } + + return (ISC_TRUE); +} + +#ifdef DLZ +/* + * Callback from DLZ configure when the driver sets up a writeable zone + */ +static isc_result_t +dlzconfigure_callback(dns_view_t *view, dns_zone_t *zone) { + dns_name_t *origin = dns_zone_getorigin(zone); + dns_rdataclass_t zclass = view->rdclass; + isc_result_t result; + + result = dns_zonemgr_managezone(ns_g_server->zonemgr, zone); + if (result != ISC_R_SUCCESS) + return result; + dns_zone_setstats(zone, ns_g_server->zonestats); + + return ns_zone_configure_writeable_dlz(view->dlzdatabase, + zone, zclass, origin); +} +#endif + +static isc_result_t +dns64_reverse(dns_view_t *view, isc_mem_t *mctx, isc_netaddr_t *na, + unsigned int prefixlen, const char *server, + const char *contact) +{ + char *cp; + char reverse[48+sizeof("ip6.arpa.")]; + const char *dns64_dbtype[4] = { "_builtin", "dns64", ".", "." }; + const char *sep = ": view "; + const char *viewname = view->name; + const unsigned char *s6; + dns_fixedname_t fixed; + dns_name_t *name; + dns_zone_t *zone = NULL; + int dns64_dbtypec = 4; + isc_buffer_t b; + isc_result_t result; + + REQUIRE(prefixlen == 32 || prefixlen == 40 || prefixlen == 48 || + prefixlen == 56 || prefixlen == 64 || prefixlen == 96); + + if (!strcmp(viewname, "_default")) { + sep = ""; + viewname = ""; + } + + /* + * Construct the reverse name of the zone. + */ + cp = reverse; + s6 = na->type.in6.s6_addr; + while (prefixlen > 0) { + prefixlen -= 8; + sprintf(cp, "%x.%x.", s6[prefixlen/8] & 0xf, + (s6[prefixlen/8] >> 4) & 0xf); + cp += 4; + } + strcat(cp, "ip6.arpa."); + + /* + * Create the actual zone. + */ + if (server != NULL) + dns64_dbtype[2] = server; + if (contact != NULL) + dns64_dbtype[3] = contact; + dns_fixedname_init(&fixed); + name = dns_fixedname_name(&fixed); + isc_buffer_init(&b, reverse, strlen(reverse)); + isc_buffer_add(&b, strlen(reverse)); + CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); + CHECK(dns_zone_create(&zone, mctx)); + CHECK(dns_zone_setorigin(zone, name)); + dns_zone_setview(zone, view); + CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone)); + dns_zone_setclass(zone, view->rdclass); + dns_zone_settype(zone, dns_zone_master); + dns_zone_setstats(zone, ns_g_server->zonestats); + CHECK(dns_zone_setdbtype(zone, dns64_dbtypec, dns64_dbtype)); + if (view->queryacl != NULL) + dns_zone_setqueryacl(zone, view->queryacl); + if (view->queryonacl != NULL) + dns_zone_setqueryonacl(zone, view->queryonacl); + dns_zone_setdialup(zone, dns_dialuptype_no); + dns_zone_setnotifytype(zone, dns_notifytype_no); + dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, ISC_TRUE); + CHECK(setquerystats(zone, mctx, ISC_FALSE)); /* XXXMPA */ + CHECK(dns_view_addzone(view, zone)); + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, + ISC_LOG_INFO, "dns64 reverse zone%s%s: %s", sep, + viewname, reverse); + +cleanup: + if (zone != NULL) + dns_zone_detach(&zone); + return (result); +} + +static isc_result_t +configure_rpz(dns_view_t *view, const cfg_listelt_t *element) { + const cfg_obj_t *rpz_obj, *policy_obj; + const char *str; + dns_fixedname_t fixed; + dns_name_t *origin; + dns_rpz_zone_t *old, *new; + dns_zone_t *zone = NULL; + isc_result_t result; + unsigned int l1, l2; + + new = isc_mem_get(view->mctx, sizeof(*new)); + if (new == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + + memset(new, 0, sizeof(*new)); + dns_name_init(&new->nsdname, NULL); + dns_name_init(&new->origin, NULL); + dns_name_init(&new->cname, NULL); + ISC_LIST_INITANDAPPEND(view->rpz_zones, new, link); + + rpz_obj = cfg_listelt_value(element); + policy_obj = cfg_tuple_get(rpz_obj, "policy"); + if (cfg_obj_isvoid(policy_obj)) { + new->policy = DNS_RPZ_POLICY_GIVEN; + } else { + str = cfg_obj_asstring(policy_obj); + new->policy = dns_rpz_str2policy(str); + INSIST(new->policy != DNS_RPZ_POLICY_ERROR); + } + + dns_fixedname_init(&fixed); + origin = dns_fixedname_name(&fixed); + str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "name")); + result = dns_name_fromstring(origin, str, DNS_NAME_DOWNCASE, NULL); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, + "invalid zone '%s'", str); + goto cleanup; + } + + result = dns_name_fromstring2(&new->nsdname, DNS_RPZ_NSDNAME_ZONE, + origin, DNS_NAME_DOWNCASE, view->mctx); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, + "invalid zone '%s'", str); + goto cleanup; + } + + /* + * The origin is part of 'nsdname' so we don't need to keep it + * seperately. + */ + l1 = dns_name_countlabels(&new->nsdname); + l2 = dns_name_countlabels(origin); + dns_name_getlabelsequence(&new->nsdname, l1 - l2, l2, &new->origin); + + /* + * Are we configured to with the reponse policy zone? + */ + result = dns_view_findzone(view, &new->origin, &zone); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, + "unknown zone '%s'", str); + goto cleanup; + } + + if (dns_zone_gettype(zone) != dns_zone_master && + dns_zone_gettype(zone) != dns_zone_slave) { + cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, + "zone '%s' is neither master nor slave", str); + dns_zone_detach(&zone); + result = DNS_R_NOTMASTER; + goto cleanup; + } + dns_zone_detach(&zone); + + for (old = ISC_LIST_HEAD(view->rpz_zones); + old != new; + old = ISC_LIST_NEXT(old, link)) { + ++new->num; + if (dns_name_equal(&old->origin, &new->origin)) { + cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, + "duplicate '%s'", str); + result = DNS_R_DUPLICATE; + goto cleanup; + } + } + + if (new->policy == DNS_RPZ_POLICY_CNAME) { + str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "cname")); + result = dns_name_fromstring(&new->cname, str, 0, view->mctx); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, + "invalid cname '%s'", str); + goto cleanup; + } + } + + return (ISC_R_SUCCESS); + + cleanup: + dns_rpz_view_destroy(view); + return (result); +} + /* * Configure 'view' according to 'vconfig', taking defaults from 'config' * where values are missing in 'vconfig'. @@ -1004,12 +1554,15 @@ cache_reusable(dns_view_t *originview, dns_view_t *view, * global defaults in 'config' used exclusively. */ static isc_result_t -configure_view(dns_view_t *view, const cfg_obj_t *config, - const cfg_obj_t *vconfig, isc_mem_t *mctx, - cfg_aclconfctx_t *actx, isc_boolean_t need_hints) +configure_view(dns_view_t *view, cfg_parser_t* parser, + cfg_obj_t *config, cfg_obj_t *vconfig, + ns_cachelist_t *cachelist, const cfg_obj_t *bindkeys, + isc_mem_t *mctx, cfg_aclconfctx_t *actx, + isc_boolean_t need_hints) { const cfg_obj_t *maps[4]; const cfg_obj_t *cfgmaps[3]; + const cfg_obj_t *optionmaps[3]; const cfg_obj_t *options = NULL; const cfg_obj_t *voptions = NULL; const cfg_obj_t *forwardtype; @@ -1028,17 +1581,20 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, dns_cache_t *cache = NULL; isc_result_t result; isc_uint32_t max_adb_size; + unsigned int cleaning_interval; isc_uint32_t max_cache_size; isc_uint32_t max_acache_size; isc_uint32_t lame_ttl; - dns_tsig_keyring_t *ring; + dns_tsig_keyring_t *ring = NULL; dns_view_t *pview = NULL; /* Production view */ isc_mem_t *cmctx; dns_dispatch_t *dispatch4 = NULL; dns_dispatch_t *dispatch6 = NULL; isc_boolean_t reused_cache = ISC_FALSE; - int i; + isc_boolean_t shared_cache = ISC_FALSE; + int i = 0, j = 0, k = 0; const char *str; + const char *cachename = NULL; dns_order_t *order = NULL; isc_uint32_t udpsize; unsigned int resopts = 0; @@ -1052,7 +1608,14 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, const cfg_obj_t *disablelist = NULL; isc_stats_t *resstats = NULL; dns_stats_t *resquerystats = NULL; + isc_boolean_t auto_dlv = ISC_FALSE; + isc_boolean_t auto_root = ISC_FALSE; + ns_cache_t *nsc; isc_boolean_t zero_no_soattl; + cfg_parser_t *newzones_parser = NULL; + cfg_obj_t *nzfconf = NULL; + dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL; + unsigned int query_timeout; REQUIRE(DNS_VIEW_VALID(view)); @@ -1061,22 +1624,28 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, if (config != NULL) (void)cfg_map_get(config, "options", &options); - i = 0; + /* + * maps: view options, options, defaults + * cfgmaps: view options, config + * optionmaps: view options, options + */ if (vconfig != NULL) { voptions = cfg_tuple_get(vconfig, "options"); maps[i++] = voptions; + optionmaps[j++] = voptions; + cfgmaps[k++] = voptions; } - if (options != NULL) + if (options != NULL) { maps[i++] = options; + optionmaps[j++] = options; + } + maps[i++] = ns_g_defaults; maps[i] = NULL; - - i = 0; - if (voptions != NULL) - cfgmaps[i++] = voptions; + optionmaps[j] = NULL; if (config != NULL) - cfgmaps[i++] = config; - cfgmaps[i] = NULL; + cfgmaps[k++] = config; + cfgmaps[k] = NULL; if (!strcmp(viewname, "_default")) { sep = ""; @@ -1137,12 +1706,12 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, dns_acache_setcachesize(view->acache, max_acache_size); } - CHECK(configure_view_acl(vconfig, config, "allow-query", actx, + CHECK(configure_view_acl(vconfig, config, "allow-query", NULL, actx, ns_g_mctx, &view->queryacl)); - if (view->queryacl == NULL) { - CHECK(configure_view_acl(NULL, ns_g_config, "allow-query", actx, - ns_g_mctx, &view->queryacl)); + CHECK(configure_view_acl(NULL, ns_g_config, "allow-query", + NULL, actx, ns_g_mctx, + &view->queryacl)); } /* @@ -1159,7 +1728,62 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, { const cfg_obj_t *zconfig = cfg_listelt_value(element); CHECK(configure_zone(config, zconfig, vconfig, mctx, view, - actx)); + actx, ISC_FALSE)); + } + + /* + * Are we allowing zones to be added and deleted dynamically? + */ + obj = NULL; + result = ns_config_get(maps, "allow-new-zones", &obj); + if (result == ISC_R_SUCCESS) { + isc_boolean_t allow = cfg_obj_asboolean(obj); + struct cfg_context *cfg = NULL; + if (allow) { + cfg = isc_mem_get(view->mctx, sizeof(*cfg)); + if (cfg == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + memset(cfg, 0, sizeof(*cfg)); + isc_mem_attach(view->mctx, &cfg->mctx); + if (config != NULL) + cfg_obj_attach(config, &cfg->config); + cfg_parser_attach(parser, &cfg->parser); + cfg_aclconfctx_clone(actx, &cfg->actx); + } + dns_view_setnewzones(view, allow, cfg, cfgctx_destroy); + } + + /* + * If we're allowing added zones, then load zone configuration + * from the newzone file for zones that were added during previous + * runs. + */ + if (view->new_zone_file != NULL) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "loading additional zones for view '%s'", + view->name); + + CHECK(cfg_parser_create(view->mctx, ns_g_lctx, + &newzones_parser)); + result = cfg_parse_file(newzones_parser, view->new_zone_file, + &cfg_type_newzones, &nzfconf); + if (result == ISC_R_SUCCESS) { + zonelist = NULL; + cfg_map_get(nzfconf, "zone", &zonelist); + for (element = cfg_list_first(zonelist); + element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *zconfig = + cfg_listelt_value(element); + CHECK(configure_zone(config, zconfig, vconfig, + mctx, view, actx, + ISC_TRUE)); + } + } } #ifdef DLZ @@ -1197,6 +1821,14 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, isc_mem_put(mctx, dlzargv, dlzargc * sizeof(*dlzargv)); if (result != ISC_R_SUCCESS) goto cleanup; + + /* + * If the dlz backend supports configuration, + * then call its configure method now. + */ + result = dns_dlzconfigure(view, dlzconfigure_callback); + if (result != ISC_R_SUCCESS) + goto cleanup; } } #endif @@ -1205,6 +1837,32 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, * Obtain configuration parameters that affect the decision of whether * we can reuse/share an existing cache. */ + obj = NULL; + result = ns_config_get(maps, "cleaning-interval", &obj); + INSIST(result == ISC_R_SUCCESS); + cleaning_interval = cfg_obj_asuint32(obj) * 60; + + obj = NULL; + result = ns_config_get(maps, "max-cache-size", &obj); + INSIST(result == ISC_R_SUCCESS); + if (cfg_obj_isstring(obj)) { + str = cfg_obj_asstring(obj); + INSIST(strcasecmp(str, "unlimited") == 0); + max_cache_size = ISC_UINT32_MAX; + } else { + isc_resourcevalue_t value; + value = cfg_obj_asuint64(obj); + if (value > ISC_UINT32_MAX) { + cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, + "'max-cache-size " + "%" ISC_PRINT_QUADFORMAT "d' is too large", + value); + result = ISC_R_RANGE; + goto cleanup; + } + max_cache_size = (isc_uint32_t)value; + } + /* Check-names. */ obj = NULL; result = ns_checknames_get(maps, "response", &obj); @@ -1229,6 +1887,109 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, zero_no_soattl = cfg_obj_asboolean(obj); obj = NULL; + result = ns_config_get(maps, "dns64", &obj); + if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") && + strcmp(view->name, "_meta")) { + const cfg_listelt_t *element; + isc_netaddr_t na, suffix, *sp; + unsigned int prefixlen; + const char *server, *contact; + const cfg_obj_t *myobj; + + myobj = NULL; + result = ns_config_get(maps, "dns64-server", &myobj); + if (result == ISC_R_SUCCESS) + server = cfg_obj_asstring(myobj); + else + server = NULL; + + myobj = NULL; + result = ns_config_get(maps, "dns64-contact", &myobj); + if (result == ISC_R_SUCCESS) + contact = cfg_obj_asstring(myobj); + else + contact = NULL; + + for (element = cfg_list_first(obj); + element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *map = cfg_listelt_value(element); + dns_dns64_t *dns64 = NULL; + unsigned int dns64options = 0; + + cfg_obj_asnetprefix(cfg_map_getname(map), &na, + &prefixlen); + + obj = NULL; + (void)cfg_map_get(map, "suffix", &obj); + if (obj != NULL) { + sp = &suffix; + isc_netaddr_fromsockaddr(sp, + cfg_obj_assockaddr(obj)); + } else + sp = NULL; + + clients = mapped = excluded = NULL; + obj = NULL; + (void)cfg_map_get(map, "clients", &obj); + if (obj != NULL) { + result = cfg_acl_fromconfig(obj, config, + ns_g_lctx, actx, + mctx, 0, &clients); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + obj = NULL; + (void)cfg_map_get(map, "mapped", &obj); + if (obj != NULL) { + result = cfg_acl_fromconfig(obj, config, + ns_g_lctx, actx, + mctx, 0, &mapped); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + obj = NULL; + (void)cfg_map_get(map, "exclude", &obj); + if (obj != NULL) { + result = cfg_acl_fromconfig(obj, config, + ns_g_lctx, actx, + mctx, 0, &excluded); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + + obj = NULL; + (void)cfg_map_get(map, "recursive-only", &obj); + if (obj != NULL && cfg_obj_asboolean(obj)) + dns64options |= DNS_DNS64_RECURSIVE_ONLY; + + obj = NULL; + (void)cfg_map_get(map, "break-dnssec", &obj); + if (obj != NULL && cfg_obj_asboolean(obj)) + dns64options |= DNS_DNS64_BREAK_DNSSEC; + + result = dns_dns64_create(mctx, &na, prefixlen, sp, + clients, mapped, excluded, + dns64options, &dns64); + if (result != ISC_R_SUCCESS) + goto cleanup; + dns_dns64_append(&view->dns64, dns64); + view->dns64cnt++; + result = dns64_reverse(view, mctx, &na, prefixlen, + server, contact); + if (result != ISC_R_SUCCESS) + goto cleanup; + if (clients != NULL) + dns_acl_detach(&clients); + if (mapped != NULL) + dns_acl_detach(&mapped); + if (excluded != NULL) + dns_acl_detach(&excluded); + } + } + + obj = NULL; result = ns_config_get(maps, "dnssec-accept-expired", &obj); INSIST(result == ISC_R_SUCCESS); view->acceptexpired = cfg_obj_asboolean(obj); @@ -1236,7 +1997,13 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, obj = NULL; result = ns_config_get(maps, "dnssec-validation", &obj); INSIST(result == ISC_R_SUCCESS); - view->enablevalidation = cfg_obj_asboolean(obj); + if (cfg_obj_isboolean(obj)) { + view->enablevalidation = cfg_obj_asboolean(obj); + } else { + /* If dnssec-validation is not boolean, it must be "auto" */ + view->enablevalidation = ISC_TRUE; + auto_root = ISC_TRUE; + } obj = NULL; result = ns_config_get(maps, "max-cache-ttl", &obj); @@ -1251,53 +2018,113 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, view->maxncachettl = 7 * 24 * 3600; /* - * Configure the view's cache. Try to reuse an existing - * cache if possible, otherwise create a new cache. - * Note that the ADB is not preserved in either case. - * When a matching view is found, the associated statistics are - * also retrieved and reused. + * Configure the view's cache. + * + * First, check to see if there are any attach-cache options. If yes, + * attempt to lookup an existing cache at attach it to the view. If + * there is not one, then try to reuse an existing cache if possible; + * otherwise create a new cache. * - * XXX Determining when it is safe to reuse a cache is tricky. + * Note that the ADB is not preserved or shared in either case. + * + * When a matching view is found, the associated statistics are also + * retrieved and reused. + * + * XXX Determining when it is safe to reuse or share a cache is tricky. * When the view's configuration changes, the cached data may become * invalid because it reflects our old view of the world. We check - * some of the configuration parameters that could invalidate the cache, - * but there are other configuration options that should be checked. - * For example, if a view uses a forwarder, changes in the forwarder - * configuration may invalidate the cache. At the moment, it's the - * administrator's responsibility to ensure these configuration options - * don't invalidate reusing. + * some of the configuration parameters that could invalidate the cache + * or otherwise make it unsharable, but there are other configuration + * options that should be checked. For example, if a view uses a + * forwarder, changes in the forwarder configuration may invalidate + * the cache. At the moment, it's the administrator's responsibility to + * ensure these configuration options don't invalidate reusing/sharing. */ - result = dns_viewlist_find(&ns_g_server->viewlist, - view->name, view->rdclass, - &pview); - if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) - goto cleanup; - if (pview != NULL) { - if (cache_reusable(pview, view, zero_no_soattl)) { - INSIST(pview->cache != NULL); - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, - NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(3), - "reusing existing cache"); - reused_cache = ISC_TRUE; - dns_cache_attach(pview->cache, &cache); - } else { + obj = NULL; + result = ns_config_get(maps, "attach-cache", &obj); + if (result == ISC_R_SUCCESS) + cachename = cfg_obj_asstring(obj); + else + cachename = view->name; + cache = NULL; + nsc = cachelist_find(cachelist, cachename); + if (nsc != NULL) { + if (!cache_sharable(nsc->primaryview, view, zero_no_soattl, + cleaning_interval, max_cache_size)) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, - NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), - "cache cannot be reused for view %s " + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "views %s and %s can't share the cache " "due to configuration parameter mismatch", - view->name); + nsc->primaryview->name, view->name); + result = ISC_R_FAILURE; + goto cleanup; } - dns_view_getresstats(pview, &resstats); - dns_view_getresquerystats(pview, &resquerystats); - dns_view_detach(&pview); - } - if (cache == NULL) { - CHECK(isc_mem_create(0, 0, &cmctx)); - CHECK(dns_cache_create(cmctx, ns_g_taskmgr, ns_g_timermgr, - view->rdclass, "rbt", 0, NULL, &cache)); - isc_mem_setname(cmctx, "cache", NULL); + dns_cache_attach(nsc->cache, &cache); + shared_cache = ISC_TRUE; + } else { + if (strcmp(cachename, view->name) == 0) { + result = dns_viewlist_find(&ns_g_server->viewlist, + cachename, view->rdclass, + &pview); + if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) + goto cleanup; + if (pview != NULL) { + if (!cache_reusable(pview, view, + zero_no_soattl)) { + isc_log_write(ns_g_lctx, + NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, + ISC_LOG_DEBUG(1), + "cache cannot be reused " + "for view %s due to " + "configuration parameter " + "mismatch", view->name); + } else { + INSIST(pview->cache != NULL); + isc_log_write(ns_g_lctx, + NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, + ISC_LOG_DEBUG(3), + "reusing existing cache"); + reused_cache = ISC_TRUE; + dns_cache_attach(pview->cache, &cache); + } + dns_view_getresstats(pview, &resstats); + dns_view_getresquerystats(pview, + &resquerystats); + dns_view_detach(&pview); + } + } + if (cache == NULL) { + /* + * Create a cache with the desired name. This normally + * equals the view name, but may also be a forward + * reference to a view that share the cache with this + * view but is not yet configured. If it is not the + * view name but not a forward reference either, then it + * is simply a named cache that is not shared. + */ + CHECK(isc_mem_create(0, 0, &cmctx)); + isc_mem_setname(cmctx, "cache", NULL); + CHECK(dns_cache_create2(cmctx, ns_g_taskmgr, + ns_g_timermgr, view->rdclass, + cachename, "rbt", 0, NULL, + &cache)); + } + nsc = isc_mem_get(mctx, sizeof(*nsc)); + if (nsc == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + nsc->cache = NULL; + dns_cache_attach(cache, &nsc->cache); + nsc->primaryview = view; + nsc->needflush = ISC_FALSE; + nsc->adbsizeadjusted = ISC_FALSE; + ISC_LINK_INIT(nsc, link); + ISC_LIST_APPEND(*cachelist, nsc, link); } - dns_view_setcache(view, cache); + dns_view_setcache2(view, cache, shared_cache); /* * cache-file cannot be inherited if views are present, but this @@ -1307,35 +2134,11 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, result = ns_config_get(maps, "cache-file", &obj); if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) { CHECK(dns_cache_setfilename(cache, cfg_obj_asstring(obj))); - if (!reused_cache) + if (!reused_cache && !shared_cache) CHECK(dns_cache_load(cache)); } - obj = NULL; - result = ns_config_get(maps, "cleaning-interval", &obj); - INSIST(result == ISC_R_SUCCESS); - dns_cache_setcleaninginterval(cache, cfg_obj_asuint32(obj) * 60); - - obj = NULL; - result = ns_config_get(maps, "max-cache-size", &obj); - INSIST(result == ISC_R_SUCCESS); - if (cfg_obj_isstring(obj)) { - str = cfg_obj_asstring(obj); - INSIST(strcasecmp(str, "unlimited") == 0); - max_cache_size = ISC_UINT32_MAX; - } else { - isc_resourcevalue_t value; - value = cfg_obj_asuint64(obj); - if (value > ISC_UINT32_MAX) { - cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, - "'max-cache-size " - "%" ISC_PRINT_QUADFORMAT "d' is too large", - value); - result = ISC_R_RANGE; - goto cleanup; - } - max_cache_size = (isc_uint32_t)value; - } + dns_cache_setcleaninginterval(cache, cleaning_interval); dns_cache_setcachesize(cache, max_cache_size); dns_cache_detach(&cache); @@ -1373,13 +2176,23 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, dns_view_setresquerystats(view, resquerystats); /* - * Set the ADB cache size to 1/8th of the max-cache-size. + * Set the ADB cache size to 1/8th of the max-cache-size or + * MAX_ADB_SIZE_FOR_CACHESHARE when the cache is shared. */ max_adb_size = 0; if (max_cache_size != 0) { max_adb_size = max_cache_size / 8; if (max_adb_size == 0) max_adb_size = 1; /* Force minimum. */ + if (view != nsc->primaryview && + max_adb_size > MAX_ADB_SIZE_FOR_CACHESHARE) { + max_adb_size = MAX_ADB_SIZE_FOR_CACHESHARE; + if (!nsc->adbsizeadjusted) { + dns_adb_setadbsize(nsc->primaryview->adb, + MAX_ADB_SIZE_FOR_CACHESHARE); + nsc->adbsizeadjusted = ISC_TRUE; + } + } } dns_adb_setadbsize(view->adb, max_adb_size); @@ -1395,6 +2208,18 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, dns_resolver_setlamettl(view->resolver, lame_ttl); /* + * Set the resolver's query timeout. + */ + obj = NULL; + result = ns_config_get(maps, "resolver-query-timeout", &obj); + INSIST(result == ISC_R_SUCCESS); + query_timeout = cfg_obj_asuint32(obj); + dns_resolver_settimeout(view->resolver, query_timeout); + + /* Specify whether to use 0-TTL for negative response for SOA query */ + dns_resolver_setzeronosoattl(view->resolver, zero_no_soattl); + + /* * Set the resolver's EDNS UDP size. */ obj = NULL; @@ -1482,11 +2307,31 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, } /* - * Configure the view's TSIG keys. + * Configure the view's TSIG keys. + */ + CHECK(ns_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring)); + if (ns_g_server->sessionkey != NULL) { + CHECK(dns_tsigkeyring_add(ring, ns_g_server->session_keyname, + ns_g_server->sessionkey)); + } + dns_view_setkeyring(view, ring); + dns_tsigkeyring_detach(&ring); + + /* + * See if we can re-use a dynamic key ring. */ - ring = NULL; - CHECK(ns_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring)); - dns_view_setkeyring(view, ring); + result = dns_viewlist_find(&ns_g_server->viewlist, view->name, + view->rdclass, &pview); + if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) + goto cleanup; + if (pview != NULL) { + dns_view_getdynamickeyring(pview, &ring); + if (ring != NULL) + dns_view_setdynamickeyring(view, ring); + dns_tsigkeyring_detach(&ring); + dns_view_detach(&pview); + } else + dns_view_restorekeyring(view); /* * Configure the view's peer list. @@ -1543,10 +2388,10 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, /* * Configure the "match-clients" and "match-destinations" ACL. */ - CHECK(configure_view_acl(vconfig, config, "match-clients", actx, + CHECK(configure_view_acl(vconfig, config, "match-clients", NULL, actx, ns_g_mctx, &view->matchclients)); - CHECK(configure_view_acl(vconfig, config, "match-destinations", actx, - ns_g_mctx, &view->matchdestinations)); + CHECK(configure_view_acl(vconfig, config, "match-destinations", NULL, + actx, ns_g_mctx, &view->matchdestinations)); /* * Configure the "match-recursive-only" option. @@ -1618,20 +2463,20 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, * "allow-recursion", and "allow-recursion-on" acls if * configured in named.conf. */ - CHECK(configure_view_acl(vconfig, config, "allow-query-cache", + CHECK(configure_view_acl(vconfig, config, "allow-query-cache", NULL, actx, ns_g_mctx, &view->cacheacl)); - CHECK(configure_view_acl(vconfig, config, "allow-query-cache-on", + CHECK(configure_view_acl(vconfig, config, "allow-query-cache-on", NULL, actx, ns_g_mctx, &view->cacheonacl)); if (view->cacheonacl == NULL) CHECK(configure_view_acl(NULL, ns_g_config, - "allow-query-cache-on", actx, + "allow-query-cache-on", NULL, actx, ns_g_mctx, &view->cacheonacl)); if (strcmp(view->name, "_bind") != 0) { CHECK(configure_view_acl(vconfig, config, "allow-recursion", - actx, ns_g_mctx, + NULL, actx, ns_g_mctx, &view->recursionacl)); CHECK(configure_view_acl(vconfig, config, "allow-recursion-on", - actx, ns_g_mctx, + NULL, actx, ns_g_mctx, &view->recursiononacl)); } @@ -1643,8 +2488,14 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, */ if (view->cacheacl == NULL && view->recursionacl != NULL) dns_acl_attach(view->recursionacl, &view->cacheacl); + /* + * XXXEACH: This call to configure_view_acl() is redundant. We + * are leaving it as it is because we are making a minimal change + * for a patch release. In the future this should be changed to + * dns_acl_attach(view->queryacl, &view->cacheacl). + */ if (view->cacheacl == NULL && view->recursion) - CHECK(configure_view_acl(vconfig, config, "allow-query", + CHECK(configure_view_acl(vconfig, config, "allow-query", NULL, actx, ns_g_mctx, &view->cacheacl)); if (view->recursion && view->recursionacl == NULL && view->cacheacl != NULL) @@ -1656,24 +2507,44 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, */ if (view->recursionacl == NULL && view->recursion) CHECK(configure_view_acl(NULL, ns_g_config, - "allow-recursion", + "allow-recursion", NULL, actx, ns_g_mctx, &view->recursionacl)); if (view->recursiononacl == NULL && view->recursion) CHECK(configure_view_acl(NULL, ns_g_config, - "allow-recursion-on", + "allow-recursion-on", NULL, actx, ns_g_mctx, &view->recursiononacl)); if (view->cacheacl == NULL) { if (view->recursion) CHECK(configure_view_acl(NULL, ns_g_config, - "allow-query-cache", actx, - ns_g_mctx, &view->cacheacl)); + "allow-query-cache", NULL, + actx, ns_g_mctx, + &view->cacheacl)); else - CHECK(dns_acl_none(ns_g_mctx, &view->cacheacl)); + CHECK(dns_acl_none(mctx, &view->cacheacl)); } /* + * Filter setting on addresses in the answer section. + */ + CHECK(configure_view_acl(vconfig, config, "deny-answer-addresses", + "acl", actx, ns_g_mctx, &view->denyansweracl)); + CHECK(configure_view_nametable(vconfig, config, "deny-answer-addresses", + "except-from", ns_g_mctx, + &view->answeracl_exclude)); + + /* + * Filter setting on names (CNAME/DNAME targets) in the answer section. + */ + CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases", + "name", ns_g_mctx, + &view->denyanswernames)); + CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases", + "except-from", ns_g_mctx, + &view->answernames_exclude)); + + /* * Configure sortlist, if set */ CHECK(configure_view_sortlist(vconfig, config, actx, ns_g_mctx, @@ -1686,19 +2557,19 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, */ if (view->notifyacl == NULL) CHECK(configure_view_acl(NULL, ns_g_config, - "allow-notify", actx, + "allow-notify", NULL, actx, ns_g_mctx, &view->notifyacl)); if (view->transferacl == NULL) CHECK(configure_view_acl(NULL, ns_g_config, - "allow-transfer", actx, + "allow-transfer", NULL, actx, ns_g_mctx, &view->transferacl)); if (view->updateacl == NULL) CHECK(configure_view_acl(NULL, ns_g_config, - "allow-update", actx, + "allow-update", NULL, actx, ns_g_mctx, &view->updateacl)); if (view->upfwdacl == NULL) CHECK(configure_view_acl(NULL, ns_g_config, - "allow-update-forwarding", actx, + "allow-update-forwarding", NULL, actx, ns_g_mctx, &view->upfwdacl)); obj = NULL; @@ -1728,13 +2599,47 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, cfg_obj_asuint32(obj), max_clients_per_query); +#ifdef ALLOW_FILTER_AAAA_ON_V4 + obj = NULL; + result = ns_config_get(maps, "filter-aaaa-on-v4", &obj); + INSIST(result == ISC_R_SUCCESS); + if (cfg_obj_isboolean(obj)) { + if (cfg_obj_asboolean(obj)) + view->v4_aaaa = dns_v4_aaaa_filter; + else + view->v4_aaaa = dns_v4_aaaa_ok; + } else { + const char *v4_aaaastr = cfg_obj_asstring(obj); + if (strcasecmp(v4_aaaastr, "break-dnssec") == 0) + view->v4_aaaa = dns_v4_aaaa_break_dnssec; + else + INSIST(0); + } + CHECK(configure_view_acl(vconfig, config, "filter-aaaa", NULL, + actx, ns_g_mctx, &view->v4_aaaa_acl)); +#endif + obj = NULL; result = ns_config_get(maps, "dnssec-enable", &obj); INSIST(result == ISC_R_SUCCESS); view->enablednssec = cfg_obj_asboolean(obj); obj = NULL; - result = ns_config_get(maps, "dnssec-lookaside", &obj); + result = ns_config_get(optionmaps, "dnssec-lookaside", &obj); + if (result == ISC_R_SUCCESS) { + /* If set to "auto", use the version from the defaults */ + const cfg_obj_t *dlvobj; + dlvobj = cfg_listelt_value(cfg_list_first(obj)); + if (!strcmp(cfg_obj_asstring(cfg_tuple_get(dlvobj, "domain")), + "auto") && + cfg_obj_isvoid(cfg_tuple_get(dlvobj, "trust-anchor"))) { + auto_dlv = ISC_TRUE; + obj = NULL; + result = cfg_map_get(ns_g_defaults, + "dnssec-lookaside", &obj); + } + } + if (result == ISC_R_SUCCESS) { for (element = cfg_list_first(obj); element != NULL; @@ -1745,31 +2650,13 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, dns_name_t *dlv; obj = cfg_listelt_value(element); -#if 0 - dns_fixedname_t fixed; - dns_name_t *name; - - /* - * When we support multiple dnssec-lookaside - * entries this is how to find the domain to be - * checked. XXXMPA - */ - dns_fixedname_init(&fixed); - name = dns_fixedname_name(&fixed); - str = cfg_obj_asstring(cfg_tuple_get(obj, - "domain")); - isc_buffer_init(&b, str, strlen(str)); - isc_buffer_add(&b, strlen(str)); - CHECK(dns_name_fromtext(name, &b, dns_rootname, - ISC_TRUE, NULL)); -#endif str = cfg_obj_asstring(cfg_tuple_get(obj, "trust-anchor")); isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); dlv = dns_fixedname_name(&view->dlv_fixed); CHECK(dns_name_fromtext(dlv, &b, dns_rootname, - ISC_TRUE, NULL)); + DNS_NAME_DOWNCASE, NULL)); view->dlv = dns_fixedname_name(&view->dlv_fixed); } } else @@ -1779,8 +2666,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, * For now, there is only one kind of trusted keys, the * "security roots". */ - CHECK(configure_view_dnsseckeys(vconfig, config, mctx, - &view->secroots)); + CHECK(configure_view_dnsseckeys(view, vconfig, config, bindkeys, + auto_dlv, auto_root, mctx)); dns_resolver_resetmustbesecure(view->resolver); obj = NULL; result = ns_config_get(maps, "dnssec-must-be-secure", &obj); @@ -1821,7 +2708,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); CHECK(dns_name_fromtext(name, &b, dns_rootname, - ISC_FALSE, NULL)); + 0, NULL)); CHECK(dns_view_excludedelegationonly(view, name)); } @@ -1874,8 +2761,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, str = cfg_obj_asstring(obj); isc_buffer_init(&buffer, str, strlen(str)); isc_buffer_add(&buffer, strlen(str)); - CHECK(dns_name_fromtext(name, &buffer, dns_rootname, - ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, + NULL)); isc_buffer_init(&buffer, server, sizeof(server) - 1); CHECK(dns_name_totext(name, ISC_FALSE, &buffer)); server[isc_buffer_usedlength(&buffer)] = 0; @@ -1889,8 +2776,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, str = cfg_obj_asstring(obj); isc_buffer_init(&buffer, str, strlen(str)); isc_buffer_add(&buffer, strlen(str)); - CHECK(dns_name_fromtext(name, &buffer, dns_rootname, - ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, + NULL)); isc_buffer_init(&buffer, contact, sizeof(contact) - 1); CHECK(dns_name_totext(name, ISC_FALSE, &buffer)); contact[isc_buffer_usedlength(&buffer)] = 0; @@ -1916,8 +2803,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, /* * Look for zone on drop list. */ - CHECK(dns_name_fromtext(name, &buffer, dns_rootname, - ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, + NULL)); if (disablelist != NULL && on_disable_list(disablelist, name)) continue; @@ -2012,9 +2899,40 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, } } + /* + * Make the list of response policy zone names for views that + * are used for real lookups and so care about hints. + */ + zonelist = NULL; + if (view->rdclass == dns_rdataclass_in && need_hints) { + obj = NULL; + result = ns_config_get(maps, "response-policy", &obj); + if (result == ISC_R_SUCCESS) + cfg_map_get(obj, "zone", &zonelist); + } + if (zonelist != NULL) { + + for (element = cfg_list_first(zonelist); + element != NULL; + element = cfg_list_next(element)) { + result = configure_rpz(view, element); + if (result != ISC_R_SUCCESS) + goto cleanup; + dns_rpz_set_need(ISC_TRUE); + } + } + result = ISC_R_SUCCESS; cleanup: + if (clients != NULL) + dns_acl_detach(&clients); + if (mapped != NULL) + dns_acl_detach(&mapped); + if (excluded != NULL) + dns_acl_detach(&excluded); + if (ring != NULL) + dns_tsigkeyring_detach(&ring); if (zone != NULL) dns_zone_detach(&zone); if (dispatch4 != NULL) @@ -2033,6 +2951,12 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, if (cache != NULL) dns_cache_detach(&cache); + if (newzones_parser != NULL) { + if (nzfconf != NULL) + cfg_obj_destroy(newzones_parser, &nzfconf); + cfg_parser_destroy(&newzones_parser); + } + return (result); } @@ -2105,8 +3029,8 @@ configure_alternates(const cfg_obj_t *config, dns_view_t *view, isc_buffer_add(&buffer, strlen(str)); dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); - CHECK(dns_name_fromtext(name, &buffer, dns_rootname, - ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, + NULL)); portobj = cfg_tuple_get(alternate, "port"); if (cfg_obj_isuint32(portobj)) { @@ -2286,7 +3210,7 @@ create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, static isc_result_t configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, - cfg_aclconfctx_t *aclconf) + cfg_aclconfctx_t *aclconf, isc_boolean_t added) { dns_view_t *pview = NULL; /* Production view */ dns_zone_t *zone = NULL; /* New or reused zone */ @@ -2319,7 +3243,7 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, isc_buffer_add(&buffer, strlen(zname)); dns_fixedname_init(&fixorigin); CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin), - &buffer, dns_rootname, ISC_FALSE, NULL)); + &buffer, dns_rootname, 0, NULL)); origin = dns_fixedname_name(&fixorigin); CHECK(ns_config_getclass(cfg_tuple_get(zconfig, "class"), @@ -2349,7 +3273,7 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, ztypestr = cfg_obj_asstring(typeobj); /* - * "hints zones" aren't zones. If we've got one, + * "hints zones" aren't zones. If we've got one, * configure it and return. */ if (strcasecmp(ztypestr, "hint") == 0) { @@ -2500,6 +3424,11 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, } /* + * Mark whether the zone was originally added at runtime or not + */ + dns_zone_setadded(zone, added); + + /* * Configure the zone. */ CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, zone)); @@ -2519,6 +3448,95 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, } /* + * Configure built-in zone for storing managed-key data. + */ + +#define KEYZONE "managed-keys.bind" +#define MKEYS ".mkeys" + +static isc_result_t +add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) { + isc_result_t result; + dns_view_t *pview = NULL; + dns_zone_t *zone = NULL; + dns_acl_t *none = NULL; + char filename[PATH_MAX]; + char buffer[ISC_SHA256_DIGESTSTRINGLENGTH + sizeof(MKEYS)]; + int n; + + REQUIRE(view != NULL); + + /* See if we can re-use an existing keydata zone. */ + result = dns_viewlist_find(&ns_g_server->viewlist, + view->name, view->rdclass, + &pview); + if (result != ISC_R_NOTFOUND && + result != ISC_R_SUCCESS) + return (result); + + if (pview != NULL && pview->managed_keys != NULL) { + dns_zone_attach(pview->managed_keys, &view->managed_keys); + dns_zone_setview(pview->managed_keys, view); + dns_view_detach(&pview); + return (ISC_R_SUCCESS); + } + + /* No existing keydata zone was found; create one */ + CHECK(dns_zone_create(&zone, mctx)); + CHECK(dns_zone_setorigin(zone, dns_rootname)); + + isc_sha256_data((void *)view->name, strlen(view->name), buffer); + strcat(buffer, MKEYS); + n = snprintf(filename, sizeof(filename), "%s%s%s", + directory ? directory : "", directory ? "/" : "", + strcmp(view->name, "_default") == 0 ? KEYZONE : buffer); + if (n < 0 || (size_t)n >= sizeof(filename)) { + result = (n < 0) ? ISC_R_FAILURE : ISC_R_NOSPACE; + goto cleanup; + } + CHECK(dns_zone_setfile(zone, filename)); + + dns_zone_setview(zone, view); + dns_zone_settype(zone, dns_zone_key); + dns_zone_setclass(zone, view->rdclass); + + CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone)); + + if (view->acache != NULL) + dns_zone_setacache(zone, view->acache); + + CHECK(dns_acl_none(mctx, &none)); + dns_zone_setqueryacl(zone, none); + dns_zone_setqueryonacl(zone, none); + dns_acl_detach(&none); + + dns_zone_setdialup(zone, dns_dialuptype_no); + dns_zone_setnotifytype(zone, dns_notifytype_no); + dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, ISC_TRUE); + dns_zone_setjournalsize(zone, 0); + + dns_zone_setstats(zone, ns_g_server->zonestats); + CHECK(setquerystats(zone, mctx, ISC_FALSE)); + + if (view->managed_keys != NULL) + dns_zone_detach(&view->managed_keys); + dns_zone_attach(zone, &view->managed_keys); + + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "set up managed keys zone for view %s, file '%s'", + view->name, filename); + +cleanup: + if (zone != NULL) + dns_zone_detach(&zone); + if (none != NULL) + dns_acl_detach(&none); + + return (result); +} + +/* * Configure a single server quota. */ static void @@ -2914,13 +3932,226 @@ removed(dns_zone_t *zone, void *uap) { return (ISC_R_SUCCESS); } +static void +cleanup_session_key(ns_server_t *server, isc_mem_t *mctx) { + if (server->session_keyfile != NULL) { + isc_file_remove(server->session_keyfile); + isc_mem_free(mctx, server->session_keyfile); + server->session_keyfile = NULL; + } + + if (server->session_keyname != NULL) { + if (dns_name_dynamic(server->session_keyname)) + dns_name_free(server->session_keyname, mctx); + isc_mem_put(mctx, server->session_keyname, sizeof(dns_name_t)); + server->session_keyname = NULL; + } + + if (server->sessionkey != NULL) + dns_tsigkey_detach(&server->sessionkey); + + server->session_keyalg = DST_ALG_UNKNOWN; + server->session_keybits = 0; +} + +static isc_result_t +generate_session_key(const char *filename, const char *keynamestr, + dns_name_t *keyname, const char *algstr, + dns_name_t *algname, unsigned int algtype, + isc_uint16_t bits, isc_mem_t *mctx, + dns_tsigkey_t **tsigkeyp) +{ + isc_result_t result = ISC_R_SUCCESS; + dst_key_t *key = NULL; + isc_buffer_t key_txtbuffer; + isc_buffer_t key_rawbuffer; + char key_txtsecret[256]; + char key_rawsecret[64]; + isc_region_t key_rawregion; + isc_stdtime_t now; + dns_tsigkey_t *tsigkey = NULL; + FILE *fp = NULL; + + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "generating session key for dynamic DNS"); + + /* generate key */ + result = dst_key_generate(keyname, algtype, bits, 1, 0, + DNS_KEYPROTO_ANY, dns_rdataclass_in, + mctx, &key); + if (result != ISC_R_SUCCESS) + return (result); + + /* + * Dump the key to the buffer for later use. Should be done before + * we transfer the ownership of key to tsigkey. + */ + isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret)); + CHECK(dst_key_tobuffer(key, &key_rawbuffer)); + + isc_buffer_usedregion(&key_rawbuffer, &key_rawregion); + isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret)); + CHECK(isc_base64_totext(&key_rawregion, -1, "", &key_txtbuffer)); + + /* Store the key in tsigkey. */ + isc_stdtime_get(&now); + CHECK(dns_tsigkey_createfromkey(dst_key_name(key), algname, key, + ISC_FALSE, NULL, now, now, mctx, NULL, + &tsigkey)); + + /* Dump the key to the key file. */ + fp = ns_os_openfile(filename, S_IRUSR|S_IWUSR, ISC_TRUE); + if (fp == NULL) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "could not create %s", filename); + result = ISC_R_NOPERM; + goto cleanup; + } + + fprintf(fp, "key \"%s\" {\n" + "\talgorithm %s;\n" + "\tsecret \"%.*s\";\n};\n", keynamestr, algstr, + (int) isc_buffer_usedlength(&key_txtbuffer), + (char*) isc_buffer_base(&key_txtbuffer)); + + RUNTIME_CHECK(isc_stdio_flush(fp) == ISC_R_SUCCESS); + RUNTIME_CHECK(isc_stdio_close(fp) == ISC_R_SUCCESS); + + dst_key_free(&key); + + *tsigkeyp = tsigkey; + + return (ISC_R_SUCCESS); + + cleanup: + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "failed to generate session key " + "for dynamic DNS: %s", isc_result_totext(result)); + if (tsigkey != NULL) + dns_tsigkey_detach(&tsigkey); + if (key != NULL) + dst_key_free(&key); + + return (result); +} + +static isc_result_t +configure_session_key(const cfg_obj_t **maps, ns_server_t *server, + isc_mem_t *mctx) +{ + const char *keyfile, *keynamestr, *algstr; + unsigned int algtype; + dns_fixedname_t fname; + dns_name_t *keyname, *algname; + isc_buffer_t buffer; + isc_uint16_t bits; + const cfg_obj_t *obj; + isc_boolean_t need_deleteold = ISC_FALSE; + isc_boolean_t need_createnew = ISC_FALSE; + isc_result_t result; + + obj = NULL; + result = ns_config_get(maps, "session-keyfile", &obj); + if (result == ISC_R_SUCCESS) { + if (cfg_obj_isvoid(obj)) + keyfile = NULL; /* disable it */ + else + keyfile = cfg_obj_asstring(obj); + } else + keyfile = ns_g_defaultsessionkeyfile; + + obj = NULL; + result = ns_config_get(maps, "session-keyname", &obj); + INSIST(result == ISC_R_SUCCESS); + keynamestr = cfg_obj_asstring(obj); + dns_fixedname_init(&fname); + isc_buffer_init(&buffer, keynamestr, strlen(keynamestr)); + isc_buffer_add(&buffer, strlen(keynamestr)); + keyname = dns_fixedname_name(&fname); + result = dns_name_fromtext(keyname, &buffer, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) + return (result); + + obj = NULL; + result = ns_config_get(maps, "session-keyalg", &obj); + INSIST(result == ISC_R_SUCCESS); + algstr = cfg_obj_asstring(obj); + algname = NULL; + result = ns_config_getkeyalgorithm2(algstr, &algname, &algtype, &bits); + if (result != ISC_R_SUCCESS) { + const char *s = " (keeping current key)"; + + cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, "session-keyalg: " + "unsupported or unknown algorithm '%s'%s", + algstr, + server->session_keyfile != NULL ? s : ""); + return (result); + } + + /* See if we need to (re)generate a new key. */ + if (keyfile == NULL) { + if (server->session_keyfile != NULL) + need_deleteold = ISC_TRUE; + } else if (server->session_keyfile == NULL) + need_createnew = ISC_TRUE; + else if (strcmp(keyfile, server->session_keyfile) != 0 || + !dns_name_equal(server->session_keyname, keyname) || + server->session_keyalg != algtype || + server->session_keybits != bits) { + need_deleteold = ISC_TRUE; + need_createnew = ISC_TRUE; + } + + if (need_deleteold) { + INSIST(server->session_keyfile != NULL); + INSIST(server->session_keyname != NULL); + INSIST(server->sessionkey != NULL); + + cleanup_session_key(server, mctx); + } + + if (need_createnew) { + INSIST(server->sessionkey == NULL); + INSIST(server->session_keyfile == NULL); + INSIST(server->session_keyname == NULL); + INSIST(server->session_keyalg == DST_ALG_UNKNOWN); + INSIST(server->session_keybits == 0); + + server->session_keyname = isc_mem_get(mctx, sizeof(dns_name_t)); + if (server->session_keyname == NULL) + goto cleanup; + dns_name_init(server->session_keyname, NULL); + CHECK(dns_name_dup(keyname, mctx, server->session_keyname)); + + server->session_keyfile = isc_mem_strdup(mctx, keyfile); + if (server->session_keyfile == NULL) + goto cleanup; + + server->session_keyalg = algtype; + server->session_keybits = bits; + + CHECK(generate_session_key(keyfile, keynamestr, keyname, algstr, + algname, algtype, bits, mctx, + &server->sessionkey)); + } + + return (result); + + cleanup: + cleanup_session_key(server, mctx); + return (result); +} + static isc_result_t load_configuration(const char *filename, ns_server_t *server, isc_boolean_t first_time) { cfg_aclconfctx_t aclconfctx; - cfg_obj_t *config; - cfg_parser_t *parser = NULL; + cfg_obj_t *config = NULL, *bindkeys = NULL; + cfg_parser_t *conf_parser = NULL, *bindkeys_parser = NULL; const cfg_listelt_t *element; const cfg_obj_t *builtin_views; const cfg_obj_t *maps[3]; @@ -2931,7 +4162,7 @@ load_configuration(const char *filename, ns_server_t *server, dns_view_t *view = NULL; dns_view_t *view_next; dns_viewlist_t tmpviewlist; - dns_viewlist_t viewlist; + dns_viewlist_t viewlist, builtin_viewlist; in_port_t listen_port, udpport_low, udpport_high; int i; isc_interval_t interval; @@ -2943,10 +4174,14 @@ load_configuration(const char *filename, ns_server_t *server, isc_uint32_t interface_interval; isc_uint32_t reserved; isc_uint32_t udpsize; + ns_cachelist_t cachelist, tmpcachelist; unsigned int maxsocks; + ns_cache_t *nsc; cfg_aclconfctx_init(&aclconfctx); ISC_LIST_INIT(viewlist); + ISC_LIST_INIT(builtin_viewlist); + ISC_LIST_INIT(cachelist); /* Ensure exclusive access to configuration data. */ result = isc_task_beginexclusive(server->task); @@ -2958,8 +4193,7 @@ load_configuration(const char *filename, ns_server_t *server, if (first_time) { CHECK(ns_config_parsedefaults(ns_g_parser, &ns_g_config)); RUNTIME_CHECK(cfg_map_get(ns_g_config, "options", - &ns_g_defaults) == - ISC_R_SUCCESS); + &ns_g_defaults) == ISC_R_SUCCESS); } /* @@ -2976,10 +4210,10 @@ load_configuration(const char *filename, ns_server_t *server, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "loading configuration from '%s'", filename); - CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser)); - cfg_parser_setcallback(parser, directory_callback, NULL); - result = cfg_parse_file(parser, filename, &cfg_type_namedconf, - &config); + CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &conf_parser)); + cfg_parser_setcallback(conf_parser, directory_callback, NULL); + result = cfg_parse_file(conf_parser, filename, + &cfg_type_namedconf, &config); } /* @@ -2994,10 +4228,10 @@ load_configuration(const char *filename, ns_server_t *server, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "loading configuration from '%s'", lwresd_g_resolvconffile); - if (parser != NULL) - cfg_parser_destroy(&parser); - CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser)); - result = ns_lwresd_parseeresolvconf(ns_g_mctx, parser, + if (conf_parser != NULL) + cfg_parser_destroy(&conf_parser); + CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &conf_parser)); + result = ns_lwresd_parseeresolvconf(ns_g_mctx, conf_parser, &config); } CHECK(result); @@ -3019,13 +4253,38 @@ load_configuration(const char *filename, ns_server_t *server, maps[i++] = NULL; /* + * If bind.keys exists, load it. If "dnssec-lookaside auto" + * is turned on, the keys found there will be used as default + * trust anchors. + */ + obj = NULL; + result = ns_config_get(maps, "bindkeys-file", &obj); + INSIST(result == ISC_R_SUCCESS); + CHECKM(setstring(server, &server->bindkeysfile, + cfg_obj_asstring(obj)), "strdup"); + + if (access(server->bindkeysfile, R_OK) == 0) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "reading built-in trusted " + "keys from file '%s'", server->bindkeysfile); + + CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, + &bindkeys_parser)); + + result = cfg_parse_file(bindkeys_parser, server->bindkeysfile, + &cfg_type_bindkeys, &bindkeys); + CHECK(result); + } + + /* * Set process limits, which (usually) needs to be done as root. */ set_limits(maps); /* * Check if max number of open sockets that the system allows is - * sufficiently large. Failing this condition is not necessarily fatal, + * sufficiently large. Failing this condition is not necessarily fatal, * but may cause subsequent runtime failures for a busy recursive * server. */ @@ -3078,7 +4337,7 @@ load_configuration(const char *filename, ns_server_t *server, else isc_quota_soft(&server->recursionquota, 0); - CHECK(configure_view_acl(NULL, config, "blackhole", &aclconfctx, + CHECK(configure_view_acl(NULL, config, "blackhole", NULL, &aclconfctx, ns_g_mctx, &server->blackholeacl)); if (server->blackholeacl != NULL) dns_dispatchmgr_setblackhole(ns_g_dispatchmgr, @@ -3318,6 +4577,31 @@ load_configuration(const char *filename, ns_server_t *server, &interval, ISC_FALSE)); /* + * Write the PID file. + */ + obj = NULL; + if (ns_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS) + if (cfg_obj_isvoid(obj)) + ns_os_writepidfile(NULL, first_time); + else + ns_os_writepidfile(cfg_obj_asstring(obj), first_time); + else if (ns_g_lwresdonly) + ns_os_writepidfile(lwresd_g_defaultpidfile, first_time); + else + ns_os_writepidfile(ns_g_defaultpidfile, first_time); + + /* + * Configure the server-wide session key. This must be done before + * configure views because zone configuration may need to know + * session-keyname. + * + * Failure of session key generation isn't fatal at this time; if it + * turns out that a session key is really needed but doesn't exist, + * we'll treat it as a fatal error then. + */ + (void)configure_session_key(maps, server, ns_g_mctx); + + /* * Configure and freeze all explicit views. Explicit * views that have zones were already created at parsing * time, but views with no zones must be created here. @@ -3328,12 +4612,13 @@ load_configuration(const char *filename, ns_server_t *server, element != NULL; element = cfg_list_next(element)) { - const cfg_obj_t *vconfig = cfg_listelt_value(element); + cfg_obj_t *vconfig = cfg_listelt_value(element); view = NULL; CHECK(create_view(vconfig, &viewlist, &view)); INSIST(view != NULL); - CHECK(configure_view(view, config, vconfig, + CHECK(configure_view(view, conf_parser, config, vconfig, + &cachelist, bindkeys, ns_g_mctx, &aclconfctx, ISC_TRUE)); dns_view_freeze(view); dns_view_detach(&view); @@ -3351,15 +4636,15 @@ load_configuration(const char *filename, ns_server_t *server, * In either case, we need to configure and freeze it. */ CHECK(create_view(NULL, &viewlist, &view)); - CHECK(configure_view(view, config, NULL, ns_g_mctx, - &aclconfctx, ISC_TRUE)); + CHECK(configure_view(view, conf_parser, config, NULL, + &cachelist, bindkeys, + ns_g_mctx, &aclconfctx, ISC_TRUE)); dns_view_freeze(view); dns_view_detach(&view); } /* - * Create (or recreate) the built-in views. Currently - * there is only one, the _bind view. + * Create (or recreate) the built-in views. */ builtin_views = NULL; RUNTIME_CHECK(cfg_map_get(ns_g_config, "view", @@ -3368,25 +4653,38 @@ load_configuration(const char *filename, ns_server_t *server, element != NULL; element = cfg_list_next(element)) { - const cfg_obj_t *vconfig = cfg_listelt_value(element); - CHECK(create_view(vconfig, &viewlist, &view)); - CHECK(configure_view(view, config, vconfig, ns_g_mctx, - &aclconfctx, ISC_FALSE)); + cfg_obj_t *vconfig = cfg_listelt_value(element); + + CHECK(create_view(vconfig, &builtin_viewlist, &view)); + CHECK(configure_view(view, conf_parser, config, vconfig, + &cachelist, bindkeys, + ns_g_mctx, &aclconfctx, ISC_FALSE)); dns_view_freeze(view); dns_view_detach(&view); view = NULL; } - /* - * Swap our new view list with the production one. - */ + /* Now combine the two viewlists into one */ + ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link); + + /* Swap our new view list with the production one. */ tmpviewlist = server->viewlist; server->viewlist = viewlist; viewlist = tmpviewlist; - /* - * Load the TKEY information from the configuration. - */ + /* Make the view list available to each of the views */ + view = ISC_LIST_HEAD(server->viewlist); + while (view != NULL) { + view->viewlist = &server->viewlist; + view = ISC_LIST_NEXT(view, link); + } + + /* Swap our new cache list with the production one. */ + tmpcachelist = server->cachelist; + server->cachelist = cachelist; + cachelist = tmpcachelist; + + /* Load the TKEY information from the configuration. */ if (options != NULL) { dns_tkeyctx_t *t = NULL; CHECKM(ns_tkeyctx_fromconfig(options, ns_g_mctx, ns_g_entropy, @@ -3551,16 +4849,6 @@ load_configuration(const char *filename, ns_server_t *server, } } - obj = NULL; - if (ns_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS) - if (cfg_obj_isvoid(obj)) - ns_os_writepidfile(NULL, first_time); - else - ns_os_writepidfile(cfg_obj_asstring(obj), first_time); - else if (ns_g_lwresdonly) - ns_os_writepidfile(lwresd_g_defaultpidfile, first_time); - else - ns_os_writepidfile(ns_g_defaultpidfile, first_time); obj = NULL; if (options != NULL && @@ -3591,6 +4879,12 @@ load_configuration(const char *filename, ns_server_t *server, "strdup"); obj = NULL; + result = ns_config_get(maps, "secroots-file", &obj); + INSIST(result == ISC_R_SUCCESS); + CHECKM(setstring(server, &server->secrootsfile, cfg_obj_asstring(obj)), + "strdup"); + + obj = NULL; result = ns_config_get(maps, "recursing-file", &obj); INSIST(result == ISC_R_SUCCESS); CHECKM(setstring(server, &server->recfile, cfg_obj_asstring(obj)), @@ -3647,12 +4941,18 @@ load_configuration(const char *filename, ns_server_t *server, if (v6portset != NULL) isc_portset_destroy(ns_g_mctx, &v6portset); - cfg_aclconfctx_destroy(&aclconfctx); + cfg_aclconfctx_clear(&aclconfctx); - if (parser != NULL) { + if (conf_parser != NULL) { if (config != NULL) - cfg_obj_destroy(parser, &config); - cfg_parser_destroy(&parser); + cfg_obj_destroy(conf_parser, &config); + cfg_parser_destroy(&conf_parser); + } + + if (bindkeys_parser != NULL) { + if (bindkeys != NULL) + cfg_obj_destroy(bindkeys_parser, &bindkeys); + cfg_parser_destroy(&bindkeys_parser); } if (view != NULL) @@ -3675,6 +4975,13 @@ load_configuration(const char *filename, ns_server_t *server, dns_view_detach(&view); } + /* Same cleanup for cache list. */ + while ((nsc = ISC_LIST_HEAD(cachelist)) != NULL) { + ISC_LIST_UNLINK(cachelist, nsc, link); + dns_cache_detach(&nsc->cache); + isc_mem_put(server->mctx, nsc, sizeof(*nsc)); + } + /* * Adjust the listening interfaces in accordance with the source * addresses specified in views and zones. @@ -3708,6 +5015,8 @@ load_zones(ns_server_t *server, isc_boolean_t stop) { view = ISC_LIST_NEXT(view, link)) { CHECK(dns_view_load(view, stop)); + if (view->managed_keys != NULL) + CHECK(dns_zone_load(view->managed_keys)); } /* @@ -3737,11 +5046,14 @@ load_new_zones(ns_server_t *server, isc_boolean_t stop) { view = ISC_LIST_NEXT(view, link)) { CHECK(dns_view_loadnew(view, stop)); + + /* Load managed-keys data */ + if (view->managed_keys != NULL) + CHECK(dns_zone_loadnew(view->managed_keys)); } + /* - * Force zone maintenance. Do this after loading - * so that we know when we need to force AXFR of - * slave zones whose master files are missing. + * Resume zone XFRs. */ dns_zonemgr_resumexfrs(server->zonemgr); cleanup: @@ -3820,6 +5132,7 @@ shutdown_server(isc_task_t *task, isc_event_t *event) { dns_view_t *view, *view_next; ns_server_t *server = (ns_server_t *)event->ev_arg; isc_boolean_t flush = server->flushonshutdown; + ns_cache_t *nsc; UNUSED(task); INSIST(task == server->task); @@ -3834,6 +5147,7 @@ shutdown_server(isc_task_t *task, isc_event_t *event) { ns_statschannels_shutdown(server); ns_controls_shutdown(server->controls); end_reserved_dispatches(server, ISC_TRUE); + cleanup_session_key(server, server->mctx); cfg_obj_destroy(ns_g_parser, &ns_g_config); cfg_parser_destroy(&ns_g_parser); @@ -3849,6 +5163,12 @@ shutdown_server(isc_task_t *task, isc_event_t *event) { dns_view_detach(&view); } + while ((nsc = ISC_LIST_HEAD(server->cachelist)) != NULL) { + ISC_LIST_UNLINK(server->cachelist, nsc, link); + dns_cache_detach(&nsc->cache); + isc_mem_put(server->mctx, nsc, sizeof(*nsc)); + } + isc_timer_detach(&server->interface_timer); isc_timer_detach(&server->heartbeat_timer); isc_timer_detach(&server->pps_timer); @@ -3860,6 +5180,11 @@ shutdown_server(isc_task_t *task, isc_event_t *event) { dns_zonemgr_shutdown(server->zonemgr); + if (ns_g_sessionkey != NULL) { + dns_tsigkey_detach(&ns_g_sessionkey); + dns_name_free(&ns_g_sessionkeyname, server->mctx); + } + if (server->blackholeacl != NULL) dns_acl_detach(&server->blackholeacl); @@ -3918,7 +5243,8 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { ISC_R_NOMEMORY : ISC_R_SUCCESS, "allocating reload event"); - CHECKFATAL(dst_lib_init(ns_g_mctx, ns_g_entropy, ISC_ENTROPY_GOODONLY), + CHECKFATAL(dst_lib_init2(ns_g_mctx, ns_g_entropy, + ns_g_engine, ISC_ENTROPY_GOODONLY), "initializing DST"); server->tkeyctx = NULL; @@ -3963,10 +5289,20 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { "isc_stats_create"); isc_socketmgr_setstats(ns_g_socketmgr, server->sockstats); + server->bindkeysfile = isc_mem_strdup(server->mctx, "bind.keys"); + CHECKFATAL(server->bindkeysfile == NULL ? ISC_R_NOMEMORY : + ISC_R_SUCCESS, + "isc_mem_strdup"); + server->dumpfile = isc_mem_strdup(server->mctx, "named_dump.db"); CHECKFATAL(server->dumpfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, "isc_mem_strdup"); + server->secrootsfile = isc_mem_strdup(server->mctx, "named.secroots"); + CHECKFATAL(server->secrootsfile == NULL ? ISC_R_NOMEMORY : + ISC_R_SUCCESS, + "isc_mem_strdup"); + server->recfile = isc_mem_strdup(server->mctx, "named.recursing"); CHECKFATAL(server->recfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, "isc_mem_strdup"); @@ -4008,6 +5344,14 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { ISC_LIST_INIT(server->statschannels); + ISC_LIST_INIT(server->cachelist); + + server->sessionkey = NULL; + server->session_keyfile = NULL; + server->session_keyname = NULL; + server->session_keyalg = DST_ALG_UNKNOWN; + server->session_keybits = 0; + server->magic = NS_SERVER_MAGIC; *serverp = server; } @@ -4027,7 +5371,9 @@ ns_server_destroy(ns_server_t **serverp) { isc_stats_detach(&server->sockstats); isc_mem_free(server->mctx, server->statsfile); + isc_mem_free(server->mctx, server->bindkeysfile); isc_mem_free(server->mctx, server->dumpfile); + isc_mem_free(server->mctx, server->secrootsfile); isc_mem_free(server->mctx, server->recfile); if (server->version != NULL) @@ -4047,6 +5393,7 @@ ns_server_destroy(ns_server_t **serverp) { isc_event_free(&server->reload_event); INSIST(ISC_LIST_EMPTY(server->viewlist)); + INSIST(ISC_LIST_EMPTY(server->cachelist)); dns_aclenv_destroy(&server->aclenv); @@ -4278,7 +5625,9 @@ next_token(char **stringp, const char *delim) { * set '*zonep' to NULL. */ static isc_result_t -zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep) { +zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep, + const char **zonename) +{ char *input, *ptr; const char *zonetxt; char *classtxt; @@ -4302,6 +5651,8 @@ zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep) { zonetxt = next_token(&input, " \t"); if (zonetxt == NULL) return (ISC_R_SUCCESS); + if (zonename) + *zonename = zonetxt; /* Look for the optional class name. */ classtxt = next_token(&input, " \t"); @@ -4314,7 +5665,7 @@ zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep) { isc_buffer_add(&buf, strlen(zonetxt)); dns_fixedname_init(&name); result = dns_name_fromtext(dns_fixedname_name(&name), - &buf, dns_rootname, ISC_FALSE, NULL); + &buf, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) goto fail1; @@ -4362,7 +5713,7 @@ ns_server_retransfercommand(ns_server_t *server, char *args) { dns_zone_t *zone = NULL; dns_zonetype_t type; - result = zone_from_args(server, args, &zone); + result = zone_from_args(server, args, &zone, NULL); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) @@ -4386,7 +5737,7 @@ ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t *text) { dns_zonetype_t type; const char *msg = NULL; - result = zone_from_args(server, args, &zone); + result = zone_from_args(server, args, &zone, NULL); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) { @@ -4446,7 +5797,7 @@ ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t *text) { dns_zone_t *zone = NULL; const unsigned char msg[] = "zone notify queued"; - result = zone_from_args(server, args, &zone); + result = zone_from_args(server, args, &zone, NULL); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) @@ -4471,7 +5822,7 @@ ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t *text) { const unsigned char msg2[] = "not a slave or stub zone"; dns_zonetype_t type; - result = zone_from_args(server, args, &zone); + result = zone_from_args(server, args, &zone, NULL); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) @@ -4710,15 +6061,23 @@ dumpdone(void *arg, isc_result_t result) { nextview: fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name); resume: - if (dctx->zone == NULL && dctx->cache == NULL && dctx->dumpcache) { + if (dctx->dumpcache && dns_view_iscacheshared(dctx->view->view)) { + fprintf(dctx->fp, + ";\n; Cache of view '%s' is shared as '%s'\n", + dctx->view->view->name, + dns_cache_getname(dctx->view->view->cache)); + } else if (dctx->zone == NULL && dctx->cache == NULL && + dctx->dumpcache) + { style = &dns_master_style_cache; /* start cache dump */ if (dctx->view->view->cachedb != NULL) dns_db_attach(dctx->view->view->cachedb, &dctx->cache); if (dctx->cache != NULL) { - - fprintf(dctx->fp, ";\n; Cache dump of view '%s'\n;\n", - dctx->view->view->name); + fprintf(dctx->fp, + ";\n; Cache dump of view '%s' (cache %s)\n;\n", + dctx->view->view->name, + dns_cache_getname(dctx->view->view->cache)); result = dns_master_dumptostreaminc(dctx->mctx, dctx->cache, NULL, style, dctx->fp, @@ -4880,6 +6239,68 @@ ns_server_dumpdb(ns_server_t *server, char *args) { } isc_result_t +ns_server_dumpsecroots(ns_server_t *server, char *args) { + dns_view_t *view; + dns_keytable_t *secroots = NULL; + isc_result_t result; + char *ptr; + FILE *fp = NULL; + isc_time_t now; + char tbuf[64]; + + /* Skip the command name. */ + ptr = next_token(&args, " \t"); + if (ptr == NULL) + return (ISC_R_UNEXPECTEDEND); + ptr = next_token(&args, " \t"); + + CHECKMF(isc_stdio_open(server->secrootsfile, "w", &fp), + "could not open secroots dump file", server->secrootsfile); + TIME_NOW(&now); + isc_time_formattimestamp(&now, tbuf, sizeof(tbuf)); + fprintf(fp, "%s\n", tbuf); + + nextview: + for (view = ISC_LIST_HEAD(server->viewlist); + view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + if (ptr != NULL && strcmp(view->name, ptr) != 0) + continue; + if (secroots != NULL) + dns_keytable_detach(&secroots); + result = dns_view_getsecroots(view, &secroots); + if (result == ISC_R_NOTFOUND) { + result = ISC_R_SUCCESS; + continue; + } + fprintf(fp, "\n Start view %s\n\n", view->name); + CHECK(dns_keytable_dump(secroots, fp)); + } + if (ptr != NULL) { + ptr = next_token(&args, " \t"); + if (ptr != NULL) + goto nextview; + } + + cleanup: + if (secroots != NULL) + dns_keytable_detach(&secroots); + if (fp != NULL) + (void)isc_stdio_close(fp); + if (result == ISC_R_SUCCESS) + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "dumpsecroots complete"); + else + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "dumpsecroots failed: %s", + dns_result_totext(result)); + return (result); +} + +isc_result_t ns_server_dumprecursing(ns_server_t *server) { FILE *fp = NULL; isc_result_t result; @@ -4997,6 +6418,7 @@ ns_server_flushcache(ns_server_t *server, char *args) { isc_boolean_t flushed; isc_boolean_t found; isc_result_t result; + ns_cache_t *nsc; /* Skip the command name. */ ptr = next_token(&args, " \t"); @@ -5010,22 +6432,96 @@ ns_server_flushcache(ns_server_t *server, char *args) { RUNTIME_CHECK(result == ISC_R_SUCCESS); flushed = ISC_TRUE; found = ISC_FALSE; - for (view = ISC_LIST_HEAD(server->viewlist); - view != NULL; - view = ISC_LIST_NEXT(view, link)) - { - if (viewname != NULL && strcasecmp(viewname, view->name) != 0) - continue; + + /* + * Flushing a cache is tricky when caches are shared by multiple views. + * We first identify which caches should be flushed in the local cache + * list, flush these caches, and then update other views that refer to + * the flushed cache DB. + */ + if (viewname != NULL) { + /* + * Mark caches that need to be flushed. This is an O(#view^2) + * operation in the very worst case, but should be normally + * much more lightweight because only a few (most typically just + * one) views will match. + */ + for (view = ISC_LIST_HEAD(server->viewlist); + view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + if (strcasecmp(viewname, view->name) != 0) + continue; + found = ISC_TRUE; + for (nsc = ISC_LIST_HEAD(server->cachelist); + nsc != NULL; + nsc = ISC_LIST_NEXT(nsc, link)) { + if (nsc->cache == view->cache) + break; + } + INSIST(nsc != NULL); + nsc->needflush = ISC_TRUE; + } + } else found = ISC_TRUE; - result = dns_view_flushcache(view); + + /* Perform flush */ + for (nsc = ISC_LIST_HEAD(server->cachelist); + nsc != NULL; + nsc = ISC_LIST_NEXT(nsc, link)) { + if (viewname != NULL && !nsc->needflush) + continue; + nsc->needflush = ISC_TRUE; + result = dns_view_flushcache2(nsc->primaryview, ISC_FALSE); if (result != ISC_R_SUCCESS) { flushed = ISC_FALSE; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "flushing cache in view '%s' failed: %s", - view->name, isc_result_totext(result)); + nsc->primaryview->name, + isc_result_totext(result)); + } + } + + /* + * Fix up views that share a flushed cache: let the views update the + * cache DB they're referring to. This could also be an expensive + * operation, but should typically be marginal: the inner loop is only + * necessary for views that share a cache, and if there are many such + * views the number of shared cache should normally be small. + * A worst case is that we have n views and n/2 caches, each shared by + * two views. Then this will be a O(n^2/4) operation. + */ + for (view = ISC_LIST_HEAD(server->viewlist); + view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + if (!dns_view_iscacheshared(view)) + continue; + for (nsc = ISC_LIST_HEAD(server->cachelist); + nsc != NULL; + nsc = ISC_LIST_NEXT(nsc, link)) { + if (!nsc->needflush || nsc->cache != view->cache) + continue; + result = dns_view_flushcache2(view, ISC_TRUE); + if (result != ISC_R_SUCCESS) { + flushed = ISC_FALSE; + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "fixing cache in view '%s' " + "failed: %s", view->name, + isc_result_totext(result)); + } } } + + /* Cleanup the cache list. */ + for (nsc = ISC_LIST_HEAD(server->cachelist); + nsc != NULL; + nsc = ISC_LIST_NEXT(nsc, link)) { + nsc->needflush = ISC_FALSE; + } + if (flushed && found) { if (viewname != NULL) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, @@ -5076,7 +6572,7 @@ ns_server_flushname(ns_server_t *server, char *args) { isc_buffer_add(&b, strlen(target)); dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); - result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) return (result); @@ -5094,6 +6590,11 @@ ns_server_flushname(ns_server_t *server, char *args) { if (viewname != NULL && strcasecmp(viewname, view->name) != 0) continue; found = ISC_TRUE; + /* + * It's a little inefficient to try flushing name for all views + * if some of the views share a single cache. But since the + * operation is lightweight we prefer simplicity here. + */ result = dns_view_flushname(view, name); if (result != ISC_R_SUCCESS) { flushed = ISC_FALSE; @@ -5408,6 +6909,46 @@ ns_server_tsiglist(ns_server_t *server, isc_buffer_t *text) { } /* + * Act on a "sign" or "loadkeys" command from the command channel. + */ +isc_result_t +ns_server_rekey(ns_server_t *server, char *args) { + isc_result_t result; + dns_zone_t *zone = NULL; + dns_zonetype_t type; + isc_uint16_t keyopts; + isc_boolean_t fullsign = ISC_FALSE; + + if (strncasecmp(args, NS_COMMAND_SIGN, strlen(NS_COMMAND_SIGN)) == 0) + fullsign = ISC_TRUE; + + result = zone_from_args(server, args, &zone, NULL); + if (result != ISC_R_SUCCESS) + return (result); + if (zone == NULL) + return (ISC_R_UNEXPECTEDEND); /* XXX: or do all zones? */ + + type = dns_zone_gettype(zone); + if (type != dns_zone_master) { + dns_zone_detach(&zone); + return (DNS_R_NOTMASTER); + } + + keyopts = dns_zone_getkeyopts(zone); + + /* "rndc loadkeys" requires "auto-dnssec maintain". */ + if ((keyopts & DNS_ZONEKEY_ALLOW) == 0) + result = ISC_R_NOPERM; + else if ((keyopts & DNS_ZONEKEY_MAINTAIN) == 0 && !fullsign) + result = ISC_R_NOPERM; + else + dns_zone_rekey(zone, fullsign); + + dns_zone_detach(&zone); + return (result); +} + +/* * Act on a "freeze" or "thaw" command from the command channel. */ isc_result_t @@ -5425,7 +6966,7 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, isc_boolean_t frozen; const char *msg = NULL; - result = zone_from_args(server, args, &zone); + result = zone_from_args(server, args, &zone, NULL); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) { @@ -5451,7 +6992,7 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, type = dns_zone_gettype(zone); if (type != dns_zone_master) { dns_zone_detach(&zone); - return (ISC_R_NOTFOUND); + return (DNS_R_NOTMASTER); } result = isc_task_beginexclusive(server->task); @@ -5502,8 +7043,8 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, strlen(msg) + 1); view = dns_zone_getview(zone); - if (strcmp(view->name, "_bind") == 0 || - strcmp(view->name, "_default") == 0) + if (strcmp(view->name, "_default") == 0 || + strcmp(view->name, "_bind") == 0) { vname = ""; sep = ""; @@ -5543,3 +7084,376 @@ ns_smf_add_message(isc_buffer_t *text) { return (ISC_R_SUCCESS); } #endif /* HAVE_LIBSCF */ + +/* + * Act on an "addzone" command from the command channel. + */ +isc_result_t +ns_server_add_zone(ns_server_t *server, char *args) { + isc_result_t result; + isc_buffer_t argbuf; + size_t arglen; + cfg_parser_t *parser = NULL; + cfg_obj_t *config = NULL; + const cfg_obj_t *vconfig = NULL; + const cfg_obj_t *views = NULL; + const cfg_obj_t *parms = NULL; + const cfg_obj_t *obj = NULL; + const cfg_listelt_t *element; + const char *zonename; + const char *classname = NULL; + const char *argp; + const char *viewname = NULL; + dns_rdataclass_t rdclass; + dns_view_t *view = 0; + isc_buffer_t buf, *nbuf = NULL; + dns_name_t dnsname; + dns_zone_t *zone = NULL; + FILE *fp = NULL; + struct cfg_context *cfg = NULL; + + /* Try to parse the argument string */ + arglen = strlen(args); + isc_buffer_init(&argbuf, args, arglen); + isc_buffer_add(&argbuf, strlen(args)); + CHECK(cfg_parser_create(server->mctx, ns_g_lctx, &parser)); + CHECK(cfg_parse_buffer(parser, &argbuf, &cfg_type_addzoneconf, + &config)); + CHECK(cfg_map_get(config, "addzone", &parms)); + + zonename = cfg_obj_asstring(cfg_tuple_get(parms, "name")); + isc_buffer_init(&buf, zonename, strlen(zonename)); + isc_buffer_add(&buf, strlen(zonename)); + dns_name_init(&dnsname, NULL); + isc_buffer_allocate(server->mctx, &nbuf, 256); + dns_name_setbuffer(&dnsname, nbuf); + CHECK(dns_name_fromtext(&dnsname, &buf, dns_rootname, ISC_FALSE, NULL)); + + /* Make sense of optional class argument */ + obj = cfg_tuple_get(parms, "class"); + CHECK(ns_config_getclass(obj, dns_rdataclass_in, &rdclass)); + if (rdclass != dns_rdataclass_in && obj) + classname = cfg_obj_asstring(obj); + + /* Make sense of optional view argument */ + obj = cfg_tuple_get(parms, "view"); + if (obj && cfg_obj_isstring(obj)) + viewname = cfg_obj_asstring(obj); + if (viewname == NULL || *viewname == '\0') + viewname = "_default"; + CHECK(dns_viewlist_find(&server->viewlist, viewname, rdclass, &view)); + + /* Are we accepting new zones? */ + if (view->new_zone_file == NULL) { + result = ISC_R_NOPERM; + goto cleanup; + } + + cfg = (struct cfg_context *) view->new_zone_config; + if (cfg == NULL) { + result = ISC_R_FAILURE; + goto cleanup; + } + + /* Zone shouldn't already exist */ + result = dns_zt_find(view->zonetable, &dnsname, 0, NULL, &zone); + if (result == ISC_R_SUCCESS) { + result = ISC_R_EXISTS; + goto cleanup; + } else if (result == DNS_R_PARTIALMATCH) { + /* Create our sub-zone anyway */ + dns_zone_detach(&zone); + zone = NULL; + } + else if (result != ISC_R_NOTFOUND) + goto cleanup; + + /* Find the view statement */ + cfg_map_get(cfg->config, "view", &views); + for (element = cfg_list_first(views); + element != NULL; + element = cfg_list_next(element)) + { + const char *vname; + vconfig = cfg_listelt_value(element); + vname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name")); + if (vname && !strcasecmp(vname, viewname)) + break; + vconfig = NULL; + } + + /* Open save file for write configuration */ + CHECK(isc_stdio_open(view->new_zone_file, "a", &fp)); + + /* Mark view unfrozen so that zone can be added */ + dns_view_thaw(view); + result = configure_zone(cfg->config, parms, vconfig, + server->mctx, view, &cfg->actx, ISC_FALSE); + dns_view_freeze(view); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + /* Is it there yet? */ + CHECK(dns_zt_find(view->zonetable, &dnsname, 0, NULL, &zone)); + + /* + * Load the zone from the master file. If this fails, we'll + * need to undo the configuration we've done already. + */ + result = dns_zone_loadnew(zone); + if (result != ISC_R_SUCCESS) { + dns_db_t *dbp = NULL; + + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "addzone failed; reverting."); + + /* If the zone loaded partially, unload it */ + if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { + dns_db_detach(&dbp); + dns_zone_unload(zone); + } + + /* Remove the zone from the zone table */ + dns_zt_unmount(view->zonetable, zone); + goto cleanup; + } + + /* Flag the zone as having been added at runtime */ + dns_zone_setadded(zone, ISC_TRUE); + + /* Emit just the zone name from args */ + CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL)); + CHECK(isc_stdio_write(zonename, strlen(zonename), 1, fp, NULL)); + CHECK(isc_stdio_write(" ", 1, 1, fp, NULL)); + + /* Classname, if not default */ + if (classname != NULL && *classname != '\0') { + CHECK(isc_stdio_write(classname, strlen(classname), 1, fp, + NULL)); + CHECK(isc_stdio_write(" ", 1, 1, fp, NULL)); + } + + /* Find beginning of option block from args */ + for (argp = args; *argp; argp++, arglen--) { + if (*argp == '{') { /* Assume matching '}' */ + /* Add that to our file */ + CHECK(isc_stdio_write(argp, arglen, 1, fp, NULL)); + + /* Make sure we end with a LF */ + if (argp[arglen-1] != '\n') { + CHECK(isc_stdio_write("\n", 1, 1, fp, NULL)); + } + break; + } + } + + CHECK(isc_stdio_close(fp)); + fp = NULL; + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "zone %s added to view %s via addzone", + zonename, viewname); + + result = ISC_R_SUCCESS; + + cleanup: + if (fp != NULL) + isc_stdio_close(fp); + if (parser != NULL) { + if (config != NULL) + cfg_obj_destroy(parser, &config); + cfg_parser_destroy(&parser); + } + if (zone != NULL) + dns_zone_detach(&zone); + if (view != NULL) + dns_view_detach(&view); + if (nbuf != NULL) + isc_buffer_free(&nbuf); + + return (result); +} + +/* + * Act on a "delzone" command from the command channel. + */ +isc_result_t +ns_server_del_zone(ns_server_t *server, char *args) { + isc_result_t result; + dns_zone_t *zone = NULL; + dns_view_t *view = NULL; + dns_db_t *dbp = NULL; + const char *filename = NULL; + char *tmpname = NULL; + char buf[1024]; + const char *zonename = NULL; + size_t znamelen = 0; + FILE *ifp = NULL, *ofp = NULL; + + /* Parse parameters */ + CHECK(zone_from_args(server, args, &zone, &zonename)); + if (result != ISC_R_SUCCESS) + return (result); + if (zone == NULL) { + result = ISC_R_UNEXPECTEDEND; + goto cleanup; + } + + /* + * Was this zone originally added at runtime? + * If not, we can't delete it now. + */ + if (!dns_zone_getadded(zone)) { + result = ISC_R_NOPERM; + goto cleanup; + } + + if (zonename != NULL) + znamelen = strlen(zonename); + + /* Dig out configuration for this zone */ + view = dns_zone_getview(zone); + filename = view->new_zone_file; + if (filename == NULL) { + /* No adding zones in this view */ + result = ISC_R_FAILURE; + goto cleanup; + } + + /* Rewrite zone list */ + result = isc_stdio_open(filename, "r", &ifp); + if (ifp != NULL && result == ISC_R_SUCCESS) { + char *found = NULL, *p = NULL; + size_t n; + + /* Create a temporary file */ + CHECK(isc_string_printf(buf, 1023, "%s.%ld", filename, + (long)getpid())); + if (!(tmpname = isc_mem_strdup(server->mctx, buf))) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + CHECK(isc_stdio_open(tmpname, "w", &ofp)); + + /* Look for the entry for that zone */ + while (fgets(buf, 1024, ifp)) { + /* A 'zone' line */ + if (strncasecmp(buf, "zone", 4)) { + fputs(buf, ofp); + continue; + } + p = buf+4; + + /* Locate a name */ + while (*p && + ((*p == '"') || isspace((unsigned char)*p))) + p++; + + /* Is that the zone we're looking for */ + if (strncasecmp(p, zonename, znamelen)) { + fputs(buf, ofp); + continue; + } + + /* And nothing else? */ + p += znamelen; + if (isspace((unsigned char)*p) || + *p == '"' || *p == '{') { + /* This must be the entry */ + found = p; + break; + } + + /* Spit it out, keep looking */ + fputs(buf, ofp); + } + + /* Skip over an option block (matching # of braces) */ + if (found) { + int obrace = 0, cbrace = 0; + for (;;) { + while (*p) { + if (*p == '{') obrace++; + if (*p == '}') cbrace++; + p++; + } + if (obrace && (obrace == cbrace)) + break; + if (!fgets(buf, 1024, ifp)) + break; + p = buf; + } + + /* Just spool the remainder of the file out */ + result = isc_stdio_read(buf, 1, 1024, ifp, &n); + while (n > 0U) { + if (result == ISC_R_EOF) + result = ISC_R_SUCCESS; + CHECK(result); + isc_stdio_write(buf, 1, n, ofp, NULL); + result = isc_stdio_read(buf, 1, 1024, ifp, &n); + } + + /* Move temporary into place */ + CHECK(isc_file_rename(tmpname, view->new_zone_file)); + } else { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_WARNING, + "deleted zone %s was missing from " + "new zone file", zonename); + goto cleanup; + } + } + + /* Stop answering for this zone */ + if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { + dns_db_detach(&dbp); + dns_zone_unload(zone); + } + + CHECK(dns_zt_unmount(view->zonetable, zone)); + + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "zone %s removed via delzone", zonename); + + result = ISC_R_SUCCESS; + + cleanup: + if (ifp != NULL) + isc_stdio_close(ifp); + if (ofp != NULL) { + isc_stdio_close(ofp); + isc_file_remove(tmpname); + } + if (tmpname != NULL) + isc_mem_free(server->mctx, tmpname); + if (zone != NULL) + dns_zone_detach(&zone); + + return (result); +} + +static void +cfgctx_destroy(void **cfgp) { + struct cfg_context *cfg; + isc_mem_t *mctx; + + REQUIRE(cfgp != NULL && *cfgp != NULL); + cfg = *cfgp; + mctx = cfg->mctx; + cfg->mctx = NULL; + + if (cfg->parser != NULL) { + if (cfg->config != NULL) + cfg_obj_destroy(cfg->parser, &cfg->config); + cfg_parser_destroy(&cfg->parser); + } + cfg_aclconfctx_clear(&cfg->actx); + + isc_mem_put(mctx, cfg, sizeof(*cfg)); + isc_mem_detach(&mctx); + *cfgp = NULL; +} diff --git a/bin/named/statschannel.c b/bin/named/statschannel.c index c77d3ca..6dce8e0 100644 --- a/bin/named/statschannel.c +++ b/bin/named/statschannel.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: statschannel.c,v 1.14.64.11 2010-02-04 23:47:46 tbox Exp $ */ +/* $Id: statschannel.c,v 1.26 2010-02-04 23:49:13 tbox Exp $ */ /*! \file */ @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -823,9 +824,9 @@ generatexml(ns_server_t *server, int *buflen, xmlChar **buf) { TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "cache")); TRY0(xmlTextWriterWriteAttribute(writer, - ISC_XMLCHAR "name", - ISC_XMLCHAR - view->name)); + ISC_XMLCHAR "name", + ISC_XMLCHAR + dns_cache_getname(view->cache))); dumparg.result = ISC_R_SUCCESS; dns_rdatasetstats_dump(cachestats, rdatasetstats_dump, &dumparg, 0); @@ -1405,7 +1406,15 @@ ns_stats_dump(ns_server_t *server, FILE *fp) { if (strcmp(view->name, "_default") == 0) fprintf(fp, "[View: default]\n"); else - fprintf(fp, "[View: %s]\n", view->name); + fprintf(fp, "[View: %s (Cache: %s)]\n", view->name, + dns_cache_getname(view->cache)); + if (dns_view_iscacheshared(view)) { + /* + * Avoid dumping redundant statistics when the cache is + * shared. + */ + continue; + } dns_rdatasetstats_dump(cachestats, rdatasetstats_dump, &dumparg, 0); } diff --git a/bin/named/tkeyconf.c b/bin/named/tkeyconf.c index 7344978..66c2d7f 100644 --- a/bin/named/tkeyconf.c +++ b/bin/named/tkeyconf.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: tkeyconf.c,v 1.29 2007-06-19 23:46:59 tbox Exp $ */ +/* $Id: tkeyconf.c,v 1.33 2010-12-20 23:47:20 tbox Exp $ */ /*! \file */ @@ -77,8 +77,7 @@ ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx, isc_buffer_add(&b, strlen(s)); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); - RETERR(dns_name_fromtext(name, &b, dns_rootname, - ISC_FALSE, NULL)); + RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); type = DST_TYPE_PUBLIC|DST_TYPE_PRIVATE|DST_TYPE_KEY; RETERR(dst_key_fromfile(name, (dns_keytag_t) n, DNS_KEYALG_DH, type, NULL, mctx, &tctx->dhkey)); @@ -92,8 +91,7 @@ ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx, isc_buffer_add(&b, strlen(s)); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); - RETERR(dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, - NULL)); + RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); tctx->domain = isc_mem_get(mctx, sizeof(dns_name_t)); if (tctx->domain == NULL) { result = ISC_R_NOMEMORY; @@ -112,12 +110,22 @@ ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx, isc_buffer_add(&b, strlen(s)); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); - RETERR(dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, - NULL)); - RETERR(dst_gssapi_acquirecred(name, ISC_FALSE, - &tctx->gsscred)); + RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); + RETERR(dst_gssapi_acquirecred(name, ISC_FALSE, &tctx->gsscred)); } + obj = NULL; + result = cfg_map_get(options, "tkey-gssapi-keytab", &obj); + if (result == ISC_R_SUCCESS) { + s = cfg_obj_asstring(obj); + tctx->gssapi_keytab = isc_mem_strdup(mctx, s); + if (tctx->gssapi_keytab == NULL) { + result = ISC_R_NOMEMORY; + goto failure; + } + } + + *tctxp = tctx; return (ISC_R_SUCCESS); diff --git a/bin/named/tsigconf.c b/bin/named/tsigconf.c index e90a86b..19e8d38 100644 --- a/bin/named/tsigconf.c +++ b/bin/named/tsigconf.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: tsigconf.c,v 1.30 2007-06-19 23:46:59 tbox Exp $ */ +/* $Id: tsigconf.c,v 1.35 2011-01-11 23:47:12 tbox Exp $ */ /*! \file */ @@ -82,7 +82,7 @@ add_initial_keys(const cfg_obj_t *list, dns_tsig_keyring_t *ring, isc_buffer_add(&keynamesrc, strlen(keyid)); isc_buffer_init(&keynamebuf, keynamedata, sizeof(keynamedata)); ret = dns_name_fromtext(&keyname, &keynamesrc, dns_rootname, - ISC_TRUE, &keynamebuf); + DNS_NAME_DOWNCASE, &keynamebuf); if (ret != ISC_R_SUCCESS) goto failure; @@ -149,6 +149,8 @@ ns_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig, isc_result_t result; int i; + REQUIRE(ringp != NULL && *ringp == NULL); + i = 0; if (config != NULL) maps[i++] = config; @@ -176,6 +178,6 @@ ns_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig, return (ISC_R_SUCCESS); failure: - dns_tsigkeyring_destroy(&ring); + dns_tsigkeyring_detach(&ring); return (result); } diff --git a/bin/named/unix/Makefile.in b/bin/named/unix/Makefile.in index 502db25..ca92c49 100644 --- a/bin/named/unix/Makefile.in +++ b/bin/named/unix/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 1999-2001 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.10 2007-06-19 23:46:59 tbox Exp $ +# $Id: Makefile.in,v 1.13 2009-12-05 23:31:40 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ diff --git a/bin/named/unix/include/named/os.h b/bin/named/unix/include/named/os.h index 0a84608..c2768f4 100644 --- a/bin/named/unix/include/named/os.h +++ b/bin/named/unix/include/named/os.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: os.h,v 1.29 2008-10-24 01:44:48 tbox Exp $ */ +/* $Id: os.h,v 1.31 2009-08-05 23:47:43 tbox Exp $ */ #ifndef NS_OS_H #define NS_OS_H 1 @@ -51,8 +51,12 @@ ns_os_adjustnofile(void); void ns_os_minprivs(void); +FILE * +ns_os_openfile(const char *filename, mode_t mode, isc_boolean_t switch_user); + void ns_os_writepidfile(const char *filename, isc_boolean_t first_time); + void ns_os_shutdown(void); diff --git a/bin/named/unix/os.c b/bin/named/unix/os.c index 3f07784..53e9e45 100644 --- a/bin/named/unix/os.c +++ b/bin/named/unix/os.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: os.c,v 1.89.12.5 2009-03-02 03:03:54 marka Exp $ */ +/* $Id: os.c,v 1.104 2010-11-17 23:47:08 tbox Exp $ */ /*! \file */ @@ -291,6 +291,12 @@ linux_initialprivs(void) { */ SET_CAP(CAP_SYS_RESOURCE); + /* + * We need to be able to set the ownership of the containing + * directory of the pid file when we create it. + */ + SET_CAP(CAP_CHOWN); + linux_setcaps(caps); #ifdef HAVE_LIBCAP @@ -631,7 +637,7 @@ ns_os_minprivs(void) { } static int -safe_open(const char *filename, isc_boolean_t append) { +safe_open(const char *filename, mode_t mode, isc_boolean_t append) { int fd; struct stat sb; @@ -644,13 +650,11 @@ safe_open(const char *filename, isc_boolean_t append) { } if (append) - fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, - S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, mode); else { if (unlink(filename) < 0 && errno != ENOENT) return (-1); - fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, - S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode); } return (fd); } @@ -686,6 +690,15 @@ mkdirpath(char *filename, void (*report)(const char *, ...)) { } if (mkdirpath(filename, report) == -1) goto error; + /* + * Handle "//", "/./" and "/../" in path. + */ + if (!strcmp(slash + 1, "") || + !strcmp(slash + 1, ".") || + !strcmp(slash + 1, "..")) { + *slash = '/'; + return (0); + } mode = S_IRUSR | S_IWUSR | S_IXUSR; /* u=rwx */ mode |= S_IRGRP | S_IXGRP; /* g=rx */ mode |= S_IROTH | S_IXOTH; /* o=rx */ @@ -695,6 +708,13 @@ mkdirpath(char *filename, void (*report)(const char *, ...)) { strbuf); goto error; } + if (runas_pw != NULL && + chown(filename, runas_pw->pw_uid, + runas_pw->pw_gid) == -1) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + (*report)("couldn't chown '%s': %s", filename, + strbuf); + } } *slash = '/'; } @@ -705,11 +725,127 @@ mkdirpath(char *filename, void (*report)(const char *, ...)) { return (-1); } +static void +setperms(uid_t uid, gid_t gid) { + char strbuf[ISC_STRERRORSIZE]; +#if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) + gid_t oldgid, tmpg; +#endif +#if !defined(HAVE_SETEUID) && defined(HAVE_SETRESUID) + uid_t olduid, tmpu; +#endif +#if defined(HAVE_SETEGID) + if (getegid() != gid && setegid(gid) == -1) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + ns_main_earlywarning("unable to set effective gid to %ld: %s", + (long)gid, strbuf); + } +#elif defined(HAVE_SETRESGID) + if (getresgid(&tmpg, &oldgid, &tmpg) == -1 || oldgid != gid) { + if (setresgid(-1, gid, -1) == -1) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + ns_main_earlywarning("unable to set effective " + "gid to %d: %s", gid, strbuf); + } + } +#endif + +#if defined(HAVE_SETEUID) + if (geteuid() != uid && seteuid(uid) == -1) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + ns_main_earlywarning("unable to set effective uid to %ld: %s", + (long)uid, strbuf); + } +#elif defined(HAVE_SETRESUID) + if (getresuid(&tmpu, &olduid, &tmpu) == -1 || olduid != uid) { + if (setresuid(-1, uid, -1) == -1) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + ns_main_earlywarning("unable to set effective " + "uid to %d: %s", uid, strbuf); + } + } +#endif +} + +FILE * +ns_os_openfile(const char *filename, mode_t mode, isc_boolean_t switch_user) { + char strbuf[ISC_STRERRORSIZE], *f; + FILE *fp; + int fd; + + /* + * Make the containing directory if it doesn't exist. + */ + f = strdup(filename); + if (f == NULL) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + ns_main_earlywarning("couldn't strdup() '%s': %s", + filename, strbuf); + return (NULL); + } + if (mkdirpath(f, ns_main_earlywarning) == -1) { + free(f); + return (NULL); + } + free(f); + + if (switch_user && runas_pw != NULL) { + /* Set UID/GID to the one we'll be running with eventually */ + setperms(runas_pw->pw_uid, runas_pw->pw_gid); + + fd = safe_open(filename, mode, ISC_FALSE); + +#ifndef HAVE_LINUXTHREADS + /* Restore UID/GID to root */ + setperms(0, 0); +#endif /* HAVE_LINUXTHREADS */ + + if (fd == -1) { +#ifndef HAVE_LINUXTHREADS + fd = safe_open(filename, mode, ISC_FALSE); + if (fd != -1) { + ns_main_earlywarning("Required root " + "permissions to open " + "'%s'.", filename); + } else { + ns_main_earlywarning("Could not open " + "'%s'.", filename); + } + ns_main_earlywarning("Please check file and " + "directory permissions " + "or reconfigure the filename."); +#else /* HAVE_LINUXTHREADS */ + ns_main_earlywarning("Could not open " + "'%s'.", filename); + ns_main_earlywarning("Please check file and " + "directory permissions " + "or reconfigure the filename."); +#endif /* HAVE_LINUXTHREADS */ + } + } else { + fd = safe_open(filename, mode, ISC_FALSE); + } + + if (fd < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + ns_main_earlywarning("could not open file '%s': %s", + filename, strbuf); + return (NULL); + } + + fp = fdopen(fd, "w"); + if (fp == NULL) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + ns_main_earlywarning("could not fdopen() file '%s': %s", + filename, strbuf); + } + + return (fp); +} + void ns_os_writepidfile(const char *filename, isc_boolean_t first_time) { - int fd; FILE *lockfile; - size_t len; pid_t pid; char strbuf[ISC_STRERRORSIZE]; void (*report)(const char *, ...); @@ -725,40 +861,16 @@ ns_os_writepidfile(const char *filename, isc_boolean_t first_time) { if (filename == NULL) return; - len = strlen(filename); - pidfile = malloc(len + 1); + pidfile = strdup(filename); if (pidfile == NULL) { isc__strerror(errno, strbuf, sizeof(strbuf)); - (*report)("couldn't malloc '%s': %s", filename, strbuf); + (*report)("couldn't strdup() '%s': %s", filename, strbuf); return; } - /* This is safe. */ - strcpy(pidfile, filename); - - /* - * Make the containing directory if it doesn't exist. - */ - if (mkdirpath(pidfile, report) == -1) { - free(pidfile); - pidfile = NULL; - return; - } - - fd = safe_open(filename, ISC_FALSE); - if (fd < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - (*report)("couldn't open pid file '%s': %s", filename, strbuf); - free(pidfile); - pidfile = NULL; - return; - } - lockfile = fdopen(fd, "w"); + lockfile = ns_os_openfile(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, + first_time); if (lockfile == NULL) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - (*report)("could not fdopen() pid file '%s': %s", - filename, strbuf); - (void)close(fd); cleanup_pidfile(); return; } diff --git a/bin/named/update.c b/bin/named/update.c index 1504a44..eb1ed1d 100644 --- a/bin/named/update.c +++ b/bin/named/update.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: update.c,v 1.151.12.11 2010-02-26 23:48:43 tbox Exp $ */ +/* $Id: update.c,v 1.186.16.1.2.1 2011-06-02 23:47:28 tbox Exp $ */ #include @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -45,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -281,6 +283,47 @@ inc_stats(dns_zone_t *zone, isc_statscounter_t counter) { } /*% + * Check if we could have queried for the contents of this zone or + * if the zone is potentially updateable. + * If the zone can potentially be updated and the check failed then + * log a error otherwise we log a informational message. + */ +static isc_result_t +checkqueryacl(ns_client_t *client, dns_acl_t *queryacl, dns_name_t *zonename, + dns_acl_t *updateacl, dns_ssutable_t *ssutable) +{ + char namebuf[DNS_NAME_FORMATSIZE]; + char classbuf[DNS_RDATACLASS_FORMATSIZE]; + int level; + isc_result_t result; + + result = ns_client_checkaclsilent(client, NULL, queryacl, ISC_TRUE); + if (result != ISC_R_SUCCESS) { + dns_name_format(zonename, namebuf, sizeof(namebuf)); + dns_rdataclass_format(client->view->rdclass, classbuf, + sizeof(classbuf)); + + level = (updateacl == NULL && ssutable == NULL) ? + ISC_LOG_INFO : ISC_LOG_ERROR; + + ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY, + NS_LOGMODULE_UPDATE, level, + "update '%s/%s' denied due to allow-query", + namebuf, classbuf); + } else if (updateacl == NULL && ssutable == NULL) { + dns_name_format(zonename, namebuf, sizeof(namebuf)); + dns_rdataclass_format(client->view->rdclass, classbuf, + sizeof(classbuf)); + + result = DNS_R_REFUSED; + ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY, + NS_LOGMODULE_UPDATE, ISC_LOG_INFO, + "update '%s/%s' denied", namebuf, classbuf); + } + return (result); +} + +/*% * Override the default acl logging when checking whether a client * can update the zone or whether we can forward the request to the * master based on IP address. @@ -809,6 +852,9 @@ typedef struct { /* The ssu table to check against. */ dns_ssutable_t *table; + + /* the key used for TKEY requests */ + dst_key_t *key; } ssu_check_t; static isc_result_t @@ -825,14 +871,14 @@ ssu_checkrule(void *data, dns_rdataset_t *rrset) { return (ISC_R_SUCCESS); result = dns_ssutable_checkrules(ssuinfo->table, ssuinfo->signer, ssuinfo->name, ssuinfo->tcpaddr, - rrset->type); + rrset->type, ssuinfo->key); return (result == ISC_TRUE ? ISC_R_SUCCESS : ISC_R_FAILURE); } static isc_boolean_t ssu_checkall(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_ssutable_t *ssutable, dns_name_t *signer, - isc_netaddr_t *tcpaddr) + isc_netaddr_t *tcpaddr, dst_key_t *key) { isc_result_t result; ssu_check_t ssuinfo; @@ -841,6 +887,7 @@ ssu_checkall(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, ssuinfo.table = ssutable; ssuinfo.signer = signer; ssuinfo.tcpaddr = tcpaddr; + ssuinfo.key = key; result = foreach_rrset(db, ver, name, ssu_checkrule, &ssuinfo); return (ISC_TF(result == ISC_R_SUCCESS)); } @@ -889,7 +936,7 @@ temp_check_rrset(dns_difftuple_t *a, dns_difftuple_t *b) { b->op == DNS_DIFFOP_EXISTS); INSIST(a->rdata.type == b->rdata.type); INSIST(dns_name_equal(&a->name, &b->name)); - if (dns_rdata_compare(&a->rdata, &b->rdata) != 0) + if (dns_rdata_casecompare(&a->rdata, &b->rdata) != 0) return (DNS_R_NXRRSET); a = ISC_LIST_NEXT(a, link); b = ISC_LIST_NEXT(b, link); @@ -917,7 +964,7 @@ temp_order(const void *av, const void *bv) { r = (b->rdata.type - a->rdata.type); if (r != 0) return (r); - r = dns_rdata_compare(&a->rdata, &b->rdata); + r = dns_rdata_casecompare(&a->rdata, &b->rdata); return (r); } @@ -1146,7 +1193,7 @@ rr_equal_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { * dns_rdata_equal() (that used dns_name_equal()), since it * would be faster. Not a priority. */ - return (dns_rdata_compare(update_rr, db_rr) == 0 ? + return (dns_rdata_casecompare(update_rr, db_rr) == 0 ? ISC_TRUE : ISC_FALSE); } @@ -1208,11 +1255,10 @@ replaces_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { return (ISC_FALSE); INSIST(db_rr->length >= 4 && update_rr->length >= 4); /* - * Replace records added in this UPDATE request. + * Replace NSEC3PARAM records that only differ by the + * flags field. */ if (db_rr->data[0] == update_rr->data[0] && - db_rr->data[1] & DNS_NSEC3FLAG_UPDATE && - update_rr->data[1] & DNS_NSEC3FLAG_UPDATE && memcmp(db_rr->data+2, update_rr->data+2, update_rr->length - 2) == 0) return (ISC_TRUE); @@ -1293,7 +1339,7 @@ add_rr_prepare_action(void *data, rr_t *rr) { * If the update RR is a "duplicate" of the update RR, * the update should be silently ignored. */ - equal = ISC_TF(dns_rdata_compare(&rr->rdata, ctx->update_rr) == 0); + equal = ISC_TF(dns_rdata_casecompare(&rr->rdata, ctx->update_rr) == 0); if (equal && rr->ttl == ctx->update_rr_ttl) { ctx->ignore_add = ISC_TRUE; return (ISC_R_SUCCESS); @@ -1717,35 +1763,6 @@ next_active(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, return (result); } -static isc_boolean_t -has_opt_bit(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) { - isc_result_t result; - dns_rdata_t rdata = DNS_RDATA_INIT; - dns_rdataset_t rdataset; - isc_boolean_t has_bit = ISC_FALSE; - - dns_rdataset_init(&rdataset); - CHECK(dns_db_findrdataset(db, node, version, dns_rdatatype_nsec, - dns_rdatatype_none, 0, &rdataset, NULL)); - CHECK(dns_rdataset_first(&rdataset)); - dns_rdataset_current(&rdataset, &rdata); - has_bit = dns_nsec_typepresent(&rdata, dns_rdatatype_opt); - failure: - if (dns_rdataset_isassociated(&rdataset)) - dns_rdataset_disassociate(&rdataset); - return (has_bit); -} - -static void -set_bit(unsigned char *array, unsigned int index) { - unsigned int shift, bit; - - shift = 7 - (index % 8); - bit = 1 << shift; - - array[index / 8] |= bit; -} - /*% * Add a NSEC record for "name", recording the change in "diff". * The existing NSEC is removed. @@ -1777,24 +1794,6 @@ add_nsec(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, CHECK(dns_db_findnode(db, name, ISC_FALSE, &node)); dns_rdata_init(&rdata); CHECK(dns_nsec_buildrdata(db, ver, node, target, buffer, &rdata)); - /* - * Preserve the status of the OPT bit in the origin's NSEC record. - */ - if (dns_name_equal(dns_db_origin(db), name) && - has_opt_bit(db, ver, node)) - { - isc_region_t region; - dns_name_t next; - - dns_name_init(&next, NULL); - dns_rdata_toregion(&rdata, ®ion); - dns_name_fromregion(&next, ®ion); - isc_region_consume(®ion, next.length); - INSIST(region.length > (2 + dns_rdatatype_opt / 8) && - region.base[0] == 0 && - region.base[1] > dns_rdatatype_opt / 8); - set_bit(region.base + 2, dns_rdatatype_opt); - } dns_db_detachnode(db, &node); /* @@ -1856,44 +1855,6 @@ find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, return (result); } -static isc_boolean_t -ksk_sanity(dns_db_t *db, dns_dbversion_t *ver) { - isc_boolean_t ret = ISC_FALSE; - isc_boolean_t have_ksk = ISC_FALSE, have_nonksk = ISC_FALSE; - isc_result_t result; - dns_dbnode_t *node = NULL; - dns_rdataset_t rdataset; - dns_rdata_t rdata = DNS_RDATA_INIT; - dns_rdata_dnskey_t dnskey; - - dns_rdataset_init(&rdataset); - CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node)); - CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0, - &rdataset, NULL)); - CHECK(dns_rdataset_first(&rdataset)); - while (result == ISC_R_SUCCESS && (!have_ksk || !have_nonksk)) { - dns_rdataset_current(&rdataset, &rdata); - CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL)); - if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH)) - == DNS_KEYOWNER_ZONE) { - if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) - have_ksk = ISC_TRUE; - else - have_nonksk = ISC_TRUE; - } - dns_rdata_reset(&rdata); - result = dns_rdataset_next(&rdataset); - } - if (have_ksk && have_nonksk) - ret = ISC_TRUE; - failure: - if (dns_rdataset_isassociated(&rdataset)) - dns_rdataset_disassociate(&rdataset); - if (node != NULL) - dns_db_detachnode(db, &node); - return (ret); -} - /*% * Add RRSIG records for an RRset, recording the change in "diff". */ @@ -1902,7 +1863,7 @@ add_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys, isc_stdtime_t inception, isc_stdtime_t expire, - isc_boolean_t check_ksk) + isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly) { isc_result_t result; dns_dbnode_t *node = NULL; @@ -1910,7 +1871,7 @@ add_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_rdata_t sig_rdata = DNS_RDATA_INIT; isc_buffer_t buffer; unsigned char data[1024]; /* XXX */ - unsigned int i; + unsigned int i, j; isc_boolean_t added_sig = ISC_FALSE; isc_mem_t *mctx = client->mctx; @@ -1926,13 +1887,52 @@ add_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, (isc_stdtime_t) 0, &rdataset, NULL)); dns_db_detachnode(db, &node); +#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0) +#define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0) +#define ALG(x) dst_key_alg(x) + + /* + * If we are honoring KSK flags then we need to check that we + * have both KSK and non-KSK keys that are not revoked per + * algorithm. + */ for (i = 0; i < nkeys; i++) { + isc_boolean_t both = ISC_FALSE; - if (check_ksk && type != dns_rdatatype_dnskey && - (dst_key_flags(keys[i]) & DNS_KEYFLAG_KSK) != 0) + if (!dst_key_isprivate(keys[i])) continue; - if (!dst_key_isprivate(keys[i])) + if (check_ksk && !REVOKE(keys[i])) { + isc_boolean_t have_ksk, have_nonksk; + if (KSK(keys[i])) { + have_ksk = ISC_TRUE; + have_nonksk = ISC_FALSE; + } else { + have_ksk = ISC_FALSE; + have_nonksk = ISC_TRUE; + } + for (j = 0; j < nkeys; j++) { + if (j == i || ALG(keys[i]) != ALG(keys[j])) + continue; + if (REVOKE(keys[j])) + continue; + if (KSK(keys[j])) + have_ksk = ISC_TRUE; + else + have_nonksk = ISC_TRUE; + both = have_ksk && have_nonksk; + if (both) + break; + } + } + + if (both) { + if (type == dns_rdatatype_dnskey) { + if (!KSK(keys[i]) && keyset_kskonly) + continue; + } else if (KSK(keys[i])) + continue; + } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) continue; /* Calculate the signature, creating a RRSIG RDATA. */ @@ -1950,7 +1950,7 @@ add_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, } if (!added_sig) { update_log(client, zone, ISC_LOG_ERROR, - "found no private keys, " + "found no active private keys, " "unable to generate any signatures"); result = ISC_R_NOTFOUND; } @@ -2044,7 +2044,7 @@ add_exposed_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, isc_boolean_t cut, dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys, isc_stdtime_t inception, isc_stdtime_t expire, - isc_boolean_t check_ksk) + isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly) { isc_result_t result; dns_dbnode_t *node; @@ -2090,7 +2090,8 @@ add_exposed_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, if (flag) continue;; result = add_sigs(client, zone, db, ver, name, type, diff, - keys, nkeys, inception, expire, check_ksk); + keys, nkeys, inception, expire, + check_ksk, keyset_kskonly); if (result != ISC_R_SUCCESS) goto cleanup_iterator; } @@ -2120,8 +2121,7 @@ add_exposed_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, static isc_result_t update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *oldver, dns_dbversion_t *newver, - dns_diff_t *diff, isc_uint32_t sigvalidityinterval, - isc_boolean_t *deleted_zsk) + dns_diff_t *diff, isc_uint32_t sigvalidityinterval) { isc_result_t result; dns_difftuple_t *t; @@ -2130,7 +2130,7 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_diff_t sig_diff; dns_diff_t nsec_diff; dns_diff_t nsec_mindiff; - isc_boolean_t flag; + isc_boolean_t flag, build_nsec, build_nsec3; dst_key_t *zone_keys[MAXZONEKEYS]; unsigned int nkeys = 0; unsigned int i; @@ -2140,9 +2140,10 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdataset_t rdataset; dns_dbnode_t *node = NULL; - isc_boolean_t check_ksk; + isc_boolean_t check_ksk, keyset_kskonly; isc_boolean_t unsecure; isc_boolean_t cut; + dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); dns_diff_init(client->mctx, &diffnames); dns_diff_init(client->mctx, &affected); @@ -2172,27 +2173,8 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, */ check_ksk = ISC_TF((dns_zone_getoptions(zone) & DNS_ZONEOPT_UPDATECHECKKSK) != 0); - /* - * If we are not checking the ZSK flag then all DNSKEY's are - * already signing all RRsets so we don't need to trigger special - * changes. - */ - if (*deleted_zsk && (!check_ksk || !ksk_sanity(db, oldver))) - *deleted_zsk = ISC_FALSE; - - if (check_ksk) { - check_ksk = ksk_sanity(db, newver); - if (!check_ksk && ksk_sanity(db, oldver)) - update_log(client, zone, ISC_LOG_WARNING, - "disabling update-check-ksk"); - } - - /* - * If we have deleted a ZSK and we we still have some ZSK's - * we don't need to convert the KSK's to a ZSK's. - */ - if (*deleted_zsk && check_ksk) - *deleted_zsk = ISC_FALSE; + keyset_kskonly = ISC_TF((dns_zone_getoptions(zone) & + DNS_ZONEOPT_DNSKEYKSKONLY) != 0); /* * Get the NSEC/NSEC3 TTL from the SOA MINIMUM field. @@ -2259,7 +2241,7 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, CHECK(add_sigs(client, zone, db, newver, name, type, &sig_diff, zone_keys, nkeys, inception, expire, - check_ksk)); + check_ksk, keyset_kskonly)); } skip: /* Skip any other updates to the same RRset. */ @@ -2289,12 +2271,11 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, "removed any orphaned NSEC records"); /* - * If we don't have a NSEC record at the origin then we need to - * update the NSEC3 records. + * See if we need to build NSEC or NSEC3 chains. */ - CHECK(rrset_exists(db, newver, dns_db_origin(db), dns_rdatatype_nsec, - 0, &flag)); - if (!flag) + CHECK(dns_private_chains(db, newver, privatetype, &build_nsec, + &build_nsec3)); + if (!build_nsec) goto update_nsec3; update_log(client, zone, ISC_LOG_DEBUG(3), "rebuilding NSEC chain"); @@ -2398,16 +2379,25 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_rdatatype_any, 0, NULL, diff)); } else { /* - * This name is not obscured. It should have a NSEC. + * This name is not obscured. It needs to have a + * NSEC unless it is the at the origin, in which + * case it should already exist if there is a complete + * NSEC chain and if there isn't a complete NSEC chain + * we don't want to add one as that would signal that + * there is a complete NSEC chain. */ - CHECK(rrset_exists(db, newver, name, - dns_rdatatype_nsec, 0, &flag)); - if (! flag) - CHECK(add_placeholder_nsec(db, newver, name, - diff)); + if (!dns_name_equal(name, dns_db_origin(db))) { + CHECK(rrset_exists(db, newver, name, + dns_rdatatype_nsec, 0, + &flag)); + if (!flag) + CHECK(add_placeholder_nsec(db, newver, + name, diff)); + } CHECK(add_exposed_sigs(client, zone, db, newver, name, cut, diff, zone_keys, nkeys, - inception, expire, check_ksk)); + inception, expire, check_ksk, + keyset_kskonly)); } } @@ -2469,7 +2459,7 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, CHECK(add_sigs(client, zone, db, newver, &t->name, dns_rdatatype_nsec, &sig_diff, zone_keys, nkeys, inception, expire, - check_ksk)); + check_ksk, keyset_kskonly)); } else { INSIST(0); } @@ -2491,13 +2481,7 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, INSIST(ISC_LIST_EMPTY(nsec_diff.tuples)); INSIST(ISC_LIST_EMPTY(nsec_mindiff.tuples)); - /* - * Check if we have any active NSEC3 chains by looking for a - * NSEC3PARAM RRset. - */ - CHECK(rrset_exists(db, newver, dns_db_origin(db), - dns_rdatatype_nsec3param, 0, &flag)); - if (!flag) { + if (!build_nsec3) { update_log(client, zone, ISC_LOG_DEBUG(3), "no NSEC3 chains to rebuild"); goto failure; @@ -2521,6 +2505,7 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, isc_boolean_t ns_existed, dname_existed; isc_boolean_t ns_exists, dname_exists; + isc_boolean_t exists, existed; if (t->rdata.type == dns_rdatatype_nsec || t->rdata.type == dns_rdatatype_rrsig) { @@ -2539,7 +2524,9 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, CHECK(rrset_exists(db, newver, name, dns_rdatatype_dname, 0, &dname_exists)); - if ((ns_exists || dname_exists) == (ns_existed || dname_existed)) + exists = ns_exists || dname_exists; + existed = ns_existed || dname_existed; + if (exists == existed) goto nextname; /* * There was a delegation change. Mark all subdomains @@ -2563,14 +2550,16 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, if (!flag) { CHECK(delete_if(rrsig_p, db, newver, name, dns_rdatatype_any, 0, NULL, diff)); - CHECK(dns_nsec3_delnsec3s(db, newver, name, - &nsec_diff)); + CHECK(dns_nsec3_delnsec3sx(db, newver, name, + privatetype, &nsec_diff)); } else { CHECK(add_exposed_sigs(client, zone, db, newver, name, cut, diff, zone_keys, nkeys, - inception, expire, check_ksk)); - CHECK(dns_nsec3_addnsec3s(db, newver, name, nsecttl, - unsecure, &nsec_diff)); + inception, expire, check_ksk, + keyset_kskonly)); + CHECK(dns_nsec3_addnsec3sx(db, newver, name, nsecttl, + unsecure, privatetype, + &nsec_diff)); } } @@ -2601,7 +2590,8 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, CHECK(add_sigs(client, zone, db, newver, &t->name, dns_rdatatype_nsec3, &sig_diff, zone_keys, nkeys, - inception, expire, check_ksk)); + inception, expire, check_ksk, + keyset_kskonly)); } else { INSIST(0); } @@ -2734,6 +2724,7 @@ ns_update_start(ns_client_t *client, isc_result_t sigresult) { switch(dns_zone_gettype(zone)) { case dns_zone_master: + case dns_zone_dlz: /* * We can now fail due to a bad signature as we now know * that we are the master. @@ -2943,7 +2934,7 @@ rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, result = dns_rdataset_next(&rdataset)) { dns_rdata_t myrdata = DNS_RDATA_INIT; dns_rdataset_current(&rdataset, &myrdata); - if (!dns_rdata_compare(&myrdata, rdata)) + if (!dns_rdata_casecompare(&myrdata, rdata)) break; } dns_rdataset_disassociate(&rdataset); @@ -2961,7 +2952,9 @@ rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, } static isc_result_t -get_iterations(dns_db_t *db, dns_dbversion_t *ver, unsigned int *iterationsp) { +get_iterations(dns_db_t *db, dns_dbversion_t *ver, dns_rdatatype_t privatetype, + unsigned int *iterationsp) +{ dns_dbnode_t *node = NULL; dns_rdata_nsec3param_t nsec3param; dns_rdataset_t rdataset; @@ -2975,7 +2968,33 @@ get_iterations(dns_db_t *db, dns_dbversion_t *ver, unsigned int *iterationsp) { return (result); result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0, (isc_stdtime_t) 0, &rdataset, NULL); - dns_db_detachnode(db, &node); + if (result == ISC_R_NOTFOUND) + goto try_private; + if (result != ISC_R_SUCCESS) + goto failure; + + for (result = dns_rdataset_first(&rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&rdataset)) { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_current(&rdataset, &rdata); + CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL)); + if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) + continue; + if (nsec3param.iterations > iterations) + iterations = nsec3param.iterations; + } + if (result != ISC_R_NOMORE) + goto failure; + + dns_rdataset_disassociate(&rdataset); + + try_private: + if (privatetype == 0) + goto success; + + result = dns_db_findrdataset(db, node, ver, privatetype, + 0, (isc_stdtime_t) 0, &rdataset, NULL); if (result == ISC_R_NOTFOUND) goto success; if (result != ISC_R_SUCCESS) @@ -2984,8 +3003,14 @@ get_iterations(dns_db_t *db, dns_dbversion_t *ver, unsigned int *iterationsp) { for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { + unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; + dns_rdata_t private = DNS_RDATA_INIT; dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_current(&rdataset, &rdata); + if (!dns_nsec3param_fromprivate(&private, &rdata, + buf, sizeof(buf))) + continue; CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL)); if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) continue; @@ -3000,6 +3025,8 @@ get_iterations(dns_db_t *db, dns_dbversion_t *ver, unsigned int *iterationsp) { result = ISC_R_SUCCESS; failure: + if (node != NULL) + dns_db_detachnode(db, &node); if (dns_rdataset_isassociated(&rdataset)) dns_rdataset_disassociate(&rdataset); return (result); @@ -3013,77 +3040,83 @@ static isc_result_t check_dnssec(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff) { - dns_diff_t temp_diff; - dns_diffop_t op; - dns_difftuple_t *tuple, *newtuple = NULL, *next; - isc_boolean_t flag; + dns_difftuple_t *tuple; + isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE; isc_result_t result; unsigned int iterations = 0, max; + dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); - dns_diff_init(diff->mctx, &temp_diff); - - CHECK(dns_nsec_nseconly(db, ver, &flag)); + /* Scan the tuples for an NSEC-only DNSKEY or an NSEC3PARAM */ + for (tuple = ISC_LIST_HEAD(diff->tuples); + tuple != NULL; + tuple = ISC_LIST_NEXT(tuple, link)) { + if (tuple->op != DNS_DIFFOP_ADD) + continue; - if (flag) - CHECK(dns_nsec3_active(db, ver, ISC_FALSE, &flag)); - if (flag) { - update_log(client, zone, ISC_LOG_WARNING, - "NSEC only DNSKEYs and NSEC3 chains not allowed"); - } else { - CHECK(get_iterations(db, ver, &iterations)); - CHECK(dns_nsec3_maxiterations(db, ver, client->mctx, &max)); - if (max != 0 && iterations > max) { - flag = ISC_TRUE; - update_log(client, zone, ISC_LOG_WARNING, - "too many NSEC3 iterations (%u) for " - "weakest DNSKEY (%u)", iterations, max); + if (tuple->rdata.type == dns_rdatatype_dnskey) { + isc_uint8_t alg; + alg = tuple->rdata.data[3]; + if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 || + alg == DST_ALG_DSA || alg == DST_ALG_ECC) { + nseconly = ISC_TRUE; + break; + } + } else if (tuple->rdata.type == dns_rdatatype_nsec3param) { + nsec3 = ISC_TRUE; + break; } } - if (flag) { - for (tuple = ISC_LIST_HEAD(diff->tuples); - tuple != NULL; - tuple = next) { - next = ISC_LIST_NEXT(tuple, link); - if (tuple->rdata.type != dns_rdatatype_dnskey && - tuple->rdata.type != dns_rdatatype_nsec3param) - continue; - op = (tuple->op == DNS_DIFFOP_DEL) ? - DNS_DIFFOP_ADD : DNS_DIFFOP_DEL; - CHECK(dns_difftuple_create(temp_diff.mctx, op, - &tuple->name, tuple->ttl, - &tuple->rdata, &newtuple)); - CHECK(do_one_tuple(&newtuple, db, ver, &temp_diff)); - INSIST(newtuple == NULL); - } - for (tuple = ISC_LIST_HEAD(temp_diff.tuples); - tuple != NULL; - tuple = ISC_LIST_HEAD(temp_diff.tuples)) { - ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); - dns_diff_appendminimal(diff, &tuple); - } + + /* Check existing DB for NSEC-only DNSKEY */ + if (!nseconly) + CHECK(dns_nsec_nseconly(db, ver, &nseconly)); + + /* Check existing DB for NSEC3 */ + if (!nsec3) + CHECK(dns_nsec3_activex(db, ver, ISC_FALSE, + privatetype, &nsec3)); + + /* Refuse to allow NSEC3 with NSEC-only keys */ + if (nseconly && nsec3) { + update_log(client, zone, ISC_LOG_ERROR, + "NSEC only DNSKEYs and NSEC3 chains not allowed"); + result = DNS_R_REFUSED; + goto failure; } + /* Verify NSEC3 params */ + CHECK(get_iterations(db, ver, privatetype, &iterations)); + CHECK(dns_nsec3_maxiterations(db, ver, client->mctx, &max)); + if (max != 0 && iterations > max) { + update_log(client, zone, ISC_LOG_ERROR, + "too many NSEC3 iterations (%u) for " + "weakest DNSKEY (%u)", iterations, max); + result = DNS_R_REFUSED; + goto failure; + } failure: - dns_diff_clear(&temp_diff); return (result); } -#ifdef ALLOW_NSEC3PARAM_UPDATE /* * Delay NSEC3PARAM changes as they need to be applied to the whole zone. */ static isc_result_t add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, - dns_name_t *name, dns_dbversion_t *ver, dns_diff_t *diff) + dns_dbversion_t *ver, dns_diff_t *diff) { isc_result_t result = ISC_R_SUCCESS; dns_difftuple_t *tuple, *newtuple = NULL, *next; dns_rdata_t rdata = DNS_RDATA_INIT; - unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; + unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE + 1]; dns_diff_t temp_diff; dns_diffop_t op; isc_boolean_t flag; + dns_name_t *name = dns_zone_getorigin(zone); + dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); + isc_uint32_t ttl = 0; + isc_boolean_t ttl_good = ISC_FALSE; update_log(client, zone, ISC_LOG_DEBUG(3), "checking for NSEC3PARAM changes"); @@ -3106,55 +3139,143 @@ add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, ISC_LIST_APPEND(temp_diff.tuples, tuple, link); } + /* + * Extract TTL changes pairs, we don't need to convert these to + * delayed changes. + */ for (tuple = ISC_LIST_HEAD(temp_diff.tuples); tuple != NULL; tuple = next) { - if (tuple->op == DNS_DIFFOP_ADD) { + if (!ttl_good) { + /* + * Any adds here will contain the final + * NSEC3PARAM RRset TTL. + */ + ttl = tuple->ttl; + ttl_good = ISC_TRUE; + } + /* + * Walk the temp_diff list looking for the + * corresponding delete. + */ + next = ISC_LIST_HEAD(temp_diff.tuples); + while (next != NULL) { + unsigned char *next_data = next->rdata.data; + unsigned char *tuple_data = tuple->rdata.data; + if (next->op == DNS_DIFFOP_DEL && + next->rdata.length == tuple->rdata.length && + !memcmp(next_data, tuple_data, + next->rdata.length)) { + ISC_LIST_UNLINK(temp_diff.tuples, next, + link); + ISC_LIST_APPEND(diff->tuples, next, + link); + break; + } + next = ISC_LIST_NEXT(next, link); + } + /* + * If we have not found a pair move onto the next + * tuple. + */ + if (next == NULL) { + next = ISC_LIST_NEXT(tuple, link); + continue; + } + /* + * Find the next tuple to be processed before + * unlinking then complete moving the pair to 'diff'. + */ + next = ISC_LIST_NEXT(tuple, link); + ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); + ISC_LIST_APPEND(diff->tuples, tuple, link); + } else next = ISC_LIST_NEXT(tuple, link); + } + + /* + * Preserve any ongoing changes from a BIND 9.6.x upgrade. + * + * Any NSEC3PARAM records with flags other than OPTOUT named + * in managing and should not be touched so revert such changes + * taking into account any TTL change of the NSEC3PARAM RRset. + */ + for (tuple = ISC_LIST_HEAD(temp_diff.tuples); + tuple != NULL; tuple = next) { + next = ISC_LIST_NEXT(tuple, link); + if ((tuple->rdata.data[1] & ~DNS_NSEC3FLAG_OPTOUT) != 0) { + /* + * If we havn't had any adds then the tuple->ttl must + * be the original ttl and should be used for any + * future changes. + */ + if (!ttl_good) { + ttl = tuple->ttl; + ttl_good = ISC_TRUE; + } + op = (tuple->op == DNS_DIFFOP_DEL) ? + DNS_DIFFOP_ADD : DNS_DIFFOP_DEL; + CHECK(dns_difftuple_create(diff->mctx, op, name, + ttl, &tuple->rdata, + &newtuple)); + CHECK(do_one_tuple(&newtuple, db, ver, diff)); + ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); + dns_diff_appendminimal(diff, &tuple); + } + } + + /* + * We now have just the actual changes to the NSEC3PARAM RRset. + * Convert the adds to delayed adds and the deletions into delayed + * deletions. + */ + for (tuple = ISC_LIST_HEAD(temp_diff.tuples); + tuple != NULL; tuple = next) { + /* + * If we havn't had any adds then the tuple->ttl must be the + * original ttl and should be used for any future changes. + */ + if (!ttl_good) { + ttl = tuple->ttl; + ttl_good = ISC_TRUE; + } + if (tuple->op == DNS_DIFFOP_ADD) { + /* + * Look for any deletes which match this ADD ignoring + * OPTOUT. We don't need to explictly remove them as + * they will be removed a side effect of processing + * the add. + */ + next = ISC_LIST_HEAD(temp_diff.tuples); while (next != NULL) { unsigned char *next_data = next->rdata.data; unsigned char *tuple_data = tuple->rdata.data; - if (next_data[0] != tuple_data[0] || - /* Ignore flags. */ + if (next->op != DNS_DIFFOP_DEL || + next->rdata.length != tuple->rdata.length || + next_data[0] != tuple_data[0] || next_data[2] != tuple_data[2] || next_data[3] != tuple_data[3] || - next_data[4] != tuple_data[4] || - !memcmp(&next_data[5], &tuple_data[5], - tuple_data[4])) { + memcmp(next_data + 4, tuple_data + 4, + tuple->rdata.length - 4)) { next = ISC_LIST_NEXT(next, link); continue; } - op = (next->op == DNS_DIFFOP_DEL) ? - DNS_DIFFOP_ADD : DNS_DIFFOP_DEL; - CHECK(dns_difftuple_create(diff->mctx, op, - name, next->ttl, - &next->rdata, - &newtuple)); - CHECK(do_one_tuple(&newtuple, db, ver, diff)); ISC_LIST_UNLINK(temp_diff.tuples, next, link); - dns_diff_appendminimal(diff, &next); - next = ISC_LIST_NEXT(tuple, link); + ISC_LIST_APPEND(diff->tuples, next, link); + next = ISC_LIST_HEAD(temp_diff.tuples); } - - INSIST(tuple->rdata.data[1] & DNS_NSEC3FLAG_UPDATE); - /* * See if we already have a CREATE request in progress. */ - dns_rdata_clone(&tuple->rdata, &rdata); - INSIST(rdata.length <= sizeof(buf)); - memcpy(buf, rdata.data, rdata.length); - buf[1] |= DNS_NSEC3FLAG_CREATE; - buf[1] &= ~DNS_NSEC3FLAG_UPDATE; - rdata.data = buf; - + dns_nsec3param_toprivate(&tuple->rdata, &rdata, + privatetype, buf, sizeof(buf)); + buf[2] |= DNS_NSEC3FLAG_CREATE; CHECK(rr_exists(db, ver, name, &rdata, &flag)); if (!flag) { CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, - name, tuple->ttl, - &rdata, + name, 0, &rdata, &newtuple)); CHECK(do_one_tuple(&newtuple, db, ver, diff)); } @@ -3164,26 +3285,26 @@ add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, * otherwise indentical chain with a reversed * OPTOUT state. */ - buf[1] ^= DNS_NSEC3FLAG_OPTOUT; + buf[2] ^= DNS_NSEC3FLAG_OPTOUT; CHECK(rr_exists(db, ver, name, &rdata, &flag)); if (flag) { CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, - name, tuple->ttl, - &rdata, + name, 0, &rdata, &newtuple)); CHECK(do_one_tuple(&newtuple, db, ver, diff)); } /* - * Remove the temporary add record. + * Find the next tuple to be processed and remove the + * temporary add record. */ + next = ISC_LIST_NEXT(tuple, link); CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, - name, tuple->ttl, - &tuple->rdata, &newtuple)); + name, ttl, &tuple->rdata, + &newtuple)); CHECK(do_one_tuple(&newtuple, db, ver, diff)); - next = ISC_LIST_NEXT(tuple, link); ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); dns_diff_appendminimal(diff, &tuple); dns_rdata_reset(&rdata); @@ -3191,50 +3312,33 @@ add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, next = ISC_LIST_NEXT(tuple, link); } - /* - * Reverse any pending changes. - */ for (tuple = ISC_LIST_HEAD(temp_diff.tuples); tuple != NULL; tuple = next) { - next = ISC_LIST_NEXT(tuple, link); - if ((tuple->rdata.data[1] & ~DNS_NSEC3FLAG_OPTOUT) != 0) { - op = (tuple->op == DNS_DIFFOP_DEL) ? - DNS_DIFFOP_ADD : DNS_DIFFOP_DEL; - CHECK(dns_difftuple_create(diff->mctx, op, name, - tuple->ttl, &tuple->rdata, - &newtuple)); - CHECK(do_one_tuple(&newtuple, db, ver, diff)); - ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); - dns_diff_appendminimal(diff, &tuple); - } - } - /* - * Convert deletions into delayed deletions. - */ - for (tuple = ISC_LIST_HEAD(temp_diff.tuples); - tuple != NULL; tuple = next) { + INSIST(ttl_good); + next = ISC_LIST_NEXT(tuple, link); /* * See if we already have a REMOVE request in progress. */ - dns_rdata_clone(&tuple->rdata, &rdata); - INSIST(rdata.length <= sizeof(buf)); - memcpy(buf, rdata.data, rdata.length); - buf[1] |= DNS_NSEC3FLAG_REMOVE; - rdata.data = buf; + dns_nsec3param_toprivate(&tuple->rdata, &rdata, privatetype, + buf, sizeof(buf)); + + buf[2] |= DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC; CHECK(rr_exists(db, ver, name, &rdata, &flag)); + if (!flag) { + buf[2] &= ~DNS_NSEC3FLAG_NONSEC; + CHECK(rr_exists(db, ver, name, &rdata, &flag)); + } if (!flag) { CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, - name, tuple->ttl, &rdata, - &newtuple)); + name, 0, &rdata, &newtuple)); CHECK(do_one_tuple(&newtuple, db, ver, diff)); } CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, - tuple->ttl, &tuple->rdata, - &newtuple)); + ttl, &tuple->rdata, &newtuple)); CHECK(do_one_tuple(&newtuple, db, ver, diff)); ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); dns_diff_appendminimal(diff, &tuple); @@ -3246,17 +3350,75 @@ add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_diff_clear(&temp_diff); return (result); } -#endif + +static isc_result_t +rollback_private(dns_db_t *db, dns_rdatatype_t privatetype, + dns_dbversion_t *ver, dns_diff_t *diff) +{ + dns_diff_t temp_diff; + dns_diffop_t op; + dns_difftuple_t *tuple, *newtuple = NULL, *next; + dns_name_t *name = dns_db_origin(db); + isc_mem_t *mctx = diff->mctx; + isc_result_t result; + + if (privatetype == 0) + return (ISC_R_SUCCESS); + + dns_diff_init(mctx, &temp_diff); + + /* + * Extract the changes to be rolled back. + */ + for (tuple = ISC_LIST_HEAD(diff->tuples); + tuple != NULL; tuple = next) { + + next = ISC_LIST_NEXT(tuple, link); + + if (tuple->rdata.type != privatetype || + !dns_name_equal(name, &tuple->name)) + continue; + + /* + * Allow records which indicate that a zone has been + * signed with a DNSKEY to be be removed. + */ + if (tuple->op == DNS_DIFFOP_DEL && + tuple->rdata.length == 5 && + tuple->rdata.data[0] != 0 && + tuple->rdata.data[4] != 0) + continue; + + ISC_LIST_UNLINK(diff->tuples, tuple, link); + ISC_LIST_PREPEND(temp_diff.tuples, tuple, link); + } + + /* + * Rollback the changes. + */ + while ((tuple = ISC_LIST_HEAD(temp_diff.tuples)) != NULL) { + op = (tuple->op == DNS_DIFFOP_DEL) ? + DNS_DIFFOP_ADD : DNS_DIFFOP_DEL; + CHECK(dns_difftuple_create(mctx, op, name, tuple->ttl, + &tuple->rdata, &newtuple)); + CHECK(do_one_tuple(&newtuple, db, ver, &temp_diff)); + } + result = ISC_R_SUCCESS; + + failure: + dns_diff_clear(&temp_diff); + return (result); +} /* * Add records to cause the delayed signing of the zone by added DNSKEY * to remove the RRSIG records generated by a deleted DNSKEY. */ static isc_result_t -add_signing_records(dns_db_t *db, dns_name_t *name, dns_dbversion_t *ver, - dns_rdatatype_t privatetype, dns_diff_t *diff) +add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype, + dns_dbversion_t *ver, dns_diff_t *diff) { - dns_difftuple_t *tuple, *newtuple = NULL; + dns_difftuple_t *tuple, *newtuple = NULL, *next; dns_rdata_dnskey_t dnskey; dns_rdata_t rdata = DNS_RDATA_INIT; isc_boolean_t flag; @@ -3264,13 +3426,82 @@ add_signing_records(dns_db_t *db, dns_name_t *name, dns_dbversion_t *ver, isc_result_t result = ISC_R_SUCCESS; isc_uint16_t keyid; unsigned char buf[5]; + dns_name_t *name = dns_db_origin(db); + dns_diff_t temp_diff; + + dns_diff_init(diff->mctx, &temp_diff); + /* + * Extract the DNSKEY tuples from the list. + */ for (tuple = ISC_LIST_HEAD(diff->tuples); - tuple != NULL; - tuple = ISC_LIST_NEXT(tuple, link)) { + tuple != NULL; tuple = next) { + + next = ISC_LIST_NEXT(tuple, link); + if (tuple->rdata.type != dns_rdatatype_dnskey) continue; + ISC_LIST_UNLINK(diff->tuples, tuple, link); + ISC_LIST_APPEND(temp_diff.tuples, tuple, link); + } + + /* + * Extract TTL changes pairs, we don't need signing records for these. + */ + for (tuple = ISC_LIST_HEAD(temp_diff.tuples); + tuple != NULL; tuple = next) { + if (tuple->op == DNS_DIFFOP_ADD) { + /* + * Walk the temp_diff list looking for the + * corresponding delete. + */ + next = ISC_LIST_HEAD(temp_diff.tuples); + while (next != NULL) { + unsigned char *next_data = next->rdata.data; + unsigned char *tuple_data = tuple->rdata.data; + if (next->op == DNS_DIFFOP_DEL && + dns_name_equal(&tuple->name, &next->name) && + next->rdata.length == tuple->rdata.length && + !memcmp(next_data, tuple_data, + next->rdata.length)) { + ISC_LIST_UNLINK(temp_diff.tuples, next, + link); + ISC_LIST_APPEND(diff->tuples, next, + link); + break; + } + next = ISC_LIST_NEXT(next, link); + } + /* + * If we have not found a pair move onto the next + * tuple. + */ + if (next == NULL) { + next = ISC_LIST_NEXT(tuple, link); + continue; + } + /* + * Find the next tuple to be processed before + * unlinking then complete moving the pair to 'diff'. + */ + next = ISC_LIST_NEXT(tuple, link); + ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); + ISC_LIST_APPEND(diff->tuples, tuple, link); + } else + next = ISC_LIST_NEXT(tuple, link); + } + + /* + * Process the remaining DNSKEY entries. + */ + for (tuple = ISC_LIST_HEAD(temp_diff.tuples); + tuple != NULL; + tuple = ISC_LIST_HEAD(temp_diff.tuples)) { + + ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); + ISC_LIST_APPEND(diff->tuples, tuple, link); + dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL); if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH)) @@ -3278,6 +3509,7 @@ add_signing_records(dns_db_t *db, dns_name_t *name, dns_dbversion_t *ver, continue; dns_rdata_toregion(&tuple->rdata, &r); + keyid = dst_region_computeid(&r, dnskey.algorithm); buf[0] = dnskey.algorithm; @@ -3310,87 +3542,25 @@ add_signing_records(dns_db_t *db, dns_name_t *name, dns_dbversion_t *ver, INSIST(newtuple == NULL); } } + failure: + dns_diff_clear(&temp_diff); return (result); } -#ifdef ALLOW_NSEC3PARAM_UPDATE -/* - * Mark all NSEC3 chains for deletion without creating a NSEC chain as - * a side effect of deleting the last chain. - */ -static isc_result_t -delete_chains(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, - dns_diff_t *diff) -{ - dns_dbnode_t *node = NULL; - dns_difftuple_t *tuple = NULL; - dns_name_t next; - dns_rdata_t rdata = DNS_RDATA_INIT; - dns_rdataset_t rdataset; - isc_boolean_t flag; - isc_result_t result = ISC_R_SUCCESS; - unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; - - dns_name_init(&next, NULL); - dns_rdataset_init(&rdataset); - - result = dns_db_getoriginnode(db, &node); - if (result != ISC_R_SUCCESS) - return (result); - - /* - * Cause all NSEC3 chains to be deleted. - */ - result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, - 0, (isc_stdtime_t) 0, &rdataset, NULL); - if (result == ISC_R_NOTFOUND) - goto success; - if (result != ISC_R_SUCCESS) - goto failure; - - for (result = dns_rdataset_first(&rdataset); - result == ISC_R_SUCCESS; - result = dns_rdataset_next(&rdataset)) { - dns_rdataset_current(&rdataset, &rdata); - INSIST(rdata.length <= sizeof(buf)); - memcpy(buf, rdata.data, rdata.length); - - if (buf[1] == (DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC)) { - dns_rdata_reset(&rdata); - continue; - } - - CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, - origin, 0, &rdata, &tuple)); - CHECK(do_one_tuple(&tuple, db, ver, diff)); - INSIST(tuple == NULL); - - buf[1] = DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC; - rdata.data = buf; - - CHECK(rr_exists(db, ver, origin, &rdata, &flag)); +static isc_boolean_t +isdnssec(dns_db_t *db, dns_dbversion_t *ver, dns_rdatatype_t privatetype) { + isc_result_t result; + isc_boolean_t build_nsec, build_nsec3; - if (!flag) { - CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, - origin, 0, &rdata, &tuple)); - CHECK(do_one_tuple(&tuple, db, ver, diff)); - INSIST(tuple == NULL); - } - dns_rdata_reset(&rdata); - } - if (result != ISC_R_NOMORE) - goto failure; - success: - result = ISC_R_SUCCESS; + if (dns_db_issecure(db)) + return (ISC_TRUE); - failure: - if (dns_rdataset_isassociated(&rdataset)) - dns_rdataset_disassociate(&rdataset); - dns_db_detachnode(db, &node); - return (result); + result = dns_private_chains(db, ver, privatetype, + &build_nsec, &build_nsec3); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + return (build_nsec || build_nsec3); } -#endif static void update_action(isc_task_t *task, isc_event_t *event) { @@ -3414,15 +3584,10 @@ update_action(isc_task_t *task, isc_event_t *event) { dns_fixedname_t tmpnamefixed; dns_name_t *tmpname = NULL; unsigned int options; - isc_boolean_t deleted_zsk; dns_difftuple_t *tuple; dns_rdata_dnskey_t dnskey; -#ifdef ALLOW_NSEC3PARAM_UPDATE - unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; -#endif -#if !defined(ALLOW_SECURE_TO_INSECURE) || !defined(ALLOW_INSECURE_TO_SECURE) isc_boolean_t had_dnskey; -#endif + dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); INSIST(event->ev_type == DNS_EVENT_UPDATE); @@ -3433,6 +3598,18 @@ update_action(isc_task_t *task, isc_event_t *event) { zonename = dns_db_origin(db); zoneclass = dns_db_class(db); dns_zone_getssutable(zone, &ssutable); + + /* + * Update message processing can leak record existance information + * so check that we are allowed to query this zone. Additionally + * if we would refuse all updates for this zone we bail out here. + */ + CHECK(checkqueryacl(client, dns_zone_getqueryacl(zone), zonename, + dns_zone_getupdateacl(zone), ssutable)); + + /* + * Get old and new versions now that queryacl has been checked. + */ dns_db_currentversion(db, &oldver); CHECK(dns_db_newversion(db, &ver)); @@ -3525,7 +3702,6 @@ update_action(isc_task_t *task, isc_event_t *event) { if (result != ISC_R_NOMORE) FAIL(result); - /* * Perform the final check of the "rrset exists (value dependent)" * prerequisites. @@ -3619,31 +3795,31 @@ update_action(isc_task_t *task, isc_event_t *event) { update_class); FAIL(DNS_R_FORMERR); } + /* * draft-ietf-dnsind-simple-secure-update-01 says * "Unlike traditional dynamic update, the client * is forbidden from updating NSEC records." */ - if (dns_db_issecure(db)) { - if (rdata.type == dns_rdatatype_nsec3) { - FAILC(DNS_R_REFUSED, - "explicit NSEC3 updates are not allowed " - "in secure zones"); - } else if (rdata.type == dns_rdatatype_nsec) { - FAILC(DNS_R_REFUSED, - "explicit NSEC updates are not allowed " - "in secure zones"); - } else if (rdata.type == dns_rdatatype_rrsig && - !dns_name_equal(name, zonename)) { - FAILC(DNS_R_REFUSED, - "explicit RRSIG updates are currently " - "not supported in secure zones except " - "at the apex"); - } + if (rdata.type == dns_rdatatype_nsec3) { + FAILC(DNS_R_REFUSED, + "explicit NSEC3 updates are not allowed " + "in secure zones"); + } else if (rdata.type == dns_rdatatype_nsec) { + FAILC(DNS_R_REFUSED, + "explicit NSEC updates are not allowed " + "in secure zones"); + } else if (rdata.type == dns_rdatatype_rrsig && + !dns_name_equal(name, zonename)) { + FAILC(DNS_R_REFUSED, + "explicit RRSIG updates are currently " + "not supported in secure zones except " + "at the apex"); } if (ssutable != NULL) { isc_netaddr_t *tcpaddr, netaddr; + dst_key_t *tsigkey = NULL; /* * If this is a TCP connection then pass the * address of the client through for tcp-self @@ -3656,16 +3832,22 @@ update_action(isc_task_t *task, isc_event_t *event) { tcpaddr = &netaddr; } else tcpaddr = NULL; + + if (client->message->tsigkey != NULL) + tsigkey = client->message->tsigkey->key; + if (rdata.type != dns_rdatatype_any) { if (!dns_ssutable_checkrules(ssutable, client->signer, name, tcpaddr, - rdata.type)) + rdata.type, + tsigkey)) FAILC(DNS_R_REFUSED, "rejected by secure update"); } else { if (!ssu_checkall(db, ver, name, ssutable, - client->signer, tcpaddr)) + client->signer, tcpaddr, + tsigkey)) FAILC(DNS_R_REFUSED, "rejected by secure update"); } @@ -3774,7 +3956,14 @@ update_action(isc_task_t *task, isc_event_t *event) { soa_serial_changed = ISC_TRUE; } -#ifdef ALLOW_NSEC3PARAM_UPDATE + if (rdata.type == privatetype) { + update_log(client, zone, LOGLEVEL_PROTOCOL, + "attempt to add a private type " + "(%u) record rejected internal " + "use only", privatetype); + continue; + } + if (rdata.type == dns_rdatatype_nsec3param) { /* * Ignore attempts to add NSEC3PARAM records @@ -3788,27 +3977,7 @@ update_action(isc_task_t *task, isc_event_t *event) { "flag"); continue; } - - /* - * Set the NSEC3CHAIN creation flag. - */ - INSIST(rdata.length <= sizeof(buf)); - memcpy(buf, rdata.data, rdata.length); - buf[1] |= DNS_NSEC3FLAG_UPDATE; - rdata.data = buf; - /* - * Force the TTL to zero for NSEC3PARAM records. - */ - ttl = 0; } -#else - if (rdata.type == dns_rdatatype_nsec3param) { - update_log(client, zone, LOGLEVEL_PROTOCOL, - "attempt to add NSEC3PARAM " - "record ignored"); - continue; - }; -#endif if ((options & DNS_ZONEOPT_CHECKWILDCARD) != 0 && dns_name_internalwildcard(name)) { @@ -3885,13 +4054,6 @@ update_action(isc_task_t *task, isc_event_t *event) { dns_rdatatype_any, 0, &rdata, &diff)); } -#ifndef ALLOW_NSEC3PARAM_UPDATE - } else if (rdata.type == dns_rdatatype_nsec3param) { - update_log(client, zone, LOGLEVEL_PROTOCOL, - "attempt to delete a NSEC3PARAM " - "records ignored"); - continue; -#endif } else if (dns_name_equal(name, zonename) && (rdata.type == dns_rdatatype_soa || rdata.type == dns_rdatatype_ns)) { @@ -3920,6 +4082,9 @@ update_action(isc_task_t *task, isc_event_t *event) { &diff)); } } else if (update_class == dns_rdataclass_none) { + char namestr[DNS_NAME_FORMATSIZE]; + char typestr[DNS_RDATATYPE_FORMATSIZE]; + /* * The (name == zonename) condition appears in * RFC2136 3.4.2.4 but is missing from the pseudocode. @@ -3947,11 +4112,13 @@ update_action(isc_task_t *task, isc_event_t *event) { } } } - update_log(client, zone, - LOGLEVEL_PROTOCOL, - "deleting an RR"); - CHECK(delete_if(rr_equal_p, db, ver, name, - rdata.type, covers, &rdata, &diff)); + dns_name_format(name, namestr, sizeof(namestr)); + dns_rdatatype_format(rdata.type, typestr, + sizeof(typestr)); + update_log(client, zone, LOGLEVEL_PROTOCOL, + "deleting an RR at %s %s", namestr, typestr); + CHECK(delete_if(rr_equal_p, db, ver, name, rdata.type, + covers, &rdata, &diff)); } } if (result != ISC_R_NOMORE) @@ -3965,6 +4132,18 @@ update_action(isc_task_t *task, isc_event_t *event) { if (! ISC_LIST_EMPTY(diff.tuples)) CHECK(check_dnssec(client, zone, db, ver, &diff)); + if (! ISC_LIST_EMPTY(diff.tuples)) { + unsigned int errors = 0; + CHECK(dns_zone_nscheck(zone, db, ver, &errors)); + if (errors != 0) { + update_log(client, zone, LOGLEVEL_PROTOCOL, + "update rejected: post update name server " + "sanity check failed"); + result = DNS_R_REFUSED; + goto failure; + } + } + /* * If any changes were made, increment the SOA serial number, * update RRSIGs and NSECs (if zone is secure), and write the update @@ -3990,37 +4169,29 @@ update_action(isc_task_t *task, isc_event_t *event) { CHECK(rrset_exists(db, ver, zonename, dns_rdatatype_dnskey, 0, &has_dnskey)); -#if !defined(ALLOW_SECURE_TO_INSECURE) || !defined(ALLOW_INSECURE_TO_SECURE) - CHECK(rrset_exists(db, oldver, zonename, dns_rdatatype_dnskey, - 0, &had_dnskey)); +#define ALLOW_SECURE_TO_INSECURE(zone) \ + ((dns_zone_getoptions(zone) & DNS_ZONEOPT_SECURETOINSECURE) != 0) -#ifndef ALLOW_SECURE_TO_INSECURE - if (had_dnskey && !has_dnskey) { - update_log(client, zone, LOGLEVEL_PROTOCOL, - "update rejected: all DNSKEY records " - "removed"); - result = DNS_R_REFUSED; - goto failure; - } -#endif -#ifndef ALLOW_INSECURE_TO_SECURE - if (!had_dnskey && has_dnskey) { - update_log(client, zone, LOGLEVEL_PROTOCOL, - "update rejected: DNSKEY record added"); - result = DNS_R_REFUSED; - goto failure; + if (!ALLOW_SECURE_TO_INSECURE(zone)) { + CHECK(rrset_exists(db, oldver, zonename, + dns_rdatatype_dnskey, 0, + &had_dnskey)); + if (had_dnskey && !has_dnskey) { + update_log(client, zone, LOGLEVEL_PROTOCOL, + "update rejected: all DNSKEY " + "records removed and " + "'dnssec-secure-to-insecure' " + "not set"); + result = DNS_R_REFUSED; + goto failure; + } } -#endif -#endif - CHECK(add_signing_records(db, zonename, ver, - dns_zone_getprivatetype(zone), - &diff)); + CHECK(rollback_private(db, privatetype, ver, &diff)); + + CHECK(add_signing_records(db, privatetype, ver, &diff)); -#ifdef ALLOW_NSEC3PARAM_UPDATE - CHECK(add_nsec3param_records(client, zone, db, zonename, - ver, &diff)); -#endif + CHECK(add_nsec3param_records(client, zone, db, ver, &diff)); if (!has_dnskey) { /* @@ -4029,15 +4200,13 @@ update_action(isc_task_t *task, isc_event_t *event) { * the last signature for the DNSKEY records are * remove any NSEC chain present will also be removed. */ -#ifdef ALLOW_NSEC3PARAM_UPDATE - CHECK(delete_chains(db, ver, zonename, &diff)); -#endif - } else if (has_dnskey && dns_db_isdnssec(db)) { + CHECK(dns_nsec3param_deletechains(db, ver, zone, + &diff)); + } else if (has_dnskey && isdnssec(db, ver, privatetype)) { isc_uint32_t interval; interval = dns_zone_getsigvalidityinterval(zone); result = update_signatures(client, zone, db, oldver, - ver, &diff, interval, - &deleted_zsk); + ver, &diff, interval); if (result != ISC_R_SUCCESS) { update_log(client, zone, ISC_LOG_ERROR, @@ -4123,7 +4292,6 @@ update_action(isc_task_t *task, isc_event_t *event) { } } -#ifdef ALLOW_NSEC3PARAM_UPDATE /* * Cause the zone to add/delete NSEC3 chains for the * deferred NSEC3PARAM changes. @@ -4133,13 +4301,18 @@ update_action(isc_task_t *task, isc_event_t *event) { for (tuple = ISC_LIST_HEAD(diff.tuples); tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link)) { + unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; + dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_nsec3param_t nsec3param; - if (tuple->rdata.type != dns_rdatatype_nsec3param || + if (tuple->rdata.type != privatetype || tuple->op != DNS_DIFFOP_ADD) continue; - dns_rdata_tostruct(&tuple->rdata, &nsec3param, NULL); + if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata, + buf, sizeof(buf))) + continue; + dns_rdata_tostruct(&rdata, &nsec3param, NULL); if (nsec3param.flags == 0) continue; @@ -4150,7 +4323,6 @@ update_action(isc_task_t *task, isc_event_t *event) { dns_result_totext(result)); } } -#endif } else { update_log(client, zone, LOGLEVEL_DEBUG, "redundant request"); dns_db_closeversion(db, &ver, ISC_TRUE); diff --git a/bin/named/xfrout.c b/bin/named/xfrout.c index e61dc72..b036ed1 100644 --- a/bin/named/xfrout.c +++ b/bin/named/xfrout.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: xfrout.c,v 1.131.26.6 2010-05-27 23:48:18 tbox Exp $ */ +/* $Id: xfrout.c,v 1.139 2010-12-18 01:56:19 each Exp $ */ #include @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -112,43 +113,6 @@ } while (0) /**************************************************************************/ -/*% - * A db_rr_iterator_t is an iterator that iterates over an entire database, - * returning one RR at a time, in some arbitrary order. - */ - -typedef struct db_rr_iterator db_rr_iterator_t; - -/*% db_rr_iterator structure */ -struct db_rr_iterator { - isc_result_t result; - dns_db_t *db; - dns_dbiterator_t *dbit; - dns_dbversion_t *ver; - isc_stdtime_t now; - dns_dbnode_t *node; - dns_fixedname_t fixedname; - dns_rdatasetiter_t *rdatasetit; - dns_rdataset_t rdataset; - dns_rdata_t rdata; -}; - -static isc_result_t -db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver, - isc_stdtime_t now); - -static isc_result_t -db_rr_iterator_first(db_rr_iterator_t *it); - -static isc_result_t -db_rr_iterator_next(db_rr_iterator_t *it); - -static void -db_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name, - isc_uint32_t *ttl, dns_rdata_t **rdata); - -static void -db_rr_iterator_destroy(db_rr_iterator_t *it); static inline void inc_stats(dns_zone_t *zone, isc_statscounter_t counter) { @@ -160,145 +124,6 @@ inc_stats(dns_zone_t *zone, isc_statscounter_t counter) { } } -static isc_result_t -db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver, - isc_stdtime_t now) -{ - isc_result_t result; - it->db = db; - it->dbit = NULL; - it->ver = ver; - it->now = now; - it->node = NULL; - result = dns_db_createiterator(it->db, 0, &it->dbit); - if (result != ISC_R_SUCCESS) - return (result); - it->rdatasetit = NULL; - dns_rdata_init(&it->rdata); - dns_rdataset_init(&it->rdataset); - dns_fixedname_init(&it->fixedname); - INSIST(! dns_rdataset_isassociated(&it->rdataset)); - it->result = ISC_R_SUCCESS; - return (it->result); -} - -static isc_result_t -db_rr_iterator_first(db_rr_iterator_t *it) { - it->result = dns_dbiterator_first(it->dbit); - /* - * The top node may be empty when out of zone glue exists. - * Walk the tree to find the first node with data. - */ - while (it->result == ISC_R_SUCCESS) { - it->result = dns_dbiterator_current(it->dbit, &it->node, - dns_fixedname_name(&it->fixedname)); - if (it->result != ISC_R_SUCCESS) - return (it->result); - - it->result = dns_db_allrdatasets(it->db, it->node, - it->ver, it->now, - &it->rdatasetit); - if (it->result != ISC_R_SUCCESS) - return (it->result); - - it->result = dns_rdatasetiter_first(it->rdatasetit); - if (it->result != ISC_R_SUCCESS) { - /* - * This node is empty. Try next node. - */ - dns_rdatasetiter_destroy(&it->rdatasetit); - dns_db_detachnode(it->db, &it->node); - it->result = dns_dbiterator_next(it->dbit); - continue; - } - dns_rdatasetiter_current(it->rdatasetit, &it->rdataset); - it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER; - it->result = dns_rdataset_first(&it->rdataset); - return (it->result); - } - return (it->result); -} - - -static isc_result_t -db_rr_iterator_next(db_rr_iterator_t *it) { - if (it->result != ISC_R_SUCCESS) - return (it->result); - - INSIST(it->dbit != NULL); - INSIST(it->node != NULL); - INSIST(it->rdatasetit != NULL); - - it->result = dns_rdataset_next(&it->rdataset); - if (it->result == ISC_R_NOMORE) { - dns_rdataset_disassociate(&it->rdataset); - it->result = dns_rdatasetiter_next(it->rdatasetit); - /* - * The while loop body is executed more than once - * only when an empty dbnode needs to be skipped. - */ - while (it->result == ISC_R_NOMORE) { - dns_rdatasetiter_destroy(&it->rdatasetit); - dns_db_detachnode(it->db, &it->node); - it->result = dns_dbiterator_next(it->dbit); - if (it->result == ISC_R_NOMORE) { - /* We are at the end of the entire database. */ - return (it->result); - } - if (it->result != ISC_R_SUCCESS) - return (it->result); - it->result = dns_dbiterator_current(it->dbit, - &it->node, - dns_fixedname_name(&it->fixedname)); - if (it->result != ISC_R_SUCCESS) - return (it->result); - it->result = dns_db_allrdatasets(it->db, it->node, - it->ver, it->now, - &it->rdatasetit); - if (it->result != ISC_R_SUCCESS) - return (it->result); - it->result = dns_rdatasetiter_first(it->rdatasetit); - } - if (it->result != ISC_R_SUCCESS) - return (it->result); - dns_rdatasetiter_current(it->rdatasetit, &it->rdataset); - it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER; - it->result = dns_rdataset_first(&it->rdataset); - if (it->result != ISC_R_SUCCESS) - return (it->result); - } - return (it->result); -} - -static void -db_rr_iterator_pause(db_rr_iterator_t *it) { - RUNTIME_CHECK(dns_dbiterator_pause(it->dbit) == ISC_R_SUCCESS); -} - -static void -db_rr_iterator_destroy(db_rr_iterator_t *it) { - if (dns_rdataset_isassociated(&it->rdataset)) - dns_rdataset_disassociate(&it->rdataset); - if (it->rdatasetit != NULL) - dns_rdatasetiter_destroy(&it->rdatasetit); - if (it->node != NULL) - dns_db_detachnode(it->db, &it->node); - dns_dbiterator_destroy(&it->dbit); -} - -static void -db_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name, - isc_uint32_t *ttl, dns_rdata_t **rdata) -{ - REQUIRE(name != NULL && *name == NULL); - REQUIRE(it->result == ISC_R_SUCCESS); - *name = dns_fixedname_name(&it->fixedname); - *ttl = it->rdataset.ttl; - dns_rdata_reset(&it->rdata); - dns_rdataset_current(&it->rdataset, &it->rdata); - *rdata = &it->rdata; -} - /**************************************************************************/ /*% Log an RR (for debugging) */ @@ -488,7 +313,7 @@ static rrstream_methods_t ixfr_rrstream_methods = { typedef struct axfr_rrstream { rrstream_t common; - db_rr_iterator_t it; + dns_rriterator_t it; isc_boolean_t it_valid; } axfr_rrstream_t; @@ -516,7 +341,7 @@ axfr_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver, s->common.methods = &axfr_rrstream_methods; s->it_valid = ISC_FALSE; - CHECK(db_rr_iterator_init(&s->it, db, ver, 0)); + CHECK(dns_rriterator_init(&s->it, db, ver, 0)); s->it_valid = ISC_TRUE; *sp = (rrstream_t *) s; @@ -531,7 +356,7 @@ static isc_result_t axfr_rrstream_first(rrstream_t *rs) { axfr_rrstream_t *s = (axfr_rrstream_t *) rs; isc_result_t result; - result = db_rr_iterator_first(&s->it); + result = dns_rriterator_first(&s->it); if (result != ISC_R_SUCCESS) return (result); /* Skip SOA records. */ @@ -539,11 +364,11 @@ axfr_rrstream_first(rrstream_t *rs) { dns_name_t *name_dummy = NULL; isc_uint32_t ttl_dummy; dns_rdata_t *rdata = NULL; - db_rr_iterator_current(&s->it, &name_dummy, - &ttl_dummy, &rdata); + dns_rriterator_current(&s->it, &name_dummy, + &ttl_dummy, NULL, &rdata); if (rdata->type != dns_rdatatype_soa) break; - result = db_rr_iterator_next(&s->it); + result = dns_rriterator_next(&s->it); if (result != ISC_R_SUCCESS) break; } @@ -560,11 +385,11 @@ axfr_rrstream_next(rrstream_t *rs) { dns_name_t *name_dummy = NULL; isc_uint32_t ttl_dummy; dns_rdata_t *rdata = NULL; - result = db_rr_iterator_next(&s->it); + result = dns_rriterator_next(&s->it); if (result != ISC_R_SUCCESS) break; - db_rr_iterator_current(&s->it, &name_dummy, - &ttl_dummy, &rdata); + dns_rriterator_current(&s->it, &name_dummy, + &ttl_dummy, NULL, &rdata); if (rdata->type != dns_rdatatype_soa) break; } @@ -576,20 +401,20 @@ axfr_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl, dns_rdata_t **rdata) { axfr_rrstream_t *s = (axfr_rrstream_t *) rs; - db_rr_iterator_current(&s->it, name, ttl, rdata); + dns_rriterator_current(&s->it, name, ttl, NULL, rdata); } static void axfr_rrstream_pause(rrstream_t *rs) { axfr_rrstream_t *s = (axfr_rrstream_t *) rs; - db_rr_iterator_pause(&s->it); + dns_rriterator_pause(&s->it); } static void axfr_rrstream_destroy(rrstream_t **rsp) { axfr_rrstream_t *s = (axfr_rrstream_t *) *rsp; if (s->it_valid) - db_rr_iterator_destroy(&s->it); + dns_rriterator_destroy(&s->it); isc_mem_put(s->common.mctx, s, sizeof(*s)); } @@ -1038,6 +863,7 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { switch(dns_zone_gettype(zone)) { case dns_zone_master: case dns_zone_slave: + case dns_zone_dlz: break; /* Master and slave zones are OK for transfer. */ default: FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class); diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index 367ddd3..eb93f1b 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zoneconf.c,v 1.147.50.2 2009-01-29 23:47:44 tbox Exp $ */ +/* $Id: zoneconf.c,v 1.170 2011-01-06 23:47:00 tbox Exp $ */ /*% */ @@ -30,10 +30,16 @@ #include #include +#include #include #include #include +#include #include +#include +#include +#include +#include #include #include #include @@ -55,16 +61,18 @@ typedef enum { allow_update_forwarding } acl_type_t; -/*% - * These are BIND9 server defaults, not necessarily identical to the - * library defaults defined in zone.c. - */ #define RETERR(x) do { \ isc_result_t _r = (x); \ if (_r != ISC_R_SUCCESS) \ return (_r); \ } while (0) +#define CHECK(x) do { \ + result = (x); \ + if (result != ISC_R_SUCCESS) \ + goto cleanup; \ + } while (0) + /*% * Convenience function for configuring a single zone ACL. */ @@ -133,8 +141,11 @@ configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, } /* Check for default ACLs that haven't been parsed yet */ - if (vconfig != NULL) - maps[i++] = cfg_tuple_get(vconfig, "options"); + if (vconfig != NULL) { + const cfg_obj_t *options = cfg_tuple_get(vconfig, "options"); + if (options != NULL) + maps[i++] = options; + } if (config != NULL) { const cfg_obj_t *options = NULL; (void)cfg_map_get(config, "options", &options); @@ -169,19 +180,29 @@ parse_acl: * Parse the zone update-policy statement. */ static isc_result_t -configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) { +configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone, + const char *zname) +{ const cfg_obj_t *updatepolicy = NULL; const cfg_listelt_t *element, *element2; dns_ssutable_t *table = NULL; isc_mem_t *mctx = dns_zone_getmctx(zone); + isc_boolean_t autoddns = ISC_FALSE; isc_result_t result; (void)cfg_map_get(zconfig, "update-policy", &updatepolicy); + if (updatepolicy == NULL) { dns_zone_setssutable(zone, NULL); return (ISC_R_SUCCESS); } + if (cfg_obj_isstring(updatepolicy) && + strcmp("local", cfg_obj_asstring(updatepolicy)) == 0) { + autoddns = ISC_TRUE; + updatepolicy = NULL; + } + result = dns_ssutable_create(mctx, &table); if (result != ISC_R_SUCCESS) return (result); @@ -198,6 +219,7 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) { const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types"); const char *str; isc_boolean_t grant = ISC_FALSE; + isc_boolean_t usezone = ISC_FALSE; unsigned int mtype = DNS_SSUMATCHTYPE_NAME; dns_fixedname_t fname, fident; isc_buffer_t b; @@ -237,6 +259,11 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) { mtype = DNS_SSUMATCHTYPE_TCPSELF; else if (strcasecmp(str, "6to4-self") == 0) mtype = DNS_SSUMATCHTYPE_6TO4SELF; + else if (strcasecmp(str, "zonesub") == 0) { + mtype = DNS_SSUMATCHTYPE_SUBDOMAIN; + usezone = ISC_TRUE; + } else if (strcasecmp(str, "external") == 0) + mtype = DNS_SSUMATCHTYPE_EXTERNAL; else INSIST(0); @@ -245,7 +272,7 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) { isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); result = dns_name_fromtext(dns_fixedname_name(&fident), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, "'%s' is not a valid name", str); @@ -253,15 +280,27 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) { } dns_fixedname_init(&fname); - str = cfg_obj_asstring(dname); - isc_buffer_init(&b, str, strlen(str)); - isc_buffer_add(&b, strlen(str)); - result = dns_name_fromtext(dns_fixedname_name(&fname), &b, - dns_rootname, ISC_FALSE, NULL); - if (result != ISC_R_SUCCESS) { - cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, - "'%s' is not a valid name", str); - goto cleanup; + if (usezone) { + result = dns_name_copy(dns_zone_getorigin(zone), + dns_fixedname_name(&fname), + NULL); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, + "error copying origin: %s", + isc_result_totext(result)); + goto cleanup; + } + } else { + str = cfg_obj_asstring(dname); + isc_buffer_init(&b, str, strlen(str)); + isc_buffer_add(&b, strlen(str)); + result = dns_name_fromtext(dns_fixedname_name(&fname), + &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, + "'%s' is not a valid name", str); + goto cleanup; + } } n = ns_config_listcount(typelist); @@ -311,7 +350,34 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) { if (result != ISC_R_SUCCESS) { goto cleanup; } + } + + /* + * If "update-policy local;" and a session key exists, + * then use the default policy, which is equivalent to: + * update-policy { grant zonesub any; }; + */ + if (autoddns) { + dns_rdatatype_t any = dns_rdatatype_any; + + if (ns_g_server->session_keyname == NULL) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "failed to enable auto DDNS policy " + "for zone %s: session key not found", + zname); + result = ISC_R_NOTFOUND; + goto cleanup; + } + result = dns_ssutable_addrule(table, ISC_TRUE, + ns_g_server->session_keyname, + DNS_SSUMATCHTYPE_SUBDOMAIN, + dns_zone_getorigin(zone), + 1, &any); + + if (result != ISC_R_SUCCESS) + goto cleanup; } result = ISC_R_SUCCESS; @@ -322,6 +388,323 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) { return (result); } +/* + * This is the TTL used for internally generated RRsets for static-stub zones. + * The value doesn't matter because the mapping is static, but needs to be + * defined for the sake of implementation. + */ +#define STATICSTUB_SERVER_TTL 86400 + +/*% + * Configure an apex NS with glues for a static-stub zone. + * For example, for the zone named "example.com", the following RRs will be + * added to the zone DB: + * example.com. NS example.com. + * example.com. A 192.0.2.1 + * example.com. AAAA 2001:db8::1 + */ +static isc_result_t +configure_staticstub_serveraddrs(const cfg_obj_t *zconfig, dns_zone_t *zone, + dns_rdatalist_t *rdatalist_ns, + dns_rdatalist_t *rdatalist_a, + dns_rdatalist_t *rdatalist_aaaa) +{ + const cfg_listelt_t *element; + isc_mem_t *mctx = dns_zone_getmctx(zone); + isc_region_t region, sregion; + dns_rdata_t *rdata; + isc_result_t result = ISC_R_SUCCESS; + + for (element = cfg_list_first(zconfig); + element != NULL; + element = cfg_list_next(element)) + { + const isc_sockaddr_t* sa; + isc_netaddr_t na; + const cfg_obj_t *address = cfg_listelt_value(element); + dns_rdatalist_t *rdatalist; + + sa = cfg_obj_assockaddr(address); + if (isc_sockaddr_getport(sa) != 0) { + cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, + "port is not configurable for " + "static stub server-addresses"); + return (ISC_R_FAILURE); + } + isc_netaddr_fromsockaddr(&na, sa); + if (isc_netaddr_getzone(&na) != 0) { + cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, + "scoped address is not allowed " + "for static stub " + "server-addresses"); + return (ISC_R_FAILURE); + } + + switch (na.family) { + case AF_INET: + region.length = sizeof(na.type.in); + rdatalist = rdatalist_a; + break; + default: + INSIST(na.family == AF_INET6); + region.length = sizeof(na.type.in6); + rdatalist = rdatalist_aaaa; + break; + } + + rdata = isc_mem_get(mctx, sizeof(*rdata) + region.length); + if (rdata == NULL) + return (ISC_R_NOMEMORY); + region.base = (unsigned char *)(rdata + 1); + memcpy(region.base, &na.type, region.length); + dns_rdata_init(rdata); + dns_rdata_fromregion(rdata, dns_zone_getclass(zone), + rdatalist->type, ®ion); + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + } + + /* + * If no address is specified (unlikely in this context, but possible), + * there's nothing to do anymore. + */ + if (ISC_LIST_EMPTY(rdatalist_a->rdata) && + ISC_LIST_EMPTY(rdatalist_aaaa->rdata)) { + return (ISC_R_SUCCESS); + } + + /* Add to the list an apex NS with the ns name being the origin name */ + dns_name_toregion(dns_zone_getorigin(zone), &sregion); + rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length); + if (rdata == NULL) { + /* + * Already allocated data will be freed in the caller, so + * we can simply return here. + */ + return (ISC_R_NOMEMORY); + } + region.length = sregion.length; + region.base = (unsigned char *)(rdata + 1); + memcpy(region.base, sregion.base, region.length); + dns_rdata_init(rdata); + dns_rdata_fromregion(rdata, dns_zone_getclass(zone), + dns_rdatatype_ns, ®ion); + ISC_LIST_APPEND(rdatalist_ns->rdata, rdata, link); + + return (result); +} + +/*% + * Configure an apex NS with an out-of-zone NS names for a static-stub zone. + * For example, for the zone named "example.com", something like the following + * RRs will be added to the zone DB: + * example.com. NS ns.example.net. + */ +static isc_result_t +configure_staticstub_servernames(const cfg_obj_t *zconfig, dns_zone_t *zone, + dns_rdatalist_t *rdatalist, const char *zname) +{ + const cfg_listelt_t *element; + isc_mem_t *mctx = dns_zone_getmctx(zone); + dns_rdata_t *rdata; + isc_region_t sregion, region; + isc_result_t result = ISC_R_SUCCESS; + + for (element = cfg_list_first(zconfig); + element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *obj; + const char *str; + dns_fixedname_t fixed_name; + dns_name_t *nsname; + isc_buffer_t b; + + obj = cfg_listelt_value(element); + str = cfg_obj_asstring(obj); + + dns_fixedname_init(&fixed_name); + nsname = dns_fixedname_name(&fixed_name); + + isc_buffer_init(&b, str, strlen(str)); + isc_buffer_add(&b, strlen(str)); + result = dns_name_fromtext(nsname, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, + "server-name '%s' is not a valid " + "name", str); + return (result); + } + if (dns_name_issubdomain(nsname, dns_zone_getorigin(zone))) { + cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, + "server-name '%s' must not be a " + "subdomain of zone name '%s'", + str, zname); + return (ISC_R_FAILURE); + } + + dns_name_toregion(nsname, &sregion); + rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length); + if (rdata == NULL) + return (ISC_R_NOMEMORY); + region.length = sregion.length; + region.base = (unsigned char *)(rdata + 1); + memcpy(region.base, sregion.base, region.length); + dns_rdata_init(rdata); + dns_rdata_fromregion(rdata, dns_zone_getclass(zone), + dns_rdatatype_ns, ®ion); + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + } + + return (result); +} + +/*% + * Configure static-stub zone. + */ +static isc_result_t +configure_staticstub(const cfg_obj_t *zconfig, dns_zone_t *zone, + const char *zname, const char *dbtype) +{ + int i = 0; + const cfg_obj_t *obj; + isc_mem_t *mctx = dns_zone_getmctx(zone); + dns_db_t *db = NULL; + dns_dbversion_t *dbversion = NULL; + dns_dbnode_t *apexnode = NULL; + dns_name_t apexname; + isc_result_t result; + dns_rdataset_t rdataset; + dns_rdatalist_t rdatalist_ns, rdatalist_a, rdatalist_aaaa; + dns_rdatalist_t* rdatalists[] = { + &rdatalist_ns, &rdatalist_a, &rdatalist_aaaa, NULL + }; + dns_rdata_t *rdata; + isc_region_t region; + + /* Create the DB beforehand */ + RETERR(dns_db_create(mctx, dbtype, dns_zone_getorigin(zone), + dns_dbtype_stub, dns_zone_getclass(zone), + 0, NULL, &db)); + dns_zone_setdb(zone, db); + + dns_rdatalist_init(&rdatalist_ns); + rdatalist_ns.rdclass = dns_zone_getclass(zone); + rdatalist_ns.type = dns_rdatatype_ns; + rdatalist_ns.ttl = STATICSTUB_SERVER_TTL; + + dns_rdatalist_init(&rdatalist_a); + rdatalist_a.rdclass = dns_zone_getclass(zone); + rdatalist_a.type = dns_rdatatype_a; + rdatalist_a.ttl = STATICSTUB_SERVER_TTL; + + dns_rdatalist_init(&rdatalist_aaaa); + rdatalist_aaaa.rdclass = dns_zone_getclass(zone); + rdatalist_aaaa.type = dns_rdatatype_aaaa; + rdatalist_aaaa.ttl = STATICSTUB_SERVER_TTL; + + /* Prepare zone RRs from the configuration */ + obj = NULL; + result = cfg_map_get(zconfig, "server-addresses", &obj); + if (obj != NULL) { + result = configure_staticstub_serveraddrs(obj, zone, + &rdatalist_ns, + &rdatalist_a, + &rdatalist_aaaa); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + + obj = NULL; + result = cfg_map_get(zconfig, "server-names", &obj); + if (obj != NULL) { + result = configure_staticstub_servernames(obj, zone, + &rdatalist_ns, + zname); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + + /* + * Sanity check: there should be at least one NS RR at the zone apex + * to trigger delegation. + */ + if (ISC_LIST_EMPTY(rdatalist_ns.rdata)) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "No NS record is configured for a " + "static-stub zone '%s'", zname); + result = ISC_R_FAILURE; + goto cleanup; + } + + /* + * Now add NS and glue A/AAAA RRsets to the zone DB. + * First open a new version for the add operation and get a pointer + * to the apex node (all RRs are of the apex name). + */ + result = dns_db_newversion(db, &dbversion); + if (result != ISC_R_SUCCESS) + goto cleanup; + dns_name_init(&apexname, NULL); + dns_name_clone(dns_zone_getorigin(zone), &apexname); + result = dns_db_findnode(db, &apexname, ISC_FALSE, &apexnode); + if (result != ISC_R_SUCCESS) + goto cleanup; + + /* Add NS RRset */ + dns_rdataset_init(&rdataset); + RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_ns, &rdataset) + == ISC_R_SUCCESS); + result = dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset, + 0, NULL); + dns_rdataset_disassociate(&rdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + + /* Add glue A RRset, if any */ + if (!ISC_LIST_EMPTY(rdatalist_a.rdata)) { + RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_a, &rdataset) + == ISC_R_SUCCESS); + result = dns_db_addrdataset(db, apexnode, dbversion, 0, + &rdataset, 0, NULL); + dns_rdataset_disassociate(&rdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + + /* Add glue AAAA RRset, if any */ + if (!ISC_LIST_EMPTY(rdatalist_aaaa.rdata)) { + RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_aaaa, + &rdataset) + == ISC_R_SUCCESS); + result = dns_db_addrdataset(db, apexnode, dbversion, 0, + &rdataset, 0, NULL); + dns_rdataset_disassociate(&rdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + + result = ISC_R_SUCCESS; + + cleanup: + if (apexnode != NULL) + dns_db_detachnode(db, &apexnode); + if (dbversion != NULL) + dns_db_closeversion(db, &dbversion, ISC_TRUE); + if (db != NULL) + dns_db_detach(&db); + for (i = 0; rdatalists[i] != NULL; i++) { + while ((rdata = ISC_LIST_HEAD(rdatalists[i]->rdata)) != NULL) { + ISC_LIST_UNLINK(rdatalists[i]->rdata, rdata, link); + dns_rdata_toregion(rdata, ®ion); + isc_mem_put(mctx, rdata, + sizeof(*rdata) + region.length); + } + } + + return (result); +} + /*% * Convert a config file zone type into a server zone type. */ @@ -503,6 +886,19 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, if (result == ISC_R_SUCCESS) filename = cfg_obj_asstring(obj); + /* + * Unless we're using some alternative database, a master zone + * will be needing a master file. + */ + if (ztype == dns_zone_master && cpval == default_dbtype && + filename == NULL) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "zone '%s': 'file' not specified", + zname); + return (ISC_R_FAILURE); + } + masterformat = dns_masterformat_text; obj = NULL; result= ns_config_get(maps, "masterfile-format", &obj); @@ -577,7 +973,7 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, * to primary masters (type "master") and slaves * acting as masters (type "slave"), but not to stubs. */ - if (ztype != dns_zone_stub) { + if (ztype != dns_zone_stub && ztype != dns_zone_staticstub) { obj = NULL; result = ns_config_get(maps, "notify", &obj); INSIST(result == ISC_R_SUCCESS); @@ -731,6 +1127,7 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, */ if (ztype == dns_zone_master) { dns_acl_t *updateacl; + RETERR(configure_zone_acl(zconfig, vconfig, config, allow_update, ac, zone, dns_zone_setupdateacl, @@ -744,7 +1141,7 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, "address, which is insecure", zname); - RETERR(configure_zone_ssutable(zoptions, zone)); + RETERR(configure_zone_ssutable(zoptions, zone, zname)); obj = NULL; result = ns_config_get(maps, "sig-validity-interval", &obj); @@ -774,12 +1171,6 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, result = ns_config_get(maps, "key-directory", &obj); if (result == ISC_R_SUCCESS) { filename = cfg_obj_asstring(obj); - if (!isc_file_isabsolute(filename)) { - cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, - "key-directory '%s' " - "is not absolute", filename); - return (ISC_R_FAILURE); - } RETERR(dns_zone_setkeydirectory(zone, filename)); } @@ -804,6 +1195,11 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, dns_zone_setoption(zone, DNS_ZONEOPT_UPDATECHECKKSK, cfg_obj_asboolean(obj)); + obj = NULL; + result = ns_config_get(maps, "dnssec-dnskey-kskonly", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zone_setoption(zone, DNS_ZONEOPT_DNSKEYKSKONLY, + cfg_obj_asboolean(obj)); } else if (ztype == dns_zone_slave) { RETERR(configure_zone_acl(zconfig, vconfig, config, allow_update_forwarding, ac, zone, @@ -811,11 +1207,13 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, dns_zone_clearforwardacl)); } - /*% * Primary master functionality. */ if (ztype == dns_zone_master) { + isc_boolean_t allow = ISC_FALSE, maint = ISC_FALSE; + isc_boolean_t create = ISC_FALSE; + obj = NULL; result = ns_config_get(maps, "check-wildcard", &obj); if (result == ISC_R_SUCCESS) @@ -825,6 +1223,21 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, dns_zone_setoption(zone, DNS_ZONEOPT_CHECKWILDCARD, check); obj = NULL; + result = ns_config_get(maps, "check-dup-records", &obj); + INSIST(obj != NULL); + if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { + fail = ISC_FALSE; + check = ISC_TRUE; + } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { + fail = check = ISC_TRUE; + } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { + fail = check = ISC_FALSE; + } else + INSIST(0); + dns_zone_setoption(zone, DNS_ZONEOPT_CHECKDUPRR, check); + dns_zone_setoption(zone, DNS_ZONEOPT_CHECKDUPRRFAIL, fail); + + obj = NULL; result = ns_config_get(maps, "check-mx", &obj); INSIST(obj != NULL); if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { @@ -874,6 +1287,31 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, INSIST(0); dns_zone_setoption(zone, DNS_ZONEOPT_WARNSRVCNAME, warn); dns_zone_setoption(zone, DNS_ZONEOPT_IGNORESRVCNAME, ignore); + + obj = NULL; + result = ns_config_get(maps, "dnssec-secure-to-insecure", &obj); + INSIST(obj != NULL); + dns_zone_setoption(zone, DNS_ZONEOPT_SECURETOINSECURE, + cfg_obj_asboolean(obj)); + + obj = NULL; + result = cfg_map_get(zoptions, "auto-dnssec", &obj); + if (result == ISC_R_SUCCESS) { + const char *arg = cfg_obj_asstring(obj); + if (strcasecmp(arg, "allow") == 0) + allow = ISC_TRUE; + else if (strcasecmp(arg, "maintain") == 0) + allow = maint = ISC_TRUE; + else if (strcasecmp(arg, "create") == 0) + allow = maint = create = ISC_TRUE; + else if (strcasecmp(arg, "off") == 0) + ; + else + INSIST(0); + dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow); + dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint); + dns_zone_setkeyopt(zone, DNS_ZONEKEY_CREATE, create); + } } /* @@ -982,6 +1420,11 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, cfg_obj_asboolean(obj)); break; + case dns_zone_staticstub: + RETERR(configure_staticstub(zoptions, zone, zname, + default_dbtype)); + break; + default: break; } @@ -989,6 +1432,31 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, return (ISC_R_SUCCESS); } + +#ifdef DLZ +/* + * Set up a DLZ zone as writeable + */ +isc_result_t +ns_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone, + dns_rdataclass_t rdclass, dns_name_t *name) +{ + dns_db_t *db = NULL; + isc_time_t now; + isc_result_t result; + + TIME_NOW(&now); + + dns_zone_settype(zone, dns_zone_dlz); + result = dns_sdlz_setdb(dlzdatabase, rdclass, name, &db); + if (result != ISC_R_SUCCESS) + return result; + result = dns_zone_dlzpostload(zone, db); + dns_db_detach(&db); + return result; +} +#endif + isc_boolean_t ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) { const cfg_obj_t *zoptions = NULL; @@ -1001,6 +1469,13 @@ ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) { if (zonetype_fromconfig(zoptions) != dns_zone_gettype(zone)) return (ISC_FALSE); + /* + * We always reconfigure a static-stub zone for simplicity, assuming + * the amount of data to be loaded is small. + */ + if (zonetype_fromconfig(zoptions) == dns_zone_staticstub) + return (ISC_FALSE); + obj = NULL; (void)cfg_map_get(zoptions, "file", &obj); if (obj != NULL) diff --git a/bin/nsupdate/Makefile.in b/bin/nsupdate/Makefile.in index f7f6346..a65aad9 100644 --- a/bin/nsupdate/Makefile.in +++ b/bin/nsupdate/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2006-2008 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2006-2009 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 2000-2002 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.29 2008-08-29 23:47:22 tbox Exp $ +# $Id: Makefile.in,v 1.36 2009-12-05 23:31:40 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -24,7 +24,7 @@ top_srcdir = @top_srcdir@ @BIND9_MAKE_INCLUDES@ CINCLUDES = ${LWRES_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} \ - ${ISC_INCLUDES} @DST_GSSAPI_INC@ + ${ISC_INCLUDES} ${ISCCFG_INCLUDES} @DST_GSSAPI_INC@ CDEFINES = @USE_GSSAPI@ CWARNINGS = @@ -33,6 +33,7 @@ LWRESLIBS = ../../lib/lwres/liblwres.@A@ DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ BIND9LIBS = ../../lib/bind9/libbind9.@A@ ISCLIBS = ../../lib/isc/libisc.@A@ +ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@ @@ -43,7 +44,9 @@ ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ DEPLIBS = ${DNSDEPLIBS} ${BIND9DEPLIBS} ${ISCDEPLIBS} ${ISCCFGDEPLIBS} -LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCLIBS} ${ISCCFGLIBS} @LIBS@ +LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} ${ISCLIBS} @LIBS@ + +NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} ${ISCNOSYMLIBS} @LIBS@ SUBDIRS = @@ -63,8 +66,14 @@ MANOBJS = ${MANPAGES} ${HTMLPAGES} @BIND9_MAKE_RULES@ +nsupdate.@O@: nsupdate.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ + -DSESSION_KEYFILE=\"${localstatedir}/run/named/session.key\" \ + -c ${srcdir}/nsupdate.c + nsupdate@EXEEXT@: nsupdate.@O@ ${UOBJS} ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ nsupdate.@O@ ${UOBJS} ${LIBS} + export BASEOBJS="nsupdate.@O@ ${UOBJS}"; \ + ${FINALBUILDCMD} doc man:: ${MANOBJS} diff --git a/bin/nsupdate/nsupdate.1 b/bin/nsupdate/nsupdate.1 index 6c03486..9d82891 100644 --- a/bin/nsupdate/nsupdate.1 +++ b/bin/nsupdate/nsupdate.1 @@ -13,18 +13,18 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: nsupdate.1,v 1.3.48.4 2010-07-10 02:06:17 tbox Exp $ +.\" $Id: nsupdate.1,v 1.13 2010-07-10 01:14:19 tbox Exp $ .\" .hy 0 .ad l .\" Title: nsupdate .\" Author: .\" Generator: DocBook XSL Stylesheets v1.71.1 -.\" Date: Jun 30, 2000 +.\" Date: Aug 25, 2009 .\" Manual: BIND9 .\" Source: BIND9 .\" -.TH "NSUPDATE" "1" "Jun 30, 2000" "BIND9" "BIND9" +.TH "NSUPDATE" "1" "Aug 25, 2009" "BIND9" "BIND9" .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) @@ -33,11 +33,11 @@ nsupdate \- Dynamic DNS update utility .SH "SYNOPSIS" .HP 9 -\fBnsupdate\fR [\fB\-d\fR] [\fB\-D\fR] [[\fB\-g\fR] | [\fB\-o\fR] | [\fB\-y\ \fR\fB\fI[hmac:]\fR\fIkeyname:secret\fR\fR] | [\fB\-k\ \fR\fB\fIkeyfile\fR\fR]] [\fB\-t\ \fR\fB\fItimeout\fR\fR] [\fB\-u\ \fR\fB\fIudptimeout\fR\fR] [\fB\-r\ \fR\fB\fIudpretries\fR\fR] [\fB\-R\ \fR\fB\fIrandomdev\fR\fR] [\fB\-v\fR] [filename] +\fBnsupdate\fR [\fB\-d\fR] [\fB\-D\fR] [[\fB\-g\fR] | [\fB\-o\fR] | [\fB\-l\fR] | [\fB\-y\ \fR\fB\fI[hmac:]\fR\fIkeyname:secret\fR\fR] | [\fB\-k\ \fR\fB\fIkeyfile\fR\fR]] [\fB\-t\ \fR\fB\fItimeout\fR\fR] [\fB\-u\ \fR\fB\fIudptimeout\fR\fR] [\fB\-r\ \fR\fB\fIudpretries\fR\fR] [\fB\-R\ \fR\fB\fIrandomdev\fR\fR] [\fB\-v\fR] [filename] .SH "DESCRIPTION" .PP \fBnsupdate\fR -is used to submit Dynamic DNS Update requests as defined in RFC2136 to a name server. This allows resource records to be added or removed from a zone without manually editing the zone file. A single update request can contain requests to add or remove more than one resource record. +is used to submit Dynamic DNS Update requests as defined in RFC 2136 to a name server. This allows resource records to be added or removed from a zone without manually editing the zone file. A single update request can contain requests to add or remove more than one resource record. .PP Zones that are under dynamic control via \fBnsupdate\fR @@ -60,7 +60,11 @@ option makes report additional debugging information to \fB\-d\fR. .PP -Transaction signatures can be used to authenticate the Dynamic DNS updates. These use the TSIG resource record type described in RFC2845 or the SIG(0) record described in RFC3535 and RFC2931 or GSS\-TSIG as described in RFC3645. TSIG relies on a shared secret that should only be known to +The +\fB\-L\fR +option with an integer argument of zero or higher sets the logging debug level. If zero, logging is disabled. +.PP +Transaction signatures can be used to authenticate the Dynamic DNS updates. These use the TSIG resource record type described in RFC 2845 or the SIG(0) record described in RFC 2535 and RFC 2931 or GSS\-TSIG as described in RFC 3645. TSIG relies on a shared secret that should only be known to \fBnsupdate\fR and the name server. Currently, the only supported encryption algorithm for TSIG is HMAC\-MD5, which is defined in RFC 2104. Once other algorithms are defined for TSIG, applications will need to ensure they select the appropriate algorithm as well as the key when authenticating each other. For instance, suitable \fBkey\fR @@ -71,22 +75,22 @@ statements would be added to so that the name server can associate the appropriate secret key and algorithm with the IP address of the client application that will be using TSIG authentication. SIG(0) uses public key cryptography. To use a SIG(0) key, the public key must be stored in a KEY record in a zone served by the name server. \fBnsupdate\fR does not read -\fI/etc/named.conf\fR. GSS\-TSIG uses Kerberos credentials. +\fI/etc/named.conf\fR. +.PP +GSS\-TSIG uses Kerberos credentials. Standard GSS\-TSIG mode is switched on with the +\fB\-g\fR +flag. A non\-standards\-compliant variant of GSS\-TSIG used by Windows 2000 can be switched on with the +\fB\-o\fR +flag. .PP \fBnsupdate\fR uses the \fB\-y\fR or \fB\-k\fR -option to provide the shared secret needed to generate a TSIG record for authenticating Dynamic DNS update requests, default type HMAC\-MD5. These options are mutually exclusive. With the -\fB\-k\fR -option, -\fBnsupdate\fR -reads the shared secret from the file -\fIkeyfile\fR, whose name is of the form -\fIK{name}.+157.+{random}.private\fR. For historical reasons, the file -\fIK{name}.+157.+{random}.key\fR -must also be present. When the +option to provide the shared secret needed to generate a TSIG record for authenticating Dynamic DNS update requests, default type HMAC\-MD5. These options are mutually exclusive. +.PP +When the \fB\-y\fR option is used, a signature is generated from [\fIhmac:\fR]\fIkeyname:secret.\fR @@ -99,17 +103,37 @@ option is discouraged because the shared secret is supplied as a command line ar \fBps\fR(1) or in a history file maintained by the user's shell. .PP -The +With the +\fB\-k\fR +option, +\fBnsupdate\fR +reads the shared secret from the file +\fIkeyfile\fR. Keyfiles may be in two formats: a single file containing a +\fInamed.conf\fR\-format +\fBkey\fR +statement, which may be generated automatically by +\fBddns\-confgen\fR, or a pair of files whose names are of the format +\fIK{name}.+157.+{random}.key\fR +and +\fIK{name}.+157.+{random}.private\fR, which can be generated by +\fBdnssec\-keygen\fR. The \fB\-k\fR may also be used to specify a SIG(0) key used to authenticate Dynamic DNS update requests. In this case, the key specified is not an HMAC\-MD5 key. .PP -The -\fB\-g\fR -and -\fB\-o\fR -specify that GSS\-TSIG is to be used. The -\fB\-o\fR -should only be used with old Microsoft Windows 2000 servers. +\fBnsupdate\fR +can be run in a local\-host only mode using the +\fB\-l\fR +flag. This sets the server address to localhost (disabling the +\fBserver\fR +so that the server address cannot be overridden). Connections to the local server will use a TSIG key found in +\fI/var/run/named/session.key\fR, which is automatically generated by +\fBnamed\fR +if any local master zone has set +\fBupdate\-policy\fR +to +\fBlocal\fR. The location of this key file can be overridden with the +\fB\-k\fR +option. .PP By default, \fBnsupdate\fR @@ -120,6 +144,10 @@ option makes use a TCP connection. This may be preferable when a batch of update requests is made. .PP The +\fB\-p\fR +sets the default port number to use for connections to a name server. The default is 53. +.PP +The \fB\-t\fR option sets the maximum time an update request can take before it is aborted. The default is 300 seconds. Zero can be used to disable the timeout. .PP @@ -367,7 +395,7 @@ with IP address 172.16.1.1 is added. The newly\-added record has a 1 day TTL (86 .sp .PP The prerequisite condition gets the name server to check that there are no resource records of any type for -\fBnickname.example.com\fR. If there are, the update request fails. If this name does not exist, a CNAME for it is added. This ensures that when the CNAME is added, it cannot conflict with the long\-standing rule in RFC1034 that a name must not exist as any other record type if it exists as a CNAME. (The rule has been updated for DNSSEC in RFC2535 to allow CNAMEs to have RRSIG, DNSKEY and NSEC records.) +\fBnickname.example.com\fR. If there are, the update request fails. If this name does not exist, a CNAME for it is added. This ensures that when the CNAME is added, it cannot conflict with the long\-standing rule in RFC 1034 that a name must not exist as any other record type if it exists as a CNAME. (The rule has been updated for DNSSEC in RFC 2535 to allow CNAMEs to have RRSIG, DNSKEY and NSEC records.) .SH "FILES" .PP \fB/etc/resolv.conf\fR @@ -375,6 +403,11 @@ The prerequisite condition gets the name server to check that there are no resou used to identify default name server .RE .PP +\fB/var/run/named/session.key\fR +.RS 4 +sets the default TSIG key for use in local\-only mode +.RE +.PP \fBK{name}.+157.+{random}.key\fR .RS 4 base\-64 encoding of HMAC\-MD5 key created by @@ -388,14 +421,15 @@ base\-64 encoding of HMAC\-MD5 key created by .RE .SH "SEE ALSO" .PP -\fBRFC2136\fR(), -\fBRFC3007\fR(), -\fBRFC2104\fR(), -\fBRFC2845\fR(), -\fBRFC1034\fR(), -\fBRFC2535\fR(), -\fBRFC2931\fR(), +RFC 2136, +RFC 3007, +RFC 2104, +RFC 2845, +RFC 1034, +RFC 2535, +RFC 2931, \fBnamed\fR(8), +\fBddns\-confgen\fR(8), \fBdnssec\-keygen\fR(8). .SH "BUGS" .PP diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index d9ee488..9bbea4b 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nsupdate.c,v 1.163.48.15 2010-12-09 04:30:57 tbox Exp $ */ +/* $Id: nsupdate.c,v 1.193 2011-01-10 05:32:03 marka Exp $ */ /*! \file */ @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +51,8 @@ #include #include +#include + #include #include #include @@ -78,6 +81,7 @@ #ifdef GSSAPI #include +#include ISC_PLATFORM_KRB5HEADER #endif #include @@ -106,6 +110,8 @@ extern int h_errno; #define DNSDEFAULTPORT 53 +static isc_uint16_t dnsport = DNSDEFAULTPORT; + #ifndef RESOLV_CONF #define RESOLV_CONF "/etc/resolv.conf" #endif @@ -119,6 +125,7 @@ static isc_boolean_t usevc = ISC_FALSE; static isc_boolean_t usegsstsig = ISC_FALSE; static isc_boolean_t use_win2k_gsstsig = ISC_FALSE; static isc_boolean_t tried_other_gsstsig = ISC_FALSE; +static isc_boolean_t local_only = ISC_FALSE; static isc_taskmgr_t *taskmgr = NULL; static isc_task_t *global_task = NULL; static isc_event_t *global_event = NULL; @@ -148,7 +155,8 @@ static isc_sockaddr_t *userserver = NULL; static isc_sockaddr_t *localaddr = NULL; static isc_sockaddr_t *serveraddr = NULL; static isc_sockaddr_t tempaddr; -static char *keystr = NULL, *keyfile = NULL; +static const char *keyfile = NULL; +static char *keystr = NULL; static isc_entropy_t *entropy = NULL; static isc_boolean_t shuttingdown = ISC_FALSE; static FILE *input; @@ -174,8 +182,10 @@ typedef struct nsu_requestinfo { static void sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, dns_message_t *msg, dns_request_t **request); -static void -fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); + +ISC_PLATFORM_NORETURN_PRE static void +fatal(const char *format, ...) +ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; static void debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); @@ -406,7 +416,7 @@ reset_system(void) { if (tsigkey != NULL) dns_tsigkey_detach(&tsigkey); if (gssring != NULL) - dns_tsigkeyring_destroy(&gssring); + dns_tsigkeyring_detach(&gssring); tried_other_gsstsig = ISC_FALSE; } } @@ -479,6 +489,19 @@ parse_hmac(dns_name_t **hmac, const char *hmacstr, size_t len) { return (digestbits); } +static int +basenamelen(const char *file) { + int len = strlen(file); + + if (len > 1 && file[len - 1] == '.') + len -= 1; + else if (len > 8 && strcmp(file + len - 8, ".private") == 0) + len -= 8; + else if (len > 4 && strcmp(file + len - 4, ".key") == 0) + len -= 4; + return (len); +} + static void setup_keystr(void) { unsigned char *secret = NULL; @@ -520,8 +543,7 @@ setup_keystr(void) { isc_buffer_add(&keynamesrc, n - name); debug("namefromtext"); - result = dns_name_fromtext(keyname, &keynamesrc, dns_rootname, - ISC_FALSE, NULL); + result = dns_name_fromtext(keyname, &keynamesrc, dns_rootname, 0, NULL); check_result(result, "dns_name_fromtext"); secretlen = strlen(secretstr) * 3 / 4; @@ -553,21 +575,67 @@ setup_keystr(void) { isc_mem_free(mctx, secret); } -static int -basenamelen(const char *file) { - int len = strlen(file); +/* + * Get a key from a named.conf format keyfile + */ +static isc_result_t +read_sessionkey(isc_mem_t *mctx, isc_log_t *lctx) { + cfg_parser_t *pctx = NULL; + cfg_obj_t *sessionkey = NULL; + const cfg_obj_t *key = NULL; + const cfg_obj_t *secretobj = NULL; + const cfg_obj_t *algorithmobj = NULL; + const char *keyname; + const char *secretstr; + const char *algorithm; + isc_result_t result; + int len; - if (len > 1 && file[len - 1] == '.') - len -= 1; - else if (len > 8 && strcmp(file + len - 8, ".private") == 0) - len -= 8; - else if (len > 4 && strcmp(file + len - 4, ".key") == 0) - len -= 4; - return (len); + if (! isc_file_exists(keyfile)) + return (ISC_R_FILENOTFOUND); + + result = cfg_parser_create(mctx, lctx, &pctx); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey, + &sessionkey); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = cfg_map_get(sessionkey, "key", &key); + if (result != ISC_R_SUCCESS) + goto cleanup; + + (void) cfg_map_get(key, "secret", &secretobj); + (void) cfg_map_get(key, "algorithm", &algorithmobj); + if (secretobj == NULL || algorithmobj == NULL) + fatal("key must have algorithm and secret"); + + keyname = cfg_obj_asstring(cfg_map_getname(key)); + secretstr = cfg_obj_asstring(secretobj); + algorithm = cfg_obj_asstring(algorithmobj); + + len = strlen(algorithm) + strlen(keyname) + strlen(secretstr) + 3; + keystr = isc_mem_allocate(mctx, len); + snprintf(keystr, len, "%s:%s:%s", algorithm, keyname, secretstr); + setup_keystr(); + + cleanup: + if (pctx != NULL) { + if (sessionkey != NULL) + cfg_obj_destroy(pctx, &sessionkey); + cfg_parser_destroy(&pctx); + } + + if (keystr != NULL) + isc_mem_free(mctx, keystr); + + return (result); } static void -setup_keyfile(void) { +setup_keyfile(isc_mem_t *mctx, isc_log_t *lctx) { dst_key_t *dstkey = NULL; isc_result_t result; dns_name_t *hmacname = NULL; @@ -577,15 +645,25 @@ setup_keyfile(void) { if (sig0key != NULL) dst_key_free(&sig0key); - result = dst_key_fromnamedfile(keyfile, + /* Try reading the key from a K* pair */ + result = dst_key_fromnamedfile(keyfile, NULL, DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, &dstkey); + + /* If that didn't work, try reading it as a session.key keyfile */ + if (result != ISC_R_SUCCESS) { + result = read_sessionkey(mctx, lctx); + if (result == ISC_R_SUCCESS) + return; + } + if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not read key from %.*s.{private,key}: " "%s\n", basenamelen(keyfile), keyfile, isc_result_totext(result)); return; } + switch (dst_key_alg(dstkey)) { case DST_ALG_HMACMD5: hmacname = DNS_TSIG_HMACMD5_NAME; @@ -746,7 +824,7 @@ setup_system(void) { if (servers == NULL) fatal("out of memory"); localhost.s_addr = htonl(INADDR_LOOPBACK); - isc_sockaddr_fromin(&servers[0], &localhost, DNSDEFAULTPORT); + isc_sockaddr_fromin(&servers[0], &localhost, dnsport); } else { servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t)); if (servers == NULL) @@ -755,12 +833,12 @@ setup_system(void) { if (lwconf->nameservers[i].family == LWRES_ADDRTYPE_V4) { struct in_addr in4; memcpy(&in4, lwconf->nameservers[i].address, 4); - isc_sockaddr_fromin(&servers[i], &in4, DNSDEFAULTPORT); + isc_sockaddr_fromin(&servers[i], &in4, dnsport); } else { struct in6_addr in6; memcpy(&in6, lwconf->nameservers[i].address, 16); isc_sockaddr_fromin6(&servers[i], &in6, - DNSDEFAULTPORT); + dnsport); } } } @@ -827,8 +905,13 @@ setup_system(void) { if (keystr != NULL) setup_keystr(); - else if (keyfile != NULL) - setup_keyfile(); + else if (local_only) { + result = read_sessionkey(mctx, lctx); + if (result != ISC_R_SUCCESS) + fatal("can't read key from %s: %s\n", + keyfile, isc_result_totext(result)); + } else if (keyfile != NULL) + setup_keyfile(mctx, lctx); } static void @@ -845,7 +928,7 @@ get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) { INSIST(count == 1); } -#define PARSE_ARGS_FMT "dDMl:y:govk:rR::t:u:" +#define PARSE_ARGS_FMT "dDML:y:ghlovk:p:rR::t:u:" static void pre_parse_args(int argc, char **argv) { @@ -862,10 +945,11 @@ pre_parse_args(int argc, char **argv) { break; case '?': + case 'h': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", argv[0], isc_commandline_option); - fprintf(stderr, "usage: nsupdate [-d] " + fprintf(stderr, "usage: nsupdate [-dD] [-L level] [-l]" "[-g | -o | -y keyname:secret | -k keyfile] " "[-v] [filename]\n"); exit(1); @@ -897,6 +981,9 @@ parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) { case 'M': break; case 'l': + local_only = ISC_TRUE; + break; + case 'L': result = isc_parse_uint32(&i, isc_commandline_argument, 10); if (result != ISC_R_SUCCESS) { @@ -923,6 +1010,15 @@ parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) { usegsstsig = ISC_TRUE; use_win2k_gsstsig = ISC_TRUE; break; + case 'p': + result = isc_parse_uint16(&dnsport, + isc_commandline_argument, 10); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "bad port number " + "'%s'\n", isc_commandline_argument); + exit(1); + } + break; case 't': result = isc_parse_uint32(&timeout, isc_commandline_argument, 10); @@ -968,6 +1064,22 @@ parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) { exit(1); } + if (local_only) { + struct in_addr localhost; + + if (keyfile == NULL) + keyfile = SESSION_KEYFILE; + + if (userserver == NULL) { + userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t)); + if (userserver == NULL) + fatal("out of memory"); + } + + localhost.s_addr = htonl(INADDR_LOOPBACK); + isc_sockaddr_fromin(userserver, &localhost, dnsport); + } + #ifdef GSSAPI if (usegsstsig && (keyfile != NULL || keystr != NULL)) { fprintf(stderr, "%s: cannot specify -g with -k or -y\n", @@ -976,7 +1088,7 @@ parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) { } #else if (usegsstsig) { - fprintf(stderr, "%s: cannot specify -g or -o, " \ + fprintf(stderr, "%s: cannot specify -g or -o, " \ "program not linked with GSS API Library\n", argv[0]); exit(1); @@ -1022,8 +1134,7 @@ parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) { dns_message_takebuffer(msg, &namebuf); isc_buffer_init(&source, word, strlen(word)); isc_buffer_add(&source, strlen(word)); - result = dns_name_fromtext(*namep, &source, dns_rootname, - ISC_FALSE, NULL); + result = dns_name_fromtext(*namep, &source, dns_rootname, 0, NULL); check_result(result, "dns_name_fromtext"); isc_buffer_invalidate(&source); return (STATUS_MORE); @@ -1225,6 +1336,11 @@ evaluate_server(char *cmdline) { char *word, *server; long port; + if (local_only) { + fprintf(stderr, "cannot reset server in localhost-only mode\n"); + return (STATUS_SYNTAX); + } + word = nsu_strsep(&cmdline, " \t\r\n"); if (*word == 0) { fprintf(stderr, "could not read server name\n"); @@ -1234,7 +1350,7 @@ evaluate_server(char *cmdline) { word = nsu_strsep(&cmdline, " \t\r\n"); if (*word == 0) - port = DNSDEFAULTPORT; + port = dnsport; else { char *endp; port = strtol(word, &endp, 10); @@ -1340,7 +1456,7 @@ evaluate_key(char *cmdline) { isc_buffer_init(&b, namestr, strlen(namestr)); isc_buffer_add(&b, strlen(namestr)); - result = dns_name_fromtext(keyname, &b, dns_rootname, ISC_FALSE, NULL); + result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not parse key name\n"); return (STATUS_SYNTAX); @@ -1397,8 +1513,7 @@ evaluate_zone(char *cmdline) { userzone = dns_fixedname_name(&fuserzone); isc_buffer_init(&b, word, strlen(word)); isc_buffer_add(&b, strlen(word)); - result = dns_name_fromtext(userzone, &b, dns_rootname, ISC_FALSE, - NULL); + result = dns_name_fromtext(userzone, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { userzone = NULL; /* Lest it point to an invalid name */ fprintf(stderr, "could not parse zone name\n"); @@ -1850,9 +1965,9 @@ get_next_command(void) { "server address [port] (set master server for zone)\n" "send (send the update request)\n" "show (show the update request)\n" -"answer (show the answer to the last request)\n" +"answer (show the answer to the last request)\n" "quit (quit, any pending update is not sent\n" -"help (display this message_\n" +"help (display this message_\n" "key [hmac:]keyname secret (use TSIG to sign the request)\n" "gsstsig (use GSS_TSIG to sign the request)\n" "oldgsstsig (use Microsoft's GSS_TSIG to sign the request)\n" @@ -2013,7 +2128,7 @@ send_update(dns_name_t *zonename, isc_sockaddr_t *master, { isc_result_t result; dns_request_t *request = NULL; - unsigned int options = 0; + unsigned int options = DNS_REQUESTOPT_CASE; ddebug("send_update()"); @@ -2246,7 +2361,7 @@ recvsoa(isc_task_t *task, isc_event_t *event) { result = dns_name_totext(&master, ISC_TRUE, &buf); check_result(result, "dns_name_totext"); serverstr[isc_buffer_usedlength(&buf)] = 0; - get_address(serverstr, DNSDEFAULTPORT, &tempaddr); + get_address(serverstr, dnsport, &tempaddr); serveraddr = &tempaddr; } dns_rdata_freestruct(&soa); @@ -2317,9 +2432,60 @@ sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, } #ifdef GSSAPI + +/* + * Get the realm from the users kerberos ticket if possible + */ static void -start_gssrequest(dns_name_t *master) +get_ticket_realm(isc_mem_t *mctx) { + krb5_context ctx; + krb5_error_code rc; + krb5_ccache ccache; + krb5_principal princ; + char *name, *ticket_realm; + + rc = krb5_init_context(&ctx); + if (rc != 0) + return; + + rc = krb5_cc_default(ctx, &ccache); + if (rc != 0) { + krb5_free_context(ctx); + return; + } + + rc = krb5_cc_get_principal(ctx, ccache, &princ); + if (rc != 0) { + krb5_cc_close(ctx, ccache); + krb5_free_context(ctx); + return; + } + + rc = krb5_unparse_name(ctx, princ, &name); + if (rc != 0) { + krb5_free_principal(ctx, princ); + krb5_cc_close(ctx, ccache); + krb5_free_context(ctx); + return; + } + + ticket_realm = strrchr(name, '@'); + if (ticket_realm != NULL) { + realm = isc_mem_strdup(mctx, ticket_realm); + } + + free(name); + krb5_free_principal(ctx, princ); + krb5_cc_close(ctx, ccache); + krb5_free_context(ctx); + if (realm != NULL && debugging) + fprintf(stderr, "Found realm from ticket: %s\n", realm+1); +} + + +static void +start_gssrequest(dns_name_t *master) { gss_ctx_id_t context; isc_buffer_t buf; isc_result_t result; @@ -2330,12 +2496,13 @@ start_gssrequest(dns_name_t *master) dns_fixedname_t fname; char namestr[DNS_NAME_FORMATSIZE]; char keystr[DNS_NAME_FORMATSIZE]; + char *err_message = NULL; debug("start_gssrequest"); usevc = ISC_TRUE; if (gssring != NULL) - dns_tsigkeyring_destroy(&gssring); + dns_tsigkeyring_detach(&gssring); gssring = NULL; result = dns_tsigkeyring_create(mctx, &gssring); @@ -2350,13 +2517,16 @@ start_gssrequest(dns_name_t *master) fatal("out of memory"); } if (userserver == NULL) - get_address(namestr, DNSDEFAULTPORT, kserver); + get_address(namestr, dnsport, kserver); else (void)memcpy(kserver, userserver, sizeof(isc_sockaddr_t)); dns_fixedname_init(&fname); servname = dns_fixedname_name(&fname); + if (realm == NULL) + get_ticket_realm(mctx); + result = isc_string_printf(servicename, sizeof(servicename), "DNS/%s%s", namestr, realm ? realm : ""); if (result != ISC_R_SUCCESS) @@ -2364,8 +2534,7 @@ start_gssrequest(dns_name_t *master) isc_result_totext(result)); isc_buffer_init(&buf, servicename, strlen(servicename)); isc_buffer_add(&buf, strlen(servicename)); - result = dns_name_fromtext(servname, &buf, dns_rootname, - ISC_FALSE, NULL); + result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) fatal("dns_name_fromtext(servname) failed: %s", isc_result_totext(result)); @@ -2382,8 +2551,7 @@ start_gssrequest(dns_name_t *master) isc_buffer_init(&buf, keystr, strlen(keystr)); isc_buffer_add(&buf, strlen(keystr)); - result = dns_name_fromtext(keyname, &buf, dns_rootname, - ISC_FALSE, NULL); + result = dns_name_fromtext(keyname, &buf, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) fatal("dns_name_fromtext(keyname) failed: %s", isc_result_totext(result)); @@ -2400,9 +2568,11 @@ start_gssrequest(dns_name_t *master) /* Build first request. */ context = GSS_C_NO_CONTEXT; result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0, - &context, use_win2k_gsstsig); + &context, use_win2k_gsstsig, + mctx, &err_message); if (result == ISC_R_FAILURE) - fatal("Check your Kerberos ticket, it may have expired."); + fatal("tkey query failed: %s", + err_message != NULL ? err_message : "unknown error"); if (result != ISC_R_SUCCESS) fatal("dns_tkey_buildgssquery failed: %s", isc_result_totext(result)); @@ -2451,6 +2621,7 @@ recvgss(isc_task_t *task, isc_event_t *event) { isc_buffer_t buf; dns_name_t *servname; dns_fixedname_t fname; + char *err_message = NULL; UNUSED(task); @@ -2533,14 +2704,14 @@ recvgss(isc_task_t *task, isc_event_t *event) { servname = dns_fixedname_name(&fname); isc_buffer_init(&buf, servicename, strlen(servicename)); isc_buffer_add(&buf, strlen(servicename)); - result = dns_name_fromtext(servname, &buf, dns_rootname, - ISC_FALSE, NULL); + result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL); check_result(result, "dns_name_fromtext"); tsigkey = NULL; result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname, &context, &tsigkey, gssring, - use_win2k_gsstsig); + use_win2k_gsstsig, + &err_message); switch (result) { case DNS_R_CONTINUE: @@ -2583,7 +2754,9 @@ recvgss(isc_task_t *task, isc_event_t *event) { break; default: - fatal("dns_tkey_negotiategss: %s", isc_result_totext(result)); + fatal("dns_tkey_negotiategss: %s %s", + isc_result_totext(result), + err_message != NULL ? err_message : ""); } done: @@ -2693,8 +2866,8 @@ cleanup(void) { dns_tsigkey_detach(&tsigkey); } if (gssring != NULL) { - ddebug("Destroying GSS-TSIG keyring"); - dns_tsigkeyring_destroy(&gssring); + ddebug("Detaching GSS-TSIG keyring"); + dns_tsigkeyring_detach(&gssring); } if (kserver != NULL) { isc_mem_put(mctx, kserver, sizeof(isc_sockaddr_t)); diff --git a/bin/nsupdate/nsupdate.docbook b/bin/nsupdate/nsupdate.docbook index 4069a2b..2a92af4 100644 --- a/bin/nsupdate/nsupdate.docbook +++ b/bin/nsupdate/nsupdate.docbook @@ -18,10 +18,10 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + - Jun 30, 2000 + Aug 25, 2009 nsupdate @@ -61,6 +61,7 @@ + @@ -76,7 +77,7 @@ DESCRIPTION nsupdate - is used to submit Dynamic DNS Update requests as defined in RFC2136 + is used to submit Dynamic DNS Update requests as defined in RFC 2136 to a name server. This allows resource records to be added or removed from a zone without manually editing the zone file. @@ -112,10 +113,14 @@ report additional debugging information to . + The option with an integer argument of zero or + higher sets the logging debug level. If zero, logging is disabled. + + Transaction signatures can be used to authenticate the Dynamic DNS updates. These use the TSIG resource record type described - in RFC2845 or the SIG(0) record described in RFC3535 and - RFC2931 or GSS-TSIG as described in RFC3645. TSIG relies on + in RFC 2845 or the SIG(0) record described in RFC 2535 and + RFC 2931 or GSS-TSIG as described in RFC 3645. TSIG relies on a shared secret that should only be known to nsupdate and the name server. Currently, the only supported encryption algorithm for TSIG is HMAC-MD5, @@ -132,46 +137,61 @@ record in a zone served by the name server. nsupdate does not read /etc/named.conf. - GSS-TSIG uses Kerberos credentials. + + + GSS-TSIG uses Kerberos credentials. Standard GSS-TSIG mode + is switched on with the flag. A + non-standards-compliant variant of GSS-TSIG used by Windows + 2000 can be switched on with the flag. nsupdate uses the or option to provide the shared secret needed to generate a TSIG record for authenticating Dynamic DNS update requests, default type - HMAC-MD5. These options are mutually exclusive. With the - option, nsupdate reads - the shared secret from the file keyfile, - whose name is of the form - K{name}.+157.+{random}.private. For - historical reasons, the file - K{name}.+157.+{random}.key must also be - present. When the option is used, a - signature is generated from + HMAC-MD5. These options are mutually exclusive. + + + When the option is used, a signature is + generated from hmac:keyname:secret. keyname is the name of the key, and - secret is the base64 encoded shared - secret. Use of the option is discouraged - because the shared secret is supplied as a command line - argument in clear text. This may be visible in the output - from + secret is the base64 encoded shared secret. + Use of the option is discouraged because the + shared secret is supplied as a command line argument in clear text. + This may be visible in the output from - ps1 - or in a history file maintained by the user's - shell. + ps1 + + or in a history file maintained by the user's shell. + With the + option, nsupdate reads + the shared secret from the file keyfile. + Keyfiles may be in two formats: a single file containing + a named.conf-format key + statement, which may be generated automatically by + ddns-confgen, or a pair of files whose names are + of the format K{name}.+157.+{random}.key and + K{name}.+157.+{random}.private, which can be + generated by dnssec-keygen. The may also be used to specify a SIG(0) key used to authenticate Dynamic DNS update requests. In this case, the key specified is not an HMAC-MD5 key. - The and specify that - GSS-TSIG is to be used. The should only - be used with old Microsoft Windows 2000 servers. + nsupdate can be run in a local-host only mode + using the flag. This sets the server address to + localhost (disabling the server so that the server + address cannot be overridden). Connections to the local server will + use a TSIG key found in /var/run/named/session.key, + which is automatically generated by named if any + local master zone has set update-policy to + local. The location of this key file can be + overridden with the option. - By default, - nsupdate + By default, nsupdate uses UDP to send update requests to the name server unless they are too large to fit in a UDP request in which case TCP will be used. The @@ -182,6 +202,10 @@ This may be preferable when a batch of update requests is made. + The sets the default port number to use for + connections to a name server. The default is 53. + + The option sets the maximum time an update request can take before it is aborted. The default is 300 seconds. Zero can be @@ -650,9 +674,9 @@ If there are, the update request fails. If this name does not exist, a CNAME for it is added. This ensures that when the CNAME is added, it cannot conflict with the - long-standing rule in RFC1034 that a name must not exist as any other + long-standing rule in RFC 1034 that a name must not exist as any other record type if it exists as a CNAME. - (The rule has been updated for DNSSEC in RFC2535 to allow CNAMEs to have + (The rule has been updated for DNSSEC in RFC 2535 to allow CNAMEs to have RRSIG, DNSKEY and NSEC records.) @@ -671,6 +695,15 @@ + /var/run/named/session.key + + + sets the default TSIG key for use in local-only mode + + + + + K{name}.+157.+{random}.key @@ -699,36 +732,26 @@ SEE ALSO - - RFC2136 - , - - RFC3007 - , - - RFC2104 - , - - RFC2845 - , - - RFC1034 - , - - RFC2535 - , + + RFC 2136, + RFC 3007, + RFC 2104, + RFC 2845, + RFC 1034, + RFC 2535, + RFC 2931, - RFC2931 + named8 , - named8 + ddns-confgen8 , dnssec-keygen8 . - + BUGS diff --git a/bin/nsupdate/nsupdate.html b/bin/nsupdate/nsupdate.html index a383617..f488315 100644 --- a/bin/nsupdate/nsupdate.html +++ b/bin/nsupdate/nsupdate.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -29,12 +29,12 @@

    Synopsis

    -

    nsupdate [-d] [-D] [[-g] | [-o] | [-y [hmac:]keyname:secret] | [-k keyfile]] [-t timeout] [-u udptimeout] [-r udpretries] [-R randomdev] [-v] [filename]

    +

    nsupdate [-d] [-D] [[-g] | [-o] | [-l] | [-y [hmac:]keyname:secret] | [-k keyfile]] [-t timeout] [-u udptimeout] [-r udpretries] [-R randomdev] [-v] [filename]

    -

    DESCRIPTION

    +

    DESCRIPTION

    nsupdate - is used to submit Dynamic DNS Update requests as defined in RFC2136 + is used to submit Dynamic DNS Update requests as defined in RFC 2136 to a name server. This allows resource records to be added or removed from a zone without manually editing the zone file. @@ -70,10 +70,14 @@ report additional debugging information to -d.

    + The -L option with an integer argument of zero or + higher sets the logging debug level. If zero, logging is disabled. +

    +

    Transaction signatures can be used to authenticate the Dynamic DNS updates. These use the TSIG resource record type described - in RFC2845 or the SIG(0) record described in RFC3535 and - RFC2931 or GSS-TSIG as described in RFC3645. TSIG relies on + in RFC 2845 or the SIG(0) record described in RFC 2535 and + RFC 2931 or GSS-TSIG as described in RFC 3645. TSIG relies on a shared secret that should only be known to nsupdate and the name server. Currently, the only supported encryption algorithm for TSIG is HMAC-MD5, @@ -90,44 +94,59 @@ record in a zone served by the name server. nsupdate does not read /etc/named.conf. - GSS-TSIG uses Kerberos credentials. +

    +

    + GSS-TSIG uses Kerberos credentials. Standard GSS-TSIG mode + is switched on with the -g flag. A + non-standards-compliant variant of GSS-TSIG used by Windows + 2000 can be switched on with the -o flag.

    nsupdate uses the -y or -k option to provide the shared secret needed to generate a TSIG record for authenticating Dynamic DNS update requests, default type - HMAC-MD5. These options are mutually exclusive. With the - -k option, nsupdate reads - the shared secret from the file keyfile, - whose name is of the form - K{name}.+157.+{random}.private. For - historical reasons, the file - K{name}.+157.+{random}.key must also be - present. When the -y option is used, a - signature is generated from + HMAC-MD5. These options are mutually exclusive. +

    +

    + When the -y option is used, a signature is + generated from [hmac:]keyname:secret. keyname is the name of the key, and - secret is the base64 encoded shared - secret. Use of the -y option is discouraged - because the shared secret is supplied as a command line - argument in clear text. This may be visible in the output - from - ps(1) or in a history file maintained by the user's - shell. + secret is the base64 encoded shared secret. + Use of the -y option is discouraged because the + shared secret is supplied as a command line argument in clear text. + This may be visible in the output from + ps(1) + or in a history file maintained by the user's shell.

    + With the + -k option, nsupdate reads + the shared secret from the file keyfile. + Keyfiles may be in two formats: a single file containing + a named.conf-format key + statement, which may be generated automatically by + ddns-confgen, or a pair of files whose names are + of the format K{name}.+157.+{random}.key and + K{name}.+157.+{random}.private, which can be + generated by dnssec-keygen. The -k may also be used to specify a SIG(0) key used to authenticate Dynamic DNS update requests. In this case, the key specified is not an HMAC-MD5 key.

    - The -g and -o specify that - GSS-TSIG is to be used. The -o should only - be used with old Microsoft Windows 2000 servers. + nsupdate can be run in a local-host only mode + using the -l flag. This sets the server address to + localhost (disabling the server so that the server + address cannot be overridden). Connections to the local server will + use a TSIG key found in /var/run/named/session.key, + which is automatically generated by named if any + local master zone has set update-policy to + local. The location of this key file can be + overridden with the -k option.

    - By default, - nsupdate + By default, nsupdate uses UDP to send update requests to the name server unless they are too large to fit in a UDP request in which case TCP will be used. The @@ -138,6 +157,10 @@ This may be preferable when a batch of update requests is made.

    + The -p sets the default port number to use for + connections to a name server. The default is 53. +

    +

    The -t option sets the maximum time an update request can take before it is aborted. The default is 300 seconds. Zero can be @@ -169,7 +192,7 @@

    -

    INPUT FORMAT

    +

    INPUT FORMAT

    nsupdate reads input from filename @@ -457,7 +480,7 @@

    -

    EXAMPLES

    +

    EXAMPLES

    The examples below show how nsupdate @@ -504,19 +527,23 @@ If there are, the update request fails. If this name does not exist, a CNAME for it is added. This ensures that when the CNAME is added, it cannot conflict with the - long-standing rule in RFC1034 that a name must not exist as any other + long-standing rule in RFC 1034 that a name must not exist as any other record type if it exists as a CNAME. - (The rule has been updated for DNSSEC in RFC2535 to allow CNAMEs to have + (The rule has been updated for DNSSEC in RFC 2535 to allow CNAMEs to have RRSIG, DNSKEY and NSEC records.)

    -

    FILES

    +

    FILES

    /etc/resolv.conf

    used to identify default name server

    +
    /var/run/named/session.key
    +

    + sets the default TSIG key for use in local-only mode +

    K{name}.+157.+{random}.key

    base-64 encoding of HMAC-MD5 key created by @@ -530,20 +557,22 @@

    -

    SEE ALSO

    -

    RFC2136, - RFC3007, - RFC2104, - RFC2845, - RFC1034, - RFC2535, - RFC2931, +

    SEE ALSO

    +

    + RFC 2136, + RFC 3007, + RFC 2104, + RFC 2845, + RFC 1034, + RFC 2535, + RFC 2931, named(8), + ddns-confgen(8), dnssec-keygen(8).

    -

    BUGS

    +

    BUGS

    The TSIG key is redundantly stored in two separate files. This is a consequence of nsupdate using the DST library diff --git a/bin/rndc/Makefile.in b/bin/rndc/Makefile.in index 27d4611..6c7c56f 100644 --- a/bin/rndc/Makefile.in +++ b/bin/rndc/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 2000-2002 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.44 2007-06-18 23:47:22 tbox Exp $ +# $Id: Makefile.in,v 1.49 2009-12-05 23:31:40 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -32,6 +32,7 @@ CWARNINGS = ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ ISCCCLIBS = ../../lib/isccc/libisccc.@A@ ISCLIBS = ../../lib/isc/libisc.@A@ +ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ BIND9LIBS = ../../lib/bind9/libbind9.@A@ @@ -41,26 +42,23 @@ ISCDEPLIBS = ../../lib/isc/libisc.@A@ DNSDEPLIBS = ../../lib/dns/libdns.@A@ BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@ -RNDCLIBS = ${ISCCFGLIBS} ${ISCCCLIBS} ${BIND9LIBS} ${DNSLIBS} ${ISCLIBS} @LIBS@ +LIBS = ${ISCLIBS} @LIBS@ +NOSYMLIBS = ${ISCNOSYMLIBS} @LIBS@ + RNDCDEPLIBS = ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${BIND9DEPLIBS} ${DNSDEPLIBS} ${ISCDEPLIBS} -CONFLIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@ CONFDEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS} -SRCS= rndc.c rndc-confgen.c - -SUBDIRS = unix +SRCS= rndc.c -TARGETS = rndc@EXEEXT@ rndc-confgen@EXEEXT@ +TARGETS = rndc@EXEEXT@ -MANPAGES = rndc.8 rndc-confgen.8 rndc.conf.5 +MANPAGES = rndc.8 rndc.conf.5 -HTMLPAGES = rndc.html rndc-confgen.html rndc.conf.html +HTMLPAGES = rndc.html rndc.conf.html MANOBJS = ${MANPAGES} ${HTMLPAGES} -UOBJS = unix/os.@O@ - @BIND9_MAKE_RULES@ rndc.@O@: rndc.c @@ -70,18 +68,10 @@ rndc.@O@: rndc.c -DRNDC_KEYFILE=\"${sysconfdir}/rndc.key\" \ -c ${srcdir}/rndc.c -rndc-confgen.@O@: rndc-confgen.c - ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ - -DRNDC_KEYFILE=\"${sysconfdir}/rndc.key\" \ - -c ${srcdir}/rndc-confgen.c - rndc@EXEEXT@: rndc.@O@ util.@O@ ${RNDCDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rndc.@O@ util.@O@ \ - ${RNDCLIBS} - -rndc-confgen@EXEEXT@: rndc-confgen.@O@ util.@O@ ${UOBJS} ${CONFDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rndc-confgen.@O@ util.@O@ \ - ${UOBJS} ${CONFLIBS} + export BASEOBJS="rndc.@O@ util.@O@"; \ + export LIBS0="${ISCCFGLIBS} ${ISCCCLIBS} ${BIND9LIBS} ${DNSLIBS}"; \ + ${FINALBUILDCMD} doc man:: ${MANOBJS} @@ -93,11 +83,9 @@ installdirs: $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man5 -install:: rndc@EXEEXT@ rndc-confgen@EXEEXT@ installdirs +install:: rndc@EXEEXT@ installdirs ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} rndc@EXEEXT@ ${DESTDIR}${sbindir} - ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} rndc-confgen@EXEEXT@ ${DESTDIR}${sbindir} ${INSTALL_DATA} ${srcdir}/rndc.8 ${DESTDIR}${mandir}/man8 - ${INSTALL_DATA} ${srcdir}/rndc-confgen.8 ${DESTDIR}${mandir}/man8 ${INSTALL_DATA} ${srcdir}/rndc.conf.5 ${DESTDIR}${mandir}/man5 clean distclean maintainer-clean:: diff --git a/bin/rndc/include/rndc/os.h b/bin/rndc/include/rndc/os.h index 9f96165..91986cb 100644 --- a/bin/rndc/include/rndc/os.h +++ b/bin/rndc/include/rndc/os.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: os.h,v 1.9.332.2 2009-01-18 23:47:35 tbox Exp $ */ +/* $Id: os.h,v 1.12 2009-06-10 00:27:21 each Exp $ */ /*! \file */ @@ -27,12 +27,6 @@ ISC_LANG_BEGINDECLS -FILE *safe_create(const char *filename); -/*%< - * Open 'filename' for writing, truncate if necessary. If the file was - * created ensure that only the owner can read/write it. - */ - int set_user(FILE *fd, const char *user); /*%< * Set the owner of the file referenced by 'fd' to 'user'. diff --git a/bin/rndc/rndc-confgen.8 b/bin/rndc/rndc-confgen.8 deleted file mode 100644 index db45df4..0000000 --- a/bin/rndc/rndc-confgen.8 +++ /dev/null @@ -1,211 +0,0 @@ -.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") -.\" Copyright (C) 2001, 2003 Internet Software Consortium. -.\" -.\" 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 ISC DISCLAIMS ALL WARRANTIES WITH -.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -.\" AND FITNESS. IN NO EVENT SHALL ISC 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. -.\" -.\" $Id: rndc-confgen.8,v 1.20.418.1 2009-07-11 01:55:21 tbox Exp $ -.\" -.hy 0 -.ad l -.\" Title: rndc\-confgen -.\" Author: -.\" Generator: DocBook XSL Stylesheets v1.71.1 -.\" Date: Aug 27, 2001 -.\" Manual: BIND9 -.\" Source: BIND9 -.\" -.TH "RNDC\-CONFGEN" "8" "Aug 27, 2001" "BIND9" "BIND9" -.\" disable hyphenation -.nh -.\" disable justification (adjust text to left margin only) -.ad l -.SH "NAME" -rndc\-confgen \- rndc key generation tool -.SH "SYNOPSIS" -.HP 13 -\fBrndc\-confgen\fR [\fB\-a\fR] [\fB\-b\ \fR\fB\fIkeysize\fR\fR] [\fB\-c\ \fR\fB\fIkeyfile\fR\fR] [\fB\-h\fR] [\fB\-k\ \fR\fB\fIkeyname\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-r\ \fR\fB\fIrandomfile\fR\fR] [\fB\-s\ \fR\fB\fIaddress\fR\fR] [\fB\-t\ \fR\fB\fIchrootdir\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] -.SH "DESCRIPTION" -.PP -\fBrndc\-confgen\fR -generates configuration files for -\fBrndc\fR. It can be used as a convenient alternative to writing the -\fIrndc.conf\fR -file and the corresponding -\fBcontrols\fR -and -\fBkey\fR -statements in -\fInamed.conf\fR -by hand. Alternatively, it can be run with the -\fB\-a\fR -option to set up a -\fIrndc.key\fR -file and avoid the need for a -\fIrndc.conf\fR -file and a -\fBcontrols\fR -statement altogether. -.SH "OPTIONS" -.PP -\-a -.RS 4 -Do automatic -\fBrndc\fR -configuration. This creates a file -\fIrndc.key\fR -in -\fI/etc\fR -(or whatever -\fIsysconfdir\fR -was specified as when -BIND -was built) that is read by both -\fBrndc\fR -and -\fBnamed\fR -on startup. The -\fIrndc.key\fR -file defines a default command channel and authentication key allowing -\fBrndc\fR -to communicate with -\fBnamed\fR -on the local host with no further configuration. -.sp -Running -\fBrndc\-confgen \-a\fR -allows BIND 9 and -\fBrndc\fR -to be used as drop\-in replacements for BIND 8 and -\fBndc\fR, with no changes to the existing BIND 8 -\fInamed.conf\fR -file. -.sp -If a more elaborate configuration than that generated by -\fBrndc\-confgen \-a\fR -is required, for example if rndc is to be used remotely, you should run -\fBrndc\-confgen\fR -without the -\fB\-a\fR -option and set up a -\fIrndc.conf\fR -and -\fInamed.conf\fR -as directed. -.RE -.PP -\-b \fIkeysize\fR -.RS 4 -Specifies the size of the authentication key in bits. Must be between 1 and 512 bits; the default is 128. -.RE -.PP -\-c \fIkeyfile\fR -.RS 4 -Used with the -\fB\-a\fR -option to specify an alternate location for -\fIrndc.key\fR. -.RE -.PP -\-h -.RS 4 -Prints a short summary of the options and arguments to -\fBrndc\-confgen\fR. -.RE -.PP -\-k \fIkeyname\fR -.RS 4 -Specifies the key name of the rndc authentication key. This must be a valid domain name. The default is -\fBrndc\-key\fR. -.RE -.PP -\-p \fIport\fR -.RS 4 -Specifies the command channel port where -\fBnamed\fR -listens for connections from -\fBrndc\fR. The default is 953. -.RE -.PP -\-r \fIrandomfile\fR -.RS 4 -Specifies a source of random data for generating the authorization. If the operating system does not provide a -\fI/dev/random\fR -or equivalent device, the default source of randomness is keyboard input. -\fIrandomdev\fR -specifies the name of a character device or file containing random data to be used instead of the default. The special value -\fIkeyboard\fR -indicates that keyboard input should be used. -.RE -.PP -\-s \fIaddress\fR -.RS 4 -Specifies the IP address where -\fBnamed\fR -listens for command channel connections from -\fBrndc\fR. The default is the loopback address 127.0.0.1. -.RE -.PP -\-t \fIchrootdir\fR -.RS 4 -Used with the -\fB\-a\fR -option to specify a directory where -\fBnamed\fR -will run chrooted. An additional copy of the -\fIrndc.key\fR -will be written relative to this directory so that it will be found by the chrooted -\fBnamed\fR. -.RE -.PP -\-u \fIuser\fR -.RS 4 -Used with the -\fB\-a\fR -option to set the owner of the -\fIrndc.key\fR -file generated. If -\fB\-t\fR -is also specified only the file in the chroot area has its owner changed. -.RE -.SH "EXAMPLES" -.PP -To allow -\fBrndc\fR -to be used with no manual configuration, run -.PP -\fBrndc\-confgen \-a\fR -.PP -To print a sample -\fIrndc.conf\fR -file and corresponding -\fBcontrols\fR -and -\fBkey\fR -statements to be manually inserted into -\fInamed.conf\fR, run -.PP -\fBrndc\-confgen\fR -.SH "SEE ALSO" -.PP -\fBrndc\fR(8), -\fBrndc.conf\fR(5), -\fBnamed\fR(8), -BIND 9 Administrator Reference Manual. -.SH "AUTHOR" -.PP -Internet Systems Consortium -.SH "COPYRIGHT" -Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") -.br -Copyright \(co 2001, 2003 Internet Software Consortium. -.br diff --git a/bin/rndc/rndc-confgen.c b/bin/rndc/rndc-confgen.c deleted file mode 100644 index 1cb0a0a..0000000 --- a/bin/rndc/rndc-confgen.c +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 2001, 2003 Internet Software Consortium. - * - * 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 ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC 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. - */ - -/* $Id: rndc-confgen.c,v 1.26 2008-10-15 23:47:31 tbox Exp $ */ - -/*! \file */ - -/** - * rndc-confgen generates configuration files for rndc. It can be used - * as a convenient alternative to writing the rndc.conf file and the - * corresponding controls and key statements in named.conf by hand. - * Alternatively, it can be run with the -a option to set up a - * rndc.key file and avoid the need for a rndc.conf file and a - * controls statement altogether. - */ - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include "util.h" - -#define DEFAULT_KEYLENGTH 128 /*% Bits. */ -#define DEFAULT_KEYNAME "rndc-key" -#define DEFAULT_SERVER "127.0.0.1" -#define DEFAULT_PORT 953 - -static char program[256]; -const char *progname; - -isc_boolean_t verbose = ISC_FALSE; - -const char *keyfile, *keydef; - -static void -usage(int status) { - - fprintf(stderr, "\ -Usage:\n\ - %s [-a] [-b bits] [-c keyfile] [-k keyname] [-p port] [-r randomfile] \ -[-s addr] [-t chrootdir] [-u user]\n\ - -a: generate just the key clause and write it to keyfile (%s)\n\ - -b bits: from 1 through 512, default %d; total length of the secret\n\ - -c keyfile: specify an alternate key file (requires -a)\n\ - -k keyname: the name as it will be used in named.conf and rndc.conf\n\ - -p port: the port named will listen on and rndc will connect to\n\ - -r randomfile: a file containing random data\n\ - -s addr: the address to which rndc should connect\n\ - -t chrootdir: write a keyfile in chrootdir as well (requires -a)\n\ - -u user: set the keyfile owner to \"user\" (requires -a)\n", - progname, keydef, DEFAULT_KEYLENGTH); - - exit (status); -} - -/*% - * Write an rndc.key file to 'keyfile'. If 'user' is non-NULL, - * make that user the owner of the file. The key will have - * the name 'keyname' and the secret in the buffer 'secret'. - */ -static void -write_key_file(const char *keyfile, const char *user, - const char *keyname, isc_buffer_t *secret ) -{ - FILE *fd; - - fd = safe_create(keyfile); - if (fd == NULL) - fatal( "unable to create \"%s\"\n", keyfile); - if (user != NULL) { - if (set_user(fd, user) == -1) - fatal("unable to set file owner\n"); - } - fprintf(fd, "key \"%s\" {\n\talgorithm hmac-md5;\n" - "\tsecret \"%.*s\";\n};\n", keyname, - (int)isc_buffer_usedlength(secret), - (char *)isc_buffer_base(secret)); - fflush(fd); - if (ferror(fd)) - fatal("write to %s failed\n", keyfile); - if (fclose(fd)) - fatal("fclose(%s) failed\n", keyfile); - fprintf(stderr, "wrote key file \"%s\"\n", keyfile); -} - -int -main(int argc, char **argv) { - isc_boolean_t show_final_mem = ISC_FALSE; - isc_buffer_t key_rawbuffer; - isc_buffer_t key_txtbuffer; - isc_region_t key_rawregion; - isc_mem_t *mctx = NULL; - isc_entropy_t *ectx = NULL; - isc_entropysource_t *entropy_source = NULL; - isc_result_t result = ISC_R_SUCCESS; - dst_key_t *key = NULL; - const char *keyname = NULL; - const char *randomfile = NULL; - const char *serveraddr = NULL; - char key_rawsecret[64]; - char key_txtsecret[256]; - char *p; - int ch; - int port; - int keysize; - int entropy_flags = 0; - int open_keyboard = ISC_ENTROPY_KEYBOARDMAYBE; - struct in_addr addr4_dummy; - struct in6_addr addr6_dummy; - char *chrootdir = NULL; - char *user = NULL; - isc_boolean_t keyonly = ISC_FALSE; - int len; - - keydef = keyfile = RNDC_KEYFILE; - - result = isc_file_progname(*argv, program, sizeof(program)); - if (result != ISC_R_SUCCESS) - memcpy(program, "rndc-confgen", 13); - progname = program; - - keyname = DEFAULT_KEYNAME; - keysize = DEFAULT_KEYLENGTH; - serveraddr = DEFAULT_SERVER; - port = DEFAULT_PORT; - - isc_commandline_errprint = ISC_FALSE; - - while ((ch = isc_commandline_parse(argc, argv, - "ab:c:hk:Mmp:r:s:t:u:Vy")) != -1) { - switch (ch) { - case 'a': - keyonly = ISC_TRUE; - break; - case 'b': - keysize = strtol(isc_commandline_argument, &p, 10); - if (*p != '\0' || keysize < 0) - fatal("-b requires a non-negative number"); - if (keysize < 1 || keysize > 512) - fatal("-b must be in the range 1 through 512"); - break; - case 'c': - keyfile = isc_commandline_argument; - break; - case 'h': - usage(0); - case 'k': - case 'y': /* Compatible with rndc -y. */ - keyname = isc_commandline_argument; - break; - case 'M': - isc_mem_debugging = ISC_MEM_DEBUGTRACE; - break; - - case 'm': - show_final_mem = ISC_TRUE; - break; - case 'p': - port = strtol(isc_commandline_argument, &p, 10); - if (*p != '\0' || port < 0 || port > 65535) - fatal("port '%s' out of range", - isc_commandline_argument); - break; - case 'r': - randomfile = isc_commandline_argument; - break; - case 's': - serveraddr = isc_commandline_argument; - if (inet_pton(AF_INET, serveraddr, &addr4_dummy) != 1 && - inet_pton(AF_INET6, serveraddr, &addr6_dummy) != 1) - fatal("-s should be an IPv4 or IPv6 address"); - break; - case 't': - chrootdir = isc_commandline_argument; - break; - case 'u': - user = isc_commandline_argument; - break; - case 'V': - verbose = ISC_TRUE; - break; - case '?': - if (isc_commandline_option != '?') { - fprintf(stderr, "%s: invalid argument -%c\n", - program, isc_commandline_option); - usage(1); - } else - usage(0); - break; - default: - fprintf(stderr, "%s: unhandled option -%c\n", - program, isc_commandline_option); - exit(1); - } - } - - argc -= isc_commandline_index; - argv += isc_commandline_index; - - if (argc > 0) - usage(1); - - DO("create memory context", isc_mem_create(0, 0, &mctx)); - - DO("create entropy context", isc_entropy_create(mctx, &ectx)); - - if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) { - randomfile = NULL; - open_keyboard = ISC_ENTROPY_KEYBOARDYES; - } - DO("start entropy source", isc_entropy_usebestsource(ectx, - &entropy_source, - randomfile, - open_keyboard)); - - entropy_flags = ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY; - - DO("initialize dst library", dst_lib_init(mctx, ectx, entropy_flags)); - - DO("generate key", dst_key_generate(dns_rootname, DST_ALG_HMACMD5, - keysize, 0, 0, - DNS_KEYPROTO_ANY, - dns_rdataclass_in, mctx, &key)); - - isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret)); - - DO("dump key to buffer", dst_key_tobuffer(key, &key_rawbuffer)); - - isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret)); - isc_buffer_usedregion(&key_rawbuffer, &key_rawregion); - - DO("bsse64 encode secret", isc_base64_totext(&key_rawregion, -1, "", - &key_txtbuffer)); - - /* - * Shut down the entropy source now so the "stop typing" message - * does not muck with the output. - */ - if (entropy_source != NULL) - isc_entropy_destroysource(&entropy_source); - - if (key != NULL) - dst_key_free(&key); - - isc_entropy_detach(&ectx); - dst_lib_destroy(); - - if (keyonly) { - write_key_file(keyfile, chrootdir == NULL ? user : NULL, - keyname, &key_txtbuffer); - - if (chrootdir != NULL) { - char *buf; - len = strlen(chrootdir) + strlen(keyfile) + 2; - buf = isc_mem_get(mctx, len); - if (buf == NULL) - fatal("isc_mem_get(%d) failed\n", len); - snprintf(buf, len, "%s%s%s", chrootdir, - (*keyfile != '/') ? "/" : "", keyfile); - - write_key_file(buf, user, keyname, &key_txtbuffer); - isc_mem_put(mctx, buf, len); - } - } else { - printf("\ -# Start of rndc.conf\n\ -key \"%s\" {\n\ - algorithm hmac-md5;\n\ - secret \"%.*s\";\n\ -};\n\ -\n\ -options {\n\ - default-key \"%s\";\n\ - default-server %s;\n\ - default-port %d;\n\ -};\n\ -# End of rndc.conf\n\ -\n\ -# Use with the following in named.conf, adjusting the allow list as needed:\n\ -# key \"%s\" {\n\ -# algorithm hmac-md5;\n\ -# secret \"%.*s\";\n\ -# };\n\ -# \n\ -# controls {\n\ -# inet %s port %d\n\ -# allow { %s; } keys { \"%s\"; };\n\ -# };\n\ -# End of named.conf\n", - keyname, - (int)isc_buffer_usedlength(&key_txtbuffer), - (char *)isc_buffer_base(&key_txtbuffer), - keyname, serveraddr, port, - keyname, - (int)isc_buffer_usedlength(&key_txtbuffer), - (char *)isc_buffer_base(&key_txtbuffer), - serveraddr, port, serveraddr, keyname); - } - - if (show_final_mem) - isc_mem_stats(mctx, stderr); - - isc_mem_destroy(&mctx); - - return (0); -} diff --git a/bin/rndc/rndc-confgen.docbook b/bin/rndc/rndc-confgen.docbook deleted file mode 100644 index f71dd9f..0000000 --- a/bin/rndc/rndc-confgen.docbook +++ /dev/null @@ -1,286 +0,0 @@ -]> - - - - - - Aug 27, 2001 - - - - rndc-confgen - 8 - BIND9 - - - - rndc-confgen - rndc key generation tool - - - - - 2004 - 2005 - 2007 - Internet Systems Consortium, Inc. ("ISC") - - - 2001 - 2003 - Internet Software Consortium. - - - - - - rndc-confgen - - - - - - - - - - - - - - - DESCRIPTION - rndc-confgen - generates configuration files - for rndc. It can be used as a - convenient alternative to writing the - rndc.conf file - and the corresponding controls - and key - statements in named.conf by hand. - Alternatively, it can be run with the -a - option to set up a rndc.key file and - avoid the need for a rndc.conf file - and a controls statement altogether. - - - - - - OPTIONS - - - - -a - - - Do automatic rndc configuration. - This creates a file rndc.key - in /etc (or whatever - sysconfdir - was specified as when BIND was - built) - that is read by both rndc - and named on startup. The - rndc.key file defines a default - command channel and authentication key allowing - rndc to communicate with - named on the local host - with no further configuration. - - - Running rndc-confgen -a allows - BIND 9 and rndc to be used as - drop-in - replacements for BIND 8 and ndc, - with no changes to the existing BIND 8 - named.conf file. - - - If a more elaborate configuration than that - generated by rndc-confgen -a - is required, for example if rndc is to be used remotely, - you should run rndc-confgen without - the - -a option and set up a - rndc.conf and - named.conf - as directed. - - - - - - -b keysize - - - Specifies the size of the authentication key in bits. - Must be between 1 and 512 bits; the default is 128. - - - - - - -c keyfile - - - Used with the -a option to specify - an alternate location for rndc.key. - - - - - - -h - - - Prints a short summary of the options and arguments to - rndc-confgen. - - - - - - -k keyname - - - Specifies the key name of the rndc authentication key. - This must be a valid domain name. - The default is rndc-key. - - - - - - -p port - - - Specifies the command channel port where named - listens for connections from rndc. - The default is 953. - - - - - - -r randomfile - - - Specifies a source of random data for generating the - authorization. If the operating - system does not provide a /dev/random - or equivalent device, the default source of randomness - is keyboard input. randomdev - specifies - the name of a character device or file containing random - data to be used instead of the default. The special value - keyboard indicates that keyboard - input should be used. - - - - - - -s address - - - Specifies the IP address where named - listens for command channel connections from - rndc. The default is the loopback - address 127.0.0.1. - - - - - - -t chrootdir - - - Used with the -a option to specify - a directory where named will run - chrooted. An additional copy of the rndc.key - will be written relative to this directory so that - it will be found by the chrooted named. - - - - - - -u user - - - Used with the -a option to set the - owner - of the rndc.key file generated. - If - -t is also specified only the file - in - the chroot area has its owner changed. - - - - - - - - - EXAMPLES - - To allow rndc to be used with - no manual configuration, run - - rndc-confgen -a - - - To print a sample rndc.conf file and - corresponding controls and key - statements to be manually inserted into named.conf, - run - - rndc-confgen - - - - - SEE ALSO - - rndc8 - , - - rndc.conf5 - , - - named8 - , - BIND 9 Administrator Reference Manual. - - - - - AUTHOR - Internet Systems Consortium - - - - diff --git a/bin/rndc/rndc-confgen.html b/bin/rndc/rndc-confgen.html deleted file mode 100644 index 6ef1073..0000000 --- a/bin/rndc/rndc-confgen.html +++ /dev/null @@ -1,188 +0,0 @@ - - - - - -rndc-confgen - - -

    -
    -
    -

    Name

    -

    rndc-confgen — rndc key generation tool

    -
    -
    -

    Synopsis

    -

    rndc-confgen [-a] [-b keysize] [-c keyfile] [-h] [-k keyname] [-p port] [-r randomfile] [-s address] [-t chrootdir] [-u user]

    -
    -
    -

    DESCRIPTION

    -

    rndc-confgen - generates configuration files - for rndc. It can be used as a - convenient alternative to writing the - rndc.conf file - and the corresponding controls - and key - statements in named.conf by hand. - Alternatively, it can be run with the -a - option to set up a rndc.key file and - avoid the need for a rndc.conf file - and a controls statement altogether. -

    -
    -
    -

    OPTIONS

    -
    -
    -a
    -
    -

    - Do automatic rndc configuration. - This creates a file rndc.key - in /etc (or whatever - sysconfdir - was specified as when BIND was - built) - that is read by both rndc - and named on startup. The - rndc.key file defines a default - command channel and authentication key allowing - rndc to communicate with - named on the local host - with no further configuration. -

    -

    - Running rndc-confgen -a allows - BIND 9 and rndc to be used as - drop-in - replacements for BIND 8 and ndc, - with no changes to the existing BIND 8 - named.conf file. -

    -

    - If a more elaborate configuration than that - generated by rndc-confgen -a - is required, for example if rndc is to be used remotely, - you should run rndc-confgen without - the - -a option and set up a - rndc.conf and - named.conf - as directed. -

    -
    -
    -b keysize
    -

    - Specifies the size of the authentication key in bits. - Must be between 1 and 512 bits; the default is 128. -

    -
    -c keyfile
    -

    - Used with the -a option to specify - an alternate location for rndc.key. -

    -
    -h
    -

    - Prints a short summary of the options and arguments to - rndc-confgen. -

    -
    -k keyname
    -

    - Specifies the key name of the rndc authentication key. - This must be a valid domain name. - The default is rndc-key. -

    -
    -p port
    -

    - Specifies the command channel port where named - listens for connections from rndc. - The default is 953. -

    -
    -r randomfile
    -

    - Specifies a source of random data for generating the - authorization. If the operating - system does not provide a /dev/random - or equivalent device, the default source of randomness - is keyboard input. randomdev - specifies - the name of a character device or file containing random - data to be used instead of the default. The special value - keyboard indicates that keyboard - input should be used. -

    -
    -s address
    -

    - Specifies the IP address where named - listens for command channel connections from - rndc. The default is the loopback - address 127.0.0.1. -

    -
    -t chrootdir
    -

    - Used with the -a option to specify - a directory where named will run - chrooted. An additional copy of the rndc.key - will be written relative to this directory so that - it will be found by the chrooted named. -

    -
    -u user
    -

    - Used with the -a option to set the - owner - of the rndc.key file generated. - If - -t is also specified only the file - in - the chroot area has its owner changed. -

    -
    -
    -
    -

    EXAMPLES

    -

    - To allow rndc to be used with - no manual configuration, run -

    -

    rndc-confgen -a -

    -

    - To print a sample rndc.conf file and - corresponding controls and key - statements to be manually inserted into named.conf, - run -

    -

    rndc-confgen -

    -
    -
    -

    SEE ALSO

    -

    rndc(8), - rndc.conf(5), - named(8), - BIND 9 Administrator Reference Manual. -

    -
    -
    -

    AUTHOR

    -

    Internet Systems Consortium -

    -
    -
    - diff --git a/bin/rndc/rndc.8 b/bin/rndc/rndc.8 index 285ca9b..e4d723b 100644 --- a/bin/rndc/rndc.8 +++ b/bin/rndc/rndc.8 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: rndc.8,v 1.42.214.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: rndc.8,v 1.43 2009-07-11 01:12:46 tbox Exp $ .\" .hy 0 .ad l diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c index 133103e..1976d9c 100644 --- a/bin/rndc/rndc.c +++ b/bin/rndc/rndc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rndc.c,v 1.122.44.2 2009-01-18 23:47:35 tbox Exp $ */ +/* $Id: rndc.c,v 1.131.20.1.2.1 2011-06-02 23:47:28 tbox Exp $ */ /*! \file */ @@ -79,6 +79,7 @@ static unsigned char databuf[2048]; static isccc_ccmsg_t ccmsg; static isccc_region_t secret; static isc_boolean_t failed = ISC_FALSE; +static isc_boolean_t c_flag = ISC_FALSE; static isc_mem_t *mctx; static int sends, recvs, connects; static char *command; @@ -89,10 +90,13 @@ static isc_uint32_t serial; static void rndc_startconnect(isc_sockaddr_t *addr, isc_task_t *task); +ISC_PLATFORM_NORETURN_PRE static void +usage(int status) ISC_PLATFORM_NORETURN_POST; + static void usage(int status) { fprintf(stderr, "\ -Usage: %s [-c config] [-s server] [-p port]\n\ +Usage: %s [-b address] [-c config] [-s server] [-p port]\n\ [-k key-file ] [-y key] [-V] command\n\ \n\ command is one of the following:\n\ @@ -113,10 +117,16 @@ command is one of the following:\n\ notify zone [class [view]]\n\ Resend NOTIFY messages for the zone.\n\ reconfig Reload configuration file and new zones only.\n\ + sign zone [class [view]]\n\ + Update zone keys, and sign as needed.\n\ + loadkeys zone [class [view]]\n\ + Update keys without signing immediately.\n\ stats Write server statistics to the statistics file.\n\ querylog Toggle query logging.\n\ dumpdb [-all|-cache|-zones] [view ...]\n\ Dump cache(s) to the dump file (named_dump.db).\n\ + secroots [view ...]\n\ + Write security roots to the secroots file.\n\ stop Save pending updates to master files and stop the server.\n\ stop -p Save pending updates to master files and stop the server\n\ reporting process id.\n\ @@ -135,6 +145,10 @@ command is one of the following:\n\ validation newstate [view]\n\ Enable / disable DNSSEC validation.\n\ *restart Restart the server.\n\ + addzone [\"file\"] zone [class [view]] { zone-options }\n\ + Add zone to given view. Requires new-zone-file option.\n\ + delzone [\"file\"] zone [class [view]]\n\ + Removes zone from given view. Requires new-zone-file option.\n\ \n\ * == not yet implemented\n\ Version: %s\n", @@ -455,6 +469,10 @@ parse_config(isc_mem_t *mctx, isc_log_t *log, const char *keyname, fatal("neither %s nor %s was found", admin_conffile, admin_keyfile); key_only = ISC_TRUE; + } else if (! c_flag && isc_file_exists(admin_keyfile)) { + fprintf(stderr, "WARNING: key file (%s) exists, but using " + "default configuration file (%s)\n", + admin_keyfile, admin_conffile); } DO("create parser", cfg_parser_create(mctx, log, pctxp)); @@ -709,6 +727,7 @@ main(int argc, char **argv) { case 'c': admin_conffile = isc_commandline_argument; + c_flag = ISC_TRUE; break; case 'k': diff --git a/bin/rndc/rndc.conf.5 b/bin/rndc/rndc.conf.5 index d7ad81e..54c4af9 100644 --- a/bin/rndc/rndc.conf.5 +++ b/bin/rndc/rndc.conf.5 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: rndc.conf.5,v 1.38.366.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: rndc.conf.5,v 1.41 2009-07-11 01:12:46 tbox Exp $ .\" .hy 0 .ad l diff --git a/bin/rndc/rndc.conf.html b/bin/rndc/rndc.conf.html index 114cc15..463b99f 100644 --- a/bin/rndc/rndc.conf.html +++ b/bin/rndc/rndc.conf.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + diff --git a/bin/rndc/rndc.html b/bin/rndc/rndc.html index 0d91784..ecc0f31 100644 --- a/bin/rndc/rndc.html +++ b/bin/rndc/rndc.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + diff --git a/bin/rndc/unix/Makefile.in b/bin/rndc/unix/Makefile.in deleted file mode 100644 index e503db3..0000000 --- a/bin/rndc/unix/Makefile.in +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") -# Copyright (C) 2001 Internet Software Consortium. -# -# 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 ISC DISCLAIMS ALL WARRANTIES WITH -# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -# AND FITNESS. IN NO EVENT SHALL ISC 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. - -# $Id: Makefile.in,v 1.5 2007-06-19 23:46:59 tbox Exp $ - -srcdir = @srcdir@ -VPATH = @srcdir@ -top_srcdir = @top_srcdir@ - -@BIND9_MAKE_INCLUDES@ - -CINCLUDES = -I${srcdir}/include -I${srcdir}/../include \ - ${DNS_INCLUDES} ${ISC_INCLUDES} - -CDEFINES = -CWARNINGS = - -OBJS = os.@O@ - -SRCS = os.c - -TARGETS = ${OBJS} - -@BIND9_MAKE_RULES@ diff --git a/bin/rndc/unix/os.c b/bin/rndc/unix/os.c deleted file mode 100644 index e9ece1b..0000000 --- a/bin/rndc/unix/os.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 2001 Internet Software Consortium. - * - * 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 ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC 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. - */ - -/* $Id: os.c,v 1.10 2007-06-19 23:46:59 tbox Exp $ */ - -/*! \file */ - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -int -set_user(FILE *fd, const char *user) { - struct passwd *pw; - - pw = getpwnam(user); - if (pw == NULL) { - errno = EINVAL; - return (-1); - } - return (fchown(fileno(fd), pw->pw_uid, -1)); -} - -FILE * -safe_create(const char *filename) { - int fd; - FILE *f; - struct stat sb; - int flags = O_WRONLY; - - if (stat(filename, &sb) == -1) { - if (errno != ENOENT) - return (NULL); - flags = O_WRONLY | O_CREAT | O_EXCL; - } else if ((sb.st_mode & S_IFREG) == 0) { - errno = EOPNOTSUPP; - return (NULL); - } else - flags = O_WRONLY | O_TRUNC; - - fd = open(filename, flags, S_IRUSR | S_IWUSR); - if (fd == -1) - return (NULL); - f = fdopen(fd, "w"); - if (f == NULL) - close(fd); - return (f); -} diff --git a/bin/rndc/util.h b/bin/rndc/util.h index c5da488..8eba61a 100644 --- a/bin/rndc/util.h +++ b/bin/rndc/util.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: util.h,v 1.10 2007-06-19 23:46:59 tbox Exp $ */ +/* $Id: util.h,v 1.12 2009-09-29 23:48:03 tbox Exp $ */ #ifndef RNDC_UTIL_H #define RNDC_UTIL_H 1 @@ -23,6 +23,7 @@ /*! \file */ #include +#include #include @@ -43,8 +44,9 @@ ISC_LANG_BEGINDECLS void notify(const char *fmt, ...) ISC_FORMAT_PRINTF(1, 2); -void -fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); +ISC_PLATFORM_NORETURN_PRE void +fatal(const char *format, ...) +ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; ISC_LANG_ENDDECLS diff --git a/bin/tools/Makefile.in b/bin/tools/Makefile.in new file mode 100644 index 0000000..35b8285 --- /dev/null +++ b/bin/tools/Makefile.in @@ -0,0 +1,103 @@ +# Copyright (C) 2009, 2010 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.13 2010-01-07 23:48:53 tbox Exp $ + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCFG_INCLUDES} \ + ${LWRES_INCLUDES} ${OMAPI_INCLUDES} + +CDEFINES = +CWARNINGS = + +DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ +ISCLIBS = ../../lib/isc/libisc.@A@ @DNS_CRYPTO_LIBS@ +ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ +ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ +LWRESLIBS = ../../lib/lwres/liblwres.@A@ + +DNSDEPLIBS = ../../lib/dns/libdns.@A@ +ISCDEPLIBS = ../../lib/isc/libisc.@A@ +ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ +LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@ + +LIBS = ${ISCLIBS} @LIBS@ +NOSYMLIBS = ${ISCNOSYMLIBS} @LIBS@ + +SUBDIRS = + +TARGETS = arpaname@EXEEXT@ named-journalprint@EXEEXT@ nsec3hash@EXEEXT@ \ + genrandom@EXEEXT@ isc-hmac-fixup@EXEEXT@ +SRCS = arpaname.c named-journalprint.c nsec3hash.c genrandom.c \ + isc-hmac-fixup.c + +MANPAGES = arpaname.1 named-journalprint.8 nsec3hash.8 genrandom.8 \ + isc-hmac-fixup.8 +HTMLPAGES = arpaname.html named-journalprint.html nsec3hash.html \ + genrandom.html isc-hmac-fixup.html +MANOBJS = ${MANPAGES} ${HTMLPAGES} + +@BIND9_MAKE_RULES@ + +arpaname@EXEEXT@: arpaname.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ arpaname.@O@ \ + ${ISCLIBS} ${LIBS} + +named-journalprint@EXEEXT@: named-journalprint.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + export BASEOBJS="named-journalprint.@O@"; \ + export LIBS0="${DNSLIBS}"; \ + ${FINALBUILDCMD} + +nsec3hash@EXEEXT@: nsec3hash.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + export BASEOBJS="nsec3hash.@O@"; \ + export LIBS0="${DNSLIBS}"; \ + ${FINALBUILDCMD} + +isc-hmac-fixup@EXEEXT@: isc-hmac-fixup.@O@ ${ISCDEPLIBS} + export BASEOBJS="isc-hmac-fixup.@O@"; \ + export LIBS0="${ISCLIBS}"; \ + ${FINALBUILDCMD} + +genrandom@EXEEXT@: genrandom.@O@ + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ genrandom.@O@ @GENRANDOMLIB@ ${LIBS} + +doc man:: ${MANOBJS} + +docclean manclean maintainer-clean:: + rm -f ${MANOBJS} + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man1 + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 + +install:: ${TARGETS} installdirs + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} arpaname@EXEEXT@ ${DESTDIR}${sbindir} + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-journalprint@EXEEXT@ ${DESTDIR}${sbindir} + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} nsec3hash@EXEEXT@ ${DESTDIR}${sbindir} + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} genrandom@EXEEXT@ ${DESTDIR}${sbindir} + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} isc-hmac-fixup@EXEEXT@ ${DESTDIR}${sbindir} + ${INSTALL_DATA} ${srcdir}/arpaname.1 ${DESTDIR}${mandir}/man1 + ${INSTALL_DATA} ${srcdir}/isc-hmac-fixup.8 ${DESTDIR}${mandir}/man8 + ${INSTALL_DATA} ${srcdir}/named-journalprint.8 ${DESTDIR}${mandir}/man8 + ${INSTALL_DATA} ${srcdir}/nsec3hash.8 ${DESTDIR}${mandir}/man8 + ${INSTALL_DATA} ${srcdir}/genrandom.8 ${DESTDIR}${mandir}/man8 + +clean distclean:: + rm -f ${TARGETS} diff --git a/bin/tools/arpaname.1 b/bin/tools/arpaname.1 new file mode 100644 index 0000000..6662380 --- /dev/null +++ b/bin/tools/arpaname.1 @@ -0,0 +1,48 @@ +.\" Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +.\" +.\" 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 ISC DISCLAIMS ALL WARRANTIES WITH +.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +.\" AND FITNESS. IN NO EVENT SHALL ISC 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. +.\" +.\" $Id: arpaname.1,v 1.4 2010-05-19 01:14:14 tbox Exp $ +.\" +.hy 0 +.ad l +.\" Title: arpaname +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.71.1 +.\" Date: March 4, 2009 +.\" Manual: BIND9 +.\" Source: BIND9 +.\" +.TH "ARPANAME" "1" "March 4, 2009" "BIND9" "BIND9" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +arpaname \- translate IP addresses to the corresponding ARPA names +.SH "SYNOPSIS" +.HP 9 +\fBarpaname\fR {\fIipaddress\ \fR...} +.SH "DESCRIPTION" +.PP +\fBarpaname\fR +translates IP addresses (IPv4 and IPv6) to the corresponding IN\-ADDR.ARPA or IP6.ARPA names. +.SH "SEE ALSO" +.PP +BIND 9 Administrator Reference Manual. +.SH "AUTHOR" +.PP +Internet Systems Consortium +.SH "COPYRIGHT" +Copyright \(co 2009 Internet Systems Consortium, Inc. ("ISC") +.br diff --git a/bin/tools/arpaname.c b/bin/tools/arpaname.c new file mode 100644 index 0000000..e7f1434 --- /dev/null +++ b/bin/tools/arpaname.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: arpaname.c,v 1.4 2009-10-27 03:05:33 marka Exp $ */ + +#include "config.h" + +#include + +#include + +#define UNUSED(x) (void)(x) + +int +main(int argc, char *argv[]) { + unsigned char buf[16]; + int i; + + UNUSED(argc); + + while (argv[1]) { + if (inet_pton(AF_INET6, argv[1], buf) == 1) { + for (i = 15; i >= 0; i--) + fprintf(stdout, "%X.%X.", buf[i] & 0xf, + (buf[i] >> 4) & 0xf); + fprintf(stdout, "IP6.ARPA\n"); + argv++; + continue; + } + if (inet_pton(AF_INET, argv[1], buf) == 1) { + fprintf(stdout, "%u.%u.%u.%u.IN-ADDR.ARPA\n", + buf[3], buf[2], buf[1], buf[0]); + argv++; + continue; + } + return (1); + } + fflush(stdout); + return(ferror(stdout)); +} diff --git a/bin/tools/arpaname.docbook b/bin/tools/arpaname.docbook new file mode 100644 index 0000000..a7eb79e --- /dev/null +++ b/bin/tools/arpaname.docbook @@ -0,0 +1,76 @@ +]> + + + + + + March 4, 2009 + + + + arpaname + 1 + BIND9 + + + + arpaname + translate IP addresses to the corresponding ARPA names + + + + + 2009 + Internet Systems Consortium, Inc. ("ISC") + + + + + + arpaname + ipaddress + + + + + DESCRIPTION + + arpaname translates IP addresses (IPv4 and + IPv6) to the corresponding IN-ADDR.ARPA or IP6.ARPA names. + + + + + SEE ALSO + + BIND 9 Administrator Reference Manual. + + + + + AUTHOR + Internet Systems Consortium + + + + diff --git a/bin/tools/arpaname.html b/bin/tools/arpaname.html new file mode 100644 index 0000000..e44cfbd --- /dev/null +++ b/bin/tools/arpaname.html @@ -0,0 +1,52 @@ + + + + + +arpaname + + +
    +
    +
    +

    Name

    +

    arpaname — translate IP addresses to the corresponding ARPA names

    +
    +
    +

    Synopsis

    +

    arpaname {ipaddress ...}

    +
    +
    +

    DESCRIPTION

    +

    + arpaname translates IP addresses (IPv4 and + IPv6) to the corresponding IN-ADDR.ARPA or IP6.ARPA names. +

    +
    +
    +

    SEE ALSO

    +

    + BIND 9 Administrator Reference Manual. +

    +
    +
    +

    AUTHOR

    +

    Internet Systems Consortium +

    +
    +
    + diff --git a/bin/tools/genrandom.8 b/bin/tools/genrandom.8 new file mode 100644 index 0000000..32a4ff0 --- /dev/null +++ b/bin/tools/genrandom.8 @@ -0,0 +1,69 @@ +.\" Copyright (C) 2009, 2010 Internet Systems Consortium, Inc. ("ISC") +.\" +.\" 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 ISC DISCLAIMS ALL WARRANTIES WITH +.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +.\" AND FITNESS. IN NO EVENT SHALL ISC 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. +.\" +.\" $Id: genrandom.8,v 1.8 2010-05-19 01:14:14 tbox Exp $ +.\" +.hy 0 +.ad l +.\" Title: genrandom +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.71.1 +.\" Date: Feb 19, 2009 +.\" Manual: BIND9 +.\" Source: BIND9 +.\" +.TH "GENRANDOM" "8" "Feb 19, 2009" "BIND9" "BIND9" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +genrandom \- generate a file containing random data +.SH "SYNOPSIS" +.HP 10 +\fBgenrandom\fR [\fB\-n\ \fR\fB\fInumber\fR\fR] {\fIsize\fR} {\fIfilename\fR} +.SH "DESCRIPTION" +.PP +\fBgenrandom\fR +generates a file or a set of files containing a specified quantity of pseudo\-random data, which can be used as a source of entropy for other commands on systems with no random device. +.SH "ARGUMENTS" +.PP +\-n \fInumber\fR +.RS 4 +In place of generating one file, generates +\fBnumber\fR +(from 2 to 9) files, appending +\fBnumber\fR +to the name. +.RE +.PP +size +.RS 4 +The size of the file, in kilobytes, to generate. +.RE +.PP +domain +.RS 4 +The file name into which random data should be written. +.RE +.SH "SEE ALSO" +.PP +\fBrand\fR(3), +\fBarc4random\fR(3) +.SH "AUTHOR" +.PP +Internet Systems Consortium +.SH "COPYRIGHT" +Copyright \(co 2009, 2010 Internet Systems Consortium, Inc. ("ISC") +.br diff --git a/bin/tools/genrandom.c b/bin/tools/genrandom.c new file mode 100644 index 0000000..8473be2 --- /dev/null +++ b/bin/tools/genrandom.c @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2004, 2005, 2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2000-2003 Internet Software Consortium. + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: genrandom.c,v 1.7 2010-05-17 23:51:04 tbox Exp $ */ + +/*! \file */ +#include + +#include +#include +#include +#include + +#include +#include + +const char *program = "genrandom"; + +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + +static void +usage(void) { + fprintf(stderr, "usage: %s [-n 2..9] k file\n", program); + exit(1); +} + +static void +generate(char *filename, unsigned int bytes) { + FILE *fp; + + fp = fopen(filename, "w"); + if (fp == NULL) { + printf("failed to open %s\n", filename); + exit(1); + } + + while (bytes > 0) { +#ifndef HAVE_ARC4RANDOM + unsigned short int x = (rand() & 0xFFFF); +#else + unsigned short int x = (arc4random() & 0xFFFF); +#endif + unsigned char c = x & 0xFF; + if (putc(c, fp) == EOF) { + printf("error writing to %s\n", filename); + exit(1); + } + c = x >> 8; + if (putc(c, fp) == EOF) { + printf("error writing to %s\n", filename); + exit(1); + } + bytes -= 2; + } + fclose(fp); +} + +int +main(int argc, char **argv) { + unsigned int bytes; + unsigned int k; + char *endp; + int c, i, n = 1; + size_t len; + char *name; + + isc_commandline_errprint = ISC_FALSE; + + while ((c = isc_commandline_parse(argc, argv, "hn:")) != EOF) { + switch (c) { + case 'n': + n = strtol(isc_commandline_argument, &endp, 10); + if ((*endp != 0) || (n <= 1) || (n > 9)) + usage(); + break; + + case '?': + if (isc_commandline_option != '?') + fprintf(stderr, "%s: invalid argument -%c\n", + program, isc_commandline_option); + case 'h': + usage(); + + default: + fprintf(stderr, "%s: unhandled option -%c\n", + program, isc_commandline_option); + exit(1); + } + } + + if (isc_commandline_index + 2 != argc) + usage(); + + k = strtoul(argv[isc_commandline_index++], &endp, 10); + if (*endp != 0) + usage(); + bytes = k << 10; + +#ifndef HAVE_ARC4RANDOM + srand(0x12345678); +#endif + if (n == 1) { + generate(argv[isc_commandline_index], bytes); + return (0); + } + + len = strlen(argv[isc_commandline_index]) + 2; + name = (char *) malloc(len); + if (name == NULL) { + perror("malloc"); + exit(1); + } + + for (i = 1; i <= n; i++) { + snprintf(name, len, "%s%d", argv[isc_commandline_index], i); + generate(name, bytes); + } + free(name); + + return (0); +} diff --git a/bin/tools/genrandom.docbook b/bin/tools/genrandom.docbook new file mode 100644 index 0000000..84e4553 --- /dev/null +++ b/bin/tools/genrandom.docbook @@ -0,0 +1,119 @@ +]> + + + + + + Feb 19, 2009 + + + + genrandom + 8 + BIND9 + + + + genrandom + generate a file containing random data + + + + + 2009 + 2010 + Internet Systems Consortium, Inc. ("ISC") + + + + + + genrandom + + size + filename + + + + + DESCRIPTION + + genrandom + generates a file or a set of files containing a specified quantity + of pseudo-random data, which can be used as a source of entropy for + other commands on systems with no random device. + + + + + ARGUMENTS + + + -n number + + + In place of generating one file, generates + (from 2 to 9) files, appending to the name. + + + + + + size + + + The size of the file, in kilobytes, to generate. + + + + + + domain + + + The file name into which random data should be written. + + + + + + + + SEE ALSO + + + rand3 + , + + arc4random3 + + + + + + AUTHOR + Internet Systems Consortium + + + + diff --git a/bin/tools/genrandom.html b/bin/tools/genrandom.html new file mode 100644 index 0000000..c14af9b --- /dev/null +++ b/bin/tools/genrandom.html @@ -0,0 +1,73 @@ + + + + + +genrandom + + +
    +
    +
    +

    Name

    +

    genrandom — generate a file containing random data

    +
    +
    +

    Synopsis

    +

    genrandom [-n number] {size} {filename}

    +
    +
    +

    DESCRIPTION

    +

    + genrandom + generates a file or a set of files containing a specified quantity + of pseudo-random data, which can be used as a source of entropy for + other commands on systems with no random device. +

    +
    +
    +

    ARGUMENTS

    +
    +
    -n number
    +

    + In place of generating one file, generates number + (from 2 to 9) files, appending number to the name. +

    +
    size
    +

    + The size of the file, in kilobytes, to generate. +

    +
    domain
    +

    + The file name into which random data should be written. +

    +
    +
    +
    +

    SEE ALSO

    +

    + rand(3), + arc4random(3) +

    +
    +
    +

    AUTHOR

    +

    Internet Systems Consortium +

    +
    +
    + diff --git a/bin/tools/isc-hmac-fixup.8 b/bin/tools/isc-hmac-fixup.8 new file mode 100644 index 0000000..99c58c8 --- /dev/null +++ b/bin/tools/isc-hmac-fixup.8 @@ -0,0 +1,61 @@ +.\" Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") +.\" +.\" 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 ISC DISCLAIMS ALL WARRANTIES WITH +.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +.\" AND FITNESS. IN NO EVENT SHALL ISC 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. +.\" +.\" $Id: isc-hmac-fixup.8,v 1.4 2010-05-19 01:14:14 tbox Exp $ +.\" +.hy 0 +.ad l +.\" Title: isc\-hmac\-fixup +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.71.1 +.\" Date: January 5, 2010 +.\" Manual: BIND9 +.\" Source: BIND9 +.\" +.TH "ISC\-HMAC\-FIXUP" "1" "January 5, 2010" "BIND9" "BIND9" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +isc\-hmac\-fixup \- fixes HMAC keys generated by older versions of BIND +.SH "SYNOPSIS" +.HP 15 +\fBisc\-hmac\-fixup\fR {\fIalgorithm\fR} {\fIsecret\fR} +.SH "DESCRIPTION" +.PP +Versions of BIND 9 up to and including BIND 9.6 had a bug causing HMAC\-SHA* TSIG keys which were longer than the digest length of the hash algorithm (i.e., SHA1 keys longer than 160 bits, SHA256 keys longer than 256 bits, etc) to be used incorrectly, generating a message authentication code that was incompatible with other DNS implementations. +.PP +This bug has been fixed in BIND 9.7. However, the fix may cause incompatibility between older and newer versions of BIND, when using long keys. +\fBisc\-hmac\-fixup\fR +modifies those keys to restore compatibility. +.PP +To modify a key, run +\fBisc\-hmac\-fixup\fR +and specify the key's algorithm and secret on the command line. If the secret is longer than the digest length of the algorithm (64 bytes for SHA1 through SHA256, or 128 bytes for SHA384 and SHA512), then a new secret will be generated consisting of a hash digest of the old secret. (If the secret did not require conversion, then it will be printed without modification.) +.SH "SECURITY CONSIDERATIONS" +.PP +Secrets that have been converted by +\fBisc\-hmac\-fixup\fR +are shortened, but as this is how the HMAC protocol works in operation anyway, it does not affect security. RFC 2104 notes, "Keys longer than [the digest length] are acceptable but the extra length would not significantly increase the function strength." +.SH "SEE ALSO" +.PP +BIND 9 Administrator Reference Manual, +RFC 2104. +.SH "AUTHOR" +.PP +Internet Systems Consortium +.SH "COPYRIGHT" +Copyright \(co 2010 Internet Systems Consortium, Inc. ("ISC") +.br diff --git a/bin/tools/isc-hmac-fixup.c b/bin/tools/isc-hmac-fixup.c new file mode 100644 index 0000000..09cb85d --- /dev/null +++ b/bin/tools/isc-hmac-fixup.c @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: isc-hmac-fixup.c,v 1.4 2010-03-10 02:17:52 marka Exp $ */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HMAC_LEN 64 + +int +main(int argc, char **argv) { + isc_buffer_t buf; + unsigned char key[1024]; + char secret[1024]; + char base64[(1024*4)/3]; + isc_region_t r; + isc_result_t result; + + if (argc != 3) { + fprintf(stderr, "Usage:\t%s algorithm secret\n", argv[0]); + fprintf(stderr, "\talgorithm: (MD5 | SHA1 | SHA224 | " + "SHA256 | SHA384 | SHA512)\n"); + return (1); + } + + isc_buffer_init(&buf, secret, sizeof(secret)); + result = isc_base64_decodestring(argv[2], &buf); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "error: %s\n", isc_result_totext(result)); + return (1); + } + isc__buffer_usedregion(&buf, &r); + + if (!strcasecmp(argv[1], "md5") || + !strcasecmp(argv[1], "hmac-md5")) { + if (r.length > HMAC_LEN) { + isc_md5_t md5ctx; + isc_md5_init(&md5ctx); + isc_md5_update(&md5ctx, r.base, r.length); + isc_md5_final(&md5ctx, key); + + r.base = key; + r.length = ISC_MD5_DIGESTLENGTH; + } + } else if (!strcasecmp(argv[1], "sha1") || + !strcasecmp(argv[1], "hmac-sha1")) { + if (r.length > ISC_SHA1_DIGESTLENGTH) { + isc_sha1_t sha1ctx; + isc_sha1_init(&sha1ctx); + isc_sha1_update(&sha1ctx, r.base, r.length); + isc_sha1_final(&sha1ctx, key); + + r.base = key; + r.length = ISC_SHA1_DIGESTLENGTH; + } + } else if (!strcasecmp(argv[1], "sha224") || + !strcasecmp(argv[1], "hmac-sha224")) { + if (r.length > ISC_SHA224_DIGESTLENGTH) { + isc_sha224_t sha224ctx; + isc_sha224_init(&sha224ctx); + isc_sha224_update(&sha224ctx, r.base, r.length); + isc_sha224_final(key, &sha224ctx); + + r.base = key; + r.length = ISC_SHA224_DIGESTLENGTH; + } + } else if (!strcasecmp(argv[1], "sha256") || + !strcasecmp(argv[1], "hmac-sha256")) { + if (r.length > ISC_SHA256_DIGESTLENGTH) { + isc_sha256_t sha256ctx; + isc_sha256_init(&sha256ctx); + isc_sha256_update(&sha256ctx, r.base, r.length); + isc_sha256_final(key, &sha256ctx); + + r.base = key; + r.length = ISC_SHA256_DIGESTLENGTH; + } + } else if (!strcasecmp(argv[1], "sha384") || + !strcasecmp(argv[1], "hmac-sha384")) { + if (r.length > ISC_SHA384_DIGESTLENGTH) { + isc_sha384_t sha384ctx; + isc_sha384_init(&sha384ctx); + isc_sha384_update(&sha384ctx, r.base, r.length); + isc_sha384_final(key, &sha384ctx); + + r.base = key; + r.length = ISC_SHA384_DIGESTLENGTH; + } + } else if (!strcasecmp(argv[1], "sha512") || + !strcasecmp(argv[1], "hmac-sha512")) { + if (r.length > ISC_SHA512_DIGESTLENGTH) { + isc_sha512_t sha512ctx; + isc_sha512_init(&sha512ctx); + isc_sha512_update(&sha512ctx, r.base, r.length); + isc_sha512_final(key, &sha512ctx); + + r.base = key; + r.length = ISC_SHA512_DIGESTLENGTH; + } + } else { + fprintf(stderr, "unknown hmac/digest algorithm: %s\n", argv[1]); + return (1); + } + + isc_buffer_init(&buf, base64, sizeof(base64)); + result = isc_base64_totext(&r, 0, "", &buf); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "error: %s\n", isc_result_totext(result)); + return (1); + } + fprintf(stdout, "%.*s\n", (int)isc_buffer_usedlength(&buf), base64); + return (0); +} diff --git a/bin/tools/isc-hmac-fixup.docbook b/bin/tools/isc-hmac-fixup.docbook new file mode 100644 index 0000000..a3039ee --- /dev/null +++ b/bin/tools/isc-hmac-fixup.docbook @@ -0,0 +1,109 @@ +]> + + + + + + January 5, 2010 + + + + isc-hmac-fixup + 1 + BIND9 + + + + isc-hmac-fixup + fixes HMAC keys generated by older versions of BIND + + + + + 2010 + Internet Systems Consortium, Inc. ("ISC") + + + + + + isc-hmac-fixup + algorithm + secret + + + + + DESCRIPTION + + Versions of BIND 9 up to and including BIND 9.6 had a bug causing + HMAC-SHA* TSIG keys which were longer than the digest length of the + hash algorithm (i.e., SHA1 keys longer than 160 bits, SHA256 keys + longer than 256 bits, etc) to be used incorrectly, generating a + message authentication code that was incompatible with other DNS + implementations. + + + This bug has been fixed in BIND 9.7. However, the fix may + cause incompatibility between older and newer versions of + BIND, when using long keys. isc-hmac-fixup + modifies those keys to restore compatibility. + + + To modify a key, run isc-hmac-fixup and + specify the key's algorithm and secret on the command line. If the + secret is longer than the digest length of the algorithm (64 bytes + for SHA1 through SHA256, or 128 bytes for SHA384 and SHA512), then a + new secret will be generated consisting of a hash digest of the old + secret. (If the secret did not require conversion, then it will be + printed without modification.) + + + + + SECURITY CONSIDERATIONS + + Secrets that have been converted by isc-hmac-fixup + are shortened, but as this is how the HMAC protocol works in + operation anyway, it does not affect security. RFC 2104 notes, + "Keys longer than [the digest length] are acceptable but the + extra length would not significantly increase the function + strength." + + + + + SEE ALSO + + BIND 9 Administrator Reference Manual, + RFC 2104. + + + + + AUTHOR + Internet Systems Consortium + + + + diff --git a/bin/tools/isc-hmac-fixup.html b/bin/tools/isc-hmac-fixup.html new file mode 100644 index 0000000..8b70777 --- /dev/null +++ b/bin/tools/isc-hmac-fixup.html @@ -0,0 +1,83 @@ + + + + + +isc-hmac-fixup + + +
    +
    +
    +

    Name

    +

    isc-hmac-fixup — fixes HMAC keys generated by older versions of BIND

    +
    +
    +

    Synopsis

    +

    isc-hmac-fixup {algorithm} {secret}

    +
    +
    +

    DESCRIPTION

    +

    + Versions of BIND 9 up to and including BIND 9.6 had a bug causing + HMAC-SHA* TSIG keys which were longer than the digest length of the + hash algorithm (i.e., SHA1 keys longer than 160 bits, SHA256 keys + longer than 256 bits, etc) to be used incorrectly, generating a + message authentication code that was incompatible with other DNS + implementations. +

    +

    + This bug has been fixed in BIND 9.7. However, the fix may + cause incompatibility between older and newer versions of + BIND, when using long keys. isc-hmac-fixup + modifies those keys to restore compatibility. +

    +

    + To modify a key, run isc-hmac-fixup and + specify the key's algorithm and secret on the command line. If the + secret is longer than the digest length of the algorithm (64 bytes + for SHA1 through SHA256, or 128 bytes for SHA384 and SHA512), then a + new secret will be generated consisting of a hash digest of the old + secret. (If the secret did not require conversion, then it will be + printed without modification.) +

    +
    +
    +

    SECURITY CONSIDERATIONS

    +

    + Secrets that have been converted by isc-hmac-fixup + are shortened, but as this is how the HMAC protocol works in + operation anyway, it does not affect security. RFC 2104 notes, + "Keys longer than [the digest length] are acceptable but the + extra length would not significantly increase the function + strength." +

    +
    +
    +

    SEE ALSO

    +

    + BIND 9 Administrator Reference Manual, + RFC 2104. +

    +
    +
    +

    AUTHOR

    +

    Internet Systems Consortium +

    +
    +
    + diff --git a/bin/tools/named-journalprint.8 b/bin/tools/named-journalprint.8 new file mode 100644 index 0000000..347b67b --- /dev/null +++ b/bin/tools/named-journalprint.8 @@ -0,0 +1,60 @@ +.\" Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +.\" +.\" 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 ISC DISCLAIMS ALL WARRANTIES WITH +.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +.\" AND FITNESS. IN NO EVENT SHALL ISC 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. +.\" +.\" $Id: named-journalprint.8,v 1.4 2010-05-19 01:14:14 tbox Exp $ +.\" +.hy 0 +.ad l +.\" Title: named\-journalprint +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.71.1 +.\" Date: Feb 18, 2009 +.\" Manual: BIND9 +.\" Source: BIND9 +.\" +.TH "NAMED\-JOURNALPRINT" "8" "Feb 18, 2009" "BIND9" "BIND9" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +named\-journalprint \- print zone journal in human\-readable form +.SH "SYNOPSIS" +.HP 19 +\fBnamed\-journalprint\fR {\fIjournal\fR} +.SH "DESCRIPTION" +.PP +\fBnamed\-journalprint\fR +prints the contents of a zone journal file in a human\-readable form. +.PP +Journal files are automatically created by +\fBnamed\fR +when changes are made to dynamic zones (e.g., by +\fBnsupdate\fR). They record each addition or deletion of a resource record, in binary format, allowing the changes to be re\-applied to the zone when the server is restarted after a shutdown or crash. By default, the name of the journal file is formed by appending the extension +\fI.jnl\fR +to the name of the corresponding zone file. +.PP +\fBnamed\-journalprint\fR +converts the contents of a given journal file into a human\-readable text format. Each line begins with "add" or "del", to indicate whether the record was added or deleted, and continues with the resource record in master\-file format. +.SH "SEE ALSO" +.PP +\fBnamed\fR(8), +\fBnsupdate\fR(8), +BIND 9 Administrator Reference Manual. +.SH "AUTHOR" +.PP +Internet Systems Consortium +.SH "COPYRIGHT" +Copyright \(co 2009 Internet Systems Consortium, Inc. ("ISC") +.br diff --git a/bin/tools/named-journalprint.c b/bin/tools/named-journalprint.c new file mode 100644 index 0000000..8a00aa7 --- /dev/null +++ b/bin/tools/named-journalprint.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2000, 2001 Internet Software Consortium. + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: named-journalprint.c,v 1.2 2009-12-04 21:59:23 marka Exp $ */ + +/*! \file */ +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +/* + * Setup logging to use stderr. + */ +static isc_result_t +setup_logging(isc_mem_t *mctx, FILE *errout, isc_log_t **logp) { + isc_logdestination_t destination; + isc_logconfig_t *logconfig = NULL; + isc_log_t *log = NULL; + + RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS); + isc_log_setcontext(log); + dns_log_init(log); + dns_log_setcontext(log); + + destination.file.stream = errout; + destination.file.name = NULL; + destination.file.versions = ISC_LOG_ROLLNEVER; + destination.file.maximum_size = 0; + RUNTIME_CHECK(isc_log_createchannel(logconfig, "stderr", + ISC_LOG_TOFILEDESC, + ISC_LOG_DYNAMIC, + &destination, 0) == ISC_R_SUCCESS); + RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr", + NULL, NULL) == ISC_R_SUCCESS); + + *logp = log; + return (ISC_R_SUCCESS); +} + +int +main(int argc, char **argv) { + char *file; + isc_mem_t *mctx = NULL; + isc_result_t result; + isc_log_t *lctx = NULL; + + if (argc != 2) { + printf("usage: %s journal\n", argv[0]); + return(1); + } + + file = argv[1]; + + RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); + RUNTIME_CHECK(setup_logging(mctx, stderr, &lctx) == ISC_R_SUCCESS); + + result = dns_journal_print(mctx, file, stdout); + if (result == DNS_R_NOJOURNAL) + fprintf(stderr, "%s\n", dns_result_totext(result)); + isc_log_destroy(&lctx); + isc_mem_detach(&mctx); + return(result != ISC_R_SUCCESS ? 1 : 0); +} diff --git a/bin/tools/named-journalprint.docbook b/bin/tools/named-journalprint.docbook new file mode 100644 index 0000000..d523f8c --- /dev/null +++ b/bin/tools/named-journalprint.docbook @@ -0,0 +1,101 @@ +]> + + + + + + Feb 18, 2009 + + + + named-journalprint + 8 + BIND9 + + + + named-journalprint + print zone journal in human-readable form + + + + + 2009 + Internet Systems Consortium, Inc. ("ISC") + + + + + + named-journalprint + journal + + + + + DESCRIPTION + + named-journalprint + prints the contents of a zone journal file in a human-readable + form. + + + Journal files are automatically created by named + when changes are made to dynamic zones (e.g., by + nsupdate). They record each addition + or deletion of a resource record, in binary format, allowing the + changes to be re-applied to the zone when the server is + restarted after a shutdown or crash. By default, the name of + the journal file is formed by appending the extension + .jnl to the name of the corresponding + zone file. + + + named-journalprint converts the contents of a given + journal file into a human-readable text format. Each line begins + with "add" or "del", to indicate whether the record was added or + deleted, and continues with the resource record in master-file + format. + + + + + SEE ALSO + + + named8 + , + + nsupdate8 + , + BIND 9 Administrator Reference Manual. + + + + + AUTHOR + Internet Systems Consortium + + + + diff --git a/bin/tools/named-journalprint.html b/bin/tools/named-journalprint.html new file mode 100644 index 0000000..8878fc50 --- /dev/null +++ b/bin/tools/named-journalprint.html @@ -0,0 +1,73 @@ + + + + + +named-journalprint + + +
    +
    +
    +

    Name

    +

    named-journalprint — print zone journal in human-readable form

    +
    +
    +

    Synopsis

    +

    named-journalprint {journal}

    +
    +
    +

    DESCRIPTION

    +

    + named-journalprint + prints the contents of a zone journal file in a human-readable + form. +

    +

    + Journal files are automatically created by named + when changes are made to dynamic zones (e.g., by + nsupdate). They record each addition + or deletion of a resource record, in binary format, allowing the + changes to be re-applied to the zone when the server is + restarted after a shutdown or crash. By default, the name of + the journal file is formed by appending the extension + .jnl to the name of the corresponding + zone file. +

    +

    + named-journalprint converts the contents of a given + journal file into a human-readable text format. Each line begins + with "add" or "del", to indicate whether the record was added or + deleted, and continues with the resource record in master-file + format. +

    +
    +
    +

    SEE ALSO

    +

    + named(8), + nsupdate(8), + BIND 9 Administrator Reference Manual. +

    +
    +
    +

    AUTHOR

    +

    Internet Systems Consortium +

    +
    +
    + diff --git a/bin/tools/nsec3hash.8 b/bin/tools/nsec3hash.8 new file mode 100644 index 0000000..6fba8c8 --- /dev/null +++ b/bin/tools/nsec3hash.8 @@ -0,0 +1,70 @@ +.\" Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +.\" +.\" 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 ISC DISCLAIMS ALL WARRANTIES WITH +.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +.\" AND FITNESS. IN NO EVENT SHALL ISC 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. +.\" +.\" $Id: nsec3hash.8,v 1.5 2010-05-19 01:14:14 tbox Exp $ +.\" +.hy 0 +.ad l +.\" Title: nsec3hash +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.71.1 +.\" Date: Feb 18, 2009 +.\" Manual: BIND9 +.\" Source: BIND9 +.\" +.TH "NSEC3HASH" "8" "Feb 18, 2009" "BIND9" "BIND9" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +nsec3hash \- generate NSEC3 hash +.SH "SYNOPSIS" +.HP 10 +\fBnsec3hash\fR {\fIsalt\fR} {\fIalgorithm\fR} {\fIiterations\fR} {\fIdomain\fR} +.SH "DESCRIPTION" +.PP +\fBnsec3hash\fR +generates an NSEC3 hash based on a set of NSEC3 parameters. This can be used to check the validity of NSEC3 records in a signed zone. +.SH "ARGUMENTS" +.PP +salt +.RS 4 +The salt provided to the hash algorithm. +.RE +.PP +algorithm +.RS 4 +A number indicating the hash algorithm. Currently the only supported hash algorithm for NSEC3 is SHA\-1, which is indicated by the number 1; consequently "1" is the only useful value for this argument. +.RE +.PP +iterations +.RS 4 +The number of additional times the hash should be performed. +.RE +.PP +domain +.RS 4 +The domain name to be hashed. +.RE +.SH "SEE ALSO" +.PP +BIND 9 Administrator Reference Manual, +RFC 5155. +.SH "AUTHOR" +.PP +Internet Systems Consortium +.SH "COPYRIGHT" +Copyright \(co 2009 Internet Systems Consortium, Inc. ("ISC") +.br diff --git a/bin/tools/nsec3hash.c b/bin/tools/nsec3hash.c new file mode 100644 index 0000000..0e2a910 --- /dev/null +++ b/bin/tools/nsec3hash.c @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2006, 2008, 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: nsec3hash.c,v 1.6 2009-10-06 21:20:44 each Exp $ */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +const char *program = "nsec3hash"; + +ISC_PLATFORM_NORETURN_PRE static void +fatal(const char *format, ...) ISC_PLATFORM_NORETURN_POST; + +static void +fatal(const char *format, ...) { + va_list args; + + fprintf(stderr, "%s: ", program); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + exit(1); +} + +static void +check_result(isc_result_t result, const char *message) { + if (result != ISC_R_SUCCESS) + fatal("%s: %s", message, isc_result_totext(result)); +} + +static void +usage() { + fatal("salt hash iterations domain"); +} + +int +main(int argc, char **argv) { + dns_fixedname_t fixed; + dns_name_t *name; + isc_buffer_t buffer; + isc_region_t region; + isc_result_t result; + unsigned char hash[NSEC3_MAX_HASH_LENGTH]; + unsigned char salt[DNS_NSEC3_SALTSIZE]; + unsigned char text[1024]; + unsigned int hash_alg; + unsigned int length; + unsigned int iterations; + unsigned int salt_length; + + if (argc != 5) + usage(); + + if (strcmp(argv[1], "-") == 0) { + salt_length = 0; + salt[0] = 0; + } else { + isc_buffer_init(&buffer, salt, sizeof(salt)); + result = isc_hex_decodestring(argv[1], &buffer); + check_result(result, "isc_hex_decodestring(salt)"); + salt_length = isc_buffer_usedlength(&buffer); + if (salt_length > DNS_NSEC3_SALTSIZE) + fatal("salt too long"); + } + hash_alg = atoi(argv[2]); + if (hash_alg > 255U) + fatal("hash algorithm too large"); + iterations = atoi(argv[3]); + if (iterations > 0xffffU) + fatal("iterations to large"); + + dns_fixedname_init(&fixed); + name = dns_fixedname_name(&fixed); + isc_buffer_init(&buffer, argv[4], strlen(argv[4])); + isc_buffer_add(&buffer, strlen(argv[4])); + result = dns_name_fromtext(name, &buffer, dns_rootname, 0, NULL); + check_result(result, "dns_name_fromtext() failed"); + + dns_name_downcase(name, name, NULL); + length = isc_iterated_hash(hash, hash_alg, iterations, salt, + salt_length, name->ndata, name->length); + if (length == 0) + fatal("isc_iterated_hash failed"); + region.base = hash; + region.length = length; + isc_buffer_init(&buffer, text, sizeof(text)); + isc_base32hex_totext(®ion, 1, "", &buffer); + fprintf(stdout, "%.*s (salt=%s, hash=%u, iterations=%u)\n", + (int)isc_buffer_usedlength(&buffer), text, argv[1], hash_alg, iterations); + return(0); +} diff --git a/bin/tools/nsec3hash.docbook b/bin/tools/nsec3hash.docbook new file mode 100644 index 0000000..48eb4af --- /dev/null +++ b/bin/tools/nsec3hash.docbook @@ -0,0 +1,125 @@ +]> + + + + + + Feb 18, 2009 + + + + nsec3hash + 8 + BIND9 + + + + nsec3hash + generate NSEC3 hash + + + + + 2009 + Internet Systems Consortium, Inc. ("ISC") + + + + + + nsec3hash + salt + algorithm + iterations + domain + + + + + DESCRIPTION + + nsec3hash generates an NSEC3 hash based on + a set of NSEC3 parameters. This can be used to check the validity + of NSEC3 records in a signed zone. + + + + + ARGUMENTS + + + salt + + + The salt provided to the hash algorithm. + + + + + + algorithm + + + A number indicating the hash algorithm. Currently the + only supported hash algorithm for NSEC3 is SHA-1, which is + indicated by the number 1; consequently "1" is the only + useful value for this argument. + + + + + + iterations + + + The number of additional times the hash should be performed. + + + + + + domain + + + The domain name to be hashed. + + + + + + + + SEE ALSO + + BIND 9 Administrator Reference Manual, + RFC 5155. + + + + + AUTHOR + Internet Systems Consortium + + + + diff --git a/bin/tools/nsec3hash.html b/bin/tools/nsec3hash.html new file mode 100644 index 0000000..e6c0995 --- /dev/null +++ b/bin/tools/nsec3hash.html @@ -0,0 +1,78 @@ + + + + + +nsec3hash + + +
    +
    +
    +

    Name

    +

    nsec3hash — generate NSEC3 hash

    +
    +
    +

    Synopsis

    +

    nsec3hash {salt} {algorithm} {iterations} {domain}

    +
    +
    +

    DESCRIPTION

    +

    + nsec3hash generates an NSEC3 hash based on + a set of NSEC3 parameters. This can be used to check the validity + of NSEC3 records in a signed zone. +

    +
    +
    +

    ARGUMENTS

    +
    +
    salt
    +

    + The salt provided to the hash algorithm. +

    +
    algorithm
    +

    + A number indicating the hash algorithm. Currently the + only supported hash algorithm for NSEC3 is SHA-1, which is + indicated by the number 1; consequently "1" is the only + useful value for this argument. +

    +
    iterations
    +

    + The number of additional times the hash should be performed. +

    +
    domain
    +

    + The domain name to be hashed. +

    +
    +
    +
    +

    SEE ALSO

    +

    + BIND 9 Administrator Reference Manual, + RFC 5155. +

    +
    +
    +

    AUTHOR

    +

    Internet Systems Consortium +

    +
    +
    + diff --git a/config.guess b/config.guess index c79aebc..f8d6eac 100644 --- a/config.guess +++ b/config.guess @@ -3,7 +3,7 @@ # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. -timestamp='2004-09-07' +timestamp='2009-01-17' # 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 diff --git a/config.h.in b/config.h.in index aa1ba81..01f8b16 100644 --- a/config.h.in +++ b/config.h.in @@ -1,6 +1,6 @@ /* config.h.in. Generated from configure.in by autoheader. */ /* - * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -16,7 +16,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: config.h.in,v 1.106.40.24 2010-12-21 04:33:58 marka Exp $ */ +/* $Id: config.h.in,v 1.143.8.1 2011-02-03 05:52:35 marka Exp $ */ /*! \file */ @@ -147,6 +147,9 @@ int sigwait(const unsigned int *set, int *sig); /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD +/* Define to enable the "filter-aaaa-on-v4" option. */ +#undef ALLOW_FILTER_AAAA_ON_V4 + /* Define if recvmsg() does not meet all of the BSD socket API specifications. */ #undef BROKEN_RECVMSG @@ -157,6 +160,12 @@ int sigwait(const unsigned int *set, int *sig); /* Define to enable "rrset-order fixed" syntax. */ #undef DNS_RDATASET_FIXED +/* Define to enable rpz-nsdname rules. */ +#undef ENABLE_RPZ_NSDNAME + +/* Define to enable rpz-nsip rules. */ +#undef ENABLE_RPZ_NSIP + /* Solaris hack to get select_large_fdset. */ #undef FD_SETSIZE @@ -175,9 +184,18 @@ int sigwait(const unsigned int *set, int *sig); /* Define to 1 if you have the header file. */ #undef HAVE_DEVPOLL_H +/* Define to 1 if you have the `dlclose' function. */ +#undef HAVE_DLCLOSE + /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H +/* Define to 1 if you have the `dlopen' function. */ +#undef HAVE_DLOPEN + +/* Define to 1 if you have the `dlsym' function. */ +#undef HAVE_DLSYM + /* Define to 1 if you have the `EVP_sha256' function. */ #undef HAVE_EVP_SHA256 @@ -190,9 +208,15 @@ int sigwait(const unsigned int *set, int *sig); /* Define to 1 if you have the header file. */ #undef HAVE_GSSAPI_GSSAPI_H +/* Define to 1 if you have the header file. */ +#undef HAVE_GSSAPI_GSSAPI_KRB5_H + /* Define to 1 if you have the header file. */ #undef HAVE_GSSAPI_H +/* Define to 1 if you have the header file. */ +#undef HAVE_GSSAPI_KRB5_H + /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H @@ -211,9 +235,15 @@ int sigwait(const unsigned int *set, int *sig); /* Define to 1 if you have the `cap' library (-lcap). */ #undef HAVE_LIBCAP +/* if system have backtrace function */ +#undef HAVE_LIBCTRACE + /* Define to 1 if you have the `c_r' library (-lc_r). */ #undef HAVE_LIBC_R +/* Define to 1 if you have the `dl' library (-ldl). */ +#undef HAVE_LIBDL + /* Define to 1 if you have the `nsl' library (-lnsl). */ #undef HAVE_LIBNSL @@ -247,9 +277,27 @@ int sigwait(const unsigned int *set, int *sig); /* Define to 1 if you have the header file. */ #undef HAVE_NET_IF6_H +/* Define if your OpenSSL version supports GOST. */ +#undef HAVE_OPENSSL_GOST + +/* Define to 1 if you have the header file. */ +#undef HAVE_REGEX_H + +/* Define to 1 if you have the `setegid' function. */ +#undef HAVE_SETEGID + +/* Define to 1 if you have the `seteuid' function. */ +#undef HAVE_SETEUID + /* Define to 1 if you have the `setlocale' function. */ #undef HAVE_SETLOCALE +/* 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 header file. */ #undef HAVE_STDINT_H @@ -304,6 +352,15 @@ int sigwait(const unsigned int *set, int *sig); /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H +/* return type of gai_strerror */ +#undef IRS_GAISTRERROR_RETURN_T + +/* Define to the buffer length type used by getnameinfo(3). */ +#undef IRS_GETNAMEINFO_BUFLEN_T + +/* Define to the flags type used by getnameinfo(3). */ +#undef IRS_GETNAMEINFO_FLAGS_T + /* Defined if extern char *optarg is not declared. */ #undef NEED_OPTARG @@ -361,11 +418,8 @@ int sigwait(const unsigned int *set, int *sig); /* Define to empty if `const' does not conform to ANSI C. */ #undef const -/* 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 +/* Define to empty if your compiler does not support "static inline". */ #undef inline -#endif /* Define to `unsigned int' if does not define. */ #undef size_t diff --git a/configure.in b/configure.in index 08f0bf3..d5fb15c 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 1998-2003 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -18,7 +18,7 @@ AC_DIVERT_PUSH(1)dnl esyscmd([sed "s/^/# /" COPYRIGHT])dnl AC_DIVERT_POP()dnl -AC_REVISION($Revision: 1.457.26.28 $) +AC_REVISION($Revision: 1.512.8.1 $) AC_INIT(lib/dns/name.c) AC_PREREQ(2.59) @@ -36,6 +36,7 @@ case $build_os in sunos*) # Just set the maximum command line length for sunos as it otherwise # takes a exceptionally long time to work it out. Required for libtool. + lt_cv_sys_max_cmd_len=4096; ;; esac @@ -61,7 +62,6 @@ It is available from http://www.isc.org as a separate download.]) ;; esac - # # Make very sure that these are the first files processed by # config.status, since we use the processed output as the input for @@ -111,6 +111,8 @@ AC_SUBST(ETAGS) # # Perl is optional; it is used only by some of the system test scripts. +# Note: the backtrace feature (see below) uses perl to build the symbol table, +# but it still compiles without perl, in which case an empty table will be used. # AC_PATH_PROGS(PERL, perl5 perl) AC_SUBST(PERL) @@ -269,7 +271,7 @@ esac AC_HEADER_STDC -AC_CHECK_HEADERS(fcntl.h sys/time.h unistd.h sys/sockio.h sys/select.h sys/param.h sys/sysctl.h net/if6.h,,, +AC_CHECK_HEADERS(fcntl.h regex.h sys/time.h unistd.h sys/sockio.h sys/select.h sys/param.h sys/sysctl.h net/if6.h,,, [$ac_includes_default #ifdef HAVE_SYS_PARAM_H # include @@ -283,6 +285,12 @@ AC_CHECK_FUNC(sysctlbyname, AC_DEFINE(HAVE_SYSCTLBYNAME)) AC_C_FLEXIBLE_ARRAY_MEMBER # +# Older versions of HP/UX don't define seteuid() and setegid() +# +AC_CHECK_FUNCS(seteuid setresuid) +AC_CHECK_FUNCS(setegid setresgid) + +# # UnixWare 7.1.1 with the feature supplement to the UDK compiler # is reported to not support "static inline" (RT #1212). # @@ -300,7 +308,7 @@ AC_TRY_COMPILE(, [ ], [AC_MSG_RESULT(no)], [AC_MSG_RESULT(yes) - AC_DEFINE(inline, )]) + AC_DEFINE(inline, ,[Define to empty if your compiler does not support "static inline".])]) AC_TYPE_SIZE_T AC_CHECK_TYPE(ssize_t, int) @@ -332,6 +340,20 @@ AC_TRY_COMPILE([],[long long i = 0; return (0);], AC_SUBST(ISC_PLATFORM_HAVELONGLONG) # +# check for GCC noreturn attribute +# +AC_MSG_CHECKING(for GCC noreturn attribute) +AC_TRY_COMPILE([],[void foo() __attribute__((noreturn));], + [AC_MSG_RESULT(yes) + ISC_PLATFORM_NORETURN_PRE="#define ISC_PLATFORM_NORETURN_PRE" + ISC_PLATFORM_NORETURN_POST="#define ISC_PLATFORM_NORETURN_POST __attribute__((noreturn))"], + [AC_MSG_RESULT(no) + ISC_PLATFORM_NORETURN_PRE="#define ISC_PLATFORM_NORETURN_PRE" + ISC_PLATFORM_NORETURN_POST="#define ISC_PLATFORM_NORETURN_POST"]) +AC_SUBST(ISC_PLATFORM_NORETURN_PRE) +AC_SUBST(ISC_PLATFORM_NORETURN_POST) + +# # check if we have lifconf # AC_MSG_CHECKING(for struct lifconf) @@ -495,6 +517,7 @@ then fi done fi +OPENSSL_GOST="" case "$use_openssl" in no) AC_MSG_RESULT(no) @@ -650,6 +673,42 @@ esac AC_MSG_RESULT(no) fi AC_CHECK_FUNCS(EVP_sha256 EVP_sha512) + + AC_MSG_CHECKING(for OpenSSL GOST support) + have_gost="" + AC_TRY_RUN([ +#include +#include +int main() { +#if (OPENSSL_VERSION_NUMBER >= 0x10000000L) + ENGINE *e; + + OPENSSL_config(NULL); + + e = ENGINE_by_id("gost"); + if (e == NULL) + return (1); + if (ENGINE_init(e) <= 0) + return (1); + return (0); +#else + return (1); +#endif +} +], + [AC_MSG_RESULT(yes) + have_gost="yes"], + [AC_MSG_RESULT(no) + have_gost="no"]) + case $have_gost in + yes) + OPENSSL_GOST="yes" + AC_DEFINE(HAVE_OPENSSL_GOST, 1, + [Define if your OpenSSL version supports GOST.]) + ;; + *) + ;; + esac CFLAGS="$saved_cflags" LIBS="$saved_libs" OPENSSLLINKOBJS='${OPENSSLLINKOBJS}' @@ -667,9 +726,34 @@ AC_SUBST(USE_OPENSSL) AC_SUBST(DST_OPENSSL_INC) AC_SUBST(OPENSSLLINKOBJS) AC_SUBST(OPENSSLLINKSRCS) +AC_SUBST(OPENSSL_GOST) DNS_CRYPTO_LIBS="$DNS_CRYPTO_LIBS $DNS_OPENSSL_LIBS" # +# Use OpenSSL for hash functions +# + +AC_ARG_ENABLE(openssl-hash, + [ --enable-openssl-hash use OpenSSL for hash functions [[default=no]]], + want_openssl_hash="$enableval", want_openssl_hash="no") +case $want_openssl_hash in + yes) + if test "$USE_OPENSSL" = "" + then + AC_MSG_ERROR([No OpenSSL for hash functions]) + fi + ISC_PLATFORM_OPENSSLHASH="#define ISC_PLATFORM_OPENSSLHASH 1" + ISC_OPENSSL_INC="$DST_OPENSSL_INC" + ;; + no) + ISC_PLATFORM_OPENSSLHASH="#undef ISC_PLATFORM_OPENSSLHASH" + ISC_OPENSSL_INC="" + ;; +esac +AC_SUBST(ISC_PLATFORM_OPENSSLHASH) +AC_SUBST(ISC_OPENSSL_INC) + +# # PKCS11 (aka crypto hardware) support # # This works only with the right OpenSSL with PKCS11 engine! @@ -677,21 +761,37 @@ DNS_CRYPTO_LIBS="$DNS_CRYPTO_LIBS $DNS_OPENSSL_LIBS" AC_MSG_CHECKING(for PKCS11 support) AC_ARG_WITH(pkcs11, -[ --with-pkcs11 Build with PKCS11 support], - use_pkcs11="yes", use_pkcs11="no") +[ --with-pkcs11[=PATH] Build with PKCS11 support [yes|no|path] + (PATH is for the PKCS11 provider)], + use_pkcs11="$withval", use_pkcs11="no") case "$use_pkcs11" in - no) + no|'') AC_MSG_RESULT(disabled) - USE_PKCS11="" + USE_PKCS11='' + PKCS11_TOOLS='' ;; - yes) + yes|*) AC_MSG_RESULT(using OpenSSL with PKCS11 support) USE_PKCS11='-DUSE_PKCS11' + PKCS11_TOOLS=pkcs11 ;; esac - AC_SUBST(USE_PKCS11) +AC_SUBST(PKCS11_TOOLS) + +AC_MSG_CHECKING(for PKCS11 tools) +case "$use_pkcs11" in + no|yes|'') + AC_MSG_RESULT(disabled) + PKCS11_PROVIDER="undefined" + ;; + *) + AC_MSG_RESULT(PKCS11 provider is "$use_pkcs11") + PKCS11_PROVIDER="$use_pkcs11" + ;; +esac +AC_SUBST(PKCS11_PROVIDER) AC_MSG_CHECKING(for GSSAPI library) AC_ARG_WITH(gssapi, @@ -731,6 +831,9 @@ case "$use_gssapi" in AC_MSG_ERROR([gssapi.h not found]) fi + AC_CHECK_HEADERS(gssapi_krb5.h gssapi/gssapi_krb5.h, + [ISC_PLATFORM_GSSAPI_KRB5_HEADER="#define ISC_PLATFORM_GSSAPI_KRB5_HEADER <$ac_header>"]) + AC_CHECK_HEADERS(krb5.h krb5/krb5.h kerberosv5/krb5.h, [ISC_PLATFORM_KRB5HEADER="#define ISC_PLATFORM_KRB5HEADER <$ac_header>"]) @@ -775,7 +878,12 @@ case "$use_gssapi" in # -L/usr/local/lib to LIBS, which can make the # -lgssapi_krb5 test succeed with shared libraries even # when you are trying to build with KTH in /usr/lib. - LIBS="-L$use_gssapi/lib $TRY_LIBS" + if test "$use_gssapi" = "/usr" + then + LIBS="$TRY_LIBS" + else + LIBS="-L$use_gssapi/lib $TRY_LIBS" + fi AC_MSG_CHECKING(linking as $TRY_LIBS) AC_TRY_LINK( , [gss_acquire_cred();krb5_init_context()], gssapi_linked=yes, gssapi_linked=no) @@ -839,6 +947,7 @@ esac AC_SUBST(ISC_PLATFORM_HAVEGSSAPI) AC_SUBST(ISC_PLATFORM_GSSAPIHEADER) +AC_SUBST(ISC_PLATFORM_GSSAPI_KRB5_HEADER) AC_SUBST(ISC_PLATFORM_KRB5HEADER) AC_SUBST(USE_GSSAPI) @@ -1304,6 +1413,65 @@ case $use_libtool in esac # +# enable/disable dumping stack backtrace. Also check if the system supports +# glibc-compatible backtrace() function. +# +AC_ARG_ENABLE(backtrace, +[ --enable-backtrace log stack backtrace on abort [[default=yes]]], + want_backtrace="$enableval", want_backtrace="yes") +case $want_backtrace in +yes) + ISC_PLATFORM_USEBACKTRACE="#define ISC_PLATFORM_USEBACKTRACE 1" + AC_TRY_LINK([#include ], + [return (backtrace((void **)0, 0));], + [AC_DEFINE([HAVE_LIBCTRACE], [], [if system have backtrace function])],) + ;; +*) + ISC_PLATFORM_USEBACKTRACE="#undef ISC_PLATFORM_USEBACKTRACE" + ;; +esac +AC_SUBST(ISC_PLATFORM_USEBACKTRACE) + +AC_ARG_ENABLE(symtable, +[ --enable-symtable use internal symbol table for backtrace + [[all|minimal(default)|none]]], + want_symtable="$enableval", want_symtable="minimal") +case $want_symtable in +yes|all|minimal) # "yes" is a hidden value equivalent to "minimal" + if test "$PERL" = "" + then + AC_MSG_ERROR([Internal symbol table requires perl but no perl is found. +Install perl or explicitly disable the feature by --disable-symtable.]) + fi + if test "$use_libtool" = "yes"; then + AC_MSG_WARN([Internal symbol table does not work with libtool. Disabling symbol table.]) + else + # we generate the internal symbol table only for those systems + # known to work to avoid unexpected build failure. Also, warn + # about unsupported systems when the feature is enabled + # manually. + case $host_os in + freebsd*|netbsd*|openbsd*|linux*|solaris*|darwin*) + MKSYMTBL_PROGRAM="$PERL" + if test $want_symtable = all; then + ALWAYS_MAKE_SYMTABLE="yes" + fi + ;; + *) + if test $want_symtable = yes -o $want_symtable = all + then + AC_MSG_WARN([this system is not known to generate internal symbol table safely; disabling it]) + fi + esac + fi + ;; +*) + ;; +esac +AC_SUBST(MKSYMTBL_PROGRAM) +AC_SUBST(ALWAYS_MAKE_SYMTABLE) + +# # File name extension for static archive files, for those few places # where they are treated differently from dynamic ones. # @@ -1320,6 +1488,54 @@ AC_SUBST(LIBTOOL_ALLOW_UNDEFINED) AC_SUBST(LIBTOOL_IN_MAIN) # +# build exportable DNS library? +# +AC_ARG_ENABLE(exportlib, + [ --enable-exportlib build exportable library (GNU make required) + [[default=no]]]) +case "$enable_exportlib" in + yes) + gmake= + for x in gmake gnumake make; do + if $x --version 2>/dev/null | grep GNU > /dev/null; then + gmake=$x + break; + fi + done + if test -z "$gmake"; then + AC_MSG_ERROR([exportlib requires GNU make. Install it or disable the feature.]) + fi + LIBEXPORT=lib/export + AC_SUBST(LIBEXPORT) + BIND9_CO_RULE="%.$O: \${srcdir}/%.c" + ;; + no|*) + BIND9_CO_RULE=".c.$O:" + ;; +esac +AC_SUBST(BIND9_CO_RULE) + +AC_ARG_WITH(export-libdir, + [ --with-export-libdir[=PATH] + installation directory for the export library + [[EPREFIX/lib/bind9]]], + export_libdir="$withval",) +if test -z "$export_libdir"; then + export_libdir="\${exec_prefix}/lib/bind9/" +fi +AC_SUBST(export_libdir) + +AC_ARG_WITH(export-includedir, + [ --with-export-includedir[=PATH] + installation directory for the header files of the + export library [[PREFIX/include/bind9]]], + export_includedir="$withval",) +if test -z "$export_includedir"; then + export_includedir="\${prefix}/include/bind9/" +fi +AC_SUBST(export_includedir) + +# # Here begins a very long section to determine the system's networking # capabilities. The order of the tests is significant. # @@ -1703,10 +1919,13 @@ AC_TRY_COMPILE([ [struct addrinfo a; return (0);], [AC_MSG_RESULT(yes) ISC_LWRES_NEEDADDRINFO="#undef ISC_LWRES_NEEDADDRINFO" + ISC_IRS_NEEDADDRINFO="#undef ISC_IRS_NEEDADDRINFO" AC_DEFINE(HAVE_ADDRINFO)], [AC_MSG_RESULT(no) - ISC_LWRES_NEEDADDRINFO="#define ISC_LWRES_NEEDADDRINFO 1"]) + ISC_LWRES_NEEDADDRINFO="#define ISC_LWRES_NEEDADDRINFO 1" + ISC_IRS_NEEDADDRINFO="#define ISC_IRS_NEEDADDRINFO 1"]) AC_SUBST(ISC_LWRES_NEEDADDRINFO) +AC_SUBST(ISC_IRS_NEEDADDRINFO) # # Check for rrsetinfo @@ -1793,6 +2012,53 @@ AC_TRY_COMPILE([ ISC_LWRES_NEEDHERRNO="#define ISC_LWRES_NEEDHERRNO 1"]) AC_SUBST(ISC_LWRES_NEEDHERRNO) +# +# Sadly, the definitions of system-supplied getnameinfo(3) vary. Try to catch +# known variations here: +# +AC_MSG_CHECKING(for getnameinfo prototype definitions) +AC_TRY_COMPILE([ +#include +#include +#include +int getnameinfo(const struct sockaddr *, socklen_t, char *, + socklen_t, char *, socklen_t, unsigned int);], +[ return (0);], + [AC_MSG_RESULT(socklen_t for buflen; u_int for flags) + AC_DEFINE(IRS_GETNAMEINFO_BUFLEN_T, socklen_t, + [Define to the buffer length type used by getnameinfo(3).]) + AC_DEFINE(IRS_GETNAMEINFO_FLAGS_T, unsigned int, + [Define to the flags type used by getnameinfo(3).])], +[AC_TRY_COMPILE([ +#include +#include +#include +int getnameinfo(const struct sockaddr *, socklen_t, char *, + size_t, char *, size_t, int);], +[ return (0);], + [AC_MSG_RESULT(size_t for buflen; int for flags) + AC_DEFINE(IRS_GETNAMEINFO_BUFLEN_T, size_t) + AC_DEFINE(IRS_GETNAMEINFO_FLAGS_T, int)], +[AC_MSG_RESULT(not match any subspecies; assume standard definition) +AC_DEFINE(IRS_GETNAMEINFO_BUFLEN_T, socklen_t) +AC_DEFINE(IRS_GETNAMEINFO_FLAGS_T, int)])]) + +# +# ...and same for gai_strerror(). +# +AC_MSG_CHECKING(for gai_strerror prototype definitions) +AC_TRY_COMPILE([ +#include +#include +#include +char *gai_strerror(int ecode);], +[ return (0); ], + [AC_MSG_RESULT(returning char *) + AC_DEFINE([IRS_GAISTRERROR_RETURN_T], [char *], + [return type of gai_strerror])], +[AC_MSG_RESULT(not match any subspecies; assume standard definition) +AC_DEFINE([IRS_GAISTRERROR_RETURN_T], [const char *])]) + AC_CHECK_FUNC(getipnodebyname, [ISC_LWRES_GETIPNODEPROTO="#undef ISC_LWRES_GETIPNODEPROTO"], [ISC_LWRES_GETIPNODEPROTO="#define ISC_LWRES_GETIPNODEPROTO 1"]) @@ -1807,6 +2073,7 @@ AC_CHECK_FUNC(gai_strerror, AC_DEFINE(HAVE_GAISTRERROR)) AC_SUBST(ISC_LWRES_GETIPNODEPROTO) AC_SUBST(ISC_LWRES_GETADDRINFOPROTO) AC_SUBST(ISC_LWRES_GETNAMEINFOPROTO) +AC_SUBST(ISC_IRS_GETNAMEINFOSOCKLEN) AC_ARG_ENABLE(getifaddrs, [ --enable-getifaddrs Enable the use of getifaddrs() [[yes|no]].], @@ -2140,6 +2407,8 @@ AC_SUBST(ISC_PLATFORM_USEDECLSPEC) ISC_PLATFORM_USEDECLSPEC="#undef ISC_PLATFORM_USEDECLSPEC" AC_SUBST(LWRES_PLATFORM_USEDECLSPEC) LWRES_PLATFORM_USEDECLSPEC="#undef LWRES_PLATFORM_USEDECLSPEC" +AC_SUBST(IRS_PLATFORM_USEDECLSPEC) +IRS_PLATFORM_USEDECLSPEC="#undef IRS_PLATFORM_USEDECLSPEC" # # Random remaining OS-specific issues involving compiler warnings. @@ -2461,6 +2730,61 @@ case "$enable_fixed" in esac # +# Enable response policy rewriting using NS IP addresses +# +AC_ARG_ENABLE(rpz-nsip, + [ --enable-rpz-nsip enable rpz-nsip rules [[default=no]]], + enable_nsip="$enableval", + enable_nsip="no") +case "$enable_nsip" in + yes) + AC_DEFINE(ENABLE_RPZ_NSIP, 1, + [Define to enable rpz-nsip rules.]) + ;; + no) + ;; + *) + ;; +esac + +# +# Enable response policy rewriting using NS name +# +AC_ARG_ENABLE(rpz-nsdname, + [ --enable-rpz-nsdname enable rpz-nsdname rules [[default=no]]], + enable_nsdname="$enableval", + enable_nsdname="no") +case "$enable_nsdname" in + yes) + AC_DEFINE(ENABLE_RPZ_NSDNAME, 1, + [Define to enable rpz-nsdname rules.]) + ;; + no) + ;; + *) + ;; +esac + +# +# Activate "filter-aaaa-on-v4" or not? +# +AC_ARG_ENABLE(filter-aaaa, + [ --enable-filter-aaaa enable filtering of AAAA records over IPv4 + [[default=no]]], + enable_filter="$enableval", + enable_filter="no") +case "$enable_filter" in + yes) + AC_DEFINE(ALLOW_FILTER_AAAA_ON_V4, 1, + [Define to enable the "filter-aaaa-on-v4" option.]) + ;; + no) + ;; + *) + ;; +esac + +# # The following sets up how non-blocking i/o is established. # Sunos, cygwin and solaris 2.x (x<5) require special handling. # @@ -2780,6 +3104,9 @@ LIBBIND9_API=$srcdir/lib/bind9/api AC_SUBST_FILE(LIBLWRES_API) LIBLWRES_API=$srcdir/lib/lwres/api +AC_SUBST_FILE(LIBIRS_API) +LIBIRS_API=$srcdir/lib/irs/api + # # Configure any DLZ drivers. # @@ -2947,37 +3274,115 @@ AC_CONFIG_COMMANDS( # AC_CONFIG_FILES([ + make/Makefile + make/mkdep Makefile - make/Makefile - make/mkdep + bin/Makefile + bin/check/Makefile + bin/confgen/Makefile + bin/confgen/unix/Makefile + bin/dig/Makefile + bin/dnssec/Makefile + bin/named/Makefile + bin/named/unix/Makefile + bin/nsupdate/Makefile + bin/pkcs11/Makefile + bin/rndc/Makefile + bin/tests/Makefile + bin/tests/atomic/Makefile + bin/tests/db/Makefile + bin/tests/dst/Makefile + bin/tests/hashes/Makefile + bin/tests/headerdep_test.sh + bin/tests/master/Makefile + bin/tests/mem/Makefile + bin/tests/names/Makefile + bin/tests/net/Makefile + bin/tests/rbt/Makefile + bin/tests/resolver/Makefile + bin/tests/sockaddr/Makefile + bin/tests/system/Makefile + bin/tests/system/conf.sh + bin/tests/system/filter-aaaa/Makefile + bin/tests/system/gost/prereq.sh + bin/tests/system/lwresd/Makefile + bin/tests/system/rpz/Makefile + bin/tests/system/tkey/Makefile + bin/tests/tasks/Makefile + bin/tests/timers/Makefile + bin/tests/virtual-time/Makefile + bin/tests/virtual-time/conf.sh + bin/tools/Makefile + contrib/check-secure-delegation.pl + contrib/zone-edit.sh + doc/Makefile + doc/arm/Makefile + doc/doxygen/Doxyfile + doc/doxygen/Makefile + doc/doxygen/doxygen-input-filter + doc/misc/Makefile + doc/xsl/Makefile + doc/xsl/isc-docbook-chunk.xsl + doc/xsl/isc-docbook-html.xsl + doc/xsl/isc-docbook-latex.xsl + doc/xsl/isc-manpage.xsl + isc-config.sh lib/Makefile + lib/bind9/Makefile + lib/bind9/include/Makefile + lib/bind9/include/bind9/Makefile + lib/dns/Makefile + lib/dns/include/Makefile + lib/dns/include/dns/Makefile + lib/dns/include/dst/Makefile + lib/export/Makefile + lib/export/dns/Makefile + lib/export/dns/include/Makefile + lib/export/dns/include/dns/Makefile + lib/export/dns/include/dst/Makefile + lib/export/irs/Makefile + lib/export/irs/include/Makefile + lib/export/irs/include/irs/Makefile + lib/export/isc/$thread_dir/Makefile + lib/export/isc/$thread_dir/include/Makefile + lib/export/isc/$thread_dir/include/isc/Makefile + lib/export/isc/Makefile + lib/export/isc/include/Makefile + lib/export/isc/include/isc/Makefile + lib/export/isc/nls/Makefile + lib/export/isc/unix/Makefile + lib/export/isc/unix/include/Makefile + lib/export/isc/unix/include/isc/Makefile + lib/export/isccfg/Makefile + lib/export/isccfg/include/Makefile + lib/export/isccfg/include/isccfg/Makefile + lib/export/samples/Makefile + lib/export/samples/Makefile-postinstall + lib/irs/Makefile + lib/irs/include/Makefile + lib/irs/include/irs/Makefile + lib/irs/include/irs/netdb.h + lib/irs/include/irs/platform.h + lib/isc/$arch/Makefile + lib/isc/$arch/include/Makefile + lib/isc/$arch/include/isc/Makefile + lib/isc/$thread_dir/Makefile + lib/isc/$thread_dir/include/Makefile + lib/isc/$thread_dir/include/isc/Makefile lib/isc/Makefile lib/isc/include/Makefile lib/isc/include/isc/Makefile lib/isc/include/isc/platform.h + lib/isc/nls/Makefile lib/isc/unix/Makefile lib/isc/unix/include/Makefile lib/isc/unix/include/isc/Makefile - lib/isc/nls/Makefile - lib/isc/$thread_dir/Makefile - lib/isc/$thread_dir/include/Makefile - lib/isc/$thread_dir/include/isc/Makefile - lib/isc/$arch/Makefile - lib/isc/$arch/include/Makefile - lib/isc/$arch/include/isc/Makefile lib/isccc/Makefile lib/isccc/include/Makefile lib/isccc/include/isccc/Makefile lib/isccfg/Makefile lib/isccfg/include/Makefile lib/isccfg/include/isccfg/Makefile - lib/dns/Makefile - lib/dns/include/Makefile - lib/dns/include/dns/Makefile - lib/dns/include/dst/Makefile - lib/bind9/Makefile - lib/bind9/include/Makefile - lib/bind9/include/bind9/Makefile lib/lwres/Makefile lib/lwres/include/Makefile lib/lwres/include/lwres/Makefile @@ -2990,44 +3395,6 @@ AC_CONFIG_FILES([ lib/tests/Makefile lib/tests/include/Makefile lib/tests/include/tests/Makefile - bin/Makefile - bin/check/Makefile - bin/named/Makefile - bin/named/unix/Makefile - bin/rndc/Makefile - bin/rndc/unix/Makefile - bin/dig/Makefile - bin/nsupdate/Makefile - bin/tests/Makefile - bin/tests/names/Makefile - bin/tests/master/Makefile - bin/tests/rbt/Makefile - bin/tests/db/Makefile - bin/tests/tasks/Makefile - bin/tests/timers/Makefile - bin/tests/dst/Makefile - bin/tests/mem/Makefile - bin/tests/hashes/Makefile - bin/tests/net/Makefile - bin/tests/sockaddr/Makefile - bin/tests/system/Makefile - bin/tests/system/conf.sh - bin/tests/system/lwresd/Makefile - bin/tests/system/tkey/Makefile - bin/tests/headerdep_test.sh - bin/dnssec/Makefile - doc/Makefile - doc/arm/Makefile - doc/misc/Makefile - isc-config.sh - doc/xsl/Makefile - doc/xsl/isc-docbook-chunk.xsl - doc/xsl/isc-docbook-html.xsl - doc/xsl/isc-docbook-latex.xsl - doc/xsl/isc-manpage.xsl - doc/doxygen/Doxyfile - doc/doxygen/Makefile - doc/doxygen/doxygen-input-filter ]) # diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 0013c2e..c351784 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -2,7 +2,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" []> - + BIND 9 Administrator Reference Manual @@ -31,6 +31,7 @@ 2008 2009 2010 + 2011 Internet Systems Consortium, Inc. ("ISC") @@ -69,7 +70,7 @@ - This version of the manual corresponds to BIND version 9.6. + This version of the manual corresponds to BIND version 9.7. @@ -644,9 +645,9 @@ ISC BIND 9 compiles and runs on a large number - of Unix-like operating systems and on NT-derived versions of - Microsoft Windows such as Windows 2000 and Windows XP. For an - up-to-date + of Unix-like operating systems and on + Microsoft Windows Server 2003 and 2008, and Windows XP and Vista. + For an up-to-date list of supported systems, see the README file in the top level directory of the BIND 9 source distribution. @@ -680,10 +681,13 @@ // Two corporate subnets we wish to allow queries from. acl corpnets { 192.168.4.0/24; 192.168.7.0/24; }; options { - directory "/etc/namedb"; // Working directory + // Working directory + directory "/etc/namedb"; + allow-query { corpnets; }; }; -// Provide a reverse mapping for the loopback address 127.0.0.1 +// Provide a reverse mapping for the loopback +// address 127.0.0.1 zone "0.0.127.in-addr.arpa" { type master; file "localhost.rev"; @@ -703,13 +707,18 @@ zone "0.0.127.in-addr.arpa" { options { - directory "/etc/namedb"; // Working directory - allow-query-cache { none; }; // Do not allow access to cache - allow-query { any; }; // This is the default - recursion no; // Do not provide recursive service + // Working directory + directory "/etc/namedb"; + // Do not allow access to cache + allow-query-cache { none; }; + // This is the default + allow-query { any; }; + // Do not provide recursive service + recursion no; }; -// Provide a reverse mapping for the loopback address 127.0.0.1 +// Provide a reverse mapping for the loopback +// address 127.0.0.1 zone "0.0.127.in-addr.arpa" { type master; file "localhost.rev"; @@ -719,7 +728,8 @@ zone "0.0.127.in-addr.arpa" { zone "example.com" { type master; file "example.com.db"; - // IP addresses of slave servers allowed to transfer example.com + // IP addresses of slave servers allowed to + // transfer example.com allow-transfer { 192.168.4.14; 192.168.5.53; @@ -881,7 +891,7 @@ zone "eng.example.com" { For more detail on ordering responses, check the - rrset-order substatement in the + rrset-order sub-statement in the options statement, see . @@ -1162,7 +1172,62 @@ zone "eng.example.com" { + sign zone + class + view + + + Fetch all DNSSEC keys for the given zone + from the key directory (see + key-directory in + ). If they are within + their publication period, merge them into the + zone's DNSKEY RRset. If the DNSKEY RRset + is changed, then the zone is automatically + re-signed with the new key set. + + + This command requires that the + auto-dnssec zone option to be set + to allow, + maintain, or + create, and also requires + the zone to be configured to allow dynamic DNS. + See for + more details. + + + + + loadkeys zone + class + view + + + Fetch all DNSSEC keys for the given zone + from the key directory (see + key-directory in + ). If they are within + their publication period, merge them into the + zone's DNSKEY RRset. Unlike rndc + sign, however, the zone is not + immediately re-signed by the new keys, but is + allowed to incrementally re-sign over time. + + + This command requires that the + auto-dnssec zone option to + be set to maintain or + create, and also requires + the zone to be configured to allow dynamic DNS. + See for + more details. + + + + + freeze zone class @@ -1271,6 +1336,19 @@ zone "eng.example.com" { + secroots + view ... + + + Dump the server's security roots to the secroots + file for the specified views. If no view is + specified, security roots for all + views are dumped. + + + + + stop -p @@ -1383,6 +1461,65 @@ zone "eng.example.com" { + + addzone + zone + class + view + configuration + + + + Add a zone while the server is running. This + command requires the + allow-new-zones option to be set + to yes. The + configuration string + specified on the command line is the zone + configuration text that would ordinarily be + placed in named.conf. + + + The configuration is saved in a file called + hash.nzf, + where hash is a + cryptographic hash generated from the name of + the view. When named is + restarted, the file will be loaded into the view + configuration, so that zones that were added + can persist after a restart. + + + This sample addzone command + would add the zone example.com + to the default view: + + +$ rndc addzone example.com '{ type master; file "example.com.db"; };' + + + (Note the brackets and semi-colon around the zone + configuration text.) + + + + + + delzone + zone + class + view + + + + Delete a zone while the server is running. + Only zones that were originally added via + rndc addzone can be deleted + in this matter. + + + + @@ -1488,7 +1625,8 @@ zone "eng.example.com" { key rndc_key { algorithm "hmac-md5"; - secret "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K"; + secret + "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K"; }; options { default-server 127.0.0.1; @@ -1514,7 +1652,8 @@ options { controls { - inet 127.0.0.1 allow { localhost; } keys { rndc_key; }; + inet 127.0.0.1 + allow { localhost; } keys { rndc_key; }; }; @@ -1641,14 +1780,27 @@ controls { Dynamic update is enabled by including an - allow-update or update-policy - clause in the zone statement. The - tkey-gssapi-credential and - tkey-domain clauses in the - options statement enable the - server to negotiate keys that can be matched against those - in update-policy or - allow-update. + allow-update or an update-policy + clause in the zone statement. + + + + If the zone's update-policy is set to + local, updates to the zone + will be permitted for the key local-ddns, + which will be generated by named at startup. + See for more details. + + + + Dynamic updates using Kerberos signed requests can be made + using the TKEY/GSS protocol by setting either the + tkey-gssapi-keytab option, or alternatively + by setting both the tkey-gssapi-credential + and tkey-domain options. Once enabled, + Kerberos signed requests will be matched against the update + policies for the zone, using the Kerberos principal as the + signer for the request. @@ -1660,7 +1812,7 @@ controls { - The journal file + The journal file All changes made to a zone using dynamic update are stored @@ -1814,7 +1966,7 @@ controls { and site2.example.com, to the servers in the DMZ. These internal servers will have complete sets of information - for site1.example.com, site2.example.com, site1.internal, + for site1.example.com, site2.example.com, site1.internal, and site2.internal. @@ -1927,26 +2079,32 @@ options { ... ... forward only; - forwarders { // forward to external servers + // forward to external servers + forwarders { bastion-ips-go-here; }; - allow-transfer { none; }; // sample allow-transfer (no one) - allow-query { internals; externals; }; // restrict query access - allow-recursion { internals; }; // restrict recursion + // sample allow-transfer (no one) + allow-transfer { none; }; + // restrict query access + allow-query { internals; externals; }; + // restrict recursion + allow-recursion { internals; }; ... ... }; -zone "site1.example.com" { // sample master zone +// sample master zone +zone "site1.example.com" { type master; file "m/site1.example.com"; - forwarders { }; // do normal iterative - // resolution (do not forward) + // do normal iterative resolution (do not forward) + forwarders { }; allow-query { internals; externals; }; allow-transfer { internals; }; }; -zone "site2.example.com" { // sample slave zone +// sample slave zone +zone "site2.example.com" { type slave; file "s/site2.example.com"; masters { 172.16.72.3; }; @@ -1985,15 +2143,20 @@ acl externals { bastion-ips-go-here; }; options { ... ... - allow-transfer { none; }; // sample allow-transfer (no one) - allow-query { any; }; // default query access - allow-query-cache { internals; externals; }; // restrict cache access - allow-recursion { internals; externals; }; // restrict recursion + // sample allow-transfer (no one) + allow-transfer { none; }; + // default query access + allow-query { any; }; + // restrict cache access + allow-query-cache { internals; externals; }; + // restrict recursion + allow-recursion { internals; externals; }; ... ... }; -zone "site1.example.com" { // sample slave zone +// sample slave zone +zone "site1.example.com" { type master; file "m/site1.foo.com"; allow-transfer { internals; externals; }; @@ -2187,9 +2350,8 @@ allow-update { key host1-host2. ;}; - You may want to read about the more powerful - update-policy statement in - . + See for a discussion of + the more flexible update-policy statement. @@ -2453,12 +2615,23 @@ allow-update { key host1-host2. ;}; To enable named to validate answers from - other servers, the dnssec-enable and - dnssec-validation options must both be - set to yes (the default setting in BIND 9.5 - and later), and at least one trust anchor must be configured - with a trusted-keys statement in - named.conf. + other servers, the dnssec-enable option + must be set to yes, and the + dnssec-validation options must be set to + yes or auto. + + + + If dnssec-validation is set to + auto, then a default + trust anchor for the DNS root zone will be used. + If it is set to yes, however, + then at least one trust anchor must be configured + with a trusted-keys or + managed-keys statement in + named.conf, or DNSSEC validation + will not occur. The default setting is + yes. @@ -2471,7 +2644,14 @@ allow-update { key host1-host2. ;}; - trusted-keys are described in more detail + managed-keys are trusted keys which are + automatically kept up to date via RFC 5011 trust anchor + maintenance. + + + + trusted-keys and + managed-keys are described in more detail later in this document. @@ -2484,45 +2664,59 @@ allow-update { key host1-host2. ;}; After DNSSEC gets established, a typical DNSSEC configuration - will look something like the following. It has a one or + will look something like the following. It has one or more public keys for the root. This allows answers from outside the organization to be validated. It will also have several keys for parts of the namespace the organization - controls. These are here to ensure that named is immune - to compromises in the DNSSEC components of the security - of parent zones. + controls. These are here to ensure that named + is immune to compromises in the DNSSEC components of the security + of parent zones. -trusted-keys { - +managed-keys { /* Root Key */ -"." 257 3 3 "BNY4wrWM1nCfJ+CXd0rVXyYmobt7sEEfK3clRbGaTwSJxrGkxJWoZu6I7PzJu/ - E9gx4UC1zGAHlXKdE4zYIpRhaBKnvcC2U9mZhkdUpd1Vso/HAdjNe8LmMlnzY3 - zy2Xy4klWOADTPzSv9eamj8V18PHGjBLaVtYvk/ln5ZApjYghf+6fElrmLkdaz - MQ2OCnACR817DF4BBa7UR/beDHyp5iWTXWSi6XmoJLbG9Scqc7l70KDqlvXR3M - /lUUVRbkeg1IPJSidmK3ZyCllh4XSKbje/45SKucHgnwU5jefMtq66gKodQj+M - iA21AfUVe7u99WzTLzY3qlxDhxYQQ20FQ97S+LKUTpQcq27R7AT3/V5hRQxScI - Nqwcz4jYqZD2fQdgxbcDTClU0CRBdiieyLMNzXG3"; - -/* Key for our organization's forward zone */ -example.com. 257 3 5 "AwEAAaxPMcR2x0HbQV4WeZB6oEDX+r0QM65KbhTjrW1ZaARmPhEZZe - 3Y9ifgEuq7vZ/zGZUdEGNWy+JZzus0lUptwgjGwhUS1558Hb4JKUbb - OTcM8pwXlj0EiX3oDFVmjHO444gLkBO UKUf/mC7HvfwYH/Be22GnC - lrinKJp1Og4ywzO9WglMk7jbfW33gUKvirTHr25GL7STQUzBb5Usxt - 8lgnyTUHs1t3JwCY5hKZ6CqFxmAVZP20igTixin/1LcrgX/KMEGd/b - iuvF4qJCyduieHukuY3H4XMAcR+xia2 nIUPvm/oyWR8BW/hWdzOvn - SCThlHf3xiYleDbt/o1OTQ09A0="; - -/* Key for our reverse zone. */ -2.0.192.IN-ADDRPA.NET. 257 3 5 "AQOnS4xn/IgOUpBPJ3bogzwcxOdNax071L18QqZnQQQA - VVr+iLhGTnNGp3HoWQLUIzKrJVZ3zggy3WwNT6kZo6c0 - tszYqbtvchmgQC8CzKojM/W16i6MG/ea fGU3siaOdS0 - yOI6BgPsw+YZdzlYMaIJGf4M4dyoKIhzdZyQ2bYQrjyQ - 4LB0lC7aOnsMyYKHHYeRv PxjIQXmdqgOJGq+vsevG06 - zW+1xgYJh9rCIfnm1GX/KMgxLPG2vXTD/RnLX+D3T3UL - 7HJYHJhAZD5L59VvjSPsZJHeDCUyWYrvPZesZDIRvhDD - 52SKvbheeTJUm6EhkzytNN2SN96QRk8j/iI8ib"; + "." initial-key 257 3 3 "BNY4wrWM1nCfJ+CXd0rVXyYmobt7sEEfK3clRbGaTwS + JxrGkxJWoZu6I7PzJu/E9gx4UC1zGAHlXKdE4zYIpRh + aBKnvcC2U9mZhkdUpd1Vso/HAdjNe8LmMlnzY3zy2Xy + 4klWOADTPzSv9eamj8V18PHGjBLaVtYvk/ln5ZApjYg + hf+6fElrmLkdaz MQ2OCnACR817DF4BBa7UR/beDHyp + 5iWTXWSi6XmoJLbG9Scqc7l70KDqlvXR3M/lUUVRbke + g1IPJSidmK3ZyCllh4XSKbje/45SKucHgnwU5jefMtq + 66gKodQj+MiA21AfUVe7u99WzTLzY3qlxDhxYQQ20FQ + 97S+LKUTpQcq27R7AT3/V5hRQxScINqwcz4jYqZD2fQ + dgxbcDTClU0CRBdiieyLMNzXG3"; +}; + +trusted-keys { + /* Key for our organization's forward zone */ + example.com. 257 3 5 "AwEAAaxPMcR2x0HbQV4WeZB6oEDX+r0QM6 + 5KbhTjrW1ZaARmPhEZZe3Y9ifgEuq7vZ/z + GZUdEGNWy+JZzus0lUptwgjGwhUS1558Hb + 4JKUbbOTcM8pwXlj0EiX3oDFVmjHO444gL + kBOUKUf/mC7HvfwYH/Be22GnClrinKJp1O + g4ywzO9WglMk7jbfW33gUKvirTHr25GL7S + TQUzBb5Usxt8lgnyTUHs1t3JwCY5hKZ6Cq + FxmAVZP20igTixin/1LcrgX/KMEGd/biuv + F4qJCyduieHukuY3H4XMAcR+xia2nIUPvm + /oyWR8BW/hWdzOvnSCThlHf3xiYleDbt/o + 1OTQ09A0="; + + /* Key for our reverse zone. */ + 2.0.192.IN-ADDRPA.NET. 257 3 5 "AQOnS4xn/IgOUpBPJ3bogzwc + xOdNax071L18QqZnQQQAVVr+i + LhGTnNGp3HoWQLUIzKrJVZ3zg + gy3WwNT6kZo6c0tszYqbtvchm + gQC8CzKojM/W16i6MG/eafGU3 + siaOdS0yOI6BgPsw+YZdzlYMa + IJGf4M4dyoKIhzdZyQ2bYQrjy + Q4LB0lC7aOnsMyYKHHYeRvPxj + IQXmdqgOJGq+vsevG06zW+1xg + YJh9rCIfnm1GX/KMgxLPG2vXT + D/RnLX+D3T3UL7HJYHJhAZD5L + 59VvjSPsZJHeDCUyWYrvPZesZ + DIRvhDD52SKvbheeTJUm6Ehkz + ytNN2SN96QRk8j/iI8ib"; }; options { @@ -2575,6 +2769,13 @@ options { + + + + + + + IPv6 Support in <acronym>BIND</acronym> 9 @@ -2653,7 +2854,8 @@ host 3600 IN AAAA 2001:db8::1 $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. -1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 14400 IN PTR host.example.com. +1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 14400 IN PTR ( + host.example.com. ) @@ -2831,6 +3033,19 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. + namelist + + + + + A list of one or more domain_name + elements. + + + + + + dotted_decimal @@ -3224,7 +3439,8 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. /* This is a BIND comment as in C */ // This is a BIND comment as in C++ - # This is a BIND comment as in common UNIX shells and perl + # This is a BIND comment as in common UNIX shells +# and perl @@ -3439,6 +3655,17 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. + managed-keys + + + + lists DNSSEC keys to be kept up to date + using RFC 5011 trust anchor maintenance. + + + + + view @@ -3559,10 +3786,12 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. <command>controls</command> Statement Grammar controls { - [ inet ( ip_addr | * ) [ port ip_port ] allow { address_match_list } + [ inet ( ip_addr | * ) [ port ip_port ] + allow { address_match_list } keys { key_list }; ] [ inet ...; ] - [ unix path perm number owner number group number keys { key_list }; ] + [ unix path perm number owner number group number + keys { key_list }; ] [ unix ...; ] }; @@ -4031,32 +4260,30 @@ notrace. All debugging messages in the server have a debug channel default_syslog { - syslog daemon; // send to syslog's daemon - // facility - severity info; // only send priority info - // and higher -}; + // send to syslog's daemon facility + syslog daemon; + // only send priority info and higher + severity info; channel default_debug { - file "named.run"; // write to named.run in - // the working directory - // Note: stderr is used instead - // of "named.run" - // if the server is started - // with the '-f' option. - severity dynamic; // log at the server's - // current debug level + // write to named.run in the working directory + // Note: stderr is used instead of "named.run" if + // the server is started with the '-f' option. + file "named.run"; + // log at the server's current debug level + severity dynamic; }; channel default_stderr { - stderr; // writes to stderr - severity info; // only send priority info - // and higher + // writes to stderr + stderr; + // only send priority info and higher + severity info; }; channel null { - null; // toss anything sent to - // this channel + // toss anything sent to this channel + null; }; @@ -4308,12 +4535,14 @@ category notify { null; }; The query log entry reports the client's IP address and port number, and the query name, - class and type. It also reports whether the + class and type. Next it reports whether the Recursion Desired flag was set (+ if set, - if not set), if the query was signed (S), - EDNS was in use (E), if DO (DNSSEC Ok) was - set (D), or if CD (Checking Disabled) was set - (C). + EDNS was in use (E), if TCP was used (T), if + DO (DNSSEC Ok) was set (D), or if CD (Checking + Disabled) was set (C). After this the + destination address the query was sent to is + reported. @@ -4453,7 +4682,13 @@ category notify { null; }; The log message will look like as follows: - fetch completed at resolver.c:2970 for www.example.com/A in 30.000183: timed out/success [domain:example.com,referral:2,restart:7,qrysent:8,timeout:5,lame:0,neterr:0,badresp:1,adberr:0,findfail:0,valfail:0] + + +fetch completed at resolver.c:2970 for www.example.com/A +in 30.000183: timed out/success [domain:example.com, +referral:2,restart:7,qrysent:8,timeout:5,lame:0,neterr:0, +badresp:1,adberr:0,findfail:0,valfail:0] + The first part before the colon shows that a recursive @@ -4485,8 +4720,8 @@ category notify { null; }; - - + + @@ -4651,7 +4886,8 @@ category notify { null; }; lwres { - listen-on { ip_addr port ip_port ; ip_addr port ip_port ; ... }; + listen-on { ip_addr port ip_port ; + ip_addr port ip_port ; ... }; view view_name; search { domain_name ; domain_name ; ... }; ndots number; @@ -4718,7 +4954,8 @@ category notify { null; }; <command>masters</command> Statement Grammar -masters name port ip_port { ( masters_list | ip_addr port ip_port key key ) ; ... }; +masters name port ip_port { ( masters_list | + ip_addr port ip_port key key ) ; ... }; @@ -4741,17 +4978,21 @@ category notify { null; }; options { + attach-cache cache_name; version version_string; hostname hostname_string; server-id server_id_string; directory path_name; key-directory path_name; + managed-keys-directory path_name; named-xfer path_name; + tkey-gssapi-keytab path_name; tkey-gssapi-credential principal; tkey-domain domainname; tkey-dhkey key_name key_tag; cache-file path_name; dump-file path_name; + bindkeys-file path_name; memstatistics yes_or_no; memstatistics-file path_name; pid-file path_name; @@ -4776,8 +5017,9 @@ category notify { null; }; maintain-ixfr-base yes_or_no; ixfr-from-differences (yes_or_no | master | slave); dnssec-enable yes_or_no; - dnssec-validation yes_or_no; - dnssec-lookaside domain trust-anchor domain; + dnssec-validation (yes_or_no | auto); + dnssec-lookaside ( auto | + domain trust-anchor domain ); dnssec-must-be-secure domain yes_or_no; dnssec-accept-expired yes_or_no; forward ( only | first ); @@ -4788,12 +5030,14 @@ category notify { null; }; ... }; check-names ( master | slave | response ) ( warn | fail | ignore ); + check-dup-records ( warn | fail | ignore ); check-mx ( warn | fail | ignore ); check-wildcard yes_or_no; check-integrity yes_or_no; check-mx-cname ( warn | fail | ignore ); check-srv-cname ( warn | fail | ignore ); check-sibling yes_or_no; + allow-new-zones { yes_or_no }; allow-notify { address_match_list }; allow-query { address_match_list }; allow-query-on { address_match_list }; @@ -4805,6 +5049,8 @@ category notify { null; }; allow-update { address_match_list }; allow-update-forwarding { address_match_list }; update-check-ksk yes_or_no; + dnssec-dnskey-kskonly yes_or_no; + dnssec-secure-to-insecure yes_or_no ; try-tcp-refresh yes_or_no; allow-v6-synthesis { address_match_list }; blackhole { address_match_list }; @@ -4816,12 +5062,12 @@ category notify { null; }; listen-on-v6 port ip_port { address_match_list }; query-source ( ( ip4_addr | * ) port ( ip_port | * ) | - address ( ip4_addr | * ) - port ( ip_port | * ) ) ; + address ( ip4_addr | * ) + port ( ip_port | * ) ) ; query-source-v6 ( ( ip6_addr | * ) - port ( ip_port | * ) | - address ( ip6_addr | * ) - port ( ip_port | * ) ) ; + port ( ip_port | * ) | + address ( ip6_addr | * ) + port ( ip_port | * ) ) ; use-queryport-pool yes_or_no; queryport-pool-ports number; queryport-pool-updateinterval number; @@ -4842,13 +5088,15 @@ category notify { null; }; transfer-source (ip4_addr | *) port ip_port ; transfer-source-v6 (ip6_addr | *) port ip_port ; alt-transfer-source (ip4_addr | *) port ip_port ; - alt-transfer-source-v6 (ip6_addr | *) port ip_port ; + alt-transfer-source-v6 (ip6_addr | *) + port ip_port ; use-alt-transfer-source yes_or_no; notify-delay seconds ; notify-source (ip4_addr | *) port ip_port ; notify-source-v6 (ip6_addr | *) port ip_port ; notify-to-soa yes_or_no ; - also-notify { ip_addr port ip_port ; ip_addr port ip_port ; ... }; + also-notify { ip_addr port ip_port ; + ip_addr port ip_port ; ... }; max-ixfr-log-size number; max-journal-size size_spec; coresize size_spec ; @@ -4884,12 +5132,25 @@ category notify { null; }; random-device path_name ; max-cache-size size_spec ; match-mapped-addresses yes_or_no; + filter-aaaa-on-v4 ( yes_or_no | break-dnssec ); + filter-aaaa { address_match_list }; + dns64 IPv6-prefix { + clients { address_match_list }; + mapped { address_match_list }; + exclude { address_match_list }; + suffix IPv6-address; + recursive-only yes_or_no; + break-dnssec yes_or_no; + }; ; + dns64-server name + dns64-contact name preferred-glue ( A | AAAA | NONE ); edns-udp-size number; max-udp-size number; root-delegation-only exclude { namelist } ; querylog yes_or_no ; - disable-algorithms domain { algorithm; algorithm; }; + disable-algorithms domain { algorithm; + algorithm; }; acache-enable yes_or_no ; acache-cleaning-interval number; max-acache-size size_spec ; @@ -4902,6 +5163,10 @@ category notify { null; }; disable-empty-zone zone_name ; zero-no-soa-ttl yes_or_no ; zero-no-soa-ttl-cache yes_or_no ; + resolver-query-timeout number ; + deny-answer-addresses { address_match_list } except-from { namelist } ; + deny-answer-aliases { namelist } except-from { namelist } ; + response-policy { zone_name policy given | no-op | nxdomain | nodata | cname domain ; } ; }; @@ -4923,6 +5188,102 @@ category notify { null; }; + + attach-cache + + + Allows multiple views to share a single cache + database. + Each view has its own cache database by default, but + if multiple views have the same operational policy + for name resolution and caching, those views can + share a single cache to save memory and possibly + improve resolution efficiency by using this option. + + + + The attach-cache option + may also be specified in view + statements, in which case it overrides the + global attach-cache option. + + + + The cache_name specifies + the cache to be shared. + When the named server configures + views which are supposed to share a cache, it + creates a cache with the specified name for the + first view of these sharing views. + The rest of the views will simply refer to the + already created cache. + + + + One common configuration to share a cache would be to + allow all views to share a single cache. + This can be done by specifying + the attach-cache as a global + option with an arbitrary name. + + + + Another possible operation is to allow a subset of + all views to share a cache while the others to + retain their own caches. + For example, if there are three views A, B, and C, + and only A and B should share a cache, specify the + attach-cache option as a view A (or + B)'s option, referring to the other view name: + + + + view "A" { + // this view has its own cache + ... + }; + view "B" { + // this view refers to A's cache + attach-cache "A"; + }; + view "C" { + // this view has its own cache + ... + }; + + + + Views that share a cache must have the same policy + on configurable parameters that may affect caching. + The current implementation requires the following + configurable options be consistent among these + views: + check-names, + cleaning-interval, + dnssec-accept-expired, + dnssec-validation, + max-cache-ttl, + max-ncache-ttl, + max-cache-size, and + zero-no-soa-ttl. + + + + Note that there may be other parameters that may + cause confusion if they are inconsistent for + different views that share a single cache. + For example, if these views define different sets of + forwarders that can return different answers for the + same question, sharing the answer does not make + sense or could even be harmful. + It is administrator's responsibility to ensure + configuration differences in different views do + not cause disruption with a shared cache. + + + + + directory @@ -4950,10 +5311,24 @@ category notify { null; }; When performing dynamic update of secure zones, the directory where the public and private DNSSEC key files should be found, if different than the current working - directory. The directory specified must be an absolute - path. (Note that this option has no effect on the paths - for files containing non-DNSSEC keys such as the - rndc.key. + directory. (Note that this option has no effect on the + paths for files containing non-DNSSEC keys such as + bind.keys, + rndc.key or + session.key.) + + + + + + managed-keys-directory + + + The directory used to hold the files used to track managed keys. + By default it is the working directory. It there are no + views then the file managed-keys.bind + otherwise a SHA256 hash of the view name is used with + .mkeys extension added. @@ -4973,19 +5348,33 @@ category notify { null; }; + tkey-gssapi-keytab + + + The KRB5 keytab file to use for GSS-TSIG updates. If + this option is set and tkey-gssapi-credential is not + set, then updates will be allowed with any key + matching a principal in the specified keytab. + + + + + tkey-gssapi-credential The security credential with which the server should authenticate keys requested by the GSS-TSIG protocol. Currently only Kerberos 5 authentication is available - and the credential is a Kerberos principal which - the server can acquire through the default system - key file, normally /etc/krb5.keytab. - Normally this principal is of the form - "DNS/server.domain". - To use GSS-TSIG, tkey-domain - must also be set. + and the credential is a Kerberos principal which the + server can acquire through the default system key + file, normally /etc/krb5.keytab. + The location keytab file can be overridden using the + tkey-gssapi-keytab option. Normally this principal is + of the form "DNS/server.domain". + To use GSS-TSIG, tkey-domain must + also be set if a specific keytab is not set with + tkey-gssapi-keytab. @@ -5007,7 +5396,8 @@ category notify { null; }; should be the server's domain name, or an otherwise non-existent subdomain like "_tkey.domainname". If you are - using GSS-TSIG, this variable must be defined. + using GSS-TSIG, this variable must be defined, unless + you specify a specific keytab using tkey-gssapi-keytab. @@ -5106,6 +5496,84 @@ category notify { null; }; + bindkeys-file + + + The pathname of a file to override the built-in trusted + keys provided by named. + See the discussion of dnssec-lookaside + and dnssec-validation for details. + If not specified, the default is + /etc/bind.keys. + + + + + + secroots-file + + + The pathname of the file the server dumps + security roots to when instructed to do so with + rndc secroots. + If not specified, the default is named.secroots. + + + + + + session-keyfile + + + The pathname of the file into which to write a TSIG + session key generated by named for use by + nsupdate -l. If not specified, the + default is /var/run/named/session.key. + (See , and in + particular the discussion of the + update-policy statement's + local option for more + information about this feature.) + + + + + + session-keyname + + + The key name to use for the TSIG session key. + If not specified, the default is "local-ddns". + + + + + + session-keyalg + + + The algorithm to use for the TSIG session key. + Valid values are hmac-sha1, hmac-sha224, hmac-sha256, + hmac-sha384, hmac-sha512 and hmac-md5. If not + specified, the default is hmac-sha256. + + + + + + session-keyfile + + + The pathname of the file into which to write a session TSIG + key for use by nsupdate -l. (See the + discussion of the update-policy + statement's local option for more + details on this feature.) + + + + + port @@ -5167,14 +5635,14 @@ category notify { null; }; DS queries are expected to be made to and be answered by delegation only zones. Such queries and responses are - treated as a exception to delegation-only processing + treated as an exception to delegation-only processing and are not converted to NXDOMAIN responses provided a CNAME is not discovered at the query name. If a delegation only zone server also serves a child zone it is not always possible to determine whether - a answer comes from the delegation only zone or the + an answer comes from the delegation only zone or the child zone. SOA NS and DNSKEY records are apex only records and a matching response that contains these records or DS is treated as coming from a @@ -5223,21 +5691,46 @@ options { dnssec-lookaside - When set, dnssec-lookaside - provides the - validator with an alternate method to validate DNSKEY records - at the - top of a zone. When a DNSKEY is at or below a domain - specified by the - deepest dnssec-lookaside, and - the normal DNSSEC validation - has left the key untrusted, the trust-anchor will be append to - the key - name and a DLV record will be looked up to see if it can - validate the - key. If the DLV record validates a DNSKEY (similarly to the - way a DS + When set, dnssec-lookaside provides the + validator with an alternate method to validate DNSKEY + records at the top of a zone. When a DNSKEY is at or + below a domain specified by the deepest + dnssec-lookaside, and the normal DNSSEC + validation has left the key untrusted, the trust-anchor + will be appended to the key name and a DLV record will be + looked up to see if it can validate the key. If the DLV + record validates a DNSKEY (similarly to the way a DS record does) the DNSKEY RRset is deemed to be trusted. + + + If dnssec-lookaside is set to + auto, then built-in default + values for the DLV domain and trust anchor will be + used, along with a built-in key for validation. + + + The default DLV key is stored in the file + bind.keys; + named will load that key at + startup if dnssec-lookaside is set to + auto. A copy of the file is + installed along with BIND 9, and is + current as of the release date. If the DLV key expires, a + new copy of bind.keys can be downloaded + from https://www.isc.org/solutions/dlv. + + + (To prevent problems if bind.keys is + not found, the current key is also compiled in to + named. Relying on this is not + recommended, however, as it requires named + to be recompiled with a new key when the DLV key expires.) + + + NOTE: named only loads certain specific + keys from bind.keys: those for the + DLV zone and for the DNS root zone. The file cannot be + used to store keys for other zones. @@ -5246,21 +5739,86 @@ options { dnssec-must-be-secure - Specify hierarchies which must be or may not be secure (signed and - validated). - If yes, then named will only accept - answers if they - are secure. - If no, then normal DNSSEC validation - applies - allowing for insecure answers to be accepted. - The specified domain must be under a trusted-key or - dnssec-lookaside must be - active. + Specify hierarchies which must be or may not be secure + (signed and validated). If yes, + then named will only accept answers if + they are secure. If no, then normal + DNSSEC validation applies allowing for insecure answers to + be accepted. The specified domain must be under a + trusted-keys or + managed-keys statement, or + dnssec-lookaside must be active. + + dns64 + + + This directive instructs named to + return mapped IPv4 addresses to AAAA queries when + there are no AAAA records. It is intended to be + used in conjunction with a NAT64. Each + dns64 defines one DNS64 prefix. + Multiple DNS64 prefixes can be defined. + + + Compatible IPv6 prefixes have lengths of 32, 40, 48, 56, + 64 and 96 as per RFC 6052. + + + Additionally a reverse IP6.ARPA zone will be created for + the prefix to provide a mapping from the IP6.ARPA names + to the corresponding IN-ADDR.ARPA names using synthesized + CNAMEs. dns64-server and + dns64-contact can be used to specify + the name of the server and contact for the zones. These + are settable at the view / options level. These are + not settable on a per-prefix basis. + + + Each dns64 supports an optional + clients ACL that determines which + clients are affected by this directive. If not defined, + it defaults to any;. + + + Each dns64 supports an optional + mapped ACL that selects which + IPv4 addresses are to be mapped in the corresponding + A RRset. If not defined it defaults to + any;. + + + Each dns64 supports an optional + exclude ACL that selects which + IPv6 addresses will be ignored for the purposes + of determining whether dns64 is to be applied. + Any non-matching address will prevent further + DNS64 processing from occurring for this client. + + + A optional suffix can also + be defined to set the bits trailing the mapped + IPv4 address bits. By default these bits are + set to ::. The bits + matching the prefix and mapped IPv4 address + must be zero. + + + acl rfc1918 { 10/8; 192.168/16; 172.16/12; }; + + dns64 64:FF9B::/96 { + clients { any; }; + mapped { !rfc1918; any; }; + exclude { 64:FF9B::/96; ::ffff:0000:0000/96; }; + suffix ::; + }; + + + + @@ -5269,6 +5827,18 @@ options { + allow-new-zones + + + If yes, then zones can be + added at runtime via rndc addzone + or deleted via rndc delzone. + The default is no. + + + + + auth-nxdomain @@ -5755,6 +6325,7 @@ options { off on a per-zone basis by specifying zone-statistics no in the zone statement). + The default is no. These statistics may be accessed using rndc stats, which will dump them to the file listed @@ -5928,6 +6499,60 @@ options { + filter-aaaa-on-v4 + + + This option is only available when + BIND 9 is compiled with the + --enable-filter-aaaa option on the + "configure" command line. It is intended to help the + transition from IPv4 to IPv6 by not giving IPv6 addresses + to DNS clients unless they have connections to the IPv6 + Internet. This is not recommended unless absolutely + necessary. The default is no. + The filter-aaaa-on-v4 option + may also be specified in view statements + to override the global filter-aaaa-on-v4 + option. + + + If yes, + the DNS client is at an IPv4 address, in filter-aaaa, + and if the response does not include DNSSEC signatures, + then all AAAA records are deleted from the response. + This filtering applies to all responses and not only + authoritative responses. + + + If break-dnssec, + then AAAA records are deleted even when dnssec is enabled. + As suggested by the name, this makes the response not verify, + because the DNSSEC protocol is designed detect deletions. + + + This mechanism can erroneously cause other servers to + not give AAAA records to their clients. + A recursing server with both IPv6 and IPv4 network connections + that queries an authoritative server using this mechanism + via IPv4 will be denied AAAA records even if its client is + using IPv6. + + + This mechanism is applied to authoritative as well as + non-authoritative records. + A client using IPv4 that is not allowed recursion can + erroneously be given AAAA records because the server is not + allowed to check for A records. + + + Some AAAA records are given to IPv4 clients in glue records. + IPv4 clients that are servers can then erroneously + answer requests for AAAA records received via IPv4. + + + + + ixfr-from-differences @@ -5996,7 +6621,15 @@ options { Enable DNSSEC validation in named. Note dnssec-enable also needs to be set to yes to be effective. - The default is yes. + If set to no, DNSSEC validation + is disabled. If set to auto, + DNSSEC validation is enabled, and a default + trust-anchor for the DNS root zone is used. If set to + yes, DNSSEC validation is enabled, + but a trust anchor must be manually configured using + a trusted-keys or + managed-keys statement. The default + is yes. @@ -6007,7 +6640,9 @@ options { Accept expired signatures when verifying DNSSEC signatures. The default is no. - Setting this option to "yes" leaves named vulnerable to replay attacks. + Setting this option to yes + leaves named vulnerable to + replay attacks. @@ -6057,6 +6692,19 @@ options { + check-dup-records + + + Check master zones for records that are treated as different + by DNSSEC but are semantically equal in plain DNS. The + default is to warn. Other possible + values are fail and + ignore. + + + + + check-mx @@ -6161,13 +6809,49 @@ options { update-check-ksk - When regenerating the RRSIGs following a UPDATE - request to a secure zone, check the KSK flag on - the DNSKEY RR to determine if this key should be - used to generate the RRSIG. This flag is ignored - if there are not DNSKEY RRs both with and without - a KSK. - The default is yes. + When set to the default value of yes, + check the KSK bit in each key to determine how the key + should be used when generating RRSIGs for a secure zone. + + + Ordinarily, zone-signing keys (that is, keys without the + KSK bit set) are used to sign the entire zone, while + key-signing keys (keys with the KSK bit set) are only + used to sign the DNSKEY RRset at the zone apex. + However, if this option is set to no, + then the KSK bit is ignored; KSKs are treated as if they + were ZSKs and are used to sign the entire zone. This is + similar to the dnssec-signzone -z + command line option. + + + When this option is set to yes, there + must be at least two active keys for every algorithm + represented in the DNSKEY RRset: at least one KSK and one + ZSK per algorithm. If there is any algorithm for which + this requirement is not met, this option will be ignored + for that algorithm. + + + + + + dnssec-dnskey-kskonly + + + When this option and update-check-ksk + are both set to yes, only key-signing + keys (that is, keys with the KSK bit set) will be used + to sign the DNSKEY RRset at the zone apex. Zone-signing + keys (keys without the KSK bit set) will be used to sign + the remainder of the zone, but not the DNSKEY RRset. + This is similar to the + dnssec-signzone -x command line option. + + + The default is no. If + update-check-ksk is set to + no, this option is ignored. @@ -6183,6 +6867,34 @@ options { + + dnssec-secure-to-insecure + + + Allow a dynamic zone to transition from secure to + insecure (i.e., signed to unsigned) by deleting all + of the DNSKEY records. The default is no. + If set to yes, and if the DNSKEY RRset + at the zone apex is deleted, all RRSIG and NSEC records + will be removed from the zone as well. + + + If the zone uses NSEC3, then it is also necessary to + delete the NSEC3PARAM RRset from the zone apex; this will + cause the removal of all corresponding NSEC3 records. + (It is expected that this requirement will be eliminated + in a future release.) + + + Note that if a zone has been configured with + auto-dnssec maintain and the + private keys remain accessible in the key repository, + then the zone will be automatically signed again the + next time named is started. + + + + @@ -6483,18 +7195,41 @@ options { - blackhole + blackhole + + + Specifies a list of addresses that the + server will not accept queries from or use to resolve a + query. Queries + from these addresses will not be responded to. The default + is none. + + + + + + filter-aaaa + + + Specifies a list of addresses to which + filter-aaaa-on-v4 + is applies. The default is any. + + + + + + resolver-query-timeout - Specifies a list of addresses that the - server will not accept queries from or use to resolve a - query. Queries - from these addresses will not be responded to. The default - is none. + The amount of time the resolver will spend attempting + to resolve a recursive query before failing. The + default is 10 and the maximum is + 30. Setting it to 0 + will result in the default being used. - @@ -7542,20 +8277,26 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; sortlist { - { localhost; // IF the local host - { localnets; // THEN first fit on the - 192.168.1/24; // following nets + // IF the local host + // THEN first fit on the following nets + { localhost; + { localnets; + 192.168.1/24; { 192.168.2/24; 192.168.3/24; }; }; }; - { 192.168.1/24; // IF on class C 192.168.1 - { 192.168.1/24; // THEN use .1, or .2 or .3 + // IF on class C 192.168.1 THEN use .1, or .2 or .3 + { 192.168.1/24; + { 192.168.1/24; { 192.168.2/24; 192.168.3/24; }; }; }; - { 192.168.2/24; // IF on class C 192.168.2 - { 192.168.2/24; // THEN use .2, or .1 or .3 + // IF on class C 192.168.2 THEN use .2, or .1 or .3 + { 192.168.2/24; + { 192.168.2/24; { 192.168.1/24; 192.168.3/24; }; }; }; - { 192.168.3/24; // IF on class C 192.168.3 - { 192.168.3/24; // THEN use .3, or .1 or .2 + // IF on class C 192.168.3 THEN use .3, or .1 or .2 + { 192.168.3/24; + { 192.168.3/24; { 192.168.1/24; 192.168.2/24; }; }; }; - { { 192.168.4/24; 192.168.5/24; }; // if .4 or .5, prefer that net + // IF .4 or .5 THEN prefer that net + { { 192.168.4/24; 192.168.5/24; }; }; }; @@ -7772,7 +8513,7 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; DNSSEC signatures automatically generated as a result of dynamic updates () will expire. There - is a optional second field which specifies how + is an optional second field which specifies how long before expiry that the signatures will be regenerated. If not specified, the signatures will be regenerated at 1/4 of base interval. The second @@ -7877,7 +8618,7 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; Sets the advertised EDNS UDP buffer size in bytes to control the size of packets received. - Valid values are 512 to 4096 (values outside this range + Valid values are 1024 to 4096 (values outside this range will be silently adjusted). The default value is 4096. The usual reason for setting edns-udp-size to a non-default @@ -7885,24 +8626,36 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; firewalls that block fragmented packets and/or block UDP packets that are greater than 512 bytes. + + named will fallback to using 512 bytes + if it get a series of timeout at the initial value. 512 + bytes is not being offered to encourage sites to fix their + firewalls. Small EDNS UDP sizes will result in the + excessive use of TCP. + max-udp-size - - - Sets the maximum EDNS UDP message size named will - send in bytes. Valid values are 512 to 4096 (values outside - this range will be silently adjusted). The default + + + Sets the maximum EDNS UDP message size + named will send in bytes. + Valid values are 512 to 4096 (values outside this + range will be silently adjusted). The default value is 4096. The usual reason for setting - max-udp-size to a non-default value is to get UDP - answers to pass through broken firewalls that - block fragmented packets and/or block UDP packets - that are greater than 512 bytes. + max-udp-size to a non-default + value is to get UDP answers to pass through broken + firewalls that block fragmented packets and/or + block UDP packets that are greater than 512 bytes. This is independent of the advertised receive buffer (edns-udp-size). + + Setting this to a low value will encourage additional + TCP traffic to the nameserver. + @@ -8081,7 +8834,7 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; Named will attempt to determine if a built-in zone already exists or is active (covered by a forward-only forwarding declaration) - and will not create a empty zone in that case. + and will not create an empty zone in that case. The current list of empty zones is: @@ -8308,6 +9061,282 @@ XXX: end of RFC1918 addresses #defined out --> + + Content Filtering + + BIND 9 provides the ability to filter + out DNS responses from external DNS servers containing + certain types of data in the answer section. + Specifically, it can reject address (A or AAAA) records if + the corresponding IPv4 or IPv6 addresses match the given + address_match_list of the + deny-answer-addresses option. + It can also reject CNAME or DNAME records if the "alias" + name (i.e., the CNAME alias or the substituted query name + due to DNAME) matches the + given namelist of the + deny-answer-aliases option, where + "match" means the alias name is a subdomain of one of + the name_list elements. + If the optional namelist is specified + with except-from, records whose query name + matches the list will be accepted regardless of the filter + setting. + Likewise, if the alias name is a subdomain of the + corresponding zone, the deny-answer-aliases + filter will not apply; + for example, even if "example.com" is specified for + deny-answer-aliases, + +www.example.com. CNAME xxx.example.com. + + + returned by an "example.com" server will be accepted. + + + + In the address_match_list of the + deny-answer-addresses option, only + ip_addr + and ip_prefix + are meaningful; + any key_id will be silently ignored. + + + + If a response message is rejected due to the filtering, + the entire message is discarded without being cached, and + a SERVFAIL error will be returned to the client. + + + + This filtering is intended to prevent "DNS rebinding attacks," in + which an attacker, in response to a query for a domain name the + attacker controls, returns an IP address within your own network or + an alias name within your own domain. + A naive web browser or script could then serve as an + unintended proxy, allowing the attacker + to get access to an internal node of your local network + that couldn't be externally accessed otherwise. + See the paper available at + + http://portal.acm.org/citation.cfm?id=1315245.1315298 + + for more details about the attacks. + + + + For example, if you own a domain named "example.net" and + your internal network uses an IPv4 prefix 192.0.2.0/24, + you might specify the following rules: + + +deny-answer-addresses { 192.0.2.0/24; } except-from { "example.net"; }; +deny-answer-aliases { "example.net"; }; + + + + If an external attacker lets a web browser in your local + network look up an IPv4 address of "attacker.example.com", + the attacker's DNS server would return a response like this: + + +attacker.example.com. A 192.0.2.1 + + + in the answer section. + Since the rdata of this record (the IPv4 address) matches + the specified prefix 192.0.2.0/24, this response will be + ignored. + + + + On the other hand, if the browser looks up a legitimate + internal web server "www.example.net" and the + following response is returned to + the BIND 9 server + + +www.example.net. A 192.0.2.2 + + + it will be accepted since the owner name "www.example.net" + matches the except-from element, + "example.net". + + + + Note that this is not really an attack on the DNS per se. + In fact, there is nothing wrong for an "external" name to + be mapped to your "internal" IP address or domain name + from the DNS point of view. + It might actually be provided for a legitimate purpose, + such as for debugging. + As long as the mapping is provided by the correct owner, + it is not possible or does not make sense to detect + whether the intent of the mapping is legitimate or not + within the DNS. + The "rebinding" attack must primarily be protected at the + application that uses the DNS. + For a large site, however, it may be difficult to protect + all possible applications at once. + This filtering feature is provided only to help such an + operational environment; + it is generally discouraged to turn it on unless you are + very sure you have no other choice and the attack is a + real threat for your applications. + + + + Care should be particularly taken if you want to use this + option for addresses within 127.0.0.0/8. + These addresses are obviously "internal", but many + applications conventionally rely on a DNS mapping from + some name to such an address. + Filtering out DNS records containing this address + spuriously can break such applications. + + + + + Response Policy Zone (RPZ) Rewriting + + BIND 9 includes an intentionally limited + mechanism to modify DNS responses for recursive requests + similar to email anti-spam DNS blacklists. + All response policy zones are named in the + response-policy option for the view or among the + global options if there is no response-policy option for the view. + + + + The rules encoded in a response policy zone (RPZ) are applied + only to responses to queries that ask for recursion (RD=1). + RPZs are normal DNS zones containing RRsets + that can be queried normally if allowed. + It is usually best to restrict those queries with something like + allow-query {none; }; or + allow-query { 127.0.0.1; };. + + + + There are four kinds of RPZ rewrite rules. QNAME rules are + applied to query names in requests and to targets of CNAME + records resolved in the process of generating the response. + The owner name of a QNAME rule is the query name relativized + to the RPZ. + The records in a rewrite rule are usually A, AAAA, or special + CNAMEs, but can be any type except DNAME. + + + + IP rules are triggered by addresses in A and AAAA records. + All IP addresses in A or AAAA RRsets are tested and the rule + longest prefix is applied. Ties between rules with equal prefixes + are broken in favor of the first RPZ mentioned in the + response-policy option. + The rule matching the smallest IP address is chosen among equal + prefix rules from a single RPZ. + IP rules are expressed in RRsets with owner names that are + subdomains of rpz-ip and encoding an IP address block, reversed + as in IN-ARPA. + prefix.B.B.B.B with prefix between 1 and 32 and B between 1 and 255 + encodes an IPv4 address. + IPv6 addresses are encoded by with prefix.W.W.W.W.W.W.W.W or + prefix.WORDS.zz.WORDS. The words in the standard IPv6 text + representation are reversed, "::" is replaced with ".zz.", + and ":" becomes ".". + + + + NSDNAME rules match names in NS RRsets for the response or a + parent. They are encoded as subdomains of rpz-nsdomain relativized + to the RPZ origin name. + + + + NSIP rules match IP addresses in A and AAAA RRsets for names of + responsible servers or the names that can be matched by NSDNAME + rules. The are encoded like IP rules except as subdomains of + rpz-nsip. + + + + Authority verification issues and variations in authority data in + the current version of BIND 9 can cause + inconsistent results from NSIP and NSDNAME. So they are available + only when BIND is built with the + --enable-rpz-nsip or + --enable-rpz-nsdname options + on the "configure" command line. + + + + Four policies can be expressed. + The NXDOMAIN policy causes a NXDOMAIN response + and is expressed with an RRset consisting of a single CNAME + whose target is the root domain (.). + NODATA generates NODATA or ANCOUNT=1 regardless + of query type. + It is expressed with a CNAME whose target is the wildcard + top-level domain (*.). + The NO-OP policy does not change the response + and is used to "poke holes" in policies for larger CIDR blocks or in + zones named later in the response-policy option. + The NO-OP policy is expressed by a CNAME with a target consisting + of the variable part of the owner name, such as "example.com." for + a QNAME rule or "128.1.0.0.127." for an IP rule. + The CNAME policy is used to replace the RRsets + of response. + A and AAAA RRsets are most common and useful to capture + an evil domain in a walled garden, but any valid set of RRsets + is possible. + + + + All of the policies in an RPZ can be overridden with a + policy clause. + given says "do not override." + no-op says "do nothing" regardless of the policy + in RPZ records. + nxdomain causes all RPZ rules to generate + NXDOMAIN results. + nodata gives nodata. + cname domain causes all RPZ rules to act as if + the consisted of a "cname domain" record. + + + + For example, you might use this option statement + +response-policy { zone "bl"; }; + + and this zone statement + +zone "bl" {type master; file "example/bl"; allow-query {none;}; }; + + with this zone file + +$TTL 1H +@ SOA LOCALHOST. named-mgr.example.com (1 1h 15m 30d 2h) + +; QNAME rules +nxdomain.domain.com CNAME . +nodata.domain.com CNAME *. +bad.domain.com A 10.0.0.1 + AAAA 2001:2::1 +ok.domain.com CNAME ok.domain.com. +*.badzone.domain.com CNAME garden.example.com. + +; IP rules rewriting all answers for 127/8 except 127.0.0.1 +8.0.0.0.127.ip CNAME . +32.1.0.0.127.ip CNAME 32.1.0.0.127. + +; NSDNAME and NSIP rules +ns.domain.com.rpz-nsdname CNAME . +48.zz.2.2001.rpz-nsip CNAME . + + @@ -8327,8 +9356,10 @@ XXX: end of RFC1918 addresses #defined out --> transfer-source-v6 (ip6_addr | *) port ip_port ; notify-source (ip4_addr | *) port ip_port ; notify-source-v6 (ip6_addr | *) port ip_port ; - query-source address ( ip_addr | * ) port ( ip_port | * ) ; - query-source-v6 address ( ip_addr | * ) port ( ip_port | * ) ; + query-source address ( ip_addr | * ) + port ( ip_port | * ) ; + query-source-v6 address ( ip_addr | * ) + port ( ip_port | * ) ; use-queryport-pool yes_or_no; queryport-pool-ports number; queryport-pool-updateinterval number; @@ -8526,7 +9557,8 @@ XXX: end of RFC1918 addresses #defined out --> <command>statistics-channels</command> Statement Grammar statistics-channels { - [ inet ( ip_addr | * ) [ port ip_port ] [allow { address_match_list } ]; ] + [ inet ( ip_addr | * ) [ port ip_port ] + [ allow { address_match_list } ]; ] [ inet ...; ] }; @@ -8590,7 +9622,7 @@ XXX: end of RFC1918 addresses #defined out --> - + <command>trusted-keys</command> Statement Grammar trusted-keys { @@ -8632,6 +9664,136 @@ XXX: end of RFC1918 addresses #defined out --> in the key data, so the configuration may be split up into multiple lines. + + trusted-keys may be set at the top level + of named.conf or within a view. If it is + set in both places, they are additive: keys defined at the top + level are inherited by all views, but keys defined in a view + are only used within that view. + + + + + <command>managed-keys</command> Statement Grammar + +managed-keys { + string initial-key number number number string ; + string initial-key number number number string ; ... +}; + + + + + <command>managed-keys</command> Statement Definition + and Usage + + The managed-keys statement, like + trusted-keys, defines DNSSEC + security roots. The difference is that + managed-keys can be kept up to date + automatically, without intervention from the resolver + operator. + + + Suppose, for example, that a zone's key-signing + key was compromised, and the zone owner had to revoke and + replace the key. A resolver which had the old key in a + trusted-keys statement would be + unable to validate this zone any longer; it would + reply with a SERVFAIL response code. This would + continue until the resolver operator had updated the + trusted-keys statement with the new key. + + + If, however, the zone were listed in a + managed-keys statement instead, then the + zone owner could add a "stand-by" key to the zone in advance. + named would store the stand-by key, and + when the original key was revoked, named + would be able to transition smoothly to the new key. It would + also recognize that the old key had been revoked, and cease + using that key to validate answers, minimizing the damage that + the compromised key could do. + + + A managed-keys statement contains a list of + the keys to be managed, along with information about how the + keys are to be initialized for the first time. The only + initialization method currently supported (as of + BIND 9.7.0) is initial-key. + This means the managed-keys statement must + contain a copy of the initializing key. (Future releases may + allow keys to be initialized by other methods, eliminating this + requirement.) + + + Consequently, a managed-keys statement + appears similar to a trusted-keys, differing + in the presence of the second field, containing the keyword + initial-key. The difference is, whereas the + keys listed in a trusted-keys continue to be + trusted until they are removed from + named.conf, an initializing key listed + in a managed-keys statement is only trusted + once: for as long as it takes to load the + managed key database and start the RFC 5011 key maintenance + process. + + + The first time named runs with a managed key + configured in named.conf, it fetches the + DNSKEY RRset directly from the zone apex, and validates it + using the key specified in the managed-keys + statement. If the DNSKEY RRset is validly signed, then it is + used as the basis for a new managed keys database. + + + From that point on, whenever named runs, it + sees the managed-keys statement, checks to + make sure RFC 5011 key maintenance has already been initialized + for the specified domain, and if so, it simply moves on. The + key specified in the managed-keys is not + used to validate answers; it has been superseded by the key or + keys stored in the managed keys database. + + + The next time named runs after a name + has been removed from the + managed-keys statement, the corresponding + zone will be removed from the managed keys database, + and RFC 5011 key maintenance will no longer be used for that + domain. + + + named only maintains a single managed keys + database; consequently, unlike trusted-keys, + managed-keys may only be set at the top + level of named.conf, not within a view. + + + In the current implementation, the managed keys database is + stored as a master-format zone file called + managed-keys.bind. When the key database + is changed, the zone is updated. As with any other dynamic + zone, changes will be written into a journal file, + managed-keys.bind.jnl. They are committed + to the master file as soon as possible afterward; in the case + of the managed key database, this will usually occur within 30 + seconds. So, whenever named is using + automatic key maintenance, those two files can be expected to + exist in the working directory. (For this reason among others, + the working directory should be always be writable by + named.) + + + If the dnssec-lookaside option is + set to auto, named + will automatically initialize a managed key for the + zone dlv.isc.org. The key that is + used to initialize the key maintenance process is built + into named, and can be overridden + from bindkeys-file. + @@ -8746,11 +9908,12 @@ XXX: end of RFC1918 addresses #defined out --> // This should match our internal networks. match-clients { 10.0.0.0/8; }; - // Provide recursive service to internal clients only. + // Provide recursive service to internal + // clients only. recursion yes; - // Provide a complete view of the example.com zone - // including addresses of internal hosts. + // Provide a complete view of the example.com + // zone including addresses of internal hosts. zone "example.com" { type master; file "example-internal.db"; @@ -8758,14 +9921,15 @@ XXX: end of RFC1918 addresses #defined out --> }; view "external" { - // Match all clients not matched by the previous view. + // Match all clients not matched by the + // previous view. match-clients { any; }; // Refuse recursive service to external clients. recursion no; - // Provide a restricted view of the example.com zone - // containing only publicly accessible hosts. + // Provide a restricted view of the example.com + // zone containing only publicly accessible hosts. zone "example.com" { type master; file "example-external.db"; @@ -8784,8 +9948,9 @@ view "external" { allow-query-on { address_match_list }; allow-transfer { address_match_list }; allow-update { address_match_list }; - update-policy { update_policy_rule ... }; - also-notify { ip_addr port ip_port ; ip_addr port ip_port ; ... }; + update-policy local | { update_policy_rule ... }; + also-notify { ip_addr port ip_port ; + ip_addr port ip_port ; ... }; check-names (warn|fail|ignore) ; check-mx (warn|fail|ignore) ; check-wildcard yes_or_no; @@ -8821,6 +9986,7 @@ view "external" { min-retry-time number ; max-retry-time number ; key-directory path_name; + auto-dnssec allow|maintain|create|off; zero-no-soa-ttl yes_or_no ; }; @@ -8832,8 +9998,11 @@ zone zone_name class allow-transfer { address_match_list }; allow-update-forwarding { address_match_list }; update-check-ksk yes_or_no; + dnssec-dnskey-kskonly yes_or_no; + dnssec-secure-to-insecure yes_or_no ; try-tcp-refresh yes_or_no; - also-notify { ip_addr port ip_port ; ip_addr port ip_port ; ... }; + also-notify { ip_addr port ip_port ; + ip_addr port ip_port ; ... }; check-names (warn|fail|ignore) ; dialup dialup_option ; file string ; @@ -8846,7 +10015,9 @@ zone zone_name class ixfr-from-differences yes_or_no; ixfr-tmp-file string ; maintain-ixfr-base yes_or_no ; - masters port ip_port { ( masters_list | ip_addr port ip_port key key ) ; ... }; + masters port ip_port { ( masters_list | ip_addr + port ip_port + key key ) ; ... }; max-ixfr-log-size number ; max-transfer-idle-in number ; max-transfer-idle-out number ; @@ -8859,7 +10030,8 @@ zone zone_name class transfer-source (ip4_addr | *) port ip_port ; transfer-source-v6 (ip6_addr | *) port ip_port ; alt-transfer-source (ip4_addr | *) port ip_port ; - alt-transfer-source-v6 (ip6_addr | *) port ip_port ; + alt-transfer-source-v6 (ip6_addr | *) + port ip_port ; use-alt-transfer-source yes_or_no; notify-source (ip4_addr | *) port ip_port ; notify-source-v6 (ip6_addr | *) port ip_port ; @@ -8877,7 +10049,7 @@ zone zone_name classstring ; delegation-only yes_or_no ; - check-names (warn|fail|ignore) ; // Not Implemented. + check-names (warn|fail|ignore) ; // Not Implemented. }; zone zone_name class { @@ -8891,14 +10063,18 @@ zone zone_name class masterfile-format (text|raw) ; forward (only|first) ; forwarders { ip_addr port ip_port ; ... }; - masters port ip_port { ( masters_list | ip_addr port ip_port key key ) ; ... }; + masters port ip_port { ( masters_list | ip_addr + port ip_port + key key ) ; ... }; max-transfer-idle-in number ; max-transfer-time-in number ; pubkey number number number string ; transfer-source (ip4_addr | *) port ip_port ; - transfer-source-v6 (ip6_addr | *) port ip_port ; + transfer-source-v6 (ip6_addr | *) + port ip_port ; alt-transfer-source (ip4_addr | *) port ip_port ; - alt-transfer-source-v6 (ip6_addr | *) port ip_port ; + alt-transfer-source-v6 (ip6_addr | *) + port ip_port ; use-alt-transfer-source yes_or_no; zone-statistics yes_or_no ; database string ; @@ -8910,6 +10086,14 @@ zone zone_name classzone_name class { + type static-stub; + allow-query { address_match_list }; + server-addresses { ip_addr ; ... }; + server-names { namelist }; + zone-statistics yes_or_no ; +}; + +zone zone_name class { type forward; forward (only|first) ; forwarders { ip_addr port ip_port ; ... }; @@ -9056,6 +10240,55 @@ zone zone_name class + static-stub + + + + + A static-stub zone is similar to a stub zone + with the following exceptions: + the zone data is statically configured, rather + than transferred from a master server; + when recursion is necessary for a query that + matches a static-stub zone, the locally + configured data (nameserver names and glue addresses) + is always used even if different authoritative + information is cached. + + + Zone data is configured via the + server-addresses and + server-names zone options. + + + The zone data is maintained in the form of NS + and (if necessary) glue A or AAAA RRs + internally, which can be seen by dumping zone + databases by rndc dumpdb -all. + The configured RRs are considered local configuration + parameters rather than public data. + Non recursive queries (i.e., those with the RD + bit off) to a static-stub zone are therefore + prohibited and will be responded with REFUSED. + + + Since the data is statically configured, no + zone maintenance action takes place for a static-stub + zone. + For example, there is no periodic refresh + attempt, and an incoming notify message + will be rejected with an rcode of NOTAUTH. + + + Each static-stub zone is configured with + internally generated NS and (if necessary) + glue A or AAAA RRs + + + + + + forward @@ -9270,6 +10503,7 @@ zone zone_name classmaster zones the default is fail. For slave zones the default is warn. + It is not implemented for hint zones. @@ -9335,6 +10569,16 @@ zone zone_name class + dnssec-dnskey-kskonly + + + See the description of + dnssec-dnskey-kskonly in . + + + + + try-tcp-refresh @@ -9569,6 +10813,84 @@ zone zone_name class + server-addresses + + + Only meaningful for static-stub zones. + This is a list of IP addresses to which queries + should be sent in recursive resolution for the + zone. + A non empty list for this option will internally + configure the apex NS RR with associated glue A or + AAAA RRs. + + + For example, if "example.com" is configured as a + static-stub zone with 192.0.2.1 and 2001:db8::1234 + in a server-addresses option, + the following RRs will be internally configured. + +example.com. NS example.com. +example.com. A 192.0.2.1 +example.com. AAAA 2001:db8::1234 + + These records are internally used to resolve + names under the static-stub zone. + For instance, if the server receives a query for + "www.example.com" with the RD bit on, the server + will initiate recursive resolution and send + queries to 192.0.2.1 and/or 2001:db8::1234. + + + + + + server-names + + + Only meaningful for static-stub zones. + This is a list of domain names of nameservers that + act as authoritative servers of the static-stub + zone. + These names will be resolved to IP addresses when + named needs to send queries to + these servers. + To make this supplemental resolution successful, + these names must not be a subdomain of the origin + name of static-stub zone. + That is, when "example.net" is the origin of a + static-stub zone, "ns.example" and + "master.example.com" can be specified in the + server-names option, but + "ns.example.net" cannot, and will be rejected by + the configuration parser. + + + A non empty list for this option will internally + configure the apex NS RR with the specified names. + For example, if "example.com" is configured as a + static-stub zone with "ns1.example.net" and + "ns2.example.net" + in a server-names option, + the following RRs will be internally configured. + +example.com. NS ns1.example.net. +example.com. NS ns2.example.net. + + + These records are internally used to resolve + names under the static-stub zone. + For instance, if the server receives a query for + "www.example.com" with the RD bit on, the server + initiate recursive resolution, + resolve "ns1.example.net" and/or + "ns2.example.net" to IP addresses, and then send + queries to (one or more of) these addresses. + + + + + sig-validity-interval @@ -9716,6 +11038,51 @@ zone zone_name class + auto-dnssec + + + Zones configured for dynamic DNS may also use this + option to allow varying levels of automatic DNSSEC key + management. There are four possible settings: + + + auto-dnssec allow; permits + keys to be updated and the zone fully re-signed + whenever the user issues the command rndc sign + zonename. + + + auto-dnssec maintain; includes the + above, but also automatically adjusts the zone's DNSSEC + keys on schedule, according to the keys' timing metadata + (see and + ). The command + rndc sign + zonename causes + named to load keys from the key + repository and sign the zone with all keys that are + active. + rndc loadkeys + zonename causes + named to load keys from the key + repository and schedule key maintenance events to occur + in the future, but it does not sign the full zone + immediately. + + + auto-dnssec create; includes the + above, but also allows named + to create new keys in the key repository when needed. + (NOTE: This option is not yet implemented; the syntax is + being reserved for future use.) + + + The default setting is auto-dnssec off. + + + + + multi-master @@ -9735,6 +11102,16 @@ zone zone_name class + + dnssec-secure-to-insecure + + + See the description of + dnssec-secure-to-insecure in . + + + + @@ -9753,15 +11130,14 @@ zone zone_name class - The update-policy clause is new - in BIND 9 and allows more fine-grained - control over what updates are allowed. A set of rules - is specified, where each rule either grants or denies - permissions for one or more names to be updated by - one or more identities. If the dynamic update request - message is signed (that is, it includes either a TSIG - or SIG(0) record), the identity of the signer can be - determined. + The update-policy clause + allows more fine-grained control over what updates are + allowed. A set of rules is specified, where each rule + either grants or denies permissions for one or more + names to be updated by one or more identities. If + the dynamic update request message is signed (that is, + it includes either a TSIG or SIG(0) record), the + identity of the signer can be determined. Rules are specified in the update-policy @@ -9773,24 +11149,53 @@ zone zone_name class + + There is a pre-defined update-policy + rule which can be switched on with the command + update-policy local;. + Switching on this rule in a zone causes + named to generate a TSIG session + key and place it in a file, and to allow that key + to update the zone. (By default, the file is + /var/run/named/session.key, the key + name is "local-ddns" and the key algorithm is HMAC-SHA256, + but these values are configurable with the + session-keyfile, + session-keyname and + session-keyalg options, respectively). + + + A client running on the local system, and with appropriate + permissions, may read that file and use the key to sign update + requests. The zone's update policy will be set to allow that + key to change any record within the zone. Assuming the + key name is "local-ddns", this policy is equivalent to: + + + update-policy { grant local-ddns zonesub any; }; + + + + The command nsupdate -l sends update + requests to localhost, and signs them using the session key. + - This is how a rule definition looks: + Other rule definitions look like this: -( grant | deny ) identity nametype name types +( grant | deny ) identity nametype name types Each rule grants or denies privileges. Once a message has successfully matched a rule, the operation is immediately - granted - or denied and no further rules are examined. A rule is matched - when the signer matches the identity field, the name matches the - name field in accordance with the nametype field, and the type - matches - the types specified in the type field. + granted or denied and no further rules are examined. A rule + is matched when the signer matches the identity field, the + name matches the name field in accordance with the nametype + field, and the type matches the types specified in the type + field. No signer is required for tcp-self @@ -9817,7 +11222,7 @@ zone zone_name class - The nametype field has 12 + The nametype field has 13 values: name, subdomain, wildcard, self, @@ -9825,7 +11230,8 @@ zone zone_name classkrb5-self, ms-self, krb5-subdomain, ms-subdomain, - tcp-self and 6to4-self. + tcp-self, 6to4-self, + zonesub, and external. @@ -9863,6 +11269,28 @@ zone zone_name class + zonesub + + + + This rule is similar to subdomain, except that + it matches when the name being updated is a + subdomain of the zone in which the + update-policy statement + appears. This obviates the need to type the zone + name twice, and enables the use of a standard + update-policy statement in + multiple zones without modification. + + + When this rule is used, the + name field is omitted. + + + + + + wildcard @@ -9950,7 +11378,7 @@ zone zone_name class Allow the 6to4 prefix to be update by any TCP - conection from the 6to4 network or from the + connection from the 6to4 network or from the corresponding IPv4 address. This is intended to allow NS or DNAME RRsets to be added to the reverse tree. @@ -9961,14 +11389,56 @@ zone zone_name class + + + + external + + + + This rule allows named + to defer the decision of whether to allow a + given update to an external daemon. + + + The method of communicating with the daemon is + specified in the identity + field, the format of which is + "local:path", + where path is the location + of a UNIX-domain socket. (Currently, "local" is the + only supported mechanism.) + + + Requests to the external daemon are sent over the + UNIX-domain socket as datagrams with the following + format: + + + Protocol version number (4 bytes, network byte order, currently 1) + Request length (4 bytes, network byte order) + Signer (null-terminated string) + Name (null-terminated string) + TCP source address (null-terminated string) + Rdata type (null-terminated string) + Key (null-terminated string) + TKEY token length (4 bytes, network byte order) + TKEY token (remainder of packet) + + The daemon replies with a four-byte value in + network byte order, containing either 0 or 1; 0 + indicates that the specified update is not + permitted, and 1 indicates that it is. + + + In all cases, the name - field must - specify a fully-qualified domain name. + field must specify a fully-qualified domain name. @@ -11381,7 +12851,7 @@ WWW.EXAMPLE.COM. CNAME MAIN-SERVER.EXAMPLE.COM. $ORIGIN 0.0.192.IN-ADDR.ARPA. -$GENERATE 1-2 0 NS SERVER$.EXAMPLE. +$GENERATE 1-2 @ NS SERVER$.EXAMPLE. $GENERATE 1-127 $ CNAME $.0 @@ -11396,6 +12866,32 @@ $GENERATE 1-127 $ CNAME $.0 127.0.0.192.IN-ADDR.ARPA. CNAME 127.0.0.0.192.IN-ADDR.ARPA. + + Generate a set of A and MX records. Note the MX's right hand + side is a quoted string. The quotes will be stripped when the + right hand side is processed. + + + +$ORIGIN EXAMPLE. +$GENERATE 1-127 HOST-$ A 1.2.3.$ +$GENERATE 1-127 HOST-$ MX "0 ." + + + is equivalent to + + +HOST-1.EXAMPLE. A 1.2.3.1 +HOST-1.EXAMPLE. MX 0 . +HOST-2.EXAMPLE. A 1.2.3.2 +HOST-2.EXAMPLE. MX 0 . +HOST-3.EXAMPLE. A 1.2.3.3 +HOST-3.EXAMPLE. MX 0 . +... +HOST-127.EXAMPLE. A 1.2.3.127 +HOST-127.EXAMPLE. MX 0 . + + @@ -11445,20 +12941,30 @@ $GENERATE 1-127 $ CNAME $.0 Available output forms are decimal (d), octal - (o) and hexadecimal + (o), hexadecimal (x or X - for uppercase). The default modifier is + for uppercase) and nibble + (n or N\ + for uppercase). The default modifier is ${0,0,d}. If the lhs is not absolute, the current $ORIGIN is appended to the name. - - For compatibility with earlier versions, $$ is still - recognized as indicating a literal $ in the output. - - - + + In nibble mode the value will be treated as + if it was a reversed hexadecimal string + with each hexadecimal digit as a separate + label. The width field includes the label + separator. + + + For compatibility with earlier versions, + $$ is still recognized as + indicating a literal $ in the output. + + + ttl @@ -11497,8 +13003,7 @@ $GENERATE 1-127 $ CNAME $.0 - At present the only supported types are - PTR, CNAME, DNAME, A, AAAA and NS. + Any valid type. @@ -11508,8 +13013,7 @@ $GENERATE 1-127 $ CNAME $.0 - rhs is a domain name. It is processed - similarly to lhs. + rhs, optionally, quoted string. @@ -11668,9 +13172,12 @@ $GENERATE 1-127 $ CNAME $.0 - The number of RRsets per RR type (positive - or negative) and nonexistent names stored in the - cache database. + The number of RRsets per RR type and nonexistent + names stored in the cache database. + If the exclamation mark (!) is printed for a RR + type, it means that particular type of RRset is + known to be nonexistent (this is also known as + "NXRRSET"). Maintained per view. @@ -12639,6 +14146,13 @@ $GENERATE 1-127 $ CNAME $.0 Mismatch responses received. + The DNS ID, response's source address, + and/or the response's source port does not + match what was expected. + (The port must be 53 or as defined by + the port option.) + This may be an indication of a cache + poisoning attempt. @@ -13106,14 +14620,17 @@ $GENERATE 1-127 $ CNAME $.0 -// Set up an ACL named "bogusnets" that will block RFC1918 space -// and some reserved space, which is commonly used in spoofing attacks. +// Set up an ACL named "bogusnets" that will block +// RFC1918 space and some reserved space, which is +// commonly used in spoofing attacks. acl bogusnets { - 0.0.0.0/8; 1.0.0.0/8; 2.0.0.0/8; 192.0.2.0/24; 224.0.0.0/3; - 10.0.0.0/8; 172.16.0.0/12; 192.168.0.0/16; + 0.0.0.0/8; 1.0.0.0/8; 2.0.0.0/8; 192.0.2.0/24; + 224.0.0.0/3; 10.0.0.0/8; 172.16.0.0/12; + 192.168.0.0/16; }; -// Set up an ACL called our-nets. Replace this with the real IP numbers. +// Set up an ACL called our-nets. Replace this with the +// real IP numbers. acl our-nets { x.x.x.x/24; x.x.x.x/21; }; options { ... @@ -14756,8 +16273,12 @@ zone "example.com" { + + + + Manual pages @@ -14765,15 +16286,23 @@ zone "example.com" { + + + - + + + + + + diff --git a/doc/arm/Bv9ARM.ch01.html b/doc/arm/Bv9ARM.ch01.html index 4cdfb09..ff2c5ce 100644 --- a/doc/arm/Bv9ARM.ch01.html +++ b/doc/arm/Bv9ARM.ch01.html @@ -1,5 +1,5 @@ - + @@ -45,17 +45,17 @@ @@ -71,7 +71,7 @@

    -Scope of Document

    +Scope of Document

    The Berkeley Internet Name Domain (BIND) implements a @@ -82,12 +82,12 @@ system administrators.

    - This version of the manual corresponds to BIND version 9.6. + This version of the manual corresponds to BIND version 9.7.

    -Organization of This Document

    +Organization of This Document

    In this document, Chapter 1 introduces the basic DNS and BIND concepts. Chapter 2 @@ -116,7 +116,7 @@

    -Conventions Used in This Document

    +Conventions Used in This Document

    In this document, we use the following general typographic conventions: @@ -243,7 +243,7 @@

    -The Domain Name System (DNS)

    +The Domain Name System (DNS)

    The purpose of this document is to explain the installation and upkeep of the BIND (Berkeley Internet @@ -253,7 +253,7 @@

    -DNS Fundamentals

    +DNS Fundamentals

    The Domain Name System (DNS) is a hierarchical, distributed database. It stores information for mapping Internet host names to @@ -275,7 +275,7 @@

    -Domains and Domain Names

    +Domains and Domain Names

    The data stored in the DNS is identified by domain names that are organized as a tree according to organizational or administrative boundaries. Each node of the tree, @@ -321,7 +321,7 @@

    -Zones

    +Zones

    To properly operate a name server, it is important to understand the difference between a zone @@ -374,7 +374,7 @@

    -Authoritative Name Servers

    +Authoritative Name Servers

    Each zone is served by at least one authoritative name server, @@ -391,7 +391,7 @@

    -The Primary Master

    +The Primary Master

    The authoritative server where the master copy of the zone data is maintained is called the @@ -411,7 +411,7 @@

    -Slave Servers

    +Slave Servers

    The other authoritative servers, the slave servers (also known as secondary servers) @@ -427,7 +427,7 @@

    -Stealth Servers

    +Stealth Servers

    Usually all of the zone's authoritative servers are listed in NS records in the parent zone. These NS records constitute @@ -462,7 +462,7 @@

    -Caching Name Servers

    +Caching Name Servers

    The resolver libraries provided by most operating systems are stub resolvers, meaning that they are not @@ -489,7 +489,7 @@

    -Forwarding

    +Forwarding

    Even a caching name server does not necessarily perform the complete recursive lookup itself. Instead, it can @@ -516,7 +516,7 @@

    -Name Servers in Multiple Roles

    +Name Servers in Multiple Roles

    The BIND name server can simultaneously act as diff --git a/doc/arm/Bv9ARM.ch02.html b/doc/arm/Bv9ARM.ch02.html index 5181a2a..a9fde32 100644 --- a/doc/arm/Bv9ARM.ch02.html +++ b/doc/arm/Bv9ARM.ch02.html @@ -1,5 +1,5 @@ - + @@ -45,16 +45,16 @@

    -Hardware requirements

    +Hardware requirements

    DNS hardware requirements have traditionally been quite modest. @@ -73,7 +73,7 @@

    -CPU Requirements

    +CPU Requirements

    CPU requirements for BIND 9 range from i486-class machines @@ -84,7 +84,7 @@

    -Memory Requirements

    +Memory Requirements

    The memory of the server has to be large enough to fit the cache and zones loaded off disk. The max-cache-size @@ -107,7 +107,7 @@

    -Name Server Intensive Environment Issues

    +Name Server Intensive Environment Issues

    For name server intensive environments, there are two alternative configurations that may be used. The first is where clients and @@ -124,13 +124,13 @@

    -Supported Operating Systems

    +Supported Operating Systems

    ISC BIND 9 compiles and runs on a large number - of Unix-like operating systems and on NT-derived versions of - Microsoft Windows such as Windows 2000 and Windows XP. For an - up-to-date + of Unix-like operating systems and on + Microsoft Windows Server 2003 and 2008, and Windows XP and Vista. + For an up-to-date list of supported systems, see the README file in the top level directory of the BIND 9 source distribution. diff --git a/doc/arm/Bv9ARM.ch03.html b/doc/arm/Bv9ARM.ch03.html index 454fdd6..e01d69e 100644 --- a/doc/arm/Bv9ARM.ch03.html +++ b/doc/arm/Bv9ARM.ch03.html @@ -1,5 +1,5 @@ - + @@ -47,14 +47,14 @@

    Sample Configurations
    -
    A Caching-only Name Server
    -
    An Authoritative-only Name Server
    +
    A Caching-only Name Server
    +
    An Authoritative-only Name Server
    -
    Load Balancing
    -
    Name Server Operations
    +
    Load Balancing
    +
    Name Server Operations
    -
    Tools for Use With the Name Server Daemon
    -
    Signals
    +
    Tools for Use With the Name Server Daemon
    +
    Signals
    @@ -68,7 +68,7 @@ Sample Configurations

    -A Caching-only Name Server

    +A Caching-only Name Server

    The following sample configuration is appropriate for a caching-only name server for use by clients internal to a corporation. All @@ -82,10 +82,13 @@ // Two corporate subnets we wish to allow queries from. acl corpnets { 192.168.4.0/24; 192.168.7.0/24; }; options { - directory "/etc/namedb"; // Working directory + // Working directory + directory "/etc/namedb"; + allow-query { corpnets; }; }; -// Provide a reverse mapping for the loopback address 127.0.0.1 +// Provide a reverse mapping for the loopback +// address 127.0.0.1 zone "0.0.127.in-addr.arpa" { type master; file "localhost.rev"; @@ -95,7 +98,7 @@ zone "0.0.127.in-addr.arpa" {

    -An Authoritative-only Name Server

    +An Authoritative-only Name Server

    This sample configuration is for an authoritative-only server that is the master server for "example.com" @@ -103,13 +106,18 @@ zone "0.0.127.in-addr.arpa" {

     options {
    -     directory "/etc/namedb";           // Working directory
    -     allow-query-cache { none; };       // Do not allow access to cache
    -     allow-query { any; };              // This is the default
    -     recursion no;                      // Do not provide recursive service
    +     // Working directory
    +     directory "/etc/namedb";
    +     // Do not allow access to cache
    +     allow-query-cache { none; };
    +     // This is the default
    +     allow-query { any; };
    +     // Do not provide recursive service
    +     recursion no;
     };
     
    -// Provide a reverse mapping for the loopback address 127.0.0.1
    +// Provide a reverse mapping for the loopback
    +// address 127.0.0.1
     zone "0.0.127.in-addr.arpa" {
          type master;
          file "localhost.rev";
    @@ -119,7 +127,8 @@ zone "0.0.127.in-addr.arpa" {
     zone "example.com" {
          type master;
          file "example.com.db";
    -     // IP addresses of slave servers allowed to transfer example.com
    +     // IP addresses of slave servers allowed to
    +     // transfer example.com
          allow-transfer {
               192.168.4.14;
               192.168.5.53;
    @@ -137,7 +146,7 @@ zone "eng.example.com" {
     
     

    -Load Balancing

    +Load Balancing

    A primitive form of load balancing can be achieved in the DNS by using multiple records @@ -273,17 +282,17 @@ zone "eng.example.com" {

    For more detail on ordering responses, check the - rrset-order substatement in the + rrset-order sub-statement in the options statement, see RRset Ordering.

    -Name Server Operations

    +Name Server Operations

    -Tools for Use With the Name Server Daemon

    +Tools for Use With the Name Server Daemon

    This section describes several indispensable diagnostic, administrative and monitoring tools available to the system @@ -463,6 +472,60 @@ zone "eng.example.com" {

    Retransfer the given zone from the master.

    +
    sign zone + [class + [view]]
    +
    +

    + Fetch all DNSSEC keys for the given zone + from the key directory (see + key-directory in + the section called “options Statement Definition and + Usage”). If they are within + their publication period, merge them into the + zone's DNSKEY RRset. If the DNSKEY RRset + is changed, then the zone is automatically + re-signed with the new key set. +

    +

    + This command requires that the + auto-dnssec zone option to be set + to allow, + maintain, or + create, and also requires + the zone to be configured to allow dynamic DNS. + See the section called “Dynamic Update Policies” for + more details. +

    +
    +
    loadkeys zone + [class + [view]]
    +
    +

    + Fetch all DNSSEC keys for the given zone + from the key directory (see + key-directory in + the section called “options Statement Definition and + Usage”). If they are within + their publication period, merge them into the + zone's DNSKEY RRset. Unlike rndc + sign, however, the zone is not + immediately re-signed by the new keys, but is + allowed to incrementally re-sign over time. +

    +

    + This command requires that the + auto-dnssec zone option to + be set to maintain or + create, and also requires + the zone to be configured to allow dynamic DNS. + See the section called “Dynamic Update Policies” for + more details. +

    +
    freeze [zone [class @@ -536,6 +599,14 @@ zone "eng.example.com" { specified, all views are dumped.

    +
    secroots + [view ...]
    +

    + Dump the server's security roots to the secroots + file for the specified views. If no view is + specified, security roots for all + views are dumped. +

    stop [-p]

    Stop the server, making sure any recent changes @@ -599,6 +670,57 @@ zone "eng.example.com" { set to yes to be effective. It defaults to enabled.

    +
    addzone + zone + [class + [view]] + configuration +
    +
    +

    + Add a zone while the server is running. This + command requires the + allow-new-zones option to be set + to yes. The + configuration string + specified on the command line is the zone + configuration text that would ordinarily be + placed in named.conf. +

    +

    + The configuration is saved in a file called + hash.nzf, + where hash is a + cryptographic hash generated from the name of + the view. When named is + restarted, the file will be loaded into the view + configuration, so that zones that were added + can persist after a restart. +

    +

    + This sample addzone command + would add the zone example.com + to the default view: +

    +

    +$ rndc addzone example.com '{ type master; file "example.com.db"; };' +

    +

    + (Note the brackets and semi-colon around the zone + configuration text.) +

    +
    +
    delzone + zone + [class + [view]] +
    +

    + Delete a zone while the server is running. + Only zones that were originally added via + rndc addzone can be deleted + in this matter. +

    A configuration file is required, since all @@ -699,7 +821,8 @@ zone "eng.example.com" {

     key rndc_key {
          algorithm "hmac-md5";
    -     secret "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K";
    +     secret
    +       "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K";
     };
     options {
          default-server 127.0.0.1;
    @@ -721,7 +844,8 @@ options {
                     

     controls {
    -        inet 127.0.0.1 allow { localhost; } keys { rndc_key; };
    +        inet 127.0.0.1
    +            allow { localhost; } keys { rndc_key; };
     };
     

    @@ -749,7 +873,7 @@ controls {

    -Signals

    +Signals

    Certain UNIX signals cause the name server to take specific actions, as described in the following table. These signals can diff --git a/doc/arm/Bv9ARM.ch04.html b/doc/arm/Bv9ARM.ch04.html index 7b8a200..77b74cb 100644 --- a/doc/arm/Bv9ARM.ch04.html +++ b/doc/arm/Bv9ARM.ch04.html @@ -1,5 +1,5 @@ - + @@ -49,29 +49,59 @@

    Dynamic Update
    The journal file
    Incremental Zone Transfers (IXFR)
    -
    Split DNS
    -
    Example split DNS setup
    +
    Split DNS
    +
    Example split DNS setup
    TSIG
    -
    Generate Shared Keys for Each Pair of Hosts
    -
    Copying the Shared Secret to Both Machines
    -
    Informing the Servers of the Key's Existence
    -
    Instructing the Server to Use the Key
    -
    TSIG Key Based Access Control
    -
    Errors
    +
    Generate Shared Keys for Each Pair of Hosts
    +
    Copying the Shared Secret to Both Machines
    +
    Informing the Servers of the Key's Existence
    +
    Instructing the Server to Use the Key
    +
    TSIG Key Based Access Control
    +
    Errors
    -
    TKEY
    -
    SIG(0)
    +
    TKEY
    +
    SIG(0)
    DNSSEC
    -
    Generating Keys
    -
    Signing the Zone
    -
    Configuring Servers
    +
    Generating Keys
    +
    Signing the Zone
    +
    Configuring Servers
    -
    IPv6 Support in BIND 9
    +
    DNSSEC, Dynamic Zones, and Automatic Signing
    -
    Address Lookups Using AAAA Records
    -
    Address to Name Lookups Using Nibble Format
    +
    Converting from insecure to secure
    +
    Dynamic DNS update method
    +
    Fully automatic zone signing
    +
    Private-type records
    +
    DNSKEY rollovers
    +
    Dynamic DNS update method
    +
    Automatic key rollovers
    +
    NSEC3PARAM rollovers via UPDATE
    +
    Converting from NSEC to NSEC3
    +
    Converting from NSEC3 to NSEC
    +
    Converting from secure to insecure
    +
    Periodic re-signing
    +
    NSEC3 and OPTOUT
    +
    +
    Dynamic Trust Anchor Management
    +
    +
    Validating Resolver
    +
    Authoritative Server
    +
    +
    PKCS #11 (Cryptoki) support
    +
    +
    Prerequisites
    +
    Building BIND 9 with PKCS#11
    +
    PKCS #11 Tools
    +
    Using the HSM
    +
    Specifying the engine on the command line
    +
    Running named with automatic zone re-signing
    +
    +
    IPv6 Support in BIND 9
    +
    +
    Address Lookups Using AAAA Records
    +
    Address to Name Lookups Using Nibble Format
    @@ -113,14 +143,25 @@

    Dynamic update is enabled by including an - allow-update or update-policy - clause in the zone statement. The - tkey-gssapi-credential and - tkey-domain clauses in the - options statement enable the - server to negotiate keys that can be matched against those - in update-policy or - allow-update. + allow-update or an update-policy + clause in the zone statement. +

    +

    + If the zone's update-policy is set to + local, updates to the zone + will be permitted for the key local-ddns, + which will be generated by named at startup. + See the section called “Dynamic Update Policies” for more details. +

    +

    + Dynamic updates using Kerberos signed requests can be made + using the TKEY/GSS protocol by setting either the + tkey-gssapi-keytab option, or alternatively + by setting both the tkey-gssapi-credential + and tkey-domain options. Once enabled, + Kerberos signed requests will be matched against the update + policies for the zone, using the Kerberos principal as the + signer for the request.

    Updating of secure zones (zones using DNSSEC) follows RFC @@ -215,7 +256,7 @@

    -Split DNS

    +Split DNS

    Setting up different views, or visibility, of the DNS space to internal and external resolvers is usually referred to as a @@ -245,7 +286,7 @@

    -Example split DNS setup

    +Example split DNS setup

    Let's say a company named Example, Inc. (example.com) @@ -275,7 +316,7 @@ and site2.example.com, to the servers in the DMZ. These internal servers will have complete sets of information - for site1.example.com, site2.example.com, site1.internal, + for site1.example.com, site2.example.com, site1.internal, and site2.internal.

    @@ -373,26 +414,32 @@ options { ... ... forward only; - forwarders { // forward to external servers + // forward to external servers + forwarders { bastion-ips-go-here; }; - allow-transfer { none; }; // sample allow-transfer (no one) - allow-query { internals; externals; }; // restrict query access - allow-recursion { internals; }; // restrict recursion + // sample allow-transfer (no one) + allow-transfer { none; }; + // restrict query access + allow-query { internals; externals; }; + // restrict recursion + allow-recursion { internals; }; ... ... }; -zone "site1.example.com" { // sample master zone +// sample master zone +zone "site1.example.com" { type master; file "m/site1.example.com"; - forwarders { }; // do normal iterative - // resolution (do not forward) + // do normal iterative resolution (do not forward) + forwarders { }; allow-query { internals; externals; }; allow-transfer { internals; }; }; -zone "site2.example.com" { // sample slave zone +// sample slave zone +zone "site2.example.com" { type slave; file "s/site2.example.com"; masters { 172.16.72.3; }; @@ -429,15 +476,20 @@ acl externals { bastion-ips-go-here; }; options { ... ... - allow-transfer { none; }; // sample allow-transfer (no one) - allow-query { any; }; // default query access - allow-query-cache { internals; externals; }; // restrict cache access - allow-recursion { internals; externals; }; // restrict recursion + // sample allow-transfer (no one) + allow-transfer { none; }; + // default query access + allow-query { any; }; + // restrict cache access + allow-query-cache { internals; externals; }; + // restrict recursion + allow-recursion { internals; externals; }; ... ... }; -zone "site1.example.com" { // sample slave zone +// sample slave zone +zone "site1.example.com" { type master; file "m/site1.foo.com"; allow-transfer { internals; externals; }; @@ -491,7 +543,7 @@ nameserver 172.16.72.4

    -Generate Shared Keys for Each Pair of Hosts

    +Generate Shared Keys for Each Pair of Hosts

    A shared secret is generated to be shared between host1 and host2. An arbitrary key name is chosen: "host1-host2.". The key name must @@ -499,7 +551,7 @@ nameserver 172.16.72.4

    -Automatic Generation

    +Automatic Generation

    The following command will generate a 128-bit (16 byte) HMAC-SHA256 key as described above. Longer keys are better, but shorter keys @@ -523,7 +575,7 @@ nameserver 172.16.72.4

    -Manual Generation

    +Manual Generation

    The shared secret is simply a random sequence of bits, encoded in base-64. Most ASCII strings are valid base-64 strings (assuming @@ -538,7 +590,7 @@ nameserver 172.16.72.4

    -Copying the Shared Secret to Both Machines

    +Copying the Shared Secret to Both Machines

    This is beyond the scope of DNS. A secure transport mechanism should be used. This could be secure FTP, ssh, telephone, etc. @@ -546,7 +598,7 @@ nameserver 172.16.72.4

    -Informing the Servers of the Key's Existence

    +Informing the Servers of the Key's Existence

    Imagine host1 and host 2 are @@ -573,7 +625,7 @@ key host1-host2. {

    -Instructing the Server to Use the Key

    +Instructing the Server to Use the Key

    Since keys are shared between two hosts only, the server must be told when keys are to be used. The following is added to the named.conf file @@ -605,7 +657,7 @@ server 10.1.2.3 {

    -TSIG Key Based Access Control

    +TSIG Key Based Access Control

    BIND allows IP addresses and ranges to be specified in ACL @@ -626,14 +678,13 @@ allow-update { key host1-host2. ;}; was signed by a key named "host1-host2.".

    - You may want to read about the more powerful - update-policy statement in - the section called “Dynamic Update Policies”. + See the section called “Dynamic Update Policies” for a discussion of + the more flexible update-policy statement.

    -Errors

    +Errors

    The processing of TSIG signed messages can result in several errors. If a signed message is sent to a non-TSIG aware @@ -659,7 +710,7 @@ allow-update { key host1-host2. ;};

    -TKEY

    +TKEY

    TKEY is a mechanism for automatically generating a shared secret between two hosts. There are several "modes" of @@ -695,7 +746,7 @@ allow-update { key host1-host2. ;};

    -SIG(0)

    +SIG(0)

    BIND 9 partially supports DNSSEC SIG(0) transaction signatures as specified in RFC 2535 and RFC 2931. @@ -756,7 +807,7 @@ allow-update { key host1-host2. ;};

    -Generating Keys

    +Generating Keys

    The dnssec-keygen program is used to generate keys. @@ -812,7 +863,7 @@ allow-update { key host1-host2. ;};

    -Signing the Zone

    +Signing the Zone

    The dnssec-signzone program is used to sign a zone. @@ -854,7 +905,7 @@ allow-update { key host1-host2. ;};

    -Configuring Servers

    +Configuring Servers

    To enable named to respond appropriately to DNS requests from DNSSEC aware clients, @@ -863,12 +914,22 @@ allow-update { key host1-host2. ;};

    To enable named to validate answers from - other servers, the dnssec-enable and - dnssec-validation options must both be - set to yes (the default setting in BIND 9.5 - and later), and at least one trust anchor must be configured - with a trusted-keys statement in - named.conf. + other servers, the dnssec-enable option + must be set to yes, and the + dnssec-validation options must be set to + yes or auto. +

    +

    + If dnssec-validation is set to + auto, then a default + trust anchor for the DNS root zone will be used. + If it is set to yes, however, + then at least one trust anchor must be configured + with a trusted-keys or + managed-keys statement in + named.conf, or DNSSEC validation + will not occur. The default setting is + yes.

    trusted-keys are copies of DNSKEY RRs @@ -879,7 +940,13 @@ allow-update { key host1-host2. ;}; to validated the DNSKEY RRset that they are from.

    - trusted-keys are described in more detail + managed-keys are trusted keys which are + automatically kept up to date via RFC 5011 trust anchor + maintenance. +

    +

    + trusted-keys and + managed-keys are described in more detail later in this document.

    @@ -890,44 +957,58 @@ allow-update { key host1-host2. ;};

    After DNSSEC gets established, a typical DNSSEC configuration - will look something like the following. It has a one or + will look something like the following. It has one or more public keys for the root. This allows answers from outside the organization to be validated. It will also have several keys for parts of the namespace the organization - controls. These are here to ensure that named is immune - to compromises in the DNSSEC components of the security + controls. These are here to ensure that named + is immune to compromises in the DNSSEC components of the security of parent zones.

    -trusted-keys {
    -
    +managed-keys {
             /* Root Key */
    -"." 257 3 3 "BNY4wrWM1nCfJ+CXd0rVXyYmobt7sEEfK3clRbGaTwSJxrGkxJWoZu6I7PzJu/
    -             E9gx4UC1zGAHlXKdE4zYIpRhaBKnvcC2U9mZhkdUpd1Vso/HAdjNe8LmMlnzY3
    -             zy2Xy4klWOADTPzSv9eamj8V18PHGjBLaVtYvk/ln5ZApjYghf+6fElrmLkdaz
    -             MQ2OCnACR817DF4BBa7UR/beDHyp5iWTXWSi6XmoJLbG9Scqc7l70KDqlvXR3M
    -             /lUUVRbkeg1IPJSidmK3ZyCllh4XSKbje/45SKucHgnwU5jefMtq66gKodQj+M
    -             iA21AfUVe7u99WzTLzY3qlxDhxYQQ20FQ97S+LKUTpQcq27R7AT3/V5hRQxScI
    -             Nqwcz4jYqZD2fQdgxbcDTClU0CRBdiieyLMNzXG3";
    +        "." initial-key 257 3 3 "BNY4wrWM1nCfJ+CXd0rVXyYmobt7sEEfK3clRbGaTwS
    +                                 JxrGkxJWoZu6I7PzJu/E9gx4UC1zGAHlXKdE4zYIpRh
    +                                 aBKnvcC2U9mZhkdUpd1Vso/HAdjNe8LmMlnzY3zy2Xy
    +                                 4klWOADTPzSv9eamj8V18PHGjBLaVtYvk/ln5ZApjYg
    +                                 hf+6fElrmLkdaz MQ2OCnACR817DF4BBa7UR/beDHyp
    +                                 5iWTXWSi6XmoJLbG9Scqc7l70KDqlvXR3M/lUUVRbke
    +                                 g1IPJSidmK3ZyCllh4XSKbje/45SKucHgnwU5jefMtq
    +                                 66gKodQj+MiA21AfUVe7u99WzTLzY3qlxDhxYQQ20FQ
    +                                 97S+LKUTpQcq27R7AT3/V5hRQxScINqwcz4jYqZD2fQ
    +                                 dgxbcDTClU0CRBdiieyLMNzXG3";
    +};
     
    -/* Key for our organization's forward zone */
    -example.com. 257 3 5 "AwEAAaxPMcR2x0HbQV4WeZB6oEDX+r0QM65KbhTjrW1ZaARmPhEZZe
    -                      3Y9ifgEuq7vZ/zGZUdEGNWy+JZzus0lUptwgjGwhUS1558Hb4JKUbb
    -                      OTcM8pwXlj0EiX3oDFVmjHO444gLkBO UKUf/mC7HvfwYH/Be22GnC
    -                      lrinKJp1Og4ywzO9WglMk7jbfW33gUKvirTHr25GL7STQUzBb5Usxt
    -                      8lgnyTUHs1t3JwCY5hKZ6CqFxmAVZP20igTixin/1LcrgX/KMEGd/b
    -                      iuvF4qJCyduieHukuY3H4XMAcR+xia2 nIUPvm/oyWR8BW/hWdzOvn
    -                      SCThlHf3xiYleDbt/o1OTQ09A0=";
    +trusted-keys {
    +        /* Key for our organization's forward zone */
    +        example.com. 257 3 5 "AwEAAaxPMcR2x0HbQV4WeZB6oEDX+r0QM6
    +                              5KbhTjrW1ZaARmPhEZZe3Y9ifgEuq7vZ/z
    +                              GZUdEGNWy+JZzus0lUptwgjGwhUS1558Hb
    +                              4JKUbbOTcM8pwXlj0EiX3oDFVmjHO444gL
    +                              kBOUKUf/mC7HvfwYH/Be22GnClrinKJp1O
    +                              g4ywzO9WglMk7jbfW33gUKvirTHr25GL7S
    +                              TQUzBb5Usxt8lgnyTUHs1t3JwCY5hKZ6Cq
    +                              FxmAVZP20igTixin/1LcrgX/KMEGd/biuv
    +                              F4qJCyduieHukuY3H4XMAcR+xia2nIUPvm
    +                              /oyWR8BW/hWdzOvnSCThlHf3xiYleDbt/o
    +                              1OTQ09A0=";
     
    -/* Key for our reverse zone. */
    -2.0.192.IN-ADDRPA.NET. 257 3 5 "AQOnS4xn/IgOUpBPJ3bogzwcxOdNax071L18QqZnQQQA
    -                                VVr+iLhGTnNGp3HoWQLUIzKrJVZ3zggy3WwNT6kZo6c0
    -                                tszYqbtvchmgQC8CzKojM/W16i6MG/ea fGU3siaOdS0
    -                                yOI6BgPsw+YZdzlYMaIJGf4M4dyoKIhzdZyQ2bYQrjyQ
    -                                4LB0lC7aOnsMyYKHHYeRv PxjIQXmdqgOJGq+vsevG06
    -                                zW+1xgYJh9rCIfnm1GX/KMgxLPG2vXTD/RnLX+D3T3UL
    -                                7HJYHJhAZD5L59VvjSPsZJHeDCUyWYrvPZesZDIRvhDD
    -                                52SKvbheeTJUm6EhkzytNN2SN96QRk8j/iI8ib";
    +        /* Key for our reverse zone. */
    +        2.0.192.IN-ADDRPA.NET. 257 3 5 "AQOnS4xn/IgOUpBPJ3bogzwc
    +                                       xOdNax071L18QqZnQQQAVVr+i
    +                                       LhGTnNGp3HoWQLUIzKrJVZ3zg
    +                                       gy3WwNT6kZo6c0tszYqbtvchm
    +                                       gQC8CzKojM/W16i6MG/eafGU3
    +                                       siaOdS0yOI6BgPsw+YZdzlYMa
    +                                       IJGf4M4dyoKIhzdZyQ2bYQrjy
    +                                       Q4LB0lC7aOnsMyYKHHYeRvPxj
    +                                       IQXmdqgOJGq+vsevG06zW+1xg
    +                                       YJh9rCIfnm1GX/KMgxLPG2vXT
    +                                       D/RnLX+D3T3UL7HJYHJhAZD5L
    +                                       59VvjSPsZJHeDCUyWYrvPZesZ
    +                                       DIRvhDD52SKvbheeTJUm6Ehkz
    +                                       ytNN2SN96QRk8j/iI8ib";
     };
     
     options {
    @@ -979,7 +1060,698 @@ options {
     
     

    -IPv6 Support in BIND 9

    +DNSSEC, Dynamic Zones, and Automatic Signing
    +

    As of BIND 9.7.0 it is possible to change a dynamic zone + from insecure to signed and back again. A secure zone can use + either NSEC or NSEC3 chains.

    +

    +Converting from insecure to secure

    +

    Changing a zone from insecure to secure can be done in two + ways: using a dynamic DNS update, or the + auto-dnssec zone option.

    +

    For either method, you need to configure + named so that it can see the + K* files which contain the public and private + parts of the keys that will be used to sign the zone. These files + will have been generated by + dnssec-keygen. You can do this by placing them + in the key-directory, as specified in + named.conf:

    +
    +        zone example.net {
    +                type master;
    +                update-policy local;
    +                file "dynamic/example.net/example.net";
    +                key-directory "dynamic/example.net";
    +        };
    +
    +

    If one KSK and one ZSK DNSKEY key have been generated, this + configuration will cause all records in the zone to be signed + with the ZSK, and the DNSKEY RRset to be signed with the KSK as + well. An NSEC chain will be generated as part of the initial + signing process.

    +

    +Dynamic DNS update method

    +

    To insert the keys via dynamic update:

    +
    +        % nsupdate
    +        > ttl 3600
    +        > update add example.net DNSKEY 256 3 7 AwEAAZn17pUF0KpbPA2c7Gz76Vb18v0teKT3EyAGfBfL8eQ8al35zz3Y I1m/SAQBxIqMfLtIwqWPdgthsu36azGQAX8=
    +        > update add example.net DNSKEY 257 3 7 AwEAAd/7odU/64o2LGsifbLtQmtO8dFDtTAZXSX2+X3e/UNlq9IHq3Y0 XtC0Iuawl/qkaKVxXe2lo8Ct+dM6UehyCqk=
    +        > send
    +
    +

    While the update request will complete almost immediately, + the zone will not be completely signed until + named has had time to walk the zone and + generate the NSEC and RRSIG records. The NSEC record at the apex + will be added last, to signal that there is a complete NSEC + chain.

    +

    If you wish to sign using NSEC3 instead of NSEC, you should + add an NSEC3PARAM record to the initial update request. If you + wish the NSEC3 chain to have the OPTOUT bit set, set it in the + flags field of the NSEC3PARAM record.

    +
    +        % nsupdate
    +        > ttl 3600
    +        > update add example.net DNSKEY 256 3 7 AwEAAZn17pUF0KpbPA2c7Gz76Vb18v0teKT3EyAGfBfL8eQ8al35zz3Y I1m/SAQBxIqMfLtIwqWPdgthsu36azGQAX8=
    +        > update add example.net DNSKEY 257 3 7 AwEAAd/7odU/64o2LGsifbLtQmtO8dFDtTAZXSX2+X3e/UNlq9IHq3Y0 XtC0Iuawl/qkaKVxXe2lo8Ct+dM6UehyCqk=
    +        > update add example.net NSEC3PARAM 1 1 100 1234567890
    +        > send
    +
    +

    Again, this update request will complete almost + immediately; however, the record won't show up until + named has had a chance to build/remove the + relevant chain. A private type record will be created to record + the state of the operation (see below for more details), and will + be removed once the operation completes.

    +

    While the initial signing and NSEC/NSEC3 chain generation + is happening, other updates are possible as well.

    +

    +Fully automatic zone signing

    +

    To enable automatic signing, add the + auto-dnssec option to the zone statement in + named.conf. + auto-dnssec has two possible arguments: + allow or + maintain.

    +

    With + auto-dnssec allow, + named can search the key directory for keys + matching the zone, insert them into the zone, and use them to + sign the zone. It will do so only when it receives an + rndc sign <zonename> or + rndc loadkeys <zonename> command.

    +

    + + auto-dnssec maintain includes the above + functionality, but will also automatically adjust the zone's + DNSKEY records on schedule according to the keys' timing metadata. + (See dnssec-keygen(8) and + dnssec-settime(8) for more information.) + If keys are present in the key directory the first time the zone + is loaded, it will be signed immediately, without waiting for an + rndc sign or rndc loadkeys + command. (Those commands can still be used when there are unscheduled + key changes, however.) +

    +

    Using the + auto-dnssec option requires the zone to be + configured to allow dynamic updates, by adding an + allow-update or + update-policy statement to the zone + configuration. If this has not been done, the configuration will + fail.

    +

    +Private-type records

    +

    The state of the signing process is signaled by + private-type records (with a default type value of 65534). When + signing is complete, these records will have a nonzero value for + the final octet (for those records which have a nonzero initial + octet).

    +

    The private type record format: If the first octet is + non-zero then the record indicates that the zone needs to be + signed with the key matching the record, or that all signatures + that match the record should be removed.

    +

    +

    +


    +
    +  algorithm (octet 1)
    +  key id in network order (octet 2 and 3)
    +  removal flag (octet 4)
    +  complete flag (octet 5)
    +

    +

    +

    +

    Only records flagged as "complete" can be removed via + dynamic update. Attempts to remove other private type records + will be silently ignored.

    +

    If the first octet is zero (this is a reserved algorithm + number that should never appear in a DNSKEY record) then the + record indicates changes to the NSEC3 chains are in progress. The + rest of the record contains an NSEC3PARAM record. The flag field + tells what operation to perform based on the flag bits.

    +

    +

    +


    +
    +  0x01 OPTOUT
    +  0x80 CREATE
    +  0x40 REMOVE
    +  0x20 NONSEC
    +

    +

    +

    +

    +DNSKEY rollovers

    +

    As with insecure-to-secure conversions, rolling DNSSEC + keys can be done in two ways: using a dynamic DNS update, or the + auto-dnssec zone option.

    +

    +Dynamic DNS update method

    +

    To perform key rollovers via dynamic update, you need to add + the K* files for the new keys so that + named can find them. You can then add the new + DNSKEY RRs via dynamic update. + named will then cause the zone to be signed + with the new keys. When the signing is complete the private type + records will be updated so that the last octet is non + zero.

    +

    If this is for a KSK you need to inform the parent and any + trust anchor repositories of the new KSK.

    +

    You should then wait for the maximum TTL in the zone before + removing the old DNSKEY. If it is a KSK that is being updated, + you also need to wait for the DS RRset in the parent to be + updated and its TTL to expire. This ensures that all clients will + be able to verify at least one signature when you remove the old + DNSKEY.

    +

    The old DNSKEY can be removed via UPDATE. Take care to + specify the correct key. + named will clean out any signatures generated + by the old key after the update completes.

    +

    +Automatic key rollovers

    +

    When a new key reaches its activation date (as set by + dnssec-keygen or dnssec-settime), + if the auto-dnssec zone option is set to + maintain, named will + automatically carry out the key rollover. If the key's algorithm + has not previously been used to sign the zone, then the zone will + be fully signed as quickly as possible. However, if the new key + is replacing an existing key of the same algorithm, then the + zone will be re-signed incrementally, with signatures from the + old key being replaced with signatures from the new key as their + signature validity periods expire. By default, this rollover + completes in 30 days, after which it will be safe to remove the + old key from the DNSKEY RRset.

    +

    +NSEC3PARAM rollovers via UPDATE

    +

    Add the new NSEC3PARAM record via dynamic update. When the + new NSEC3 chain has been generated, the NSEC3PARAM flag field + will be zero. At this point you can remove the old NSEC3PARAM + record. The old chain will be removed after the update request + completes.

    +

    +Converting from NSEC to NSEC3

    +

    To do this, you just need to add an NSEC3PARAM record. When + the conversion is complete, the NSEC chain will have been removed + and the NSEC3PARAM record will have a zero flag field. The NSEC3 + chain will be generated before the NSEC chain is + destroyed.

    +

    +Converting from NSEC3 to NSEC

    +

    To do this, use nsupdate to + remove all NSEC3PARAM records with a zero flag + field. The NSEC chain will be generated before the NSEC3 chain is + removed.

    +

    +Converting from secure to insecure

    +

    To convert a signed zone to unsigned using dynamic DNS, + delete all the DNSKEY records from the zone apex using + nsupdate. All signatures, NSEC or NSEC3 chains, + and associated NSEC3PARAM records will be removed automatically. + This will take place after the update request completes.

    +

    This requires the + dnssec-secure-to-insecure option to be set to + yes in + named.conf.

    +

    In addition, if the auto-dnssec maintain + zone statement is used, it should be removed or changed to + allow instead (or it will re-sign). +

    +

    +Periodic re-signing

    +

    In any secure zone which supports dynamic updates, named + will periodically re-sign RRsets which have not been re-signed as + a result of some update action. The signature lifetimes will be + adjusted so as to spread the re-sign load over time rather than + all at once.

    +

    +NSEC3 and OPTOUT

    +

    + named only supports creating new NSEC3 chains + where all the NSEC3 records in the zone have the same OPTOUT + state. + named supports UPDATES to zones where the NSEC3 + records in the chain have mixed OPTOUT state. + named does not support changing the OPTOUT + state of an individual NSEC3 record, the entire chain needs to be + changed if the OPTOUT state of an individual NSEC3 needs to be + changed.

    + +
    +

    +Dynamic Trust Anchor Management

    +

    BIND 9.7.0 introduces support for RFC 5011, dynamic trust + anchor management. Using this feature allows + named to keep track of changes to critical + DNSSEC keys without any need for the operator to make changes to + configuration files.

    +
    +

    +Validating Resolver

    +

    To configure a validating resolver to use RFC 5011 to + maintain a trust anchor, configure the trust anchor using a + managed-keys statement. Information about + this can be found in + the section called “managed-keys Statement Definition + and Usage”.

    +
    +
    +

    +Authoritative Server

    +

    To set up an authoritative zone for RFC 5011 trust anchor + maintenance, generate two (or more) key signing keys (KSKs) for + the zone. Sign the zone with one of them; this is the "active" + KSK. All KSK's which do not sign the zone are "stand-by" + keys.

    +

    Any validating resolver which is configured to use the + active KSK as an RFC 5011-managed trust anchor will take note + of the stand-by KSKs in the zone's DNSKEY RRset, and store them + for future reference. The resolver will recheck the zone + periodically, and after 30 days, if the new key is still there, + then the key will be accepted by the resolver as a valid trust + anchor for the zone. Any time after this 30-day acceptance + timer has completed, the active KSK can be revoked, and the + zone can be "rolled over" to the newly accepted key.

    +

    The easiest way to place a stand-by key in a zone is to + use the "smart signing" features of + dnssec-keygen and + dnssec-signzone. If a key with a publication + date in the past, but an activation date which is unset or in + the future, " + dnssec-signzone -S" will include the DNSKEY + record in the zone, but will not sign with it:

    +
    +$ dnssec-keygen -K keys -f KSK -P now -A now+2y example.net
    +$ dnssec-signzone -S -K keys example.net
    +
    +

    To revoke a key, the new command + dnssec-revoke has been added. This adds the + REVOKED bit to the key flags and re-generates the + K*.key and + K*.private files.

    +

    After revoking the active key, the zone must be signed + with both the revoked KSK and the new active KSK. (Smart + signing takes care of this automatically.)

    +

    Once a key has been revoked and used to sign the DNSKEY + RRset in which it appears, that key will never again be + accepted as a valid trust anchor by the resolver. However, + validation can proceed using the new active key (which had been + accepted by the resolver when it was a stand-by key).

    +

    See RFC 5011 for more details on key rollover + scenarios.

    +

    When a key has been revoked, its key ID changes, + increasing by 128, and wrapping around at 65535. So, for + example, the key "Kexample.com.+005+10000" becomes + "Kexample.com.+005+10128".

    +

    If two keys have ID's exactly 128 apart, and one is + revoked, then the two key ID's will collide, causing several + problems. To prevent this, + dnssec-keygen will not generate a new key if + another key is present which may collide. This checking will + only occur if the new keys are written to the same directory + which holds all other keys in use for that zone.

    +

    Older versions of BIND 9 did not have this precaution. + Exercise caution if using key revocation on keys that were + generated by previous releases, or if using keys stored in + multiple directories or on multiple machines.

    +

    It is expected that a future release of BIND 9 will + address this problem in a different way, by storing revoked + keys with their original unrevoked key ID's.

    +
    +
    +
    +

    +PKCS #11 (Cryptoki) support

    +

    PKCS #11 (Public Key Cryptography Standard #11) defines a + platform- independent API for the control of hardware security + modules (HSMs) and other cryptographic support devices.

    +

    BIND 9 is known to work with two HSMs: The Sun SCA 6000 + cryptographic acceleration board, tested under Solaris x86, and + the AEP Keyper network-attached key storage device, tested with + Debian Linux, Solaris x86 and Windows Server 2003.

    +
    +

    +Prerequisites

    +

    See the HSM vendor documentation for information about + installing, initializing, testing and troubleshooting the + HSM.

    +

    BIND 9 uses OpenSSL for cryptography, but stock OpenSSL + does not yet fully support PKCS #11. However, a PKCS #11 engine + for OpenSSL is available from the OpenSolaris project. It has + been modified by ISC to work with with BIND 9, and to provide + new features such as PIN management and key by + reference.

    +

    The patched OpenSSL depends on a "PKCS #11 provider". + This is a shared library object, providing a low-level PKCS #11 + interface to the HSM hardware. It is dynamically loaded by + OpenSSL at runtime. The PKCS #11 provider comes from the HSM + vendor, and and is specific to the HSM to be controlled.

    +

    There are two "flavors" of PKCS #11 support provided by + the patched OpenSSL, one of which must be chosen at + configuration time. The correct choice depends on the HSM + hardware:

    +
      +
    • Use 'crypto-accelerator' with HSMs that have hardware + cryptographic acceleration features, such as the SCA 6000 + board. This causes OpenSSL to run all supported + cryptographic operations in the HSM.

    • +
    • Use 'sign-only' with HSMs that are designed to + function primarily as secure key storage devices, but lack + hardware acceleration. These devices are highly secure, but + are not necessarily any faster at cryptography than the + system CPU — often, they are slower. It is therefore + most efficient to use them only for those cryptographic + functions that require access to the secured private key, + such as zone signing, and to use the system CPU for all + other computationally-intensive operations. The AEP Keyper + is an example of such a device.

    • +
    +

    The modified OpenSSL code is included in the BIND 9.7.0 + release, in the form of a context diff against the latest OpenSSL. +

    +
    +

    Note

    + The latest OpenSSL version at the time of the BIND release + is 0.9.8l. + ISC will provide an updated patch as new versions of OpenSSL + are released. The version number in the following examples + is expected to change.
    +

    + Before building BIND 9 with PKCS #11 support, it will be + necessary to build OpenSSL with this patch in place and inform + it of the path to the HSM-specific PKCS #11 provider + library.

    +

    Obtain OpenSSL 0.9.8l:

    +
    +$ wget http://www.openssl.org/source/openssl-0.9.8l.tar.gz
    +
    +

    Extract the tarball:

    +
    +$ tar zxf openssl-0.9.8l.tar.gz
    +
    +

    Apply the patch from the BIND 9 release:

    +
    +$ patch -p1 -d openssl-0.9.8l \
    +            < bind-9.7.0/bin/pkcs11/openssl-0.9.8l-patch
    +
    +
    +

    Note

    (Note that the patch file may not be compatible with the + "patch" utility on all operating systems. You may need to + install GNU patch.)
    +

    When building OpenSSL, place it in a non-standard + location so that it does not interfere with OpenSSL libraries + elsewhere on the system. In the following examples, we choose + to install into "/opt/pkcs11/usr". We will use this location + when we configure BIND 9.

    +
    +

    +Building OpenSSL for the AEP Keyper on Linux

    +

    The AEP Keyper is a highly secure key storage device, + but does not provide hardware cryptographic acceleration. It + can carry out cryptographic operations, but it is probably + slower than your system's CPU. Therefore, we choose the + 'sign-only' flavor when building OpenSSL.

    +

    The Keyper-specific PKCS #11 provider library is + delivered with the Keyper software. In this example, we place + it /opt/pkcs11/usr/lib:

    +
    +$ cp pkcs11.GCC4.0.2.so.4.05 /opt/pkcs11/usr/lib/libpkcs11.so
    +
    +

    This library is only available for Linux as a 32-bit + binary. If we are compiling on a 64-bit Linux system, it is + necessary to force a 32-bit build, by specifying -m32 in the + build options.

    +

    Finally, the Keyper library requires threads, so we + must specify -pthread.

    +
    +$ cd openssl-0.9.8l
    +$ ./Configure linux-generic32 -m32 -pthread \
    +            --pk11-libname=/opt/pkcs11/usr/lib/libpkcs11.so \
    +            --pk11-flavor=sign-only \
    +            --prefix=/opt/pkcs11/usr
    +
    +

    After configuring, run "make" + and "make test". If "make + test" fails with "pthread_atfork() not found", you forgot to + add the -pthread above.

    +
    +
    +

    +Building OpenSSL for the SCA 6000 on Solaris

    +

    The SCA-6000 PKCS #11 provider is installed as a system + library, libpkcs11. It is a true crypto accelerator, up to 4 + times faster than any CPU, so the flavor shall be + 'crypto-accelerator'.

    +

    In this example, we are building on Solaris x86 on an + AMD64 system.

    +
    +$ cd openssl-0.9.8l
    +$ ./Configure solaris64-x86_64-cc \
    +            --pk11-libname=/usr/lib/64/libpkcs11.so \
    +            --pk11-flavor=crypto-accelerator \
    +            --prefix=/opt/pkcs11/usr
    +
    +

    (For a 32-bit build, use "solaris-x86-cc" and + /usr/lib/libpkcs11.so.)

    +

    After configuring, run + make and + make test.

    +

    Once you have built OpenSSL, run + "apps/openssl engine pkcs11" to confirm + that PKCS #11 support was compiled in correctly. The output + should be one of the following lines, depending on the flavor + selected:

    +
    +        (pkcs11) PKCS #11 engine support (sign only)
    +
    +

    Or:

    +
    +        (pkcs11) PKCS #11 engine support (crypto accelerator)
    +
    +

    Next, run + "apps/openssl engine pkcs11 -t". This will + attempt to initialize the PKCS #11 engine. If it is able to + do so successfully, it will report + “[ available ]”.

    +

    If the output is correct, run + "make install" which will install the + modified OpenSSL suite to + /opt/pkcs11/usr.

    +
    +
    +
    +

    +Building BIND 9 with PKCS#11

    +

    When building BIND 9, the location of the custom-built + OpenSSL library must be specified via configure.

    +
    +

    +Configuring BIND 9 for Linux

    +

    To link with the PKCS #11 provider, threads must be + enabled in the BIND 9 build.

    +

    The PKCS #11 library for the AEP Keyper is currently + only available as a 32-bit binary. If we are building on a + 64-bit host, we must force a 32-bit build by adding "-m32" to + the CC options on the "configure" command line.

    +
    +$ cd ../bind-9.7.0
    +$ ./configure CC="gcc -m32" --enable-threads \
    +           --with-openssl=/opt/pkcs11/usr \
    +           --with-pkcs11=/opt/pkcs11/usr/lib/libpkcs11.so
    +
    +
    +
    +

    +Configuring BIND 9 for Solaris

    +

    To link with the PKCS #11 provider, threads must be + enabled in the BIND 9 build.

    +
    +$ cd ../bind-9.7.0
    +$ ./configure CC="cc -xarch=amd64" --enable-threads \
    +            --with-openssl=/opt/pkcs11/usr \
    +            --with-pkcs11=/usr/lib/64/libpkcs11.so
    +
    +

    (For a 32-bit build, omit CC="cc -xarch=amd64".)

    +

    If configure complains about OpenSSL not working, you + may have a 32/64-bit architecture mismatch. Or, you may have + incorrectly specified the path to OpenSSL (it should be the + same as the --prefix argument to the OpenSSL + Configure).

    +
    +

    After configuring, run + "make", + "make test" and + "make install".

    +
    +
    +

    +PKCS #11 Tools

    +

    BIND 9 includes a minimal set of tools to operate the + HSM, including + pkcs11-keygen to generate a new key pair + within the HSM, + pkcs11-list to list objects currently + available, and + pkcs11-destroy to remove objects.

    +

    In UNIX/Linux builds, these tools are built only if BIND + 9 is configured with the --with-pkcs11 option. (NOTE: If + --with-pkcs11 is set to "yes", rather than to the path of the + PKCS #11 provider, then the tools will be built but the + provider will be left undefined. Use the -m option or the + PKCS11_PROVIDER environment variable to specify the path to the + provider.)

    +
    +
    +

    +Using the HSM

    +

    First, we must set up the runtime environment so the + OpenSSL and PKCS #11 libraries can be loaded:

    +
    +$ export LD_LIBRARY_PATH=/opt/pkcs11/usr/lib:${LD_LIBRARY_PATH}
    +
    +

    When operating an AEP Keyper, it is also necessary to + specify the location of the "machine" file, which stores + information about the Keyper for use by PKCS #11 provider + library. If the machine file is in + /opt/Keyper/PKCS11Provider/machine, + use:

    +
    +$ export KEYPER_LIBRARY_PATH=/opt/Keyper/PKCS11Provider
    +
    +

    These environment variables must be set whenever running + any tool that uses the HSM, including + pkcs11-keygen, + pkcs11-list, + pkcs11-destroy, + dnssec-keyfromlabel, + dnssec-signzone, + dnssec-keygen(which will use the HSM for + random number generation), and + named.

    +

    We can now create and use keys in the HSM. In this case, + we will create a 2048 bit key and give it the label + "sample-ksk":

    +
    +$ pkcs11-keygen -b 2048 -l sample-ksk
    +
    +

    To confirm that the key exists:

    +
    +$ pkcs11-list
    +Enter PIN:
    +object[0]: handle 2147483658 class 3 label[8] 'sample-ksk' id[0]
    +object[1]: handle 2147483657 class 2 label[8] 'sample-ksk' id[0]
    +
    +

    Before using this key to sign a zone, we must create a + pair of BIND 9 key files. The "dnssec-keyfromlabel" utility + does this. In this case, we will be using the HSM key + "sample-ksk" as the key-signing key for "example.net":

    +
    +$ dnssec-keyfromlabel -l sample-ksk -f KSK example.net
    +
    +

    The resulting K*.key and K*.private files can now be used + to sign the zone. Unlike normal K* files, which contain both + public and private key data, these files will contain only the + public key data, plus an identifier for the private key which + remains stored within the HSM. The HSM handles signing with the + private key.

    +

    If you wish to generate a second key in the HSM for use + as a zone-signing key, follow the same procedure above, using a + different keylabel, a smaller key size, and omitting "-f KSK" + from the dnssec-keyfromlabel arguments:

    +
    +$ pkcs11-keygen -b 1024 -l sample-zsk
    +$ dnssec-keyfromlabel -l sample-zsk example.net
    +
    +

    Alternatively, you may prefer to generate a conventional + on-disk key, using dnssec-keygen:

    +
    +$ dnssec-keygen example.net
    +
    +

    This provides less security than an HSM key, but since + HSMs can be slow or cumbersome to use for security reasons, it + may be more efficient to reserve HSM keys for use in the less + frequent key-signing operation. The zone-signing key can be + rolled more frequently, if you wish, to compensate for a + reduction in key security.

    +

    Now you can sign the zone. (Note: If not using the -S + option to + dnssec-signzone, it will be necessary to add + the contents of both + K*.key files to the zone master file before + signing it.)

    +
    +$ dnssec-signzone -S example.net
    +Enter PIN:
    +Verifying the zone using the following algorithms:
    +NSEC3RSASHA1.
    +Zone signing complete:
    +Algorithm: NSEC3RSASHA1: ZSKs: 1, KSKs: 1 active, 0 revoked, 0 stand-by
    +example.net.signed
    +
    +
    +
    +

    +Specifying the engine on the command line

    +

    The OpenSSL engine can be specified in + named and all of the BIND + dnssec-* tools by using the "-E + <engine>" command line option. If BIND 9 is built with + the --with-pkcs11 option, this option defaults to "pkcs11". + Specifying the engine will generally not be necessary unless + for some reason you wish to use a different OpenSSL + engine.

    +

    If you wish to disable use of the "pkcs11" engine — + for troubleshooting purposes, or because the HSM is unavailable + — set the engine to the empty string. For example:

    +
    +$ dnssec-signzone -E '' -S example.net
    +
    +

    This causes + dnssec-signzone to run as if it were compiled + without the --with-pkcs11 option.

    +
    +
    +

    +Running named with automatic zone re-signing

    +

    If you want + named to dynamically re-sign zones using HSM + keys, and/or to to sign new records inserted via nsupdate, then + named must have access to the HSM PIN. This can be accomplished + by placing the PIN into the openssl.cnf file (in the above + examples, + /opt/pkcs11/usr/ssl/openssl.cnf).

    +

    The location of the openssl.cnf file can be overridden by + setting the OPENSSL_CONF environment variable before running + named.

    +

    Sample openssl.cnf:

    +
    +        openssl_conf = openssl_def
    +        [ openssl_def ]
    +        engines = engine_section
    +        [ engine_section ]
    +        pkcs11 = pkcs11_section
    +        [ pkcs11_section ]
    +        PIN = <PLACE PIN HERE>
    +
    +

    This will also allow the dnssec-* tools to access the HSM + without PIN entry. (The pkcs11-* tools access the HSM directly, + not via OpenSSL, so a PIN will still be required to use + them.)

    +
    +

    Warning

    +

    Placing the HSM's PIN in a text file in + this manner may reduce the security advantage of using an + HSM. Be sure this is what you want to do before configuring + OpenSSL in this way.

    +
    +
    +
    +
    +

    +IPv6 Support in BIND 9

    BIND 9 fully supports all currently defined forms of IPv6 name to address and address to name @@ -1017,7 +1789,7 @@ options {

    -Address Lookups Using AAAA Records

    +Address Lookups Using AAAA Records

    The IPv6 AAAA record is a parallel to the IPv4 A record, and, unlike the deprecated A6 record, specifies the entire @@ -1036,7 +1808,7 @@ host 3600 IN AAAA 2001:db8::1

    -Address to Name Lookups Using Nibble Format

    +Address to Name Lookups Using Nibble Format

    When looking up an address in nibble format, the address components are simply reversed, just as in IPv4, and @@ -1048,7 +1820,8 @@ host 3600 IN AAAA 2001:db8::1

     $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
    -1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0   14400 IN      PTR     host.example.com.
    +1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0  14400   IN    PTR    (
    +                                    host.example.com. )
     
    diff --git a/doc/arm/Bv9ARM.ch05.html b/doc/arm/Bv9ARM.ch05.html index b0339b4..3b60755 100644 --- a/doc/arm/Bv9ARM.ch05.html +++ b/doc/arm/Bv9ARM.ch05.html @@ -1,5 +1,5 @@ - + @@ -45,13 +45,13 @@

    -The Lightweight Resolver Library

    +The Lightweight Resolver Library

    Traditionally applications have been linked with a stub resolver library that sends recursive DNS queries to a local caching name diff --git a/doc/arm/Bv9ARM.ch06.html b/doc/arm/Bv9ARM.ch06.html index d969e4b..3524348 100644 --- a/doc/arm/Bv9ARM.ch06.html +++ b/doc/arm/Bv9ARM.ch06.html @@ -1,5 +1,5 @@ - + @@ -48,55 +48,58 @@

    Configuration File Elements
    Address Match Lists
    -
    Comment Syntax
    +
    Comment Syntax
    Configuration File Grammar
    -
    acl Statement Grammar
    +
    acl Statement Grammar
    acl Statement Definition and Usage
    -
    controls Statement Grammar
    +
    controls Statement Grammar
    controls Statement Definition and Usage
    -
    include Statement Grammar
    -
    include Statement Definition and +
    include Statement Grammar
    +
    include Statement Definition and Usage
    -
    key Statement Grammar
    -
    key Statement Definition and Usage
    -
    logging Statement Grammar
    -
    logging Statement Definition and +
    key Statement Grammar
    +
    key Statement Definition and Usage
    +
    logging Statement Grammar
    +
    logging Statement Definition and Usage
    -
    lwres Statement Grammar
    -
    lwres Statement Definition and Usage
    -
    masters Statement Grammar
    -
    masters Statement Definition and +
    lwres Statement Grammar
    +
    lwres Statement Definition and Usage
    +
    masters Statement Grammar
    +
    masters Statement Definition and Usage
    -
    options Statement Grammar
    +
    options Statement Grammar
    options Statement Definition and Usage
    server Statement Grammar
    server Statement Definition and Usage
    statistics-channels Statement Grammar
    -
    statistics-channels Statement Definition and +
    statistics-channels Statement Definition and Usage
    -
    trusted-keys Statement Grammar
    -
    trusted-keys Statement Definition +
    trusted-keys Statement Grammar
    +
    trusted-keys Statement Definition + and Usage
    +
    managed-keys Statement Grammar
    +
    managed-keys Statement Definition and Usage
    view Statement Grammar
    -
    view Statement Definition and Usage
    +
    view Statement Definition and Usage
    zone Statement Grammar
    -
    zone Statement Definition and Usage
    +
    zone Statement Definition and Usage
    -
    Zone File
    +
    Zone File
    Types of Resource Records and When to Use Them
    -
    Discussion of MX Records
    +
    Discussion of MX Records
    Setting TTLs
    -
    Inverse Mapping in IPv4
    -
    Other Zone File Directives
    -
    BIND Master File Extension: the $GENERATE Directive
    +
    Inverse Mapping in IPv4
    +
    Other Zone File Directives
    +
    BIND Master File Extension: the $GENERATE Directive
    Additional File Formats
    BIND9 Statistics
    @@ -193,6 +196,19 @@

    + namelist +

    + + +

    + A list of one or more domain_name + elements. +

    + + + + +

    dotted_decimal

    @@ -461,7 +477,7 @@ Address Match Lists

    -Syntax

    +Syntax
    address_match_list = address_match_list_element ;
       [ address_match_list_element; ... ]
     address_match_list_element = [ ! ] (ip_address [/length] |
    @@ -470,7 +486,7 @@
     
     

    -Definition and Usage

    +Definition and Usage

    Address match lists are primarily used to determine access control for various server operations. They are also used in @@ -554,7 +570,7 @@

    -Comment Syntax

    +Comment Syntax

    The BIND 9 comment syntax allows for comments to appear @@ -564,7 +580,7 @@

    -Syntax

    +Syntax

    /* This is a BIND comment as in C */
    @@ -573,13 +589,14 @@
    // This is a BIND comment as in C++

    -
    # This is a BIND comment as in common UNIX shells and perl
    +
    # This is a BIND comment as in common UNIX shells
    +# and perl

    -Definition and Usage

    +Definition and Usage

    Comments may appear anywhere that whitespace may appear in a BIND configuration file. @@ -792,6 +809,17 @@ +

    managed-keys

    + + +

    + lists DNSSEC keys to be kept up to date + using RFC 5011 trust anchor maintenance. +

    + + + +

    view

    @@ -820,7 +848,7 @@

    -acl Statement Grammar

    +acl Statement Grammar
    acl acl-name {
         address_match_list
     };
    @@ -902,12 +930,14 @@
     
     

    -controls Statement Grammar

    +controls Statement Grammar
    controls {
    -   [ inet ( ip_addr | * ) [ port ip_port ] allow {  address_match_list  }
    +   [ inet ( ip_addr | * ) [ port ip_port ]
    +                allow {  address_match_list  }
                     keys { key_list }; ]
        [ inet ...; ]
    -   [ unix path perm number owner number group number keys { key_list }; ]
    +   [ unix path perm number owner number group number
    +     keys { key_list }; ]
        [ unix ...; ]
     };
     
    @@ -1024,12 +1054,12 @@

    -include Statement Grammar

    +include Statement Grammar
    include filename;

    -include Statement Definition and +include Statement Definition and Usage

    The include statement inserts the @@ -1044,7 +1074,7 @@

    -key Statement Grammar

    +key Statement Grammar
    key key_id {
         algorithm string;
         secret string;
    @@ -1053,7 +1083,7 @@
     
     

    -key Statement Definition and Usage

    +key Statement Definition and Usage

    The key statement defines a shared secret key for use with TSIG (see the section called “TSIG”) @@ -1100,7 +1130,7 @@

    -logging Statement Grammar

    +logging Statement Grammar
    logging {
        [ channel channel_name {
          ( file path_name
    @@ -1124,7 +1154,7 @@
     
     

    -logging Statement Definition and +logging Statement Definition and Usage

    The logging statement configures a @@ -1158,7 +1188,7 @@

    -The channel Phrase

    +The channel Phrase

    All log output goes to one or more channels; you can make as many of them as you want. @@ -1342,32 +1372,30 @@ notrace. All debugging messages in the server have a debug used is described in the section called “The category Phrase”.

    channel default_syslog {
    -    syslog daemon;                      // send to syslog's daemon
    -                                        // facility
    -    severity info;                      // only send priority info
    -                                        // and higher
    -};
    +    // send to syslog's daemon facility
    +    syslog daemon;
    +    // only send priority info and higher
    +    severity info;
     
     channel default_debug {
    -    file "named.run";                   // write to named.run in
    -                                        // the working directory
    -                                        // Note: stderr is used instead
    -                                        // of "named.run"
    -                                        // if the server is started
    -                                        // with the '-f' option.
    -    severity dynamic;                   // log at the server's
    -                                        // current debug level
    +    // write to named.run in the working directory
    +    // Note: stderr is used instead of "named.run" if
    +    // the server is started with the '-f' option.
    +    file "named.run";
    +    // log at the server's current debug level
    +    severity dynamic;
     };
     
     channel default_stderr {
    -    stderr;                             // writes to stderr
    -    severity info;                      // only send priority info
    -                                        // and higher
    +    // writes to stderr
    +    stderr;
    +    // only send priority info and higher
    +    severity info;
     };
     
     channel null {
    -   null;                                // toss anything sent to
    -                                        // this channel
    +   // toss anything sent to this channel
    +   null;
     };
     

    @@ -1610,12 +1638,14 @@ category notify { null; };

    The query log entry reports the client's IP address and port number, and the query name, - class and type. It also reports whether the + class and type. Next it reports whether the Recursion Desired flag was set (+ if set, - if not set), if the query was signed (S), - EDNS was in use (E), if DO (DNSSEC Ok) was - set (D), or if CD (Checking Disabled) was set - (C). + EDNS was in use (E), if TCP was used (T), if + DO (DNSSEC Ok) was set (D), or if CD (Checking + Disabled) was set (C). After this the + destination address the query was sent to is + reported.

    @@ -1723,7 +1753,7 @@ category notify { null; };

    -The query-errors Category

    +The query-errors Category

    The query-errors category is specifically intended for debugging purposes: To identify @@ -1754,7 +1784,15 @@ category notify { null; }; The log message will look like as follows:

    - fetch completed at resolver.c:2970 for www.example.com/A in 30.000183: timed out/success [domain:example.com,referral:2,restart:7,qrysent:8,timeout:5,lame:0,neterr:0,badresp:1,adberr:0,findfail:0,valfail:0] + +

    +
    +fetch completed at resolver.c:2970 for www.example.com/A
    +in 30.000183: timed out/success [domain:example.com,
    +referral:2,restart:7,qrysent:8,timeout:5,lame:0,neterr:0,
    +badresp:1,adberr:0,findfail:0,valfail:0]
    +            
    +

    The first part before the colon shows that a recursive @@ -1943,13 +1981,14 @@ category notify { null; };

    -lwres Statement Grammar

    +lwres Statement Grammar

    This is the grammar of the lwres statement in the named.conf file:

    lwres {
    -    [ listen-on { ip_addr [port ip_port] ; [ ip_addr [port ip_port] ; ... ] }; ]
    +    [ listen-on { ip_addr [port ip_port] ;
    +                [ ip_addr [port ip_port] ; ... ] }; ]
         [ view view_name; ]
         [ search { domain_name ; [ domain_name ; ... ] }; ]
         [ ndots number; ]
    @@ -1958,7 +1997,7 @@ category notify { null; };
     
     

    -lwres Statement Definition and Usage

    +lwres Statement Definition and Usage

    The lwres statement configures the name @@ -2009,14 +2048,15 @@ category notify { null; };

    -masters Statement Grammar

    +masters Statement Grammar
    -masters name [port ip_port] { ( masters_list | ip_addr [port ip_port] [key key] ) ; [...] };
    +masters name [port ip_port] { ( masters_list | 
    +      ip_addr [port ip_port] [key key] ) ; [...] };
     

    -masters Statement Definition and +masters Statement Definition and Usage

    masters lists allow for a common set of masters to be easily used by @@ -2025,23 +2065,27 @@ category notify { null; };

    -options Statement Grammar

    +options Statement Grammar

    This is the grammar of the options statement in the named.conf file:

    options {
    +    [ attach-cache cache_name; ]
         [ version version_string; ]
         [ hostname hostname_string; ]
         [ server-id server_id_string; ]
         [ directory path_name; ]
         [ key-directory path_name; ]
    +    [ managed-keys-directory path_name; ]
         [ named-xfer path_name; ]
    +    [ tkey-gssapi-keytab path_name; ]
         [ tkey-gssapi-credential principal; ]
         [ tkey-domain domainname; ]
         [ tkey-dhkey key_name key_tag; ]
         [ cache-file path_name; ]
         [ dump-file path_name; ]
    +    [ bindkeys-file path_name; ]
         [ memstatistics yes_or_no; ]
         [ memstatistics-file path_name; ]
         [ pid-file path_name; ]
    @@ -2066,8 +2110,9 @@ category notify { null; };
         [ maintain-ixfr-base yes_or_no; ]
         [ ixfr-from-differences (yes_or_no | master | slave); ]
         [ dnssec-enable yes_or_no; ]
    -    [ dnssec-validation yes_or_no; ]
    -    [ dnssec-lookaside domain trust-anchor domain; ]
    +    [ dnssec-validation (yes_or_no | auto); ]
    +    [ dnssec-lookaside ( auto | 
    +                        domain trust-anchor domain ); ]
         [ dnssec-must-be-secure domain yes_or_no; ]
         [ dnssec-accept-expired yes_or_no; ]
         [ forward ( only | first ); ]
    @@ -2078,12 +2123,14 @@ category notify { null; };
             ... }; ]
         [ check-names ( master | slave | response )
             ( warn | fail | ignore ); ]
    +    [ check-dup-records ( warn | fail | ignore ); ]
         [ check-mx ( warn | fail | ignore ); ]
         [ check-wildcard yes_or_no; ]
         [ check-integrity yes_or_no; ]
         [ check-mx-cname ( warn | fail | ignore ); ]
         [ check-srv-cname ( warn | fail | ignore ); ]
         [ check-sibling yes_or_no; ]
    +    [ allow-new-zones { yes_or_no }; ]
         [ allow-notify { address_match_list }; ]
         [ allow-query { address_match_list }; ]
         [ allow-query-on { address_match_list }; ]
    @@ -2095,6 +2142,8 @@ category notify { null; };
         [ allow-update { address_match_list }; ]
         [ allow-update-forwarding { address_match_list }; ]
         [ update-check-ksk yes_or_no; ]
    +    [ dnssec-dnskey-kskonly yes_or_no; ]
    +    [ dnssec-secure-to-insecure yes_or_no ;]
         [ try-tcp-refresh yes_or_no; ]
         [ allow-v6-synthesis { address_match_list }; ]
         [ blackhole { address_match_list }; ]
    @@ -2132,13 +2181,15 @@ category notify { null; };
         [ transfer-source (ip4_addr | *) [port ip_port] ; ]
         [ transfer-source-v6 (ip6_addr | *) [port ip_port] ; ]
         [ alt-transfer-source (ip4_addr | *) [port ip_port] ; ]
    -    [ alt-transfer-source-v6 (ip6_addr | *) [port ip_port] ; ]
    +    [ alt-transfer-source-v6 (ip6_addr | *)
    +                             [port ip_port] ; ]
         [ use-alt-transfer-source yes_or_no; ]
         [ notify-delay seconds ; ]
         [ notify-source (ip4_addr | *) [port ip_port] ; ]
         [ notify-source-v6 (ip6_addr | *) [port ip_port] ; ]
         [ notify-to-soa yes_or_no ; ]
    -    [ also-notify { ip_addr [port ip_port] ; [ ip_addr [port ip_port] ; ... ] }; ]
    +    [ also-notify { ip_addr [port ip_port] ;
    +                  [ ip_addr [port ip_port] ; ... ] }; ]
         [ max-ixfr-log-size number; ]
         [ max-journal-size size_spec; ]
         [ coresize size_spec ; ]
    @@ -2174,12 +2225,25 @@ category notify { null; };
         [ random-device path_name ; ]
         [ max-cache-size size_spec ; ]
         [ match-mapped-addresses yes_or_no; ]
    +    [ filter-aaaa-on-v4 ( yes_or_no | break-dnssec ); ]
    +    [ filter-aaaa { address_match_list }; ]
    +    [ dns64 IPv6-prefix {
    +        [ clients { address_match_list }; ]
    +        [ mapped { address_match_list }; ]
    +        [ exclude { address_match_list }; ]
    +        [ suffix IPv6-address; ]
    +        [ recursive-only yes_or_no; ]
    +        [ break-dnssec yes_or_no; ]
    +    }; ];
    +    [ dns64-server name ]
    +    [ dns64-contact name ]
         [ preferred-glue ( A | AAAA | NONE ); ]
         [ edns-udp-size number; ]
         [ max-udp-size number; ]
         [ root-delegation-only [ exclude { namelist } ] ; ]
         [ querylog yes_or_no ; ]
    -    [ disable-algorithms domain { algorithm; [ algorithm; ] }; ]
    +    [ disable-algorithms domain { algorithm;
    +                                [ algorithm; ] }; ]
         [ acache-enable yes_or_no ; ]
         [ acache-cleaning-interval number; ]
         [ max-acache-size size_spec ; ]
    @@ -2192,6 +2256,10 @@ category notify { null; };
         [ disable-empty-zone zone_name ; ]
         [ zero-no-soa-ttl yes_or_no ; ]
         [ zero-no-soa-ttl-cache yes_or_no ; ]
    +    [ resolver-query-timeout number ; ]
    +    [ deny-answer-addresses { address_match_list } [ except-from { namelist } ];]
    +    [ deny-answer-aliases { namelist } [ except-from { namelist } ];]
    +    [ response-policy { zone_name [ policy given | no-op | nxdomain | nodata | cname domain ] ; } ; ]
     };
     
    @@ -2209,6 +2277,91 @@ category notify { null; }; be used.

    +
    attach-cache
    +
    +

    + Allows multiple views to share a single cache + database. + Each view has its own cache database by default, but + if multiple views have the same operational policy + for name resolution and caching, those views can + share a single cache to save memory and possibly + improve resolution efficiency by using this option. +

    +

    + The attach-cache option + may also be specified in view + statements, in which case it overrides the + global attach-cache option. +

    +

    + The cache_name specifies + the cache to be shared. + When the named server configures + views which are supposed to share a cache, it + creates a cache with the specified name for the + first view of these sharing views. + The rest of the views will simply refer to the + already created cache. +

    +

    + One common configuration to share a cache would be to + allow all views to share a single cache. + This can be done by specifying + the attach-cache as a global + option with an arbitrary name. +

    +

    + Another possible operation is to allow a subset of + all views to share a cache while the others to + retain their own caches. + For example, if there are three views A, B, and C, + and only A and B should share a cache, specify the + attach-cache option as a view A (or + B)'s option, referring to the other view name: +

    +
    +  view "A" {
    +    // this view has its own cache
    +    ...
    +  };
    +  view "B" {
    +    // this view refers to A's cache
    +    attach-cache "A";
    +  };
    +  view "C" {
    +    // this view has its own cache
    +    ...
    +  };
    +
    +

    + Views that share a cache must have the same policy + on configurable parameters that may affect caching. + The current implementation requires the following + configurable options be consistent among these + views: + check-names, + cleaning-interval, + dnssec-accept-expired, + dnssec-validation, + max-cache-ttl, + max-ncache-ttl, + max-cache-size, and + zero-no-soa-ttl. +

    +

    + Note that there may be other parameters that may + cause confusion if they are inconsistent for + different views that share a single cache. + For example, if these views define different sets of + forwarders that can return different answers for the + same question, sharing the answer does not make + sense or could even be harmful. + It is administrator's responsibility to ensure + configuration differences in different views do + not cause disruption with a shared cache. +

    +
    directory

    The working directory of the server. @@ -2229,10 +2382,19 @@ category notify { null; }; When performing dynamic update of secure zones, the directory where the public and private DNSSEC key files should be found, if different than the current working - directory. The directory specified must be an absolute - path. (Note that this option has no effect on the paths - for files containing non-DNSSEC keys such as the - rndc.key. + directory. (Note that this option has no effect on the + paths for files containing non-DNSSEC keys such as + bind.keys, + rndc.key or + session.key.) +

    +
    managed-keys-directory
    +

    + The directory used to hold the files used to track managed keys. + By default it is the working directory. It there are no + views then the file managed-keys.bind + otherwise a SHA256 hash of the view name is used with + .mkeys extension added.

    named-xfer

    @@ -2243,18 +2405,27 @@ category notify { null; }; named-xfer program is needed; its functionality is built into the name server.

    +
    tkey-gssapi-keytab
    +

    + The KRB5 keytab file to use for GSS-TSIG updates. If + this option is set and tkey-gssapi-credential is not + set, then updates will be allowed with any key + matching a principal in the specified keytab. +

    tkey-gssapi-credential

    The security credential with which the server should authenticate keys requested by the GSS-TSIG protocol. Currently only Kerberos 5 authentication is available - and the credential is a Kerberos principal which - the server can acquire through the default system - key file, normally /etc/krb5.keytab. - Normally this principal is of the form - "DNS/server.domain". - To use GSS-TSIG, tkey-domain - must also be set. + and the credential is a Kerberos principal which the + server can acquire through the default system key + file, normally /etc/krb5.keytab. + The location keytab file can be overridden using the + tkey-gssapi-keytab option. Normally this principal is + of the form "DNS/server.domain". + To use GSS-TSIG, tkey-domain must + also be set if a specific keytab is not set with + tkey-gssapi-keytab.

    tkey-domain

    @@ -2271,7 +2442,8 @@ category notify { null; }; should be the server's domain name, or an otherwise non-existent subdomain like "_tkey.domainname". If you are - using GSS-TSIG, this variable must be defined. + using GSS-TSIG, this variable must be defined, unless + you specify a specific keytab using tkey-gssapi-keytab.

    tkey-dhkey

    @@ -2331,6 +2503,54 @@ category notify { null; }; described in the section called “The Statistics File”.

    +
    bindkeys-file
    +

    + The pathname of a file to override the built-in trusted + keys provided by named. + See the discussion of dnssec-lookaside + and dnssec-validation for details. + If not specified, the default is + /etc/bind.keys. +

    +
    secroots-file
    +

    + The pathname of the file the server dumps + security roots to when instructed to do so with + rndc secroots. + If not specified, the default is named.secroots. +

    +
    session-keyfile
    +

    + The pathname of the file into which to write a TSIG + session key generated by named for use by + nsupdate -l. If not specified, the + default is /var/run/named/session.key. + (See the section called “Dynamic Update Policies”, and in + particular the discussion of the + update-policy statement's + local option for more + information about this feature.) +

    +
    session-keyname
    +

    + The key name to use for the TSIG session key. + If not specified, the default is "local-ddns". +

    +
    session-keyalg
    +

    + The algorithm to use for the TSIG session key. + Valid values are hmac-sha1, hmac-sha224, hmac-sha256, + hmac-sha384, hmac-sha512 and hmac-md5. If not + specified, the default is hmac-sha256. +

    +
    session-keyfile
    +

    + The pathname of the file into which to write a session TSIG + key for use by nsupdate -l. (See the + discussion of the update-policy + statement's local option for more + details on this feature.) +

    port

    The UDP/TCP port number the server uses for @@ -2379,14 +2599,14 @@ category notify { null; };

    DS queries are expected to be made to and be answered by delegation only zones. Such queries and responses are - treated as a exception to delegation-only processing + treated as an exception to delegation-only processing and are not converted to NXDOMAIN responses provided a CNAME is not discovered at the query name.

    If a delegation only zone server also serves a child zone it is not always possible to determine whether - a answer comes from the delegation only zone or the + an answer comes from the delegation only zone or the child zone. SOA NS and DNSKEY records are apex only records and a matching response that contains these records or DS is treated as coming from a @@ -2423,42 +2643,138 @@ options { Only the most specific will be applied.

    dnssec-lookaside
    -

    - When set, dnssec-lookaside - provides the - validator with an alternate method to validate DNSKEY records - at the - top of a zone. When a DNSKEY is at or below a domain - specified by the - deepest dnssec-lookaside, and - the normal DNSSEC validation - has left the key untrusted, the trust-anchor will be append to - the key - name and a DLV record will be looked up to see if it can - validate the - key. If the DLV record validates a DNSKEY (similarly to the - way a DS +

    +

    + When set, dnssec-lookaside provides the + validator with an alternate method to validate DNSKEY + records at the top of a zone. When a DNSKEY is at or + below a domain specified by the deepest + dnssec-lookaside, and the normal DNSSEC + validation has left the key untrusted, the trust-anchor + will be appended to the key name and a DLV record will be + looked up to see if it can validate the key. If the DLV + record validates a DNSKEY (similarly to the way a DS record does) the DNSKEY RRset is deemed to be trusted. -

    +

    +

    + If dnssec-lookaside is set to + auto, then built-in default + values for the DLV domain and trust anchor will be + used, along with a built-in key for validation. +

    +

    + The default DLV key is stored in the file + bind.keys; + named will load that key at + startup if dnssec-lookaside is set to + auto. A copy of the file is + installed along with BIND 9, and is + current as of the release date. If the DLV key expires, a + new copy of bind.keys can be downloaded + from https://www.isc.org/solutions/dlv. +

    +

    + (To prevent problems if bind.keys is + not found, the current key is also compiled in to + named. Relying on this is not + recommended, however, as it requires named + to be recompiled with a new key when the DLV key expires.) +

    +

    + NOTE: named only loads certain specific + keys from bind.keys: those for the + DLV zone and for the DNS root zone. The file cannot be + used to store keys for other zones. +

    +
    dnssec-must-be-secure

    - Specify hierarchies which must be or may not be secure (signed and - validated). - If yes, then named will only accept - answers if they - are secure. - If no, then normal DNSSEC validation - applies - allowing for insecure answers to be accepted. - The specified domain must be under a trusted-key or - dnssec-lookaside must be - active. + Specify hierarchies which must be or may not be secure + (signed and validated). If yes, + then named will only accept answers if + they are secure. If no, then normal + DNSSEC validation applies allowing for insecure answers to + be accepted. The specified domain must be under a + trusted-keys or + managed-keys statement, or + dnssec-lookaside must be active.

    +
    dns64
    +
    +

    + This directive instructs named to + return mapped IPv4 addresses to AAAA queries when + there are no AAAA records. It is intended to be + used in conjunction with a NAT64. Each + dns64 defines one DNS64 prefix. + Multiple DNS64 prefixes can be defined. +

    +

    + Compatible IPv6 prefixes have lengths of 32, 40, 48, 56, + 64 and 96 as per RFC 6052. +

    +

    + Additionally a reverse IP6.ARPA zone will be created for + the prefix to provide a mapping from the IP6.ARPA names + to the corresponding IN-ADDR.ARPA names using synthesized + CNAMEs. dns64-server and + dns64-contact can be used to specify + the name of the server and contact for the zones. These + are settable at the view / options level. These are + not settable on a per-prefix basis. +

    +

    + Each dns64 supports an optional + clients ACL that determines which + clients are affected by this directive. If not defined, + it defaults to any;. +

    +

    + Each dns64 supports an optional + mapped ACL that selects which + IPv4 addresses are to be mapped in the corresponding + A RRset. If not defined it defaults to + any;. +

    +

    + Each dns64 supports an optional + exclude ACL that selects which + IPv6 addresses will be ignored for the purposes + of determining whether dns64 is to be applied. + Any non-matching address will prevent further + DNS64 processing from occurring for this client. +

    +

    + A optional suffix can also + be defined to set the bits trailing the mapped + IPv4 address bits. By default these bits are + set to ::. The bits + matching the prefix and mapped IPv4 address + must be zero. +

    +
    +        acl rfc1918 { 10/8; 192.168/16; 172.16/12; };
    +
    +        dns64 64:FF9B::/96 {
    +                clients { any; };
    +                mapped { !rfc1918; any; };
    +                exclude { 64:FF9B::/96; ::ffff:0000:0000/96; };
    +                suffix ::;
    +        };
    +
    +

    Boolean Options

    +
    allow-new-zones
    +

    + If yes, then zones can be + added at runtime via rndc addzone + or deleted via rndc delzone. + The default is no. +

    auth-nxdomain

    If yes, then the AA bit @@ -2863,6 +3179,7 @@ options { off on a per-zone basis by specifying zone-statistics no in the zone statement). + The default is no. These statistics may be accessed using rndc stats, which will dump them to the file listed @@ -3006,6 +3323,57 @@ options { internally. The use of this option is discouraged.

    +
    filter-aaaa-on-v4
    +
    +

    + This option is only available when + BIND 9 is compiled with the + --enable-filter-aaaa option on the + "configure" command line. It is intended to help the + transition from IPv4 to IPv6 by not giving IPv6 addresses + to DNS clients unless they have connections to the IPv6 + Internet. This is not recommended unless absolutely + necessary. The default is no. + The filter-aaaa-on-v4 option + may also be specified in view statements + to override the global filter-aaaa-on-v4 + option. +

    +

    + If yes, + the DNS client is at an IPv4 address, in filter-aaaa, + and if the response does not include DNSSEC signatures, + then all AAAA records are deleted from the response. + This filtering applies to all responses and not only + authoritative responses. +

    +

    + If break-dnssec, + then AAAA records are deleted even when dnssec is enabled. + As suggested by the name, this makes the response not verify, + because the DNSSEC protocol is designed detect deletions. +

    +

    + This mechanism can erroneously cause other servers to + not give AAAA records to their clients. + A recursing server with both IPv6 and IPv4 network connections + that queries an authoritative server using this mechanism + via IPv4 will be denied AAAA records even if its client is + using IPv6. +

    +

    + This mechanism is applied to authoritative as well as + non-authoritative records. + A client using IPv4 that is not allowed recursion can + erroneously be given AAAA records because the server is not + allowed to check for A records. +

    +

    + Some AAAA records are given to IPv4 clients in glue records. + IPv4 clients that are servers can then erroneously + answer requests for AAAA records received via IPv4. +

    +
    ixfr-from-differences

    @@ -3060,13 +3428,23 @@ options { Enable DNSSEC validation in named. Note dnssec-enable also needs to be set to yes to be effective. - The default is yes. + If set to no, DNSSEC validation + is disabled. If set to auto, + DNSSEC validation is enabled, and a default + trust-anchor for the DNS root zone is used. If set to + yes, DNSSEC validation is enabled, + but a trust anchor must be manually configured using + a trusted-keys or + managed-keys statement. The default + is yes.

    dnssec-accept-expired

    Accept expired signatures when verifying DNSSEC signatures. The default is no. - Setting this option to "yes" leaves named vulnerable to replay attacks. + Setting this option to yes + leaves named vulnerable to + replay attacks.

    querylog

    @@ -3104,6 +3482,14 @@ options { (the owner name ends in IN-ADDR.ARPA, IP6.ARPA, or IP6.INT).

    +
    check-dup-records
    +

    + Check master zones for records that are treated as different + by DNSSEC but are semantically equal in plain DNS. The + default is to warn. Other possible + values are fail and + ignore. +

    check-mx

    Check whether the MX record appears to refer to a IP address. @@ -3166,26 +3552,86 @@ options { The default is no.

    update-check-ksk
    -

    - When regenerating the RRSIGs following a UPDATE - request to a secure zone, check the KSK flag on - the DNSKEY RR to determine if this key should be - used to generate the RRSIG. This flag is ignored - if there are not DNSKEY RRs both with and without - a KSK. - The default is yes. -

    +
    +

    + When set to the default value of yes, + check the KSK bit in each key to determine how the key + should be used when generating RRSIGs for a secure zone. +

    +

    + Ordinarily, zone-signing keys (that is, keys without the + KSK bit set) are used to sign the entire zone, while + key-signing keys (keys with the KSK bit set) are only + used to sign the DNSKEY RRset at the zone apex. + However, if this option is set to no, + then the KSK bit is ignored; KSKs are treated as if they + were ZSKs and are used to sign the entire zone. This is + similar to the dnssec-signzone -z + command line option. +

    +

    + When this option is set to yes, there + must be at least two active keys for every algorithm + represented in the DNSKEY RRset: at least one KSK and one + ZSK per algorithm. If there is any algorithm for which + this requirement is not met, this option will be ignored + for that algorithm. +

    +
    +
    dnssec-dnskey-kskonly
    +
    +

    + When this option and update-check-ksk + are both set to yes, only key-signing + keys (that is, keys with the KSK bit set) will be used + to sign the DNSKEY RRset at the zone apex. Zone-signing + keys (keys without the KSK bit set) will be used to sign + the remainder of the zone, but not the DNSKEY RRset. + This is similar to the + dnssec-signzone -x command line option. +

    +

    + The default is no. If + update-check-ksk is set to + no, this option is ignored. +

    +
    try-tcp-refresh

    Try to refresh the zone using TCP if UDP queries fail. For BIND 8 compatibility, the default is yes.

    +
    dnssec-secure-to-insecure
    +
    +

    + Allow a dynamic zone to transition from secure to + insecure (i.e., signed to unsigned) by deleting all + of the DNSKEY records. The default is no. + If set to yes, and if the DNSKEY RRset + at the zone apex is deleted, all RRSIG and NSEC records + will be removed from the zone as well. +

    +

    + If the zone uses NSEC3, then it is also necessary to + delete the NSEC3PARAM RRset from the zone apex; this will + cause the removal of all corresponding NSEC3 records. + (It is expected that this requirement will be eliminated + in a future release.) +

    +

    + Note that if a zone has been configured with + auto-dnssec maintain and the + private keys remain accessible in the key repository, + then the zone will be automatically signed again the + next time named is started. +

    +

    -Forwarding

    +Forwarding

    The forwarding facility can be used to create a large site-wide cache on a few servers, reducing traffic over links to external @@ -3229,7 +3675,7 @@ options {

    -Dual-stack Servers

    +Dual-stack Servers

    Dual-stack servers are used as servers of last resort to work around @@ -3422,11 +3868,25 @@ options { from these addresses will not be responded to. The default is none.

    +
    filter-aaaa
    +

    + Specifies a list of addresses to which + filter-aaaa-on-v4 + is applies. The default is any. +

    +
    resolver-query-timeout
    +

    + The amount of time the resolver will spend attempting + to resolve a recursive query before failing. The + default is 10 and the maximum is + 30. Setting it to 0 + will result in the default being used. +

    -Interfaces

    +Interfaces

    The interfaces and ports that the server will answer queries from may be specified using the listen-on option. listen-on takes @@ -3878,7 +4338,7 @@ avoid-v6-udp-ports {};

    -UDP Port Lists

    +UDP Port Lists

    use-v4-udp-ports, avoid-v4-udp-ports, @@ -3920,7 +4380,7 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };

    -Operating System Resource Limits

    +Operating System Resource Limits

    The server's usage of many system resources can be limited. Scaled values are allowed when specifying resource limits. For @@ -4082,7 +4542,7 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };

    -Periodic Task Intervals

    +Periodic Task Intervals
    cleaning-interval

    @@ -4252,20 +4712,26 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; their directly connected networks.

    sortlist {
    -    { localhost;                                   // IF   the local host
    -        { localnets;                               // THEN first fit on the
    -            192.168.1/24;                          //   following nets
    +    // IF the local host
    +    // THEN first fit on the following nets
    +    { localhost;
    +        { localnets;
    +            192.168.1/24;
                 { 192.168.2/24; 192.168.3/24; }; }; };
    -    { 192.168.1/24;                                // IF   on class C 192.168.1
    -        { 192.168.1/24;                            // THEN use .1, or .2 or .3
    +    // IF on class C 192.168.1 THEN use .1, or .2 or .3
    +    { 192.168.1/24;
    +        { 192.168.1/24;
                 { 192.168.2/24; 192.168.3/24; }; }; };
    -    { 192.168.2/24;                                // IF   on class C 192.168.2
    -        { 192.168.2/24;                            // THEN use .2, or .1 or .3
    +    // IF on class C 192.168.2 THEN use .2, or .1 or .3
    +    { 192.168.2/24;
    +        { 192.168.2/24;
                 { 192.168.1/24; 192.168.3/24; }; }; };
    -    { 192.168.3/24;                                // IF   on class C 192.168.3
    -        { 192.168.3/24;                            // THEN use .3, or .1 or .2
    +    // IF on class C 192.168.3 THEN use .3, or .1 or .2
    +    { 192.168.3/24;
    +        { 192.168.3/24;
                 { 192.168.1/24; 192.168.2/24; }; }; };
    -    { { 192.168.4/24; 192.168.5/24; };             // if .4 or .5, prefer that net
    +    // IF .4 or .5 THEN prefer that net
    +    { { 192.168.4/24; 192.168.5/24; };
         };
     };

    @@ -4456,7 +4922,7 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; Specifies the number of days into the future when DNSSEC signatures automatically generated as a result of dynamic updates (the section called “Dynamic Update”) will expire. There - is a optional second field which specifies how + is an optional second field which specifies how long before expiry that the signatures will be regenerated. If not specified, the signatures will be regenerated at 1/4 of base interval. The second @@ -4537,30 +5003,46 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };

    edns-udp-size
    -

    +

    +

    Sets the advertised EDNS UDP buffer size in bytes to control the size of packets received. - Valid values are 512 to 4096 (values outside this range + Valid values are 1024 to 4096 (values outside this range will be silently adjusted). The default value is 4096. The usual reason for setting edns-udp-size to a non-default value is to get UDP answers to pass through broken firewalls that block fragmented packets and/or block UDP packets that are greater than 512 bytes. -

    +

    +

    + named will fallback to using 512 bytes + if it get a series of timeout at the initial value. 512 + bytes is not being offered to encourage sites to fix their + firewalls. Small EDNS UDP sizes will result in the + excessive use of TCP. +

    +
    max-udp-size
    -

    - Sets the maximum EDNS UDP message size named will - send in bytes. Valid values are 512 to 4096 (values outside - this range will be silently adjusted). The default +

    +

    + Sets the maximum EDNS UDP message size + named will send in bytes. + Valid values are 512 to 4096 (values outside this + range will be silently adjusted). The default value is 4096. The usual reason for setting - max-udp-size to a non-default value is to get UDP - answers to pass through broken firewalls that - block fragmented packets and/or block UDP packets - that are greater than 512 bytes. + max-udp-size to a non-default + value is to get UDP answers to pass through broken + firewalls that block fragmented packets and/or + block UDP packets that are greater than 512 bytes. This is independent of the advertised receive buffer (edns-udp-size). -

    +

    +

    + Setting this to a low value will encourage additional + TCP traffic to the nameserver. +

    +
    masterfile-format

    Specifies the file format of zone files (see @@ -4705,7 +5187,7 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };

    Named will attempt to determine if a built-in zone already exists or is active (covered by a forward-only forwarding declaration) - and will not create a empty zone in that case. + and will not create an empty zone in that case.

    The current list of empty zones is: @@ -4873,6 +5355,260 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };

    +
    +

    +Content Filtering

    +

    + BIND 9 provides the ability to filter + out DNS responses from external DNS servers containing + certain types of data in the answer section. + Specifically, it can reject address (A or AAAA) records if + the corresponding IPv4 or IPv6 addresses match the given + address_match_list of the + deny-answer-addresses option. + It can also reject CNAME or DNAME records if the "alias" + name (i.e., the CNAME alias or the substituted query name + due to DNAME) matches the + given namelist of the + deny-answer-aliases option, where + "match" means the alias name is a subdomain of one of + the name_list elements. + If the optional namelist is specified + with except-from, records whose query name + matches the list will be accepted regardless of the filter + setting. + Likewise, if the alias name is a subdomain of the + corresponding zone, the deny-answer-aliases + filter will not apply; + for example, even if "example.com" is specified for + deny-answer-aliases, +

    +
    www.example.com. CNAME xxx.example.com.
    +

    + returned by an "example.com" server will be accepted. +

    +

    + In the address_match_list of the + deny-answer-addresses option, only + ip_addr + and ip_prefix + are meaningful; + any key_id will be silently ignored. +

    +

    + If a response message is rejected due to the filtering, + the entire message is discarded without being cached, and + a SERVFAIL error will be returned to the client. +

    +

    + This filtering is intended to prevent "DNS rebinding attacks," in + which an attacker, in response to a query for a domain name the + attacker controls, returns an IP address within your own network or + an alias name within your own domain. + A naive web browser or script could then serve as an + unintended proxy, allowing the attacker + to get access to an internal node of your local network + that couldn't be externally accessed otherwise. + See the paper available at + + http://portal.acm.org/citation.cfm?id=1315245.1315298 + + for more details about the attacks. +

    +

    + For example, if you own a domain named "example.net" and + your internal network uses an IPv4 prefix 192.0.2.0/24, + you might specify the following rules: +

    +
    deny-answer-addresses { 192.0.2.0/24; } except-from { "example.net"; };
    +deny-answer-aliases { "example.net"; };
    +
    +

    + If an external attacker lets a web browser in your local + network look up an IPv4 address of "attacker.example.com", + the attacker's DNS server would return a response like this: +

    +
    attacker.example.com. A 192.0.2.1
    +

    + in the answer section. + Since the rdata of this record (the IPv4 address) matches + the specified prefix 192.0.2.0/24, this response will be + ignored. +

    +

    + On the other hand, if the browser looks up a legitimate + internal web server "www.example.net" and the + following response is returned to + the BIND 9 server +

    +
    www.example.net. A 192.0.2.2
    +

    + it will be accepted since the owner name "www.example.net" + matches the except-from element, + "example.net". +

    +

    + Note that this is not really an attack on the DNS per se. + In fact, there is nothing wrong for an "external" name to + be mapped to your "internal" IP address or domain name + from the DNS point of view. + It might actually be provided for a legitimate purpose, + such as for debugging. + As long as the mapping is provided by the correct owner, + it is not possible or does not make sense to detect + whether the intent of the mapping is legitimate or not + within the DNS. + The "rebinding" attack must primarily be protected at the + application that uses the DNS. + For a large site, however, it may be difficult to protect + all possible applications at once. + This filtering feature is provided only to help such an + operational environment; + it is generally discouraged to turn it on unless you are + very sure you have no other choice and the attack is a + real threat for your applications. +

    +

    + Care should be particularly taken if you want to use this + option for addresses within 127.0.0.0/8. + These addresses are obviously "internal", but many + applications conventionally rely on a DNS mapping from + some name to such an address. + Filtering out DNS records containing this address + spuriously can break such applications. +

    +
    +
    +

    +Response Policy Zone (RPZ) Rewriting

    +

    + BIND 9 includes an intentionally limited + mechanism to modify DNS responses for recursive requests + similar to email anti-spam DNS blacklists. + All response policy zones are named in the + response-policy option for the view or among the + global options if there is no response-policy option for the view. +

    +

    + The rules encoded in a response policy zone (RPZ) are applied + only to responses to queries that ask for recursion (RD=1). + RPZs are normal DNS zones containing RRsets + that can be queried normally if allowed. + It is usually best to restrict those queries with something like + allow-query {none; }; or + allow-query { 127.0.0.1; };. +

    +

    + There are four kinds of RPZ rewrite rules. QNAME rules are + applied to query names in requests and to targets of CNAME + records resolved in the process of generating the response. + The owner name of a QNAME rule is the query name relativized + to the RPZ. + The records in a rewrite rule are usually A, AAAA, or special + CNAMEs, but can be any type except DNAME. +

    +

    + IP rules are triggered by addresses in A and AAAA records. + All IP addresses in A or AAAA RRsets are tested and the rule + longest prefix is applied. Ties between rules with equal prefixes + are broken in favor of the first RPZ mentioned in the + response-policy option. + The rule matching the smallest IP address is chosen among equal + prefix rules from a single RPZ. + IP rules are expressed in RRsets with owner names that are + subdomains of rpz-ip and encoding an IP address block, reversed + as in IN-ARPA. + prefix.B.B.B.B with prefix between 1 and 32 and B between 1 and 255 + encodes an IPv4 address. + IPv6 addresses are encoded by with prefix.W.W.W.W.W.W.W.W or + prefix.WORDS.zz.WORDS. The words in the standard IPv6 text + representation are reversed, "::" is replaced with ".zz.", + and ":" becomes ".". +

    +

    + NSDNAME rules match names in NS RRsets for the response or a + parent. They are encoded as subdomains of rpz-nsdomain relativized + to the RPZ origin name. +

    +

    + NSIP rules match IP addresses in A and AAAA RRsets for names of + responsible servers or the names that can be matched by NSDNAME + rules. The are encoded like IP rules except as subdomains of + rpz-nsip. +

    +

    + Authority verification issues and variations in authority data in + the current version of BIND 9 can cause + inconsistent results from NSIP and NSDNAME. So they are available + only when BIND is built with the + --enable-rpz-nsip or + --enable-rpz-nsdname options + on the "configure" command line. +

    +

    + Four policies can be expressed. + The NXDOMAIN policy causes a NXDOMAIN response + and is expressed with an RRset consisting of a single CNAME + whose target is the root domain (.). + NODATA generates NODATA or ANCOUNT=1 regardless + of query type. + It is expressed with a CNAME whose target is the wildcard + top-level domain (*.). + The NO-OP policy does not change the response + and is used to "poke holes" in policies for larger CIDR blocks or in + zones named later in the response-policy option. + The NO-OP policy is expressed by a CNAME with a target consisting + of the variable part of the owner name, such as "example.com." for + a QNAME rule or "128.1.0.0.127." for an IP rule. + The CNAME policy is used to replace the RRsets + of response. + A and AAAA RRsets are most common and useful to capture + an evil domain in a walled garden, but any valid set of RRsets + is possible. +

    +

    + All of the policies in an RPZ can be overridden with a + policy clause. + given says "do not override." + no-op says "do nothing" regardless of the policy + in RPZ records. + nxdomain causes all RPZ rules to generate + NXDOMAIN results. + nodata gives nodata. + cname domain causes all RPZ rules to act as if + the consisted of a "cname domain" record. +

    +

    + For example, you might use this option statement +

    +
    response-policy { zone "bl"; };
    +

    + and this zone statement +

    +
    zone "bl" {type master; file "example/bl"; allow-query {none;}; };
    +

    + with this zone file +

    +
    $TTL 1H
    +@                   SOA LOCALHOST. named-mgr.example.com (1 1h 15m 30d 2h)
    +
    +; QNAME rules
    +nxdomain.domain.com         CNAME   .
    +nodata.domain.com           CNAME   *.
    +bad.domain.com              A       10.0.0.1
    +                            AAAA    2001:2::1
    +ok.domain.com               CNAME   ok.domain.com.
    +*.badzone.domain.com        CNAME   garden.example.com.
    +
    +; IP rules rewriting all answers for 127/8 except 127.0.0.1
    +8.0.0.0.127.ip              CNAME   .
    +32.1.0.0.127.ip             CNAME   32.1.0.0.127.
    +
    +; NSDNAME and NSIP rules
    +ns.domain.com.rpz-nsdname   CNAME   .
    +48.zz.2.2001.rpz-nsip       CNAME   .
    +
    +

    @@ -4891,8 +5627,10 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; [ transfer-source-v6 (ip6_addr | *) [port ip_port] ; ] [ notify-source (ip4_addr | *) [port ip_port] ; ] [ notify-source-v6 (ip6_addr | *) [port ip_port] ; ] - [ query-source [ address ( ip_addr | * ) ] [ port ( ip_port | * ) ]; ] - [ query-source-v6 [ address ( ip_addr | * ) ] [ port ( ip_port | * ) ]; ] + [ query-source [ address ( ip_addr | * ) ] + [ port ( ip_port | * ) ]; ] + [ query-source-v6 [ address ( ip_addr | * ) ] + [ port ( ip_port | * ) ]; ] [ use-queryport-pool yes_or_no; ] [ queryport-pool-ports number; ] [ queryport-pool-updateinterval number; ] @@ -5072,14 +5810,15 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };

    statistics-channels Statement Grammar

    statistics-channels {
    -   [ inet ( ip_addr | * ) [ port ip_port ] [allow {  address_match_list  } ]; ]
    +   [ inet ( ip_addr | * ) [ port ip_port ]
    +   [ allow {  address_match_list  } ]; ]
        [ inet ...; ]
     };
     

    -statistics-channels Statement Definition and +statistics-channels Statement Definition and Usage

    The statistics-channels statement @@ -5130,7 +5869,7 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };

    -trusted-keys Statement Grammar

    +trusted-keys Statement Grammar
    trusted-keys {
         string number number number string ;
         [ string number number number string ; [...]]
    @@ -5139,7 +5878,7 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };
     

    -trusted-keys Statement Definition +trusted-keys Statement Definition and Usage

    The trusted-keys statement defines @@ -5169,6 +5908,135 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; in the key data, so the configuration may be split up into multiple lines.

    +

    + trusted-keys may be set at the top level + of named.conf or within a view. If it is + set in both places, they are additive: keys defined at the top + level are inherited by all views, but keys defined in a view + are only used within that view. +

    +
    +
    +

    +managed-keys Statement Grammar

    +
    managed-keys {
    +    string initial-key number number number string ;
    +    [ string initial-key number number number string ; [...]]
    +};
    +
    +
    +
    +

    +managed-keys Statement Definition + and Usage

    +

    + The managed-keys statement, like + trusted-keys, defines DNSSEC + security roots. The difference is that + managed-keys can be kept up to date + automatically, without intervention from the resolver + operator. +

    +

    + Suppose, for example, that a zone's key-signing + key was compromised, and the zone owner had to revoke and + replace the key. A resolver which had the old key in a + trusted-keys statement would be + unable to validate this zone any longer; it would + reply with a SERVFAIL response code. This would + continue until the resolver operator had updated the + trusted-keys statement with the new key. +

    +

    + If, however, the zone were listed in a + managed-keys statement instead, then the + zone owner could add a "stand-by" key to the zone in advance. + named would store the stand-by key, and + when the original key was revoked, named + would be able to transition smoothly to the new key. It would + also recognize that the old key had been revoked, and cease + using that key to validate answers, minimizing the damage that + the compromised key could do. +

    +

    + A managed-keys statement contains a list of + the keys to be managed, along with information about how the + keys are to be initialized for the first time. The only + initialization method currently supported (as of + BIND 9.7.0) is initial-key. + This means the managed-keys statement must + contain a copy of the initializing key. (Future releases may + allow keys to be initialized by other methods, eliminating this + requirement.) +

    +

    + Consequently, a managed-keys statement + appears similar to a trusted-keys, differing + in the presence of the second field, containing the keyword + initial-key. The difference is, whereas the + keys listed in a trusted-keys continue to be + trusted until they are removed from + named.conf, an initializing key listed + in a managed-keys statement is only trusted + once: for as long as it takes to load the + managed key database and start the RFC 5011 key maintenance + process. +

    +

    + The first time named runs with a managed key + configured in named.conf, it fetches the + DNSKEY RRset directly from the zone apex, and validates it + using the key specified in the managed-keys + statement. If the DNSKEY RRset is validly signed, then it is + used as the basis for a new managed keys database. +

    +

    + From that point on, whenever named runs, it + sees the managed-keys statement, checks to + make sure RFC 5011 key maintenance has already been initialized + for the specified domain, and if so, it simply moves on. The + key specified in the managed-keys is not + used to validate answers; it has been superseded by the key or + keys stored in the managed keys database. +

    +

    + The next time named runs after a name + has been removed from the + managed-keys statement, the corresponding + zone will be removed from the managed keys database, + and RFC 5011 key maintenance will no longer be used for that + domain. +

    +

    + named only maintains a single managed keys + database; consequently, unlike trusted-keys, + managed-keys may only be set at the top + level of named.conf, not within a view. +

    +

    + In the current implementation, the managed keys database is + stored as a master-format zone file called + managed-keys.bind. When the key database + is changed, the zone is updated. As with any other dynamic + zone, changes will be written into a journal file, + managed-keys.bind.jnl. They are committed + to the master file as soon as possible afterward; in the case + of the managed key database, this will usually occur within 30 + seconds. So, whenever named is using + automatic key maintenance, those two files can be expected to + exist in the working directory. (For this reason among others, + the working directory should be always be writable by + named.) +

    +

    + If the dnssec-lookaside option is + set to auto, named + will automatically initialize a managed key for the + zone dlv.isc.org. The key that is + used to initialize the key maintenance process is built + into named, and can be overridden + from bindkeys-file. +

    @@ -5185,7 +6053,7 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };

    -view Statement Definition and Usage

    +view Statement Definition and Usage

    The view statement is a powerful feature @@ -5274,11 +6142,12 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; // This should match our internal networks. match-clients { 10.0.0.0/8; }; - // Provide recursive service to internal clients only. + // Provide recursive service to internal + // clients only. recursion yes; - // Provide a complete view of the example.com zone - // including addresses of internal hosts. + // Provide a complete view of the example.com + // zone including addresses of internal hosts. zone "example.com" { type master; file "example-internal.db"; @@ -5286,14 +6155,15 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; }; view "external" { - // Match all clients not matched by the previous view. + // Match all clients not matched by the + // previous view. match-clients { any; }; // Refuse recursive service to external clients. recursion no; - // Provide a restricted view of the example.com zone - // containing only publicly accessible hosts. + // Provide a restricted view of the example.com + // zone containing only publicly accessible hosts. zone "example.com" { type master; file "example-external.db"; @@ -5311,8 +6181,9 @@ view "external" { [ allow-query-on { address_match_list }; ] [ allow-transfer { address_match_list }; ] [ allow-update { address_match_list }; ] - [ update-policy { update_policy_rule [...] }; ] - [ also-notify { ip_addr [port ip_port] ; [ ip_addr [port ip_port] ; ... ] }; ] + [ update-policy local | { update_policy_rule [...] }; ] + [ also-notify { ip_addr [port ip_port] ; + [ ip_addr [port ip_port] ; ... ] }; ] [ check-names (warn|fail|ignore) ; ] [ check-mx (warn|fail|ignore) ; ] [ check-wildcard yes_or_no; ] @@ -5348,6 +6219,7 @@ view "external" { [ min-retry-time number ; ] [ max-retry-time number ; ] [ key-directory path_name; ] + [ auto-dnssec allow|maintain|create|off; ] [ zero-no-soa-ttl yes_or_no ; ] }; @@ -5359,8 +6231,11 @@ zone zone_name [ allow-transfer { address_match_list }; ] [ allow-update-forwarding { address_match_list }; ] [ update-check-ksk yes_or_no; ] + [ dnssec-dnskey-kskonly yes_or_no; ] + [ dnssec-secure-to-insecure yes_or_no ; ] [ try-tcp-refresh yes_or_no; ] - [ also-notify { ip_addr [port ip_port] ; [ ip_addr [port ip_port] ; ... ] }; ] + [ also-notify { ip_addr [port ip_port] ; + [ ip_addr [port ip_port] ; ... ] }; ] [ check-names (warn|fail|ignore) ; ] [ dialup dialup_option ; ] [ file string ; ] @@ -5373,7 +6248,9 @@ zone zone_name [ ixfr-from-differences yes_or_no; ] [ ixfr-tmp-file string ; ] [ maintain-ixfr-base yes_or_no ; ] - [ masters [port ip_port] { ( masters_list | ip_addr [port ip_port] [key key] ) ; [...] }; ] + [ masters [port ip_port] { ( masters_list | ip_addr + [port ip_port] + [key key] ) ; [...] }; ] [ max-ixfr-log-size number ; ] [ max-transfer-idle-in number ; ] [ max-transfer-idle-out number ; ] @@ -5386,7 +6263,8 @@ zone zone_name [ transfer-source (ip4_addr | *) [port ip_port] ; ] [ transfer-source-v6 (ip6_addr | *) [port ip_port] ; ] [ alt-transfer-source (ip4_addr | *) [port ip_port] ; ] - [ alt-transfer-source-v6 (ip6_addr | *) [port ip_port] ; ] + [ alt-transfer-source-v6 (ip6_addr | *) + [port ip_port] ; ] [ use-alt-transfer-source yes_or_no; ] [ notify-source (ip4_addr | *) [port ip_port] ; ] [ notify-source-v6 (ip6_addr | *) [port ip_port] ; ] @@ -5404,7 +6282,7 @@ zone zone_name [string ; [ delegation-only yes_or_no ; ] - [ check-names (warn|fail|ignore) ; // Not Implemented. ] + [ check-names (warn|fail|ignore) ; ] // Not Implemented. }; zone zone_name [class] { @@ -5418,14 +6296,18 @@ zone zone_name [ masterfile-format (text|raw) ; ] [ forward (only|first) ; ] [ forwarders { [ ip_addr [port ip_port] ; ... ] }; ] - [ masters [port ip_port] { ( masters_list | ip_addr [port ip_port] [key key] ) ; [...] }; ] + [ masters [port ip_port] { ( masters_list | ip_addr + [port ip_port] + [key key] ) ; [...] }; ] [ max-transfer-idle-in number ; ] [ max-transfer-time-in number ; ] [ pubkey number number number string ; ] [ transfer-source (ip4_addr | *) [port ip_port] ; ] - [ transfer-source-v6 (ip6_addr | *) [port ip_port] ; ] + [ transfer-source-v6 (ip6_addr | *) + [port ip_port] ; ] [ alt-transfer-source (ip4_addr | *) [port ip_port] ; ] - [ alt-transfer-source-v6 (ip6_addr | *) [port ip_port] ; ] + [ alt-transfer-source-v6 (ip6_addr | *) + [port ip_port] ; ] [ use-alt-transfer-source yes_or_no; ] [ zone-statistics yes_or_no ; ] [ database string ; ] @@ -5437,6 +6319,14 @@ zone zone_name [zone_name [class] { + type static-stub; + [ allow-query { address_match_list }; ] + [ server-addresses { [ ip_addr ; ... ] }; ] + [ server-names { [ namelist ] }; ] + [ zone-statistics yes_or_no ; ] +}; + +zone zone_name [class] { type forward; [ forward (only|first) ; ] [ forwarders { [ ip_addr [port ip_port] ; ... ] }; ] @@ -5451,10 +6341,10 @@ zone zone_name [

    -zone Statement Definition and Usage

    +zone Statement Definition and Usage

    -Zone Types

    +Zone Types
    @@ -5583,6 +6473,55 @@ zone zone_name [ + + + + @@ -5665,7 +6604,7 @@ zone zone_name [

    -Class

    +Class

    The zone's name may optionally be followed by a class. If a class is not specified, class IN (for Internet), @@ -5687,7 +6626,7 @@ zone zone_name [

    -Zone Options

    +Zone Options
    allow-notify

    @@ -5752,6 +6691,7 @@ zone zone_name [master zones the default is fail. For slave zones the default is warn. + It is not implemented for hint zones.

    check-mx

    @@ -5783,6 +6723,11 @@ zone zone_name [update-check-ksk in the section called “Boolean Options”.

    +
    dnssec-dnskey-kskonly
    +

    + See the description of + dnssec-dnskey-kskonly in the section called “Boolean Options”. +

    try-tcp-refresh

    See the description of @@ -5926,6 +6871,78 @@ zone zone_name [statistics-file defined in the server options.

    +
    server-addresses
    +
    +

    + Only meaningful for static-stub zones. + This is a list of IP addresses to which queries + should be sent in recursive resolution for the + zone. + A non empty list for this option will internally + configure the apex NS RR with associated glue A or + AAAA RRs. +

    +

    + For example, if "example.com" is configured as a + static-stub zone with 192.0.2.1 and 2001:db8::1234 + in a server-addresses option, + the following RRs will be internally configured. +

    +
    example.com. NS example.com.
    +example.com. A 192.0.2.1
    +example.com. AAAA 2001:db8::1234
    +

    + These records are internally used to resolve + names under the static-stub zone. + For instance, if the server receives a query for + "www.example.com" with the RD bit on, the server + will initiate recursive resolution and send + queries to 192.0.2.1 and/or 2001:db8::1234. +

    +
    +
    server-names
    +
    +

    + Only meaningful for static-stub zones. + This is a list of domain names of nameservers that + act as authoritative servers of the static-stub + zone. + These names will be resolved to IP addresses when + named needs to send queries to + these servers. + To make this supplemental resolution successful, + these names must not be a subdomain of the origin + name of static-stub zone. + That is, when "example.net" is the origin of a + static-stub zone, "ns.example" and + "master.example.com" can be specified in the + server-names option, but + "ns.example.net" cannot, and will be rejected by + the configuration parser. +

    +

    + A non empty list for this option will internally + configure the apex NS RR with the specified names. + For example, if "example.com" is configured as a + static-stub zone with "ns1.example.net" and + "ns2.example.net" + in a server-names option, + the following RRs will be internally configured. +

    +
    example.com. NS ns1.example.net.
    +example.com. NS ns2.example.net.
    +
    +

    + These records are internally used to resolve + names under the static-stub zone. + For instance, if the server receives a query for + "www.example.com" with the RD bit on, the server + initiate recursive resolution, + resolve "ns1.example.net" and/or + "ns2.example.net" to IP addresses, and then send + queries to (one or more of) these addresses. +

    +
    sig-validity-interval

    See the description of @@ -6003,6 +7020,48 @@ zone zone_name [the section called “options Statement Definition and Usage”.

    +
    auto-dnssec
    +
    +

    + Zones configured for dynamic DNS may also use this + option to allow varying levels of automatic DNSSEC key + management. There are four possible settings: +

    +

    + auto-dnssec allow; permits + keys to be updated and the zone fully re-signed + whenever the user issues the command rndc sign + zonename. +

    +

    + auto-dnssec maintain; includes the + above, but also automatically adjusts the zone's DNSSEC + keys on schedule, according to the keys' timing metadata + (see dnssec-keygen(8) and + dnssec-settime(8)). The command + rndc sign + zonename causes + named to load keys from the key + repository and sign the zone with all keys that are + active. + rndc loadkeys + zonename causes + named to load keys from the key + repository and schedule key maintenance events to occur + in the future, but it does not sign the full zone + immediately. +

    +

    + auto-dnssec create; includes the + above, but also allows named + to create new keys in the key repository when needed. + (NOTE: This option is not yet implemented; the syntax is + being reserved for future use.) +

    +

    + The default setting is auto-dnssec off. +

    +
    multi-master

    See the description of multi-master in @@ -6013,6 +7072,11 @@ zone zone_name [masterfile-format in the section called “Tuning”.

    +
    dnssec-secure-to-insecure
    +

    + See the description of + dnssec-secure-to-insecure in the section called “Boolean Options”. +

    @@ -6031,15 +7095,14 @@ zone zone_name [

    - The update-policy clause is new - in BIND 9 and allows more fine-grained - control over what updates are allowed. A set of rules - is specified, where each rule either grants or denies - permissions for one or more names to be updated by - one or more identities. If the dynamic update request - message is signed (that is, it includes either a TSIG - or SIG(0) record), the identity of the signer can be - determined. + The update-policy clause + allows more fine-grained control over what updates are + allowed. A set of rules is specified, where each rule + either grants or denies permissions for one or more + names to be updated by one or more identities. If + the dynamic update request message is signed (that is, + it includes either a TSIG or SIG(0) record), the + identity of the signer can be determined.

    Rules are specified in the update-policy @@ -6052,20 +7115,47 @@ zone zone_name [

    - This is how a rule definition looks: + There is a pre-defined update-policy + rule which can be switched on with the command + update-policy local;. + Switching on this rule in a zone causes + named to generate a TSIG session + key and place it in a file, and to allow that key + to update the zone. (By default, the file is + /var/run/named/session.key, the key + name is "local-ddns" and the key algorithm is HMAC-SHA256, + but these values are configurable with the + session-keyfile, + session-keyname and + session-keyalg options, respectively). +

    +

    + A client running on the local system, and with appropriate + permissions, may read that file and use the key to sign update + requests. The zone's update policy will be set to allow that + key to change any record within the zone. Assuming the + key name is "local-ddns", this policy is equivalent to: +

    +
    update-policy { grant local-ddns zonesub any; };
    +            
    +

    + The command nsupdate -l sends update + requests to localhost, and signs them using the session key. +

    +

    + Other rule definitions look like this:

    -( grant | deny ) identity nametype name [ types ]
    +( grant | deny ) identity nametype [ name ] [ types ]
     

    Each rule grants or denies privileges. Once a message has successfully matched a rule, the operation is immediately - granted - or denied and no further rules are examined. A rule is matched - when the signer matches the identity field, the name matches the - name field in accordance with the nametype field, and the type - matches - the types specified in the type field. + granted or denied and no further rules are examined. A rule + is matched when the signer matches the identity field, the + name matches the name field in accordance with the nametype + field, and the type matches the types specified in the type + field.

    No signer is required for tcp-self @@ -6091,7 +7181,7 @@ zone zone_name [

    - The nametype field has 12 + The nametype field has 13 values: name, subdomain, wildcard, self, @@ -6099,7 +7189,8 @@ zone zone_name [krb5-self, ms-self, krb5-subdomain, ms-subdomain, - tcp-self and 6to4-self. + tcp-self, 6to4-self, + zonesub, and external.

    + static-stub +

    +
    +

    + A static-stub zone is similar to a stub zone + with the following exceptions: + the zone data is statically configured, rather + than transferred from a master server; + when recursion is necessary for a query that + matches a static-stub zone, the locally + configured data (nameserver names and glue addresses) + is always used even if different authoritative + information is cached. +

    +

    + Zone data is configured via the + server-addresses and + server-names zone options. +

    +

    + The zone data is maintained in the form of NS + and (if necessary) glue A or AAAA RRs + internally, which can be seen by dumping zone + databases by rndc dumpdb -all. + The configured RRs are considered local configuration + parameters rather than public data. + Non recursive queries (i.e., those with the RD + bit off) to a static-stub zone are therefore + prohibited and will be responded with REFUSED. +

    +

    + Since the data is statically configured, no + zone maintenance action takes place for a static-stub + zone. + For example, there is no periodic refresh + attempt, and an incoming notify message + will be rejected with an rcode of NOTAUTH. +

    +

    + Each static-stub zone is configured with + internally generated NS and (if necessary) + glue A or AAAA RRs +

    +
    +

    forward

    @@ -6140,6 +7231,29 @@ zone zone_name [ + + + + @@ -6233,7 +7347,7 @@ zone zone_name [

    Allow the 6to4 prefix to be update by any TCP - conection from the 6to4 network or from the + connection from the 6to4 network or from the corresponding IPv4 address. This is intended to allow NS or DNAME RRsets to be added to the reverse tree. @@ -6245,12 +7359,55 @@ zone zone_name [

    + + + +

    + zonesub +

    +
    +

    + This rule is similar to subdomain, except that + it matches when the name being updated is a + subdomain of the zone in which the + update-policy statement + appears. This obviates the need to type the zone + name twice, and enables the use of a standard + update-policy statement in + multiple zones without modification. +

    +

    + When this rule is used, the + name field is omitted. +

    +
    +

    wildcard

    +

    + external +

    +
    +

    + This rule allows named + to defer the decision of whether to allow a + given update to an external daemon. +

    +

    + The method of communicating with the daemon is + specified in the identity + field, the format of which is + "local:path", + where path is the location + of a UNIX-domain socket. (Currently, "local" is the + only supported mechanism.) +

    +

    + Requests to the external daemon are sent over the + UNIX-domain socket as datagrams with the following + format: +

    +
    +   Protocol version number (4 bytes, network byte order, currently 1)
    +   Request length (4 bytes, network byte order)
    +   Signer (null-terminated string)
    +   Name (null-terminated string)
    +   TCP source address (null-terminated string)
    +   Rdata type (null-terminated string)
    +   Key (null-terminated string)
    +   TKEY token length (4 bytes, network byte order)
    +   TKEY token (remainder of packet)
    +

    + The daemon replies with a four-byte value in + network byte order, containing either 0 or 1; 0 + indicates that the specified update is not + permitted, and 1 indicates that it is. +

    +

    In all cases, the name - field must - specify a fully-qualified domain name. + field must specify a fully-qualified domain name.

    If no types are explicitly specified, this rule matches @@ -6266,7 +7423,7 @@ zone zone_name [

    -Zone File

    +Zone File

    Types of Resource Records and When to Use Them

    @@ -6279,7 +7436,7 @@ zone zone_name [

    -Resource Records

    +Resource Records

    A domain name identifies a node. Each node has a set of resource information, which may be empty. The set of resource @@ -7016,7 +8173,7 @@ zone zone_name [

    -Textual expression of RRs

    +Textual expression of RRs

    RRs are represented in binary form in the packets of the DNS protocol, and are usually represented in highly encoded form @@ -7219,7 +8376,7 @@ zone zone_name [

    -Discussion of MX Records

    +Discussion of MX Records

    As described above, domain servers store information as a series of resource records, each of which contains a particular @@ -7475,7 +8632,7 @@ zone zone_name [

    -Inverse Mapping in IPv4

    +Inverse Mapping in IPv4

    Reverse name resolution (that is, translation from IP address to name) is achieved by means of the in-addr.arpa domain @@ -7536,7 +8693,7 @@ zone zone_name [

    -Other Zone File Directives

    +Other Zone File Directives

    The Master File Format was initially defined in RFC 1035 and has subsequently been extended. While the Master File Format @@ -7551,7 +8708,7 @@ zone zone_name [

    -The @ (at-sign)

    +The @ (at-sign)

    When used in the label (or name) field, the asperand or at-sign (@) symbol represents the current origin. @@ -7562,7 +8719,7 @@ zone zone_name [

    -The $ORIGIN Directive

    +The $ORIGIN Directive

    Syntax: $ORIGIN domain-name @@ -7591,7 +8748,7 @@ WWW.EXAMPLE.COM. CNAME MAIN-SERVER.EXAMPLE.COM.

    -The $INCLUDE Directive

    +The $INCLUDE Directive

    Syntax: $INCLUDE filename @@ -7627,7 +8784,7 @@ WWW.EXAMPLE.COM. CNAME MAIN-SERVER.EXAMPLE.COM.

    -The $TTL Directive

    +The $TTL Directive

    Syntax: $TTL default-ttl @@ -7646,7 +8803,7 @@ WWW.EXAMPLE.COM. CNAME MAIN-SERVER.EXAMPLE.COM.

    -BIND Master File Extension: the $GENERATE Directive

    +BIND Master File Extension: the $GENERATE Directive

    Syntax: $GENERATE range @@ -7666,7 +8823,7 @@ WWW.EXAMPLE.COM. CNAME MAIN-SERVER.EXAMPLE.COM. Classless IN-ADDR.ARPA delegation.

    $ORIGIN 0.0.192.IN-ADDR.ARPA.
    -$GENERATE 1-2 0 NS SERVER$.EXAMPLE.
    +$GENERATE 1-2 @ NS SERVER$.EXAMPLE.
     $GENERATE 1-127 $ CNAME $.0

    is equivalent to @@ -7678,6 +8835,28 @@ $GENERATE 1-127 $ CNAME $.0

    ... 127.0.0.192.IN-ADDR.ARPA. CNAME 127.0.0.0.192.IN-ADDR.ARPA.
    +

    + Generate a set of A and MX records. Note the MX's right hand + side is a quoted string. The quotes will be stripped when the + right hand side is processed. +

    +
    +$ORIGIN EXAMPLE.
    +$GENERATE 1-127 HOST-$ A 1.2.3.$
    +$GENERATE 1-127 HOST-$ MX "0 ."
    +

    + is equivalent to +

    +
    HOST-1.EXAMPLE.   A  1.2.3.1
    +HOST-1.EXAMPLE.   MX 0 .
    +HOST-2.EXAMPLE.   A  1.2.3.2
    +HOST-2.EXAMPLE.   MX 0 .
    +HOST-3.EXAMPLE.   A  1.2.3.3
    +HOST-3.EXAMPLE.   MX 0 .
    +...
    +HOST-127.EXAMPLE. A  1.2.3.127
    +HOST-127.EXAMPLE. MX 0 .
    +
    @@ -7728,8 +8907,10 @@ $GENERATE 1-127 $ CNAME $.0 Available output forms are decimal (d), octal - (o) and hexadecimal + (o), hexadecimal (x or X + for uppercase) and nibble + (n or N\ for uppercase). The default modifier is ${0,0,d}. If the lhs is not absolute, the @@ -7737,8 +8918,16 @@ $GENERATE 1-127 $ CNAME $.0 to the name.

    - For compatibility with earlier versions, $$ is still - recognized as indicating a literal $ in the output. + In nibble mode the value will be treated as + if it was a reversed hexadecimal string + with each hexadecimal digit as a separate + label. The width field includes the label + separator. +

    +

    + For compatibility with earlier versions, + $$ is still recognized as + indicating a literal $ in the output.

    @@ -7780,8 +8969,7 @@ $GENERATE 1-127 $ CNAME $.0 @@ -7791,8 +8979,7 @@ $GENERATE 1-127 $ CNAME $.0 @@ -7942,9 +9129,12 @@ $GENERATE 1-127 $ CNAME $.0 @@ -8037,7 +9227,7 @@ $GENERATE 1-127 $ CNAME $.0

    -Name Server Statistics Counters

    +Name Server Statistics Counters

    - At present the only supported types are - PTR, CNAME, DNAME, A, AAAA and NS. + Any valid type.

    - rhs is a domain name. It is processed - similarly to lhs. + rhs, optionally, quoted string.

    - The number of RRsets per RR type (positive - or negative) and nonexistent names stored in the - cache database. + The number of RRsets per RR type and nonexistent + names stored in the cache database. + If the exclamation mark (!) is printed for a RR + type, it means that particular type of RRset is + known to be nonexistent (this is also known as + "NXRRSET"). Maintained per view.

    @@ -8594,7 +9784,7 @@ $GENERATE 1-127 $ CNAME $.0

    -Zone Maintenance Statistics Counters

    +Zone Maintenance Statistics Counters
    @@ -8748,7 +9938,7 @@ $GENERATE 1-127 $ CNAME $.0

    -Resolver Statistics Counters

    +Resolver Statistics Counters
    @@ -8900,6 +10090,13 @@ $GENERATE 1-127 $ CNAME $.0 @@ -9124,7 +10321,7 @@ $GENERATE 1-127 $ CNAME $.0

    -Socket I/O Statistics Counters

    +Socket I/O Statistics Counters

    Socket I/O statistics counters are defined per socket types, which are @@ -9279,7 +10476,7 @@ $GENERATE 1-127 $ CNAME $.0

    -Compatibility with BIND 8 Counters

    +Compatibility with BIND 8 Counters

    Most statistics counters that were available in BIND 8 are also supported in diff --git a/doc/arm/Bv9ARM.ch07.html b/doc/arm/Bv9ARM.ch07.html index ce23cad..371f4a9 100644 --- a/doc/arm/Bv9ARM.ch07.html +++ b/doc/arm/Bv9ARM.ch07.html @@ -1,5 +1,5 @@ - + @@ -46,10 +46,10 @@

    Table of Contents

    Access Control Lists
    -
    Chroot and Setuid
    +
    Chroot and Setuid
    -
    The chroot Environment
    -
    Using the setuid Function
    +
    The chroot Environment
    +
    Using the setuid Function
    Dynamic Update Security
    @@ -80,14 +80,17 @@ Here is an example of how to properly apply ACLs:

    -// Set up an ACL named "bogusnets" that will block RFC1918 space
    -// and some reserved space, which is commonly used in spoofing attacks.
    +// Set up an ACL named "bogusnets" that will block
    +// RFC1918 space and some reserved space, which is
    +// commonly used in spoofing attacks.
     acl bogusnets {
    -        0.0.0.0/8; 1.0.0.0/8; 2.0.0.0/8; 192.0.2.0/24; 224.0.0.0/3;
    -        10.0.0.0/8; 172.16.0.0/12; 192.168.0.0/16;
    +        0.0.0.0/8; 1.0.0.0/8; 2.0.0.0/8; 192.0.2.0/24;
    +        224.0.0.0/3; 10.0.0.0/8; 172.16.0.0/12;
    +        192.168.0.0/16;
     };
     
    -// Set up an ACL called our-nets. Replace this with the real IP numbers.
    +// Set up an ACL called our-nets. Replace this with the
    +// real IP numbers.
     acl our-nets { x.x.x.x/24; x.x.x.x/21; };
     options {
       ...
    @@ -119,7 +122,7 @@ zone "example.com" {
     
     

    -Chroot and Setuid +Chroot and Setuid

    On UNIX servers, it is possible to run BIND @@ -145,7 +148,7 @@ zone "example.com" {

    -The chroot Environment

    +The chroot Environment

    In order for a chroot environment to @@ -173,7 +176,7 @@ zone "example.com" {

    -Using the setuid Function

    +Using the setuid Function

    Prior to running the named daemon, use diff --git a/doc/arm/Bv9ARM.ch08.html b/doc/arm/Bv9ARM.ch08.html index bb9ecc8..0681e47 100644 --- a/doc/arm/Bv9ARM.ch08.html +++ b/doc/arm/Bv9ARM.ch08.html @@ -1,5 +1,5 @@ - + @@ -45,18 +45,18 @@

    -Common Problems

    +Common Problems

    -It's not working; how can I figure out what's wrong?

    +It's not working; how can I figure out what's wrong?

    The best solution to solving installation and configuration issues is to take preventative measures by setting @@ -68,7 +68,7 @@

    -Incrementing and Changing the Serial Number

    +Incrementing and Changing the Serial Number

    Zone serial numbers are just numbers — they aren't date related. A lot of people set them to a number that @@ -95,7 +95,7 @@

    -Where Can I Get Help?

    +Where Can I Get Help?

    The Internet Systems Consortium (ISC) offers a wide range diff --git a/doc/arm/Bv9ARM.ch09.html b/doc/arm/Bv9ARM.ch09.html index c5bd994..fd53237 100644 --- a/doc/arm/Bv9ARM.ch09.html +++ b/doc/arm/Bv9ARM.ch09.html @@ -1,5 +1,5 @@ - + @@ -45,21 +45,31 @@

    -Acknowledgments

    +Acknowledgments

    A Brief History of the DNS and BIND @@ -162,7 +172,7 @@

    -General DNS Reference Information

    +General DNS Reference Information

    IPv6 addresses (AAAA)

    @@ -250,17 +260,17 @@

    -Bibliography

    +Bibliography

    Standards

    -

    [RFC974] C. Partridge. Mail Routing and the Domain System. January 1986.

    +

    [RFC974] C. Partridge. Mail Routing and the Domain System. January 1986.

    -

    [RFC1034] P.V. Mockapetris. Domain Names — Concepts and Facilities. November 1987.

    +

    [RFC1034] P.V. Mockapetris. Domain Names — Concepts and Facilities. November 1987.

    -

    [RFC1035] P. V. Mockapetris. Domain Names — Implementation and +

    [RFC1035] P. V. Mockapetris. Domain Names — Implementation and Specification. November 1987.

    @@ -268,42 +278,42 @@

    Proposed Standards

    -

    [RFC2181] R., R. Bush Elz. Clarifications to the DNS +

    [RFC2181] R., R. Bush Elz. Clarifications to the DNS Specification. July 1997.

    -

    [RFC2308] M. Andrews. Negative Caching of DNS +

    [RFC2308] M. Andrews. Negative Caching of DNS Queries. March 1998.

    -

    [RFC1995] M. Ohta. Incremental Zone Transfer in DNS. August 1996.

    +

    [RFC1995] M. Ohta. Incremental Zone Transfer in DNS. August 1996.

    -

    [RFC1996] P. Vixie. A Mechanism for Prompt Notification of Zone Changes. August 1996.

    +

    [RFC1996] P. Vixie. A Mechanism for Prompt Notification of Zone Changes. August 1996.

    -

    [RFC2136] P. Vixie, S. Thomson, Y. Rekhter, and J. Bound. Dynamic Updates in the Domain Name System. April 1997.

    +

    [RFC2136] P. Vixie, S. Thomson, Y. Rekhter, and J. Bound. Dynamic Updates in the Domain Name System. April 1997.

    -

    [RFC2671] P. Vixie. Extension Mechanisms for DNS (EDNS0). August 1997.

    +

    [RFC2671] P. Vixie. Extension Mechanisms for DNS (EDNS0). August 1997.

    -

    [RFC2672] M. Crawford. Non-Terminal DNS Name Redirection. August 1999.

    +

    [RFC2672] M. Crawford. Non-Terminal DNS Name Redirection. August 1999.

    -

    [RFC2845] P. Vixie, O. Gudmundsson, D. Eastlake, 3rd, and B. Wellington. Secret Key Transaction Authentication for DNS (TSIG). May 2000.

    +

    [RFC2845] P. Vixie, O. Gudmundsson, D. Eastlake, 3rd, and B. Wellington. Secret Key Transaction Authentication for DNS (TSIG). May 2000.

    -

    [RFC2930] D. Eastlake, 3rd. Secret Key Establishment for DNS (TKEY RR). September 2000.

    +

    [RFC2930] D. Eastlake, 3rd. Secret Key Establishment for DNS (TKEY RR). September 2000.

    -

    [RFC2931] D. Eastlake, 3rd. DNS Request and Transaction Signatures (SIG(0)s). September 2000.

    +

    [RFC2931] D. Eastlake, 3rd. DNS Request and Transaction Signatures (SIG(0)s). September 2000.

    -

    [RFC3007] B. Wellington. Secure Domain Name System (DNS) Dynamic Update. November 2000.

    +

    [RFC3007] B. Wellington. Secure Domain Name System (DNS) Dynamic Update. November 2000.

    -

    [RFC3645] S. Kwan, P. Garg, J. Gilroy, L. Esibov, J. Westhead, and R. Hall. Generic Security Service Algorithm for Secret +

    [RFC3645] S. Kwan, P. Garg, J. Gilroy, L. Esibov, J. Westhead, and R. Hall. Generic Security Service Algorithm for Secret Key Transaction Authentication for DNS (GSS-TSIG). October 2003.

    @@ -312,19 +322,19 @@

    DNS Security Proposed Standards

    -

    [RFC3225] D. Conrad. Indicating Resolver Support of DNSSEC. December 2001.

    +

    [RFC3225] D. Conrad. Indicating Resolver Support of DNSSEC. December 2001.

    -

    [RFC3833] D. Atkins and R. Austein. Threat Analysis of the Domain Name System (DNS). August 2004.

    +

    [RFC3833] D. Atkins and R. Austein. Threat Analysis of the Domain Name System (DNS). August 2004.

    -

    [RFC4033] R. Arends, R. Austein, M. Larson, D. Massey, and S. Rose. DNS Security Introduction and Requirements. March 2005.

    +

    [RFC4033] R. Arends, R. Austein, M. Larson, D. Massey, and S. Rose. DNS Security Introduction and Requirements. March 2005.

    -

    [RFC4034] R. Arends, R. Austein, M. Larson, D. Massey, and S. Rose. Resource Records for the DNS Security Extensions. March 2005.

    +

    [RFC4034] R. Arends, R. Austein, M. Larson, D. Massey, and S. Rose. Resource Records for the DNS Security Extensions. March 2005.

    -

    [RFC4035] R. Arends, R. Austein, M. Larson, D. Massey, and S. Rose. Protocol Modifications for the DNS +

    [RFC4035] R. Arends, R. Austein, M. Larson, D. Massey, and S. Rose. Protocol Modifications for the DNS Security Extensions. March 2005.

    @@ -332,146 +342,146 @@

    Other Important RFCs About DNS Implementation

    -

    [RFC1535] E. Gavron. A Security Problem and Proposed Correction With Widely +

    [RFC1535] E. Gavron. A Security Problem and Proposed Correction With Widely Deployed DNS Software.. October 1993.

    -

    [RFC1536] A. Kumar, J. Postel, C. Neuman, P. Danzig, and S. Miller. Common DNS Implementation +

    [RFC1536] A. Kumar, J. Postel, C. Neuman, P. Danzig, and S. Miller. Common DNS Implementation Errors and Suggested Fixes. October 1993.

    -

    [RFC1982] R. Elz and R. Bush. Serial Number Arithmetic. August 1996.

    +

    [RFC1982] R. Elz and R. Bush. Serial Number Arithmetic. August 1996.

    -

    [RFC4074] Y. Morishita and T. Jinmei. Common Misbehaviour Against DNS +

    [RFC4074] Y. Morishita and T. Jinmei. Common Misbehaviour Against DNS Queries for IPv6 Addresses. May 2005.

    Resource Record Types

    -

    [RFC1183] C.F. Everhart, L. A. Mamakos, R. Ullmann, and P. Mockapetris. New DNS RR Definitions. October 1990.

    +

    [RFC1183] C.F. Everhart, L. A. Mamakos, R. Ullmann, and P. Mockapetris. New DNS RR Definitions. October 1990.

    -

    [RFC1706] B. Manning and R. Colella. DNS NSAP Resource Records. October 1994.

    +

    [RFC1706] B. Manning and R. Colella. DNS NSAP Resource Records. October 1994.

    -

    [RFC2168] R. Daniel and M. Mealling. Resolution of Uniform Resource Identifiers using +

    [RFC2168] R. Daniel and M. Mealling. Resolution of Uniform Resource Identifiers using the Domain Name System. June 1997.

    -

    [RFC1876] C. Davis, P. Vixie, T., and I. Dickinson. A Means for Expressing Location Information in the +

    [RFC1876] C. Davis, P. Vixie, T., and I. Dickinson. A Means for Expressing Location Information in the Domain Name System. January 1996.

    -

    [RFC2052] A. Gulbrandsen and P. Vixie. A DNS RR for Specifying the +

    [RFC2052] A. Gulbrandsen and P. Vixie. A DNS RR for Specifying the Location of Services.. October 1996.

    -

    [RFC2163] A. Allocchio. Using the Internet DNS to +

    [RFC2163] A. Allocchio. Using the Internet DNS to Distribute MIXER Conformant Global Address Mapping. January 1998.

    -

    [RFC2230] R. Atkinson. Key Exchange Delegation Record for the DNS. October 1997.

    +

    [RFC2230] R. Atkinson. Key Exchange Delegation Record for the DNS. October 1997.

    -

    [RFC2536] D. Eastlake, 3rd. DSA KEYs and SIGs in the Domain Name System (DNS). March 1999.

    +

    [RFC2536] D. Eastlake, 3rd. DSA KEYs and SIGs in the Domain Name System (DNS). March 1999.

    -

    [RFC2537] D. Eastlake, 3rd. RSA/MD5 KEYs and SIGs in the Domain Name System (DNS). March 1999.

    +

    [RFC2537] D. Eastlake, 3rd. RSA/MD5 KEYs and SIGs in the Domain Name System (DNS). March 1999.

    -

    [RFC2538] D. Eastlake, 3rd and O. Gudmundsson. Storing Certificates in the Domain Name System (DNS). March 1999.

    +

    [RFC2538] D. Eastlake, 3rd and O. Gudmundsson. Storing Certificates in the Domain Name System (DNS). March 1999.

    -

    [RFC2539] D. Eastlake, 3rd. Storage of Diffie-Hellman Keys in the Domain Name System (DNS). March 1999.

    +

    [RFC2539] D. Eastlake, 3rd. Storage of Diffie-Hellman Keys in the Domain Name System (DNS). March 1999.

    -

    [RFC2540] D. Eastlake, 3rd. Detached Domain Name System (DNS) Information. March 1999.

    +

    [RFC2540] D. Eastlake, 3rd. Detached Domain Name System (DNS) Information. March 1999.

    -

    [RFC2782] A. Gulbrandsen. P. Vixie. L. Esibov. A DNS RR for specifying the location of services (DNS SRV). February 2000.

    +

    [RFC2782] A. Gulbrandsen. P. Vixie. L. Esibov. A DNS RR for specifying the location of services (DNS SRV). February 2000.

    -

    [RFC2915] M. Mealling. R. Daniel. The Naming Authority Pointer (NAPTR) DNS Resource Record. September 2000.

    +

    [RFC2915] M. Mealling. R. Daniel. The Naming Authority Pointer (NAPTR) DNS Resource Record. September 2000.

    -

    [RFC3110] D. Eastlake, 3rd. RSA/SHA-1 SIGs and RSA KEYs in the Domain Name System (DNS). May 2001.

    +

    [RFC3110] D. Eastlake, 3rd. RSA/SHA-1 SIGs and RSA KEYs in the Domain Name System (DNS). May 2001.

    -

    [RFC3123] P. Koch. A DNS RR Type for Lists of Address Prefixes (APL RR). June 2001.

    +

    [RFC3123] P. Koch. A DNS RR Type for Lists of Address Prefixes (APL RR). June 2001.

    -

    [RFC3596] S. Thomson, C. Huitema, V. Ksinant, and M. Souissi. DNS Extensions to support IP +

    [RFC3596] S. Thomson, C. Huitema, V. Ksinant, and M. Souissi. DNS Extensions to support IP version 6. October 2003.

    -

    [RFC3597] A. Gustafsson. Handling of Unknown DNS Resource Record (RR) Types. September 2003.

    +

    [RFC3597] A. Gustafsson. Handling of Unknown DNS Resource Record (RR) Types. September 2003.

    DNS and the Internet

    -

    [RFC1101] P. V. Mockapetris. DNS Encoding of Network Names +

    [RFC1101] P. V. Mockapetris. DNS Encoding of Network Names and Other Types. April 1989.

    -

    [RFC1123] Braden. Requirements for Internet Hosts - Application and +

    [RFC1123] Braden. Requirements for Internet Hosts - Application and Support. October 1989.

    -

    [RFC1591] J. Postel. Domain Name System Structure and Delegation. March 1994.

    +

    [RFC1591] J. Postel. Domain Name System Structure and Delegation. March 1994.

    -

    [RFC2317] H. Eidnes, G. de Groot, and P. Vixie. Classless IN-ADDR.ARPA Delegation. March 1998.

    +

    [RFC2317] H. Eidnes, G. de Groot, and P. Vixie. Classless IN-ADDR.ARPA Delegation. March 1998.

    -

    [RFC2826] Internet Architecture Board. IAB Technical Comment on the Unique DNS Root. May 2000.

    +

    [RFC2826] Internet Architecture Board. IAB Technical Comment on the Unique DNS Root. May 2000.

    -

    [RFC2929] D. Eastlake, 3rd, E. Brunner-Williams, and B. Manning. Domain Name System (DNS) IANA Considerations. September 2000.

    +

    [RFC2929] D. Eastlake, 3rd, E. Brunner-Williams, and B. Manning. Domain Name System (DNS) IANA Considerations. September 2000.

    DNS Operations

    -

    [RFC1033] M. Lottor. Domain administrators operations guide.. November 1987.

    +

    [RFC1033] M. Lottor. Domain administrators operations guide.. November 1987.

    -

    [RFC1537] P. Beertema. Common DNS Data File +

    [RFC1537] P. Beertema. Common DNS Data File Configuration Errors. October 1993.

    -

    [RFC1912] D. Barr. Common DNS Operational and +

    [RFC1912] D. Barr. Common DNS Operational and Configuration Errors. February 1996.

    -

    [RFC2010] B. Manning and P. Vixie. Operational Criteria for Root Name Servers.. October 1996.

    +

    [RFC2010] B. Manning and P. Vixie. Operational Criteria for Root Name Servers.. October 1996.

    -

    [RFC2219] M. Hamilton and R. Wright. Use of DNS Aliases for +

    [RFC2219] M. Hamilton and R. Wright. Use of DNS Aliases for Network Services.. October 1997.

    Internationalized Domain Names

    -

    [RFC2825] IAB and R. Daigle. A Tangled Web: Issues of I18N, Domain Names, +

    [RFC2825] IAB and R. Daigle. A Tangled Web: Issues of I18N, Domain Names, and the Other Internet protocols. May 2000.

    -

    [RFC3490] P. Faltstrom, P. Hoffman, and A. Costello. Internationalizing Domain Names in Applications (IDNA). March 2003.

    +

    [RFC3490] P. Faltstrom, P. Hoffman, and A. Costello. Internationalizing Domain Names in Applications (IDNA). March 2003.

    -

    [RFC3491] P. Hoffman and M. Blanchet. Nameprep: A Stringprep Profile for Internationalized Domain Names. March 2003.

    +

    [RFC3491] P. Hoffman and M. Blanchet. Nameprep: A Stringprep Profile for Internationalized Domain Names. March 2003.

    -

    [RFC3492] A. Costello. Punycode: A Bootstring encoding of Unicode +

    [RFC3492] A. Costello. Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA). March 2003.

    @@ -487,47 +497,47 @@

    -

    [RFC1464] R. Rosenbaum. Using the Domain Name System To Store Arbitrary String +

    [RFC1464] R. Rosenbaum. Using the Domain Name System To Store Arbitrary String Attributes. May 1993.

    -

    [RFC1713] A. Romao. Tools for DNS Debugging. November 1994.

    +

    [RFC1713] A. Romao. Tools for DNS Debugging. November 1994.

    -

    [RFC1794] T. Brisco. DNS Support for Load +

    [RFC1794] T. Brisco. DNS Support for Load Balancing. April 1995.

    -

    [RFC2240] O. Vaughan. A Legal Basis for Domain Name Allocation. November 1997.

    +

    [RFC2240] O. Vaughan. A Legal Basis for Domain Name Allocation. November 1997.

    -

    [RFC2345] J. Klensin, T. Wolf, and G. Oglesby. Domain Names and Company Name Retrieval. May 1998.

    +

    [RFC2345] J. Klensin, T. Wolf, and G. Oglesby. Domain Names and Company Name Retrieval. May 1998.

    -

    [RFC2352] O. Vaughan. A Convention For Using Legal Names as Domain Names. May 1998.

    +

    [RFC2352] O. Vaughan. A Convention For Using Legal Names as Domain Names. May 1998.

    -

    [RFC3071] J. Klensin. Reflections on the DNS, RFC 1591, and Categories of Domains. February 2001.

    +

    [RFC3071] J. Klensin. Reflections on the DNS, RFC 1591, and Categories of Domains. February 2001.

    -

    [RFC3258] T. Hardie. Distributing Authoritative Name Servers via +

    [RFC3258] T. Hardie. Distributing Authoritative Name Servers via Shared Unicast Addresses. April 2002.

    -

    [RFC3901] A. Durand and J. Ihren. DNS IPv6 Transport Operational Guidelines. September 2004.

    +

    [RFC3901] A. Durand and J. Ihren. DNS IPv6 Transport Operational Guidelines. September 2004.

    Obsolete and Unimplemented Experimental RFC

    -

    [RFC1712] C. Farrell, M. Schulze, S. Pleitner, and D. Baldoni. DNS Encoding of Geographical +

    [RFC1712] C. Farrell, M. Schulze, S. Pleitner, and D. Baldoni. DNS Encoding of Geographical Location. November 1994.

    -

    [RFC2673] M. Crawford. Binary Labels in the Domain Name System. August 1999.

    +

    [RFC2673] M. Crawford. Binary Labels in the Domain Name System. August 1999.

    -

    [RFC2874] M. Crawford and C. Huitema. DNS Extensions to Support IPv6 Address Aggregation +

    [RFC2874] M. Crawford and C. Huitema. DNS Extensions to Support IPv6 Address Aggregation and Renumbering. July 2000.

    @@ -541,39 +551,39 @@

    -

    [RFC2065] D. Eastlake, 3rd and C. Kaufman. Domain Name System Security Extensions. January 1997.

    +

    [RFC2065] D. Eastlake, 3rd and C. Kaufman. Domain Name System Security Extensions. January 1997.

    -

    [RFC2137] D. Eastlake, 3rd. Secure Domain Name System Dynamic Update. April 1997.

    +

    [RFC2137] D. Eastlake, 3rd. Secure Domain Name System Dynamic Update. April 1997.

    -

    [RFC2535] D. Eastlake, 3rd. Domain Name System Security Extensions. March 1999.

    +

    [RFC2535] D. Eastlake, 3rd. Domain Name System Security Extensions. March 1999.

    -

    [RFC3008] B. Wellington. Domain Name System Security (DNSSEC) +

    [RFC3008] B. Wellington. Domain Name System Security (DNSSEC) Signing Authority. November 2000.

    -

    [RFC3090] E. Lewis. DNS Security Extension Clarification on Zone Status. March 2001.

    +

    [RFC3090] E. Lewis. DNS Security Extension Clarification on Zone Status. March 2001.

    -

    [RFC3445] D. Massey and S. Rose. Limiting the Scope of the KEY Resource Record (RR). December 2002.

    +

    [RFC3445] D. Massey and S. Rose. Limiting the Scope of the KEY Resource Record (RR). December 2002.

    -

    [RFC3655] B. Wellington and O. Gudmundsson. Redefinition of DNS Authenticated Data (AD) bit. November 2003.

    +

    [RFC3655] B. Wellington and O. Gudmundsson. Redefinition of DNS Authenticated Data (AD) bit. November 2003.

    -

    [RFC3658] O. Gudmundsson. Delegation Signer (DS) Resource Record (RR). December 2003.

    +

    [RFC3658] O. Gudmundsson. Delegation Signer (DS) Resource Record (RR). December 2003.

    -

    [RFC3755] S. Weiler. Legacy Resolver Compatibility for Delegation Signer (DS). May 2004.

    +

    [RFC3755] S. Weiler. Legacy Resolver Compatibility for Delegation Signer (DS). May 2004.

    -

    [RFC3757] O. Kolkman, J. Schlyter, and E. Lewis. Domain Name System KEY (DNSKEY) Resource Record +

    [RFC3757] O. Kolkman, J. Schlyter, and E. Lewis. Domain Name System KEY (DNSKEY) Resource Record (RR) Secure Entry Point (SEP) Flag. April 2004.

    -

    [RFC3845] J. Schlyter. DNS Security (DNSSEC) NextSECure (NSEC) RDATA Format. August 2004.

    +

    [RFC3845] J. Schlyter. DNS Security (DNSSEC) NextSECure (NSEC) RDATA Format. August 2004.

    @@ -594,16 +604,481 @@

    -Other Documents About BIND +Other Documents About BIND

    -Bibliography

    +Bibliography
    -

    Paul Albitz and Cricket Liu. DNS and BIND. Copyright © 1998 Sebastopol, CA: O'Reilly and Associates.

    +

    Paul Albitz and Cricket Liu. DNS and BIND. Copyright © 1998 Sebastopol, CA: O'Reilly and Associates.

    +
    + + + +
    +

    +BIND 9 DNS Library Support

    +

    This version of BIND 9 "exports" its internal libraries so + that they can be used by third-party applications more easily (we + call them "export" libraries in this document). In addition to + all major DNS-related APIs BIND 9 is currently using, the export + libraries provide the following features:

    +
      +
    • The newly created "DNS client" module. This is a higher + level API that provides an interface to name resolution, + single DNS transaction with a particular server, and dynamic + update. Regarding name resolution, it supports advanced + features such as DNSSEC validation and caching. This module + supports both synchronous and asynchronous mode.

    • +
    • The new "IRS" (Information Retrieval System) library. + It provides an interface to parse the traditional resolv.conf + file and more advanced, DNS-specific configuration file for + the rest of this package (see the description for the + dns.conf file below).

    • +
    • As part of the IRS library, newly implemented standard + address-name mapping functions, getaddrinfo() and + getnameinfo(), are provided. They use the DNSSEC-aware + validating resolver backend, and could use other advanced + features of the BIND 9 libraries such as caching. The + getaddrinfo() function resolves both A and AAAA RRs + concurrently (when the address family is unspecified).

    • +
    • An experimental framework to support other event + libraries than BIND 9's internal event task system.

    • +
    +
    +

    +Prerequisite

    +

    GNU make is required to build the export libraries (other + part of BIND 9 can still be built with other types of make). In + the reminder of this document, "make" means GNU make. Note that + in some platforms you may need to invoke a different command name + than "make" (e.g. "gmake") to indicate it's GNU make.

    +
    +
    +

    +Compilation

    +
    +$ ./configure --enable-exportlib [other flags]
    +$ make
    +
    +

    + This will create (in addition to usual BIND 9 programs) and a + separate set of libraries under the lib/export directory. For + example, lib/export/dns/libdns.a is the archive file of the + export version of the BIND 9 DNS library. Sample application + programs using the libraries will also be built under the + lib/export/samples directory (see below).

    +
    +
    +

    +Installation

    +
    +$ cd lib/export
    +$ make install
    +
    +

    + This will install library object files under the directory + specified by the --with-export-libdir configure option (default: + EPREFIX/lib/bind9), and header files under the directory + specified by the --with-export-includedir configure option + (default: PREFIX/include/bind9). + Root privilege is normally required. + "make install" at the top directory will do the + same. +

    +

    + To see how to build your own + application after the installation, see + lib/export/samples/Makefile-postinstall.in.

    +
    +
    +

    +Known Defects/Restrictions

    +
      +
    • Currently, win32 is not supported for the export + library. (Normal BIND 9 application can be built as + before).

    • +
    • +

      The "fixed" RRset order is not (currently) supported in + the export library. If you want to use "fixed" RRset order + for, e.g. named while still building the + export library even without the fixed order support, build + them separately: +

      +
      +$ ./configure --enable-fixed-rrset [other flags, but not --enable-exportlib]
      +$ make
      +$ ./configure --enable-exportlib [other flags, but not --enable-fixed-rrset]
      +$ cd lib/export
      +$ make
      +
      +

      +

      +
    • +
    • The client module and the IRS library currently do not + support DNSSEC validation using DLV (the underlying modules + can handle it, but there is no tunable interface to enable + the feature).

    • +
    • RFC 5011 is not supported in the validating stub + resolver of the export library. In fact, it is not clear + whether it should: trust anchors would be a system-wide + configuration which would be managed by an administrator, + while the stub resolver will be used by ordinary applications + run by a normal user.

    • +
    • Not all common /etc/resolv.conf + options are supported + in the IRS library. The only available options in this + version are "debug" and "ndots".

    • +
    +
    +
    +

    +The dns.conf File

    +

    The IRS library supports an "advanced" configuration file + related to the DNS library for configuration parameters that + would be beyond the capability of the + resolv.conf file. + Specifically, it is intended to provide DNSSEC related + configuration parameters. By default the path to this + configuration file is /etc/dns.conf. + This module is very + experimental and the configuration syntax or library interfaces + may change in future versions. Currently, only the + trusted-keys + statement is supported, whose syntax is the same as the same name + of statement for named.conf. (See + the section called “trusted-keys Statement Grammar” for details.)

    +
    +
    +

    +Sample Applications

    +

    Some sample application programs using this API are + provided for reference. The following is a brief description of + these applications. +

    +
    +

    +sample: a simple stub resolver utility

    +

    + It sends a query of a given name (of a given optional RR type) to a + specified recursive server, and prints the result as a list of + RRs. It can also act as a validating stub resolver if a trust + anchor is given via a set of command line options.

    +

    + Usage: sample [options] server_address hostname +

    +

    + Options and Arguments: +

    +
    +
    + -t RRtype +
    +

    + specify the RR type of the query. The default is the A RR. +

    +
    + [-a algorithm] [-e] -k keyname -K keystring +
    +
    +

    + specify a command-line DNS key to validate the answer. For + example, to specify the following DNSKEY of example.com: +

    +


    +                example.com. 3600 IN DNSKEY 257 3 5 xxx
    +

    +

    + specify the options as follows: +

    +
    +
    +          -e -k example.com -K "xxx"
    +
    +
    +

    + -e means that this key is a zone's "key signing key" (as known + as "secure Entry point"). + When -a is omitted rsasha1 will be used by default. +

    +
    +
    + -s domain:alt_server_address +
    +

    + specify a separate recursive server address for the specific + "domain". Example: -s example.com:2001:db8::1234 +

    +
    server_address
    +

    + an IP(v4/v6) address of the recursive server to which queries + are sent. +

    +
    hostname
    +

    + the domain name for the query +

    +
    +
    +
    +

    +sample-async: a simple stub resolver, working asynchronously

    +

    + Similar to "sample", but accepts a list + of (query) domain names as a separate file and resolves the names + asynchronously.

    +

    + Usage: sample-async [-s server_address] [-t RR_type] input_file

    +

    + Options and Arguments: +

    +
    +
    + -s server_address +
    +
    + an IPv4 address of the recursive server to which queries are sent. + (IPv6 addresses are not supported in this implementation) +
    +
    + -t RR_type +
    +
    + specify the RR type of the queries. The default is the A + RR. +
    +
    + input_file +
    +
    + a list of domain names to be resolved. each line + consists of a single domain name. Example: +


    +  www.example.com
    +  mx.examle.net
    +  ns.xxx.example
    +

    +
    +
    +
    +
    +

    +sample-request: a simple DNS transaction client

    +

    + It sends a query to a specified server, and + prints the response with minimal processing. It doesn't act as a + "stub resolver": it stops the processing once it gets any + response from the server, whether it's a referral or an alias + (CNAME or DNAME) that would require further queries to get the + ultimate answer. In other words, this utility acts as a very + simplified dig. +

    +

    + Usage: sample-request [-t RRtype] server_address hostname +

    +

    + Options and Arguments: +

    +
    +
    + -t RRtype +
    +

    + specify the RR type of + the queries. The default is the A RR. +

    +
    + server_address +
    +

    + an IP(v4/v6) + address of the recursive server to which the query is sent. +

    +
    + hostname +
    +

    + the domain name for the query +

    +
    +
    +
    +

    +sample-gai: getaddrinfo() and getnameinfo() test code

    +

    + This is a test program + to check getaddrinfo() and getnameinfo() behavior. It takes a + host name as an argument, calls getaddrinfo() with the given host + name, and calls getnameinfo() with the resulting IP addresses + returned by getaddrinfo(). If the dns.conf file exists and + defines a trust anchor, the underlying resolver will act as a + validating resolver, and getaddrinfo()/getnameinfo() will fail + with an EAI_INSECUREDATA error when DNSSEC validation fails. +

    +

    + Usage: sample-gai hostname +

    +
    +
    +

    +sample-update: a simple dynamic update client program

    +

    + It accepts a single update command as a + command-line argument, sends an update request message to the + authoritative server, and shows the response from the server. In + other words, this is a simplified nsupdate. +

    +

    + Usage: sample-update [options] (add|delete) "update data" +

    +

    + Options and Arguments: +

    +
    +
    + -a auth_server +
    +

    + An IP address of the authoritative server that has authority + for the zone containing the update name. This should normally + be the primary authoritative server that accepts dynamic + updates. It can also be a secondary server that is configured + to forward update requests to the primary server. +

    +
    + -k keyfile +
    +

    + A TSIG key file to secure the update transaction. The keyfile + format is the same as that for the nsupdate utility. +

    +
    + -p prerequisite +
    +

    + A prerequisite for the update (only one prerequisite can be + specified). The prerequisite format is the same as that is + accepted by the nsupdate utility. +

    +
    + -r recursive_server +
    +

    + An IP address of a recursive server that this utility will + use. A recursive server may be necessary to identify the + authoritative server address to which the update request is + sent. +

    +
    + -z zonename +
    +

    + The domain name of the zone that contains +

    +
    + (add|delete) +
    +

    + Specify the type of update operation. Either "add" or "delete" + must be specified. +

    +
    + "update data" +
    +

    + Specify the data to be updated. A typical example of the data + would look like "name TTL RRtype RDATA". +

    +
    +
    +

    Note

    In practice, either -a or -r must be specified. Others can + be optional; the underlying library routine tries to identify the + appropriate server and the zone name for the update.
    +

    + Examples: assuming the primary authoritative server of the + dynamic.example.com zone has an IPv6 address 2001:db8::1234, +

    +
    +$ sample-update -a sample-update -k Kxxx.+nnn+mmmm.key add "foo.dynamic.example.com 30 IN A 192.168.2.1"
    +

    + adds an A RR for foo.dynamic.example.com using the given key. +

    +
    +$ sample-update -a sample-update -k Kxxx.+nnn+mmmm.key delete "foo.dynamic.example.com 30 IN A"
    +

    + removes all A RRs for foo.dynamic.example.com using the given key. +

    +
       
    +$ sample-update -a sample-update -k Kxxx.+nnn+mmmm.key delete "foo.dynamic.example.com"
    +

    + removes all RRs for foo.dynamic.example.com using the given key. +

    +
    +
    +

    +nsprobe: domain/name server checker in terms of RFC 4074

    +

    + It checks a set + of domains to see the name servers of the domains behave + correctly in terms of RFC 4074. This is included in the set of + sample programs to show how the export library can be used in a + DNS-related application. +

    +

    + Usage: nsprobe [-d] [-v [-v...]] [-c cache_address] [input_file] +

    +

    + Options +

    +
    +
    + -d +
    +

    + run in the "debug" mode. with this option nsprobe will dump + every RRs it receives. +

    +
    + -v +
    +

    + increase verbosity of other normal log messages. This can be + specified multiple times +

    +
    + -c cache_address +
    +

    + specify an IP address of a recursive (caching) name server. + nsprobe uses this server to get the NS RRset of each domain and + the A and/or AAAA RRsets for the name servers. The default + value is 127.0.0.1. +

    +
    + input_file +
    +

    + a file name containing a list of domain (zone) names to be + probed. when omitted the standard input will be used. Each + line of the input file specifies a single domain name such as + "example.com". In general this domain name must be the apex + name of some DNS zone (unlike normal "host names" such as + "www.example.com"). nsprobe first identifies the NS RRsets for + the given domain name, and sends A and AAAA queries to these + servers for some "widely used" names under the zone; + specifically, adding "www" and "ftp" to the zone name. +

    +
    +
    +

    +Library References

    +

    As of this writing, there is no formal "manual" of the + libraries, except this document, header files (some of them + provide pretty detailed explanations), and sample application + programs.

    diff --git a/doc/arm/Bv9ARM.ch10.html b/doc/arm/Bv9ARM.ch10.html index 6929485..7ff08e1 100644 --- a/doc/arm/Bv9ARM.ch10.html +++ b/doc/arm/Bv9ARM.ch10.html @@ -1,5 +1,5 @@ - + @@ -64,6 +64,12 @@ dnssec-keygen — DNSSEC key generation tool
    +dnssec-revoke — Set the REVOKED bit on a DNSSEC key +
    +
    +dnssec-settime — Set the key timing metadata for a DNSSEC key +
    +
    dnssec-signzone — DNSSEC zone signing tool
    @@ -76,6 +82,9 @@ named — Internet domain name server
    +named-journalprint — print zone journal in human-readable form +
    +
    nsupdate — Dynamic DNS update utility
    @@ -87,6 +96,21 @@
    rndc-confgen — rndc key generation tool
    +
    +ddns-confgen — ddns key generation tool +
    +
    +arpaname — translate IP addresses to the corresponding ARPA names +
    +
    +genrandom — generate a file containing random data +
    +
    +isc-hmac-fixup — fixes HMAC keys generated by older versions of BIND +
    +
    +nsec3hash — generate NSEC3 hash +
    diff --git a/doc/arm/Bv9ARM.html b/doc/arm/Bv9ARM.html index 8c21270..7341705 100644 --- a/doc/arm/Bv9ARM.html +++ b/doc/arm/Bv9ARM.html @@ -1,5 +1,5 @@ - + @@ -41,7 +41,7 @@

    BIND 9 Administrator Reference Manual

    -
    +

    @@ -51,39 +51,39 @@
    1. Introduction
    -
    Scope of Document
    -
    Organization of This Document
    -
    Conventions Used in This Document
    -
    The Domain Name System (DNS)
    +
    Scope of Document
    +
    Organization of This Document
    +
    Conventions Used in This Document
    +
    The Domain Name System (DNS)
    -
    DNS Fundamentals
    -
    Domains and Domain Names
    -
    Zones
    -
    Authoritative Name Servers
    -
    Caching Name Servers
    -
    Name Servers in Multiple Roles
    +
    DNS Fundamentals
    +
    Domains and Domain Names
    +
    Zones
    +
    Authoritative Name Servers
    +
    Caching Name Servers
    +
    Name Servers in Multiple Roles
    2. BIND Resource Requirements
    -
    Hardware requirements
    -
    CPU Requirements
    -
    Memory Requirements
    -
    Name Server Intensive Environment Issues
    -
    Supported Operating Systems
    +
    Hardware requirements
    +
    CPU Requirements
    +
    Memory Requirements
    +
    Name Server Intensive Environment Issues
    +
    Supported Operating Systems
    3. Name Server Configuration
    Sample Configurations
    -
    A Caching-only Name Server
    -
    An Authoritative-only Name Server
    +
    A Caching-only Name Server
    +
    An Authoritative-only Name Server
    -
    Load Balancing
    -
    Name Server Operations
    +
    Load Balancing
    +
    Name Server Operations
    -
    Tools for Use With the Name Server Daemon
    -
    Signals
    +
    Tools for Use With the Name Server Daemon
    +
    Signals
    4. Advanced DNS Features
    @@ -92,34 +92,64 @@
    Dynamic Update
    The journal file
    Incremental Zone Transfers (IXFR)
    -
    Split DNS
    -
    Example split DNS setup
    +
    Split DNS
    +
    Example split DNS setup
    TSIG
    -
    Generate Shared Keys for Each Pair of Hosts
    -
    Copying the Shared Secret to Both Machines
    -
    Informing the Servers of the Key's Existence
    -
    Instructing the Server to Use the Key
    -
    TSIG Key Based Access Control
    -
    Errors
    +
    Generate Shared Keys for Each Pair of Hosts
    +
    Copying the Shared Secret to Both Machines
    +
    Informing the Servers of the Key's Existence
    +
    Instructing the Server to Use the Key
    +
    TSIG Key Based Access Control
    +
    Errors
    -
    TKEY
    -
    SIG(0)
    +
    TKEY
    +
    SIG(0)
    DNSSEC
    -
    Generating Keys
    -
    Signing the Zone
    -
    Configuring Servers
    +
    Generating Keys
    +
    Signing the Zone
    +
    Configuring Servers
    -
    IPv6 Support in BIND 9
    +
    DNSSEC, Dynamic Zones, and Automatic Signing
    -
    Address Lookups Using AAAA Records
    -
    Address to Name Lookups Using Nibble Format
    +
    Converting from insecure to secure
    +
    Dynamic DNS update method
    +
    Fully automatic zone signing
    +
    Private-type records
    +
    DNSKEY rollovers
    +
    Dynamic DNS update method
    +
    Automatic key rollovers
    +
    NSEC3PARAM rollovers via UPDATE
    +
    Converting from NSEC to NSEC3
    +
    Converting from NSEC3 to NSEC
    +
    Converting from secure to insecure
    +
    Periodic re-signing
    +
    NSEC3 and OPTOUT
    +
    +
    Dynamic Trust Anchor Management
    +
    +
    Validating Resolver
    +
    Authoritative Server
    +
    +
    PKCS #11 (Cryptoki) support
    +
    +
    Prerequisites
    +
    Building BIND 9 with PKCS#11
    +
    PKCS #11 Tools
    +
    Using the HSM
    +
    Specifying the engine on the command line
    +
    Running named with automatic zone re-signing
    +
    +
    IPv6 Support in BIND 9
    +
    +
    Address Lookups Using AAAA Records
    +
    Address to Name Lookups Using Nibble Format
    5. The BIND 9 Lightweight Resolver
    -
    The Lightweight Resolver Library
    +
    The Lightweight Resolver Library
    Running a Resolver Daemon
    6. BIND 9 Configuration Reference
    @@ -127,55 +157,58 @@
    Configuration File Elements
    Address Match Lists
    -
    Comment Syntax
    +
    Comment Syntax
    Configuration File Grammar
    -
    acl Statement Grammar
    +
    acl Statement Grammar
    acl Statement Definition and Usage
    -
    controls Statement Grammar
    +
    controls Statement Grammar
    controls Statement Definition and Usage
    -
    include Statement Grammar
    -
    include Statement Definition and +
    include Statement Grammar
    +
    include Statement Definition and Usage
    -
    key Statement Grammar
    -
    key Statement Definition and Usage
    -
    logging Statement Grammar
    -
    logging Statement Definition and +
    key Statement Grammar
    +
    key Statement Definition and Usage
    +
    logging Statement Grammar
    +
    logging Statement Definition and Usage
    -
    lwres Statement Grammar
    -
    lwres Statement Definition and Usage
    -
    masters Statement Grammar
    -
    masters Statement Definition and +
    lwres Statement Grammar
    +
    lwres Statement Definition and Usage
    +
    masters Statement Grammar
    +
    masters Statement Definition and Usage
    -
    options Statement Grammar
    +
    options Statement Grammar
    options Statement Definition and Usage
    server Statement Grammar
    server Statement Definition and Usage
    statistics-channels Statement Grammar
    -
    statistics-channels Statement Definition and +
    statistics-channels Statement Definition and Usage
    -
    trusted-keys Statement Grammar
    -
    trusted-keys Statement Definition +
    trusted-keys Statement Grammar
    +
    trusted-keys Statement Definition + and Usage
    +
    managed-keys Statement Grammar
    +
    managed-keys Statement Definition and Usage
    view Statement Grammar
    -
    view Statement Definition and Usage
    +
    view Statement Definition and Usage
    zone Statement Grammar
    -
    zone Statement Definition and Usage
    +
    zone Statement Definition and Usage
    -
    Zone File
    +
    Zone File
    Types of Resource Records and When to Use Them
    -
    Discussion of MX Records
    +
    Discussion of MX Records
    Setting TTLs
    -
    Inverse Mapping in IPv4
    -
    Other Zone File Directives
    -
    BIND Master File Extension: the $GENERATE Directive
    +
    Inverse Mapping in IPv4
    +
    Other Zone File Directives
    +
    BIND Master File Extension: the $GENERATE Directive
    Additional File Formats
    BIND9 Statistics
    @@ -184,31 +217,41 @@
    7. BIND 9 Security Considerations
    Access Control Lists
    -
    Chroot and Setuid
    +
    Chroot and Setuid
    -
    The chroot Environment
    -
    Using the setuid Function
    +
    The chroot Environment
    +
    Using the setuid Function
    Dynamic Update Security
    8. Troubleshooting
    -
    Common Problems
    -
    It's not working; how can I figure out what's wrong?
    -
    Incrementing and Changing the Serial Number
    -
    Where Can I Get Help?
    +
    Common Problems
    +
    It's not working; how can I figure out what's wrong?
    +
    Incrementing and Changing the Serial Number
    +
    Where Can I Get Help?
    A. Appendices
    -
    Acknowledgments
    +
    Acknowledgments
    A Brief History of the DNS and BIND
    -
    General DNS Reference Information
    +
    General DNS Reference Information
    IPv6 addresses (AAAA)
    Bibliography (and Suggested Reading)
    Request for Comments (RFCs)
    Internet Drafts
    -
    Other Documents About BIND
    +
    Other Documents About BIND
    +
    +
    BIND 9 DNS Library Support
    +
    +
    Prerequisite
    +
    Compilation
    +
    Installation
    +
    Known Defects/Restrictions
    +
    The dns.conf File
    +
    Sample Applications
    +
    Library References
    I. Manual pages
    @@ -229,6 +272,12 @@ dnssec-keygen — DNSSEC key generation tool
    +dnssec-revoke — Set the REVOKED bit on a DNSSEC key +
    +
    +dnssec-settime — Set the key timing metadata for a DNSSEC key +
    +
    dnssec-signzone — DNSSEC zone signing tool
    @@ -241,6 +290,9 @@ named — Internet domain name server
    +named-journalprint — print zone journal in human-readable form +
    +
    nsupdate — Dynamic DNS update utility
    @@ -252,6 +304,21 @@
    rndc-confgen — rndc key generation tool
    +
    +ddns-confgen — ddns key generation tool +
    +
    +arpaname — translate IP addresses to the corresponding ARPA names +
    +
    +genrandom — generate a file containing random data +
    +
    +isc-hmac-fixup — fixes HMAC keys generated by older versions of BIND +
    +
    +nsec3hash — generate NSEC3 hash +
    diff --git a/doc/arm/Bv9ARM.pdf b/doc/arm/Bv9ARM.pdf index 9fc0349..a8a88dc 100644 --- a/doc/arm/Bv9ARM.pdf +++ b/doc/arm/Bv9ARM.pdf @@ -321,894 +321,1218 @@ endobj << /S /GoTo /D (section.4.9) >> endobj 220 0 obj -(4.9 IPv6 Support in BIND 9) +(4.9 DNSSEC, Dynamic Zones, and Automatic Signing) endobj 221 0 obj << /S /GoTo /D (subsection.4.9.1) >> endobj 224 0 obj -(4.9.1 Address Lookups Using AAAA Records) +(4.9.1 Converting from insecure to secure) endobj 225 0 obj << /S /GoTo /D (subsection.4.9.2) >> endobj 228 0 obj -(4.9.2 Address to Name Lookups Using Nibble Format) +(4.9.2 Dynamic DNS update method) endobj 229 0 obj -<< /S /GoTo /D (chapter.5) >> +<< /S /GoTo /D (subsection.4.9.3) >> endobj 232 0 obj -(5 The BIND 9 Lightweight Resolver) +(4.9.3 Fully automatic zone signing) endobj 233 0 obj -<< /S /GoTo /D (section.5.1) >> +<< /S /GoTo /D (subsection.4.9.4) >> endobj 236 0 obj -(5.1 The Lightweight Resolver Library) +(4.9.4 Private-type records) endobj 237 0 obj -<< /S /GoTo /D (section.5.2) >> +<< /S /GoTo /D (subsection.4.9.5) >> endobj 240 0 obj -(5.2 Running a Resolver Daemon) +(4.9.5 DNSKEY rollovers) endobj 241 0 obj -<< /S /GoTo /D (chapter.6) >> +<< /S /GoTo /D (subsection.4.9.6) >> endobj 244 0 obj -(6 BIND 9 Configuration Reference) +(4.9.6 Dynamic DNS update method) endobj 245 0 obj -<< /S /GoTo /D (section.6.1) >> +<< /S /GoTo /D (subsection.4.9.7) >> endobj 248 0 obj -(6.1 Configuration File Elements) +(4.9.7 Automatic key rollovers) endobj 249 0 obj -<< /S /GoTo /D (subsection.6.1.1) >> +<< /S /GoTo /D (subsection.4.9.8) >> endobj 252 0 obj -(6.1.1 Address Match Lists) +(4.9.8 NSEC3PARAM rollovers via UPDATE) endobj 253 0 obj -<< /S /GoTo /D (subsubsection.6.1.1.1) >> +<< /S /GoTo /D (subsection.4.9.9) >> endobj 256 0 obj -(6.1.1.1 Syntax) +(4.9.9 Converting from NSEC to NSEC3) endobj 257 0 obj -<< /S /GoTo /D (subsubsection.6.1.1.2) >> +<< /S /GoTo /D (subsection.4.9.10) >> endobj 260 0 obj -(6.1.1.2 Definition and Usage) +(4.9.10 Converting from NSEC3 to NSEC) endobj 261 0 obj -<< /S /GoTo /D (subsection.6.1.2) >> +<< /S /GoTo /D (subsection.4.9.11) >> endobj 264 0 obj -(6.1.2 Comment Syntax) +(4.9.11 Converting from secure to insecure) endobj 265 0 obj -<< /S /GoTo /D (subsubsection.6.1.2.1) >> +<< /S /GoTo /D (subsection.4.9.12) >> endobj 268 0 obj -(6.1.2.1 Syntax) +(4.9.12 Periodic re-signing) endobj 269 0 obj -<< /S /GoTo /D (subsubsection.6.1.2.2) >> +<< /S /GoTo /D (subsection.4.9.13) >> endobj 272 0 obj -(6.1.2.2 Definition and Usage) +(4.9.13 NSEC3 and OPTOUT) endobj 273 0 obj -<< /S /GoTo /D (section.6.2) >> +<< /S /GoTo /D (section.4.10) >> endobj 276 0 obj -(6.2 Configuration File Grammar) +(4.10 Dynamic Trust Anchor Management) endobj 277 0 obj -<< /S /GoTo /D (subsection.6.2.1) >> +<< /S /GoTo /D (subsection.4.10.1) >> endobj 280 0 obj -(6.2.1 acl Statement Grammar) +(4.10.1 Validating Resolver) endobj 281 0 obj -<< /S /GoTo /D (subsection.6.2.2) >> +<< /S /GoTo /D (subsection.4.10.2) >> endobj 284 0 obj -(6.2.2 acl Statement Definition and Usage) +(4.10.2 Authoritative Server) endobj 285 0 obj -<< /S /GoTo /D (subsection.6.2.3) >> +<< /S /GoTo /D (section.4.11) >> endobj 288 0 obj -(6.2.3 controls Statement Grammar) +(4.11 PKCS \04311 \(Cryptoki\) support) endobj 289 0 obj -<< /S /GoTo /D (subsection.6.2.4) >> +<< /S /GoTo /D (subsection.4.11.1) >> endobj 292 0 obj -(6.2.4 controls Statement Definition and Usage) +(4.11.1 Prerequisites) endobj 293 0 obj -<< /S /GoTo /D (subsection.6.2.5) >> +<< /S /GoTo /D (subsubsection.4.11.1.1) >> endobj 296 0 obj -(6.2.5 include Statement Grammar) +(4.11.1.1 Building OpenSSL for the AEP Keyper on Linux) endobj 297 0 obj -<< /S /GoTo /D (subsection.6.2.6) >> +<< /S /GoTo /D (subsubsection.4.11.1.2) >> endobj 300 0 obj -(6.2.6 include Statement Definition and Usage) +(4.11.1.2 Building OpenSSL for the SCA 6000 on Solaris) endobj 301 0 obj -<< /S /GoTo /D (subsection.6.2.7) >> +<< /S /GoTo /D (subsection.4.11.2) >> endobj 304 0 obj -(6.2.7 key Statement Grammar) +(4.11.2 Building BIND 9 with PKCS\04311) endobj 305 0 obj -<< /S /GoTo /D (subsection.6.2.8) >> +<< /S /GoTo /D (subsubsection.4.11.2.1) >> endobj 308 0 obj -(6.2.8 key Statement Definition and Usage) +(4.11.2.1 Configuring BIND 9 for Linux) endobj 309 0 obj -<< /S /GoTo /D (subsection.6.2.9) >> +<< /S /GoTo /D (subsubsection.4.11.2.2) >> endobj 312 0 obj -(6.2.9 logging Statement Grammar) +(4.11.2.2 Configuring BIND 9 for Solaris) endobj 313 0 obj -<< /S /GoTo /D (subsection.6.2.10) >> +<< /S /GoTo /D (subsection.4.11.3) >> endobj 316 0 obj -(6.2.10 logging Statement Definition and Usage) +(4.11.3 PKCS \04311 Tools) endobj 317 0 obj -<< /S /GoTo /D (subsubsection.6.2.10.1) >> +<< /S /GoTo /D (subsection.4.11.4) >> endobj 320 0 obj -(6.2.10.1 The channel Phrase) +(4.11.4 Using the HSM) endobj 321 0 obj -<< /S /GoTo /D (subsubsection.6.2.10.2) >> +<< /S /GoTo /D (subsection.4.11.5) >> endobj 324 0 obj -(6.2.10.2 The category Phrase) +(4.11.5 Specifying the engine on the command line) endobj 325 0 obj -<< /S /GoTo /D (subsubsection.6.2.10.3) >> +<< /S /GoTo /D (subsection.4.11.6) >> endobj 328 0 obj -(6.2.10.3 The query-errors Category) +(4.11.6 Running named with automatic zone re-signing) endobj 329 0 obj -<< /S /GoTo /D (subsection.6.2.11) >> +<< /S /GoTo /D (section.4.12) >> endobj 332 0 obj -(6.2.11 lwres Statement Grammar) +(4.12 IPv6 Support in BIND 9) endobj 333 0 obj -<< /S /GoTo /D (subsection.6.2.12) >> +<< /S /GoTo /D (subsection.4.12.1) >> endobj 336 0 obj -(6.2.12 lwres Statement Definition and Usage) +(4.12.1 Address Lookups Using AAAA Records) endobj 337 0 obj -<< /S /GoTo /D (subsection.6.2.13) >> +<< /S /GoTo /D (subsection.4.12.2) >> endobj 340 0 obj -(6.2.13 masters Statement Grammar) +(4.12.2 Address to Name Lookups Using Nibble Format) endobj 341 0 obj -<< /S /GoTo /D (subsection.6.2.14) >> +<< /S /GoTo /D (chapter.5) >> endobj 344 0 obj -(6.2.14 masters Statement Definition and Usage) +(5 The BIND 9 Lightweight Resolver) endobj 345 0 obj -<< /S /GoTo /D (subsection.6.2.15) >> +<< /S /GoTo /D (section.5.1) >> endobj 348 0 obj -(6.2.15 options Statement Grammar) +(5.1 The Lightweight Resolver Library) endobj 349 0 obj -<< /S /GoTo /D (subsection.6.2.16) >> +<< /S /GoTo /D (section.5.2) >> endobj 352 0 obj -(6.2.16 options Statement Definition and Usage) +(5.2 Running a Resolver Daemon) endobj 353 0 obj -<< /S /GoTo /D (subsubsection.6.2.16.1) >> +<< /S /GoTo /D (chapter.6) >> endobj 356 0 obj -(6.2.16.1 Boolean Options) +(6 BIND 9 Configuration Reference) endobj 357 0 obj -<< /S /GoTo /D (subsubsection.6.2.16.2) >> +<< /S /GoTo /D (section.6.1) >> endobj 360 0 obj -(6.2.16.2 Forwarding) +(6.1 Configuration File Elements) endobj 361 0 obj -<< /S /GoTo /D (subsubsection.6.2.16.3) >> +<< /S /GoTo /D (subsection.6.1.1) >> endobj 364 0 obj -(6.2.16.3 Dual-stack Servers) +(6.1.1 Address Match Lists) endobj 365 0 obj -<< /S /GoTo /D (subsubsection.6.2.16.4) >> +<< /S /GoTo /D (subsubsection.6.1.1.1) >> endobj 368 0 obj -(6.2.16.4 Access Control) +(6.1.1.1 Syntax) endobj 369 0 obj -<< /S /GoTo /D (subsubsection.6.2.16.5) >> +<< /S /GoTo /D (subsubsection.6.1.1.2) >> endobj 372 0 obj -(6.2.16.5 Interfaces) +(6.1.1.2 Definition and Usage) endobj 373 0 obj -<< /S /GoTo /D (subsubsection.6.2.16.6) >> +<< /S /GoTo /D (subsection.6.1.2) >> endobj 376 0 obj -(6.2.16.6 Query Address) +(6.1.2 Comment Syntax) endobj 377 0 obj -<< /S /GoTo /D (subsubsection.6.2.16.7) >> +<< /S /GoTo /D (subsubsection.6.1.2.1) >> endobj 380 0 obj -(6.2.16.7 Zone Transfers) +(6.1.2.1 Syntax) endobj 381 0 obj -<< /S /GoTo /D (subsubsection.6.2.16.8) >> +<< /S /GoTo /D (subsubsection.6.1.2.2) >> endobj 384 0 obj -(6.2.16.8 UDP Port Lists) +(6.1.2.2 Definition and Usage) endobj 385 0 obj -<< /S /GoTo /D (subsubsection.6.2.16.9) >> +<< /S /GoTo /D (section.6.2) >> endobj 388 0 obj -(6.2.16.9 Operating System Resource Limits) +(6.2 Configuration File Grammar) endobj 389 0 obj -<< /S /GoTo /D (subsubsection.6.2.16.10) >> +<< /S /GoTo /D (subsection.6.2.1) >> endobj 392 0 obj -(6.2.16.10 Server Resource Limits) +(6.2.1 acl Statement Grammar) endobj 393 0 obj -<< /S /GoTo /D (subsubsection.6.2.16.11) >> +<< /S /GoTo /D (subsection.6.2.2) >> endobj 396 0 obj -(6.2.16.11 Periodic Task Intervals) +(6.2.2 acl Statement Definition and Usage) endobj 397 0 obj -<< /S /GoTo /D (subsubsection.6.2.16.12) >> +<< /S /GoTo /D (subsection.6.2.3) >> endobj 400 0 obj -(6.2.16.12 Topology) +(6.2.3 controls Statement Grammar) endobj 401 0 obj -<< /S /GoTo /D (subsubsection.6.2.16.13) >> +<< /S /GoTo /D (subsection.6.2.4) >> endobj 404 0 obj -(6.2.16.13 The sortlist Statement) +(6.2.4 controls Statement Definition and Usage) endobj 405 0 obj -<< /S /GoTo /D (subsubsection.6.2.16.14) >> +<< /S /GoTo /D (subsection.6.2.5) >> endobj 408 0 obj -(6.2.16.14 RRset Ordering) +(6.2.5 include Statement Grammar) endobj 409 0 obj -<< /S /GoTo /D (subsubsection.6.2.16.15) >> +<< /S /GoTo /D (subsection.6.2.6) >> endobj 412 0 obj -(6.2.16.15 Tuning) +(6.2.6 include Statement Definition and Usage) endobj 413 0 obj -<< /S /GoTo /D (subsubsection.6.2.16.16) >> +<< /S /GoTo /D (subsection.6.2.7) >> endobj 416 0 obj -(6.2.16.16 Built-in server information zones) +(6.2.7 key Statement Grammar) endobj 417 0 obj -<< /S /GoTo /D (subsubsection.6.2.16.17) >> +<< /S /GoTo /D (subsection.6.2.8) >> endobj 420 0 obj -(6.2.16.17 Built-in Empty Zones) +(6.2.8 key Statement Definition and Usage) endobj 421 0 obj -<< /S /GoTo /D (subsubsection.6.2.16.18) >> +<< /S /GoTo /D (subsection.6.2.9) >> endobj 424 0 obj -(6.2.16.18 Additional Section Caching) +(6.2.9 logging Statement Grammar) endobj 425 0 obj -<< /S /GoTo /D (subsection.6.2.17) >> +<< /S /GoTo /D (subsection.6.2.10) >> endobj 428 0 obj -(6.2.17 server Statement Grammar) +(6.2.10 logging Statement Definition and Usage) endobj 429 0 obj -<< /S /GoTo /D (subsection.6.2.18) >> +<< /S /GoTo /D (subsubsection.6.2.10.1) >> endobj 432 0 obj -(6.2.18 server Statement Definition and Usage) +(6.2.10.1 The channel Phrase) endobj 433 0 obj -<< /S /GoTo /D (subsection.6.2.19) >> +<< /S /GoTo /D (subsubsection.6.2.10.2) >> endobj 436 0 obj -(6.2.19 statistics-channels Statement Grammar) +(6.2.10.2 The category Phrase) endobj 437 0 obj -<< /S /GoTo /D (subsection.6.2.20) >> +<< /S /GoTo /D (subsubsection.6.2.10.3) >> endobj 440 0 obj -(6.2.20 statistics-channels Statement Definition and Usage) +(6.2.10.3 The query-errors Category) endobj 441 0 obj -<< /S /GoTo /D (subsection.6.2.21) >> +<< /S /GoTo /D (subsection.6.2.11) >> endobj 444 0 obj -(6.2.21 trusted-keys Statement Grammar) +(6.2.11 lwres Statement Grammar) endobj 445 0 obj -<< /S /GoTo /D (subsection.6.2.22) >> +<< /S /GoTo /D (subsection.6.2.12) >> endobj 448 0 obj -(6.2.22 trusted-keys Statement Definition and Usage) +(6.2.12 lwres Statement Definition and Usage) endobj 449 0 obj -<< /S /GoTo /D (subsection.6.2.23) >> +<< /S /GoTo /D (subsection.6.2.13) >> endobj 452 0 obj -(6.2.23 view Statement Grammar) +(6.2.13 masters Statement Grammar) endobj 453 0 obj -<< /S /GoTo /D (subsection.6.2.24) >> +<< /S /GoTo /D (subsection.6.2.14) >> endobj 456 0 obj -(6.2.24 view Statement Definition and Usage) +(6.2.14 masters Statement Definition and Usage) endobj 457 0 obj -<< /S /GoTo /D (subsection.6.2.25) >> +<< /S /GoTo /D (subsection.6.2.15) >> endobj 460 0 obj -(6.2.25 zone Statement Grammar) +(6.2.15 options Statement Grammar) endobj 461 0 obj -<< /S /GoTo /D (subsection.6.2.26) >> +<< /S /GoTo /D (subsection.6.2.16) >> endobj 464 0 obj -(6.2.26 zone Statement Definition and Usage) +(6.2.16 options Statement Definition and Usage) endobj 465 0 obj -<< /S /GoTo /D (subsubsection.6.2.26.1) >> +<< /S /GoTo /D (subsubsection.6.2.16.1) >> endobj 468 0 obj -(6.2.26.1 Zone Types) +(6.2.16.1 Boolean Options) endobj 469 0 obj -<< /S /GoTo /D (subsubsection.6.2.26.2) >> +<< /S /GoTo /D (subsubsection.6.2.16.2) >> endobj 472 0 obj -(6.2.26.2 Class) +(6.2.16.2 Forwarding) endobj 473 0 obj -<< /S /GoTo /D (subsubsection.6.2.26.3) >> +<< /S /GoTo /D (subsubsection.6.2.16.3) >> endobj 476 0 obj -(6.2.26.3 Zone Options) +(6.2.16.3 Dual-stack Servers) endobj 477 0 obj -<< /S /GoTo /D (subsubsection.6.2.26.4) >> +<< /S /GoTo /D (subsubsection.6.2.16.4) >> endobj 480 0 obj -(6.2.26.4 Dynamic Update Policies) +(6.2.16.4 Access Control) endobj 481 0 obj -<< /S /GoTo /D (section.6.3) >> +<< /S /GoTo /D (subsubsection.6.2.16.5) >> endobj 484 0 obj -(6.3 Zone File) +(6.2.16.5 Interfaces) endobj 485 0 obj -<< /S /GoTo /D (subsection.6.3.1) >> +<< /S /GoTo /D (subsubsection.6.2.16.6) >> endobj 488 0 obj -(6.3.1 Types of Resource Records and When to Use Them) +(6.2.16.6 Query Address) endobj 489 0 obj -<< /S /GoTo /D (subsubsection.6.3.1.1) >> +<< /S /GoTo /D (subsubsection.6.2.16.7) >> endobj 492 0 obj -(6.3.1.1 Resource Records) +(6.2.16.7 Zone Transfers) endobj 493 0 obj -<< /S /GoTo /D (subsubsection.6.3.1.2) >> +<< /S /GoTo /D (subsubsection.6.2.16.8) >> endobj 496 0 obj -(6.3.1.2 Textual expression of RRs) +(6.2.16.8 UDP Port Lists) endobj 497 0 obj -<< /S /GoTo /D (subsection.6.3.2) >> +<< /S /GoTo /D (subsubsection.6.2.16.9) >> endobj 500 0 obj -(6.3.2 Discussion of MX Records) +(6.2.16.9 Operating System Resource Limits) endobj 501 0 obj -<< /S /GoTo /D (subsection.6.3.3) >> +<< /S /GoTo /D (subsubsection.6.2.16.10) >> endobj 504 0 obj -(6.3.3 Setting TTLs) +(6.2.16.10 Server Resource Limits) endobj 505 0 obj -<< /S /GoTo /D (subsection.6.3.4) >> +<< /S /GoTo /D (subsubsection.6.2.16.11) >> endobj 508 0 obj -(6.3.4 Inverse Mapping in IPv4) +(6.2.16.11 Periodic Task Intervals) endobj 509 0 obj -<< /S /GoTo /D (subsection.6.3.5) >> +<< /S /GoTo /D (subsubsection.6.2.16.12) >> endobj 512 0 obj -(6.3.5 Other Zone File Directives) +(6.2.16.12 Topology) endobj 513 0 obj -<< /S /GoTo /D (subsubsection.6.3.5.1) >> +<< /S /GoTo /D (subsubsection.6.2.16.13) >> endobj 516 0 obj -(6.3.5.1 The @ \(at-sign\)) +(6.2.16.13 The sortlist Statement) endobj 517 0 obj -<< /S /GoTo /D (subsubsection.6.3.5.2) >> +<< /S /GoTo /D (subsubsection.6.2.16.14) >> endobj 520 0 obj -(6.3.5.2 The \044ORIGIN Directive) +(6.2.16.14 RRset Ordering) endobj 521 0 obj -<< /S /GoTo /D (subsubsection.6.3.5.3) >> +<< /S /GoTo /D (subsubsection.6.2.16.15) >> endobj 524 0 obj -(6.3.5.3 The \044INCLUDE Directive) +(6.2.16.15 Tuning) endobj 525 0 obj -<< /S /GoTo /D (subsubsection.6.3.5.4) >> +<< /S /GoTo /D (subsubsection.6.2.16.16) >> endobj 528 0 obj -(6.3.5.4 The \044TTL Directive) +(6.2.16.16 Built-in server information zones) endobj 529 0 obj -<< /S /GoTo /D (subsection.6.3.6) >> +<< /S /GoTo /D (subsubsection.6.2.16.17) >> endobj 532 0 obj -(6.3.6 BIND Master File Extension: the \044GENERATE Directive) +(6.2.16.17 Built-in Empty Zones) endobj 533 0 obj -<< /S /GoTo /D (subsection.6.3.7) >> +<< /S /GoTo /D (subsubsection.6.2.16.18) >> endobj 536 0 obj -(6.3.7 Additional File Formats) +(6.2.16.18 Additional Section Caching) endobj 537 0 obj -<< /S /GoTo /D (section.6.4) >> +<< /S /GoTo /D (subsubsection.6.2.16.19) >> endobj 540 0 obj -(6.4 BIND9 Statistics) +(6.2.16.19 Content Filtering) endobj 541 0 obj -<< /S /GoTo /D (subsubsection.6.4.0.1) >> +<< /S /GoTo /D (subsubsection.6.2.16.20) >> endobj 544 0 obj -(6.4.0.1 The Statistics File) +(6.2.16.20 Response Policy Zone \(RPZ\) Rewriting) endobj 545 0 obj -<< /S /GoTo /D (subsection.6.4.1) >> +<< /S /GoTo /D (subsection.6.2.17) >> endobj 548 0 obj -(6.4.1 Statistics Counters) +(6.2.17 server Statement Grammar) endobj 549 0 obj -<< /S /GoTo /D (subsubsection.6.4.1.1) >> +<< /S /GoTo /D (subsection.6.2.18) >> endobj 552 0 obj -(6.4.1.1 Name Server Statistics Counters) +(6.2.18 server Statement Definition and Usage) endobj 553 0 obj -<< /S /GoTo /D (subsubsection.6.4.1.2) >> +<< /S /GoTo /D (subsection.6.2.19) >> endobj 556 0 obj -(6.4.1.2 Zone Maintenance Statistics Counters) +(6.2.19 statistics-channels Statement Grammar) endobj 557 0 obj -<< /S /GoTo /D (subsubsection.6.4.1.3) >> +<< /S /GoTo /D (subsection.6.2.20) >> endobj 560 0 obj -(6.4.1.3 Resolver Statistics Counters) +(6.2.20 statistics-channels Statement Definition and Usage) endobj 561 0 obj -<< /S /GoTo /D (subsubsection.6.4.1.4) >> +<< /S /GoTo /D (subsection.6.2.21) >> endobj 564 0 obj -(6.4.1.4 Socket I/O Statistics Counters) +(6.2.21 trusted-keys Statement Grammar) endobj 565 0 obj -<< /S /GoTo /D (subsubsection.6.4.1.5) >> +<< /S /GoTo /D (subsection.6.2.22) >> endobj 568 0 obj -(6.4.1.5 Compatibility with BIND 8 Counters) +(6.2.22 trusted-keys Statement Definition and Usage) endobj 569 0 obj -<< /S /GoTo /D (chapter.7) >> +<< /S /GoTo /D (subsection.6.2.23) >> endobj 572 0 obj -(7 BIND 9 Security Considerations) +(6.2.23 managed-keys Statement Grammar) endobj 573 0 obj -<< /S /GoTo /D (section.7.1) >> +<< /S /GoTo /D (subsection.6.2.24) >> endobj 576 0 obj -(7.1 Access Control Lists) +(6.2.24 managed-keys Statement Definition and Usage) endobj 577 0 obj -<< /S /GoTo /D (section.7.2) >> +<< /S /GoTo /D (subsection.6.2.25) >> endobj 580 0 obj -(7.2 Chroot and Setuid) +(6.2.25 view Statement Grammar) endobj 581 0 obj -<< /S /GoTo /D (subsection.7.2.1) >> +<< /S /GoTo /D (subsection.6.2.26) >> endobj 584 0 obj -(7.2.1 The chroot Environment) +(6.2.26 view Statement Definition and Usage) endobj 585 0 obj -<< /S /GoTo /D (subsection.7.2.2) >> +<< /S /GoTo /D (subsection.6.2.27) >> endobj 588 0 obj -(7.2.2 Using the setuid Function) +(6.2.27 zone Statement Grammar) endobj 589 0 obj -<< /S /GoTo /D (section.7.3) >> +<< /S /GoTo /D (subsection.6.2.28) >> endobj 592 0 obj -(7.3 Dynamic Update Security) +(6.2.28 zone Statement Definition and Usage) endobj 593 0 obj -<< /S /GoTo /D (chapter.8) >> +<< /S /GoTo /D (subsubsection.6.2.28.1) >> endobj 596 0 obj -(8 Troubleshooting) +(6.2.28.1 Zone Types) endobj 597 0 obj -<< /S /GoTo /D (section.8.1) >> +<< /S /GoTo /D (subsubsection.6.2.28.2) >> endobj 600 0 obj -(8.1 Common Problems) +(6.2.28.2 Class) endobj 601 0 obj -<< /S /GoTo /D (subsection.8.1.1) >> +<< /S /GoTo /D (subsubsection.6.2.28.3) >> endobj 604 0 obj -(8.1.1 It's not working; how can I figure out what's wrong?) +(6.2.28.3 Zone Options) endobj 605 0 obj -<< /S /GoTo /D (section.8.2) >> +<< /S /GoTo /D (subsubsection.6.2.28.4) >> endobj 608 0 obj -(8.2 Incrementing and Changing the Serial Number) +(6.2.28.4 Dynamic Update Policies) endobj 609 0 obj -<< /S /GoTo /D (section.8.3) >> +<< /S /GoTo /D (section.6.3) >> endobj 612 0 obj -(8.3 Where Can I Get Help?) +(6.3 Zone File) endobj 613 0 obj -<< /S /GoTo /D (appendix.A) >> +<< /S /GoTo /D (subsection.6.3.1) >> endobj 616 0 obj -(A Appendices) +(6.3.1 Types of Resource Records and When to Use Them) endobj 617 0 obj -<< /S /GoTo /D (section.A.1) >> +<< /S /GoTo /D (subsubsection.6.3.1.1) >> endobj 620 0 obj -(A.1 Acknowledgments) +(6.3.1.1 Resource Records) endobj 621 0 obj -<< /S /GoTo /D (subsection.A.1.1) >> +<< /S /GoTo /D (subsubsection.6.3.1.2) >> endobj 624 0 obj -(A.1.1 A Brief History of the DNS and BIND) +(6.3.1.2 Textual expression of RRs) endobj 625 0 obj -<< /S /GoTo /D (section.A.2) >> +<< /S /GoTo /D (subsection.6.3.2) >> endobj 628 0 obj -(A.2 General DNS Reference Information) +(6.3.2 Discussion of MX Records) endobj 629 0 obj -<< /S /GoTo /D (subsection.A.2.1) >> +<< /S /GoTo /D (subsection.6.3.3) >> endobj 632 0 obj -(A.2.1 IPv6 addresses \(AAAA\)) +(6.3.3 Setting TTLs) endobj 633 0 obj -<< /S /GoTo /D (section.A.3) >> +<< /S /GoTo /D (subsection.6.3.4) >> endobj 636 0 obj -(A.3 Bibliography \(and Suggested Reading\)) +(6.3.4 Inverse Mapping in IPv4) endobj 637 0 obj -<< /S /GoTo /D (subsection.A.3.1) >> +<< /S /GoTo /D (subsection.6.3.5) >> endobj 640 0 obj -(A.3.1 Request for Comments \(RFCs\)) +(6.3.5 Other Zone File Directives) endobj 641 0 obj -<< /S /GoTo /D (subsection.A.3.2) >> +<< /S /GoTo /D (subsubsection.6.3.5.1) >> endobj 644 0 obj -(A.3.2 Internet Drafts) +(6.3.5.1 The @ \(at-sign\)) endobj 645 0 obj -<< /S /GoTo /D (subsection.A.3.3) >> +<< /S /GoTo /D (subsubsection.6.3.5.2) >> endobj 648 0 obj -(A.3.3 Other Documents About BIND) +(6.3.5.2 The \044ORIGIN Directive) endobj 649 0 obj -<< /S /GoTo /D (appendix.B) >> +<< /S /GoTo /D (subsubsection.6.3.5.3) >> endobj 652 0 obj -(B Manual pages) +(6.3.5.3 The \044INCLUDE Directive) endobj 653 0 obj -<< /S /GoTo /D (section.B.1) >> +<< /S /GoTo /D (subsubsection.6.3.5.4) >> endobj 656 0 obj -(B.1 dig) +(6.3.5.4 The \044TTL Directive) endobj 657 0 obj -<< /S /GoTo /D (section.B.2) >> +<< /S /GoTo /D (subsection.6.3.6) >> endobj 660 0 obj -(B.2 host) +(6.3.6 BIND Master File Extension: the \044GENERATE Directive) endobj 661 0 obj -<< /S /GoTo /D (section.B.3) >> +<< /S /GoTo /D (subsection.6.3.7) >> endobj 664 0 obj -(B.3 dnssec-dsfromkey) +(6.3.7 Additional File Formats) endobj 665 0 obj -<< /S /GoTo /D (section.B.4) >> +<< /S /GoTo /D (section.6.4) >> endobj 668 0 obj -(B.4 dnssec-keyfromlabel) +(6.4 BIND9 Statistics) endobj 669 0 obj -<< /S /GoTo /D (section.B.5) >> +<< /S /GoTo /D (subsubsection.6.4.0.1) >> endobj 672 0 obj -(B.5 dnssec-keygen) +(6.4.0.1 The Statistics File) endobj 673 0 obj -<< /S /GoTo /D (section.B.6) >> +<< /S /GoTo /D (subsection.6.4.1) >> endobj 676 0 obj -(B.6 dnssec-signzone) +(6.4.1 Statistics Counters) endobj 677 0 obj -<< /S /GoTo /D (section.B.7) >> +<< /S /GoTo /D (subsubsection.6.4.1.1) >> endobj 680 0 obj -(B.7 named-checkconf) +(6.4.1.1 Name Server Statistics Counters) endobj 681 0 obj -<< /S /GoTo /D (section.B.8) >> +<< /S /GoTo /D (subsubsection.6.4.1.2) >> endobj 684 0 obj -(B.8 named-checkzone) +(6.4.1.2 Zone Maintenance Statistics Counters) endobj 685 0 obj -<< /S /GoTo /D (section.B.9) >> +<< /S /GoTo /D (subsubsection.6.4.1.3) >> endobj 688 0 obj -(B.9 named) +(6.4.1.3 Resolver Statistics Counters) endobj 689 0 obj -<< /S /GoTo /D (section.B.10) >> +<< /S /GoTo /D (subsubsection.6.4.1.4) >> endobj 692 0 obj -(B.10 nsupdate) +(6.4.1.4 Socket I/O Statistics Counters) endobj 693 0 obj -<< /S /GoTo /D (section.B.11) >> +<< /S /GoTo /D (subsubsection.6.4.1.5) >> endobj 696 0 obj -(B.11 rndc) +(6.4.1.5 Compatibility with BIND 8 Counters) endobj 697 0 obj -<< /S /GoTo /D (section.B.12) >> +<< /S /GoTo /D (chapter.7) >> endobj 700 0 obj -(B.12 rndc.conf) +(7 BIND 9 Security Considerations) endobj 701 0 obj -<< /S /GoTo /D (section.B.13) >> +<< /S /GoTo /D (section.7.1) >> endobj 704 0 obj -(B.13 rndc-confgen) +(7.1 Access Control Lists) endobj 705 0 obj -<< /S /GoTo /D [706 0 R /FitH ] >> +<< /S /GoTo /D (section.7.2) >> endobj -709 0 obj << -/Length 240 -/Filter /FlateDecode ->> -stream -xÚ•OKA Åïó)rl›N2Éü9ZªRA¡27ñ°´[)¸[ºÖïïlWË‚^$0ïý˜y[Š *Z—BTK -ÛÖXx+Þ½¡oFÔ¡Šsåð‡[ LÁ+T\@1M±_8±Eo=C¥BÈÌ~À—Ù,C yÄŠƒÂ•Ë»—Ùrý´š——ì,ãf׺Ãǹ¯ÏÇ~”ž›}Ó7ݶ™¿æ a$/¾äKc¼\óXwŸõûà›Û| §â1'p®äðqH'`Ô ð3‹zšüßÚ±y±n VG³1°™ž07l(%tî[þM^Xúendstream +708 0 obj +(7.2 Chroot and Setuid) endobj -706 0 obj << -/Type /Page -/Contents 709 0 R -/Resources 708 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 715 0 R ->> endobj -707 0 obj << -/Type /XObject -/Subtype /Form -/FormType 1 -/PTEX.FileName (./isc-logo.pdf) -/PTEX.PageNumber 1 -/PTEX.InfoDict 716 0 R -/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] -/BBox [0.00000000 0.00000000 612.00000000 792.00000000] -/PieceInfo << -/Illustrator 717 0 R ->> -/Resources << -/ColorSpace << -/CS0 718 0 R ->>/Properties << -/MC0 719 0 R ->>/ExtGState << -/GS0 720 0 R ->>>> -/Length 843 -/Filter /FlateDecode ->> -stream -H‰tUIŽ$7 ¼ç+ôb‹‹¶«Û†OcàƒP°}©`ÜÿÁLU7Ð6 -ÈT¤$.Aëå·×òòåµ–Ÿ~~-Ç£–±¬tµrãâŸ??Ê÷ãåõ÷Zîo¥ŠÏgçsF)owlÿŠí¿ßŽEKÅO‹õ!ÝZq¼[oQîßî|;ÂÅ`¸–ÇáK¦GQ—¹ð²²$h¿ûñ×ñõƒ=¯KZôUà_*Oƒ·!ˬè‰Ï7ŸÒ*WYL¢›D‡m‰æ°zá[“˜Šnâ>?|°%6Kø -›Øiê?ÃÒš)0*¾ßƒ2!} j´rS…[2 1Z“ÞGA¨u£r•~îωãÞeT䲎‡¦1'ïÇIŒ‚HGGŠ`´kf ò¸—wa±FÚFBA[c)L‡4SzZŠÓ¼ÄÓSF¬äDZÊІ9ù¸> Hº¡ -J‚xi†þOá@½-M†xôÉ‚î³_¨OC8³Ä:JXl 0$‡(•vàª~FC¬žm†¢Ëj£4QzÐŒT³«´$Ù‚±³ ¬‘î5Þ[š¸FÚ3föòùˆÏAk€¥ûl0,¥·'XIo Ïy*æ#Až‡?+E#;™J¹–ºp”UQ–§Â< -F ‘åReBC[¬ÐWçz %A2×¹NôØVš‘æ -BqÕ•l9uš× ^D5 ™]ÀS—÷ã‚H¯X4¾¢oÆØ ŒÉÆÞõcUÑrΣe©úx"E]æ†`¦Øº:AcÁѶÓ}¸oüxbˆ Òétž^‚fO„€PÈúÄÙt“ÍÚ16 -Ì‹<{a˜ïºõ4ÖØ(®)tAtR÷´[bvL·>³o [Õ³ü˜“ÓÓ–²\AYŸ`IõÌõ„ˆ‰sz£“$Œ‰ýÁ˜˜IO -!=§ ¨Œø†vGc £I#/'~<1‚ÀÔRPy±´ýl1½Ͷw1 чd }¡þa#fßËþÚF¯ÞƒÇY}ïAô -Ë9b :žÎÞF" ‹>64”~0IGD˜Ë Ø°$ÙtMâ¯%Z½Gð¾¥Úñ§aÑÌ‘ I¼ ý—/øýzü+À0huendstream +709 0 obj +<< /S /GoTo /D (subsection.7.2.1) >> endobj -716 0 obj -<< -/CreationDate (D:20100303120319-08'00') -/Creator (Adobe Illustrator CS3) -/Producer (Adobe PDF library 8.00) -/ModDate (D:20100412113401-07'00') -/Title (ISC_logo_only_RGB) ->> +712 0 obj +(7.2.1 The chroot Environment) endobj -717 0 obj -<< -/Private 721 0 R -/LastModified (D:20100412113400-07'00') ->> +713 0 obj +<< /S /GoTo /D (subsection.7.2.2) >> endobj -718 0 obj -[/ICCBased 722 0 R] +716 0 obj +(7.2.2 Using the setuid Function) endobj -719 0 obj -<< -/Intent 723 0 R -/Usage 724 0 R -/Name (Layer 1) -/Type /OCG ->> +717 0 obj +<< /S /GoTo /D (section.7.3) >> endobj 720 0 obj -<< -/OPM 1 -/BM /Normal -/CA 1 -/OP false -/SMask /None -/ca 1 -/AIS false -/op false -/Type /ExtGState -/SA true ->> +(7.3 Dynamic Update Security) endobj 721 0 obj -<< -/RoundtripVersion 13 -/ContainerVersion 11 -/CreatorVersion 13 -/AIMetaData 725 0 R -/AIPrivateData1 726 0 R -/AIPrivateData2 727 0 R -/AIPrivateData3 728 0 R -/AIPrivateData4 729 0 R -/AIPrivateData5 730 0 R -/NumBlock 5 -/RoundtripStreamType 1 ->> -endobj -722 0 obj -<< -/Length 281 -/Filter /FlateDecode -/N 3 ->> -stream -H‰b``2ptqre``ÈÍ+) -rwRˆˆŒR`?ÏÀÆÀ̉ÉÅŽ> v^~^*øvD_Ö™…)p%•é?@l”’ZœÌÀÀhdg——ÅçÙ"IÙ`ö»($ÈÈ>dó¥CØW@ì$û ˆ]ôý¤>Ìfâ›aË€Ø%© {œó *‹2Ó3J ---Sò“R‚+‹KRs‹<ó’ó‹ -ò‹KRS€j!îAˆBPˆi5Zh’èo‚Öç@pø2ŠAˆ!@riQ”ÉÈdL˜0cŽƒÿR–?1“^†: üSbj† ú ûæÀÆOýendstream -endobj -723 0 obj -[/View/Design] +<< /S /GoTo /D (chapter.8) >> endobj 724 0 obj -<< -/CreatorInfo << -/Subtype /Artwork -/Creator (Adobe Illustrator 13.0) ->> ->> +(8 Troubleshooting) endobj 725 0 obj -<< -/Length 981 ->> -stream -%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 13.0 %%AI8_CreatorVersion: 13.0.2 %%For: (Brian Reid) () %%Title: (ISC_logo_only_RGB.ai) %%CreationDate: 4/12/10 11:34 AM %%BoundingBox: 247 367 366 413 %%HiResBoundingBox: 247.0869 367.5654 365.0859 412.583 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 9.0 %AI12_BuildNumber: 434 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0.658824 0.8 (ISC logo blue) %%+ 0.372549 0.376471 0.384314 (PANTONE 425 U) %%+ 0 0 0 ([Registration]) %AI3_TemplateBox: 306.5 395.5 306.5 395.5 %AI3_TileBox: 18 33.1201 594 786.96 %AI3_DocumentPreview: None %AI5_ArtSize: 612 792 %AI5_RulerUnits: 3 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 0 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 1 %AI9_OpenToView: -381 793 0.92 1268 743 26 0 0 117 75 0 0 1 1 1 0 1 %AI5_OpenViewLayers: 7 %%PageOrigin:0 0 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream +<< /S /GoTo /D (section.8.1) >> endobj -726 0 obj -<< -/Length 11082 ->> -stream -%%BoundingBox: 247 367 366 413 %%HiResBoundingBox: 247.0869 367.5654 365.0859 412.583 %AI7_Thumbnail: 128 52 8 %%BeginData: 10932 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FD1F52285252A8FD04FFFD05A8FFFFFFA87DFD4F52285252522852 %525228525252285252522852525228525252285252522852277DA8FFFFA8 %7D7D525227FD04527DA8FFFFA85252275252522852525228525252285252 %522852525228525252285252522852525228525252285252522852525228 %52525228525252285252522852525228525252285252522852525228FD21 %52A8FFFF7D7D525227FD0752275252A8FFFF7DFD215227FD2A522E522752 %2E5227522E5227522E5227522E5227522E5227522E5227527DFFFFA85252 %27522E5227522E5227522E5227522752A8FF7D5227522E5227522E522752 %2E5227522E5227522E5227522E5227522E522752277D7D7D275227522E52 %27522E5227522E5227522E5227522E5227522E5227522E5227522E522752 %2E5227FD1A52277DA8FFA87D2EFD11522E527DFFA853FD1D52A8FFFFFF7D %28FD285228525252285252522852525228525252285252522852277DFFFF %7D522752525228525252285252522852525228525252275252FFA8522752 %285252522852525228525252285252522852525228525252277DFFA852A8 %FF5227525252285252522852525228525252285252522852525228525252 %285252522852525228FD1852277DFFFFFD1B52FFA8FD1A527DFFA8275252 %FF7DFD265227522E5227522E5227522E5227522E5227522E522752277DFF %FF525227522E5227522E5227522E5227522E5227522E5227522E52275252 %FFA852275227522E5227522E5227522E5227522E5227522E522752A8A827 %522E527DA9275227522E5227522E5227522E5227522E5227522E52275227 %5227522E5227522E5227522EFD17527DFFA8FD1E527DFFA8FD17527DFFFD %0452287DFFFD155228FD075228FD08522852525228525252285252522852 %5252285252522852527D2752525228525252285252522852525228525252 %2852525228525252285252527DFF7D522852525228525252285252522852 %525228FD0452FF7D5228FD0452FF52522852525228525252285252522752 %2752527DA1A8A8FFCACFA8CAA17D5252275228FD3C52A8FFFD145228A8FF %53FD0652FFA82EFD0C527D7DCAFD04FFAFAF85AF85AFAFFFFFFFA87DFD05 %522E5227522E5227522E5227522E5227522E5227522E5227522E5227522E %5227522E5227522E5227522E5227522E5227522E5227522E5227522752A8 %FF275227522E5227522E5227522E5227522E522752FFA827522E5227522E %FF7D522E5227522E522752275252A8FFFFAFAF603CFD041413FD04143C60 %AFFFFF535227FD3A52277DFFA827FD11527DFFFD0852A8FFFD0952A8CFFF %FFAF3C3D1414141A141A141A141A141A14141461AFFFA8FD045228525252 %285252522852525228525252285252522852525228525252285252522852 %5252285252522852525228525252285252522852525227A8FF5227525252 %2852525228525252285252522EFFA85227525252285228A87D5252522852 %27527DFFFFAF603CFD07141A1414141A1414141AFD041460FFA8FD3D52FF %A8FD10527DFF7DFD0F527DFFFFA9611414141A141A141A141A141A141A14 %1A141A141A141A14143CFFA827522E5227522E5227522E5227522E522752 %2E5227522E5227522E5227522E5227522E5227522E5227522E5227522E52 %27522E5227522E5227522E527DFF525227522E5227522E5227522E522752 %A8FF27522E5227522E5227522852275252A8FFFF3C1413FD191436FFFD3C %5259FFA828FD0E52FF7DFD0D527DFFFF8B1414141A141A141A141A141A14 %1A141A141A141A141A141A141A141A141460285252522852525228525252 %285252522852525228525252275227522752275227525252285252522852 %52522852525228525252285252522852525227A8FF7D2752525228525252 %2852525227A8FF52275252522852525228522752A8FFA93CFD05141A1414 %141A1414141A1414141A1414141A1414141A1414141A1414FD1552285252 %7D527D597D527DFD065227FD1852FFA8FD0D52FFFFFD0A52277DFFFF601A %141A141A141A141A141A141A141A141A141A141A141A141A141A141A141A %141A142E5227522E5227522E5227522E5227522752527D7DA8A8FD09FFA8 %FFA8A87D532852275227522E5227522E5227522E5227522E5227522E527D %FF525227522E5227522E52275252FF7D522E5227522E522752277DFFFF36 %FD2314FD0E527D7DFD07FFA8A87DA87DA87DFD04A8FD05FFA87DFD15527D %FFA827FD0A52A8FF7DFD0952A8FFAF1414141A141A141A141A141A141A14 %1A141A141A141A141A141A141A141A141A141A141A145252285252522852 %525227527DA8FFFFFFA87D7D52522752275227522752275227522752527D %A8FFFFFFA87E52522752525228525252285252522852525227A8FF522752 %5252285252522752FFA8275252522852525227A8FF85FD05141A1414141A %1414141A1414141A1414141A1414141A1414141A1414141A1414141AFD07 %52275253A8FFFFFFA8FD045227FD0F522EFD04527D7DFFFFFFA87DFD1052 %7DFF7DFD0A52FF7DFD0852A8FF8B1414141A141A141A141A141A141A141A %141A141A141A141A141A141A141A141A141A141A141A1427522E52275227 %7DA8FFFFA85252275227522E5227522E5227522E5227522E5227522E5227 %522E52275227527DFFFFFF7D52275227522E5227522E5227522752A8A827 %5227522E52275227A8FF5227522752525227A8FF6113FD2714FD0652A8FF %FF7D7D28FD22527DA8FFFF7DFD0C5227A8FF7DFD0852A8FFFD06522EA8FF %61141A141A141A141A141A141A141A141A141A141A141A141A141A141A14 %1A141A141A141A141A141A14285227527DFFFF7D52522752285252522852 %525228525252285252522852525228525252285252522852525228522752 %52FFFFA8525228522852525228FD0452FF7D5228525252285252FF7D5252 %52285227A8FF611414141A1414141A1414141A1414141A1414141A141414 %1A1414141A1414141A1414141A1414141A141452277DFFFFA87D28FD2952 %287DFFFF7EFD0B52A8FFFD065227A8FF7D2752525227A8FF8B141A141A14 %1A141A141A141A141A141A141A141A141A141A141A141A141A141A141A14 %1A141A141A141A1428A8FFFF525227522E5227522E5227522E5227522E52 %27522E5227522E5227522E5227522E5227522E5227522E5227522E522752 %7DFFA87D275227522E522752277EFF52275227522852A8FF52522752277D %FF8BFD121413FD0F1413FD0914FFFFA8FD3352FFFFA8FD0952FF7DFD0652 %FFA8FD04527DFFAF141A141A141A141A141A141A141A141A141A14613C3C %141A141A141A141A141A141A143D3C3C141A141A141A14FF7D2752525228 %525252285252522852525228525252285252522852525228525252285252 %522852525228525252285252522852525227A8FFA8FD045228525252A8A8 %27522852277DFF7D27522752A8FFFD051461A9AF848B1414141A141436AF %AFFFFFFFAFAF36FD04141A14141461A9FFAFFFAFAF601A1414141A7D2EFD %3552277DFFFFFD0752A8FFFD05527DFFFD04527DFF3C14141A141484FFFF %FFAF1A141A141A85FD09FF841A141A141A14AFFD08FF841A141A1427522E %5227522E5227522E5227522E5227522E5227522E5227522E5227522E5227 %522E5227522E5227522E5227522E5227522E5227522E52277DA8FF52522E %5227527DFF52522E5227FFA852275252FF60FD061485FFFFFFAFFD041460 %FD0BFF36FD0414AFFD0AFF60141414FD3A5253FFFF7DFD04527DFFA85252 %527DFFA8285252FFAF1A141A141A141A84FFFFFFAF3D141A14FD05FF603D %60FD04FFAF141A1461FD04FFA96136AFFD04FF141A142852525228525252 %285252522852525228525252285252522852525228525252285252522852 %52522852525228525252285252522852525228522752A8FF5252285252FF %A8FD0452FF7D5227A8FF3C141AFD051485FFFFFFAF14141460FD04FF3614 %141460FFFFFFA91A141484FFFFFFA91A141414FD04FF611414FD3D52A8FF %FD0452A8FF525228A8FF7D277DFF8B141A141A141A141A85FFFFFFAF1A14 %1A60FD04FF3C141A1461FD04FF141A14FD04FF8B141A141AAFFFFFFF601A %142E5227522E5227522E5227522E5227522E5227522E5227522E5227522E %5227522E5227522E5227522E5227522E5227522E5227522E5227522E5227 %522752A8FF5252277DFF7D2752A8FF2752A8FFFD08141385FFFFFFAF1414 %1361FD04FF36FD04148584856014133CFD04FF60FD0414FD04FF851314FD %3D52287DFFFF525252FF7D5252FFA8527DFF3C1A141A141A141A141A85FF %FFFFAF1A141A60FD04FFAF141A141A141A141A141A3CFD04FF61141A141A %3C616061361A145252285252522852525228525252285252522852525228 %525252285252522852525228525252285252522852525228525252275252 %522752525228525252277DFF7E2752FFA82753FF7E27FFA914141A141414 %1A1414148BFFFFFFAF1414143CAFFD04FFAFFD091461FD04FF3614141AFD %07141AFD2B522852285227FD075227FD075227A8FF7D27FFA8527DFF7D7D %FF3D141A141A141A141A141484FFFFFFA91A141A1485FD06FF603C141A14 %1A14143CFD04FF61141A141A141A141A141A1427522E5227522E5227522E %5227522E5227522E5227522E5227522E5227522E5227522E522752275227 %FD04527D7DA8A8FFA8FFA8FFA8A87D7D52522752275227FFA8527DFF277D %FF52A8AF13FD0A1485FFFFFFAFFD0414138BFD06FFA860FD05143CFD04FF %36FD0B14FD2852A8A8FD07FFA8FFA8FFA8FD06FFA87D5227527DFF7D7DFF %7DA8FF7DFF3C1A141A141A141A141A141A84FFFFFFAF3D141A141A148BFD %07FF8B141A141A3CFD04FF61141A141A141A141A141A1428525252285252 %522852525228525252285252522852525228525252285252522752275252 %A8A8FFFFFFA8A87D7DFD065227FD04527D7DA8FFFFA87D2752A8FF52FF7D %A8A8CAA914141A1414141A1414141A1485FFFFFFAFFD071460A8FD06FF8B %1414143CFD04FF36FD04141A1414141A1414FD2252A8FD04FF7D7D525228 %5227FD0B52275252527DFFFFFF5253FFA8A8A8FFA8FF61141A141A141A14 %1A141A141A85FFFFFFAF1A141A141A141A141A60FD06FF85141A3CFD04FF %61141A141A141A141A141A142E5227522E5227522E5227522E5227522E52 %27522E5227522E5227522752277DA8FFFFA859522752275227522E522752 %2E5227522E5227522E5227522752277DA8FF7DA8FFFFA8FFFFAFFD0C1413 %85FFFFFFAFFD061413FD0414AFFD04FFA9141360FD04FF36FD051413FD05 %14FD1D527DFFFFFF7D7DFD1E52A8FFA8FD05FF601A141A141A141A141A14 %1A141A85FFFFFFAF1A141A143D363D141A141A14FD05FF3C1A3CFD04FF61 %141A141A60AF85AF601A1452522852525228525252285252522852525228 %52525228525252277DFFFFA87D2E52275252522852525228525252285252 %52285252522852525228525252285228527DFD06FF3C141A1414141A1414 %141A1414148BFFFFFFAF141414AFFFFFAF8BFD04143CFD04FF3C143CFD04 %FF60FD04148BFFFFFFAF1414FD1752285259FFFFA9525227FD2352A8FD04 %FFAF141A141A141A141A141A141A141484FFFFFFA91A141484FFFFFFA91A %141A1461FD04FF3C1414FD04FF8B141A141AA9FFFFFF85141427522E5227 %522E5227522E5227522E5227522E52275227527DFFA87D27522E5227522E %5227522E5227522E5227522E5227522E5227522E5227522E5227522E5227 %522752A8FFFFFF60FD0E1485FFFFFFAF14141485FD04FFFD041436FD04FF %3C141484FFFFFFA8FD0414FD04FF611414FD16527DFFFF7D5228FD275227 %A8FFFFFF3D141A141A141A141A141A141A141A84FFFFFFAF3D141460FD04 %FFAF363C3CFD05FF141A1461FD04FF853C148BFD04FF3C1A142752275227 %52275227522752275227522752275227A8FFA82852275227522752275227 %522752275227522752275227522752275227522752275227522752275227 %52275252FFFFAFFD0F1485FFFFFFAFFD0414A8FD05FFAFFD05FF36FD0414 %AFFD0AFF841414147D527D527D527D527D527D527D527D527D527D52A8FF %FF527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527DA8FF853C363D3C3C363D3C3C36 %3D3C3C363D85FFFFFFAF3D363D3685FD0AFFAF3C363D3C3C60FD0AFF6136 %3D3CFD16FFA8FD49FFAFFD11FFAFFD09FFAFFFFFFF %%EndData endstream +728 0 obj +(8.1 Common Problems) endobj -727 0 obj -<< -/Length 65536 ->> -stream -%AI12_CompressedDataxœì½ëŽ]Iv&öçÒ?tM*î—¶1@æÉLY%5º[ @±¨ÇE²Áª’Ü~zÇZëûVìs2Y]7Æ@ç“™+÷‰;"ÖýöÿÓ¯ûâöËÿüöE~nNñçOo_óñÓ¯nzó×_}õí×ß|Ð/~óË›¸îZ7Ýþõø7þÃÛO_¿ûøáWú§—iýñQ>ý‹»Oï^¸ùÍÛw_þòæ¿\àß½ûæ«·ëýÛó_}üýÇ/>~øê_üæ¯î^¾~÷K>xtÿú›u[ù˘þ2†›•ËÍí߬î>~ûáËw~÷ñÿþÕM*ý&7ù×nJÌëÏÿû»ß¼ýúúž—a´)7¾¬­–õC]:×GÒË:äc÷ß|ûþí‡o~ýéã›·_}þøÕÇO_ÿêæüÇ5û¿yýûõ—×7ÿçÛ¯¾úøï7w_½~óÖË×/ß}õv½çû×ßÜLY‘Û¿Žé‹»oß}õåß~ûþŸß®(¹8¡#þý×k¨5ªü,àþÅ_¿_ß¾ýæ›5Ûõ~õZWL¯ˆÿÃM°~÷úÓïß~³ŽÂǯ¾ýFæøÓÚšW¯ÿøV¶7Úþîo?üîã?èü^ä×lòZÀ™nbj㦗|“š='ö›^ñȨŌd C÷µÐ¿^{ûwŸÞýþ݇_abý‹¿úôî˽ß=Ý û¦o°vwÿ›üg“\ïûÍ7o?`ÒëœÿæpnÂË¿ùízâÇ/ÏßË‚-¨²¶÷Ã:Kë°ØßügýËúø·°Ùëï_¬½ùõ§wdÌÓßê_Æ¿þêÛõ§¿úôñÛ?üõ‡ùxú…„_¿þæ_&¼ýðå× ± f¿ÞØ'ôÕ»{k°…ÛøåwŽ÷»O¯ß¬ÇÞüÝ?ÿ··o¾Y`ÿôÛoß}óöOôÛ7²LŸnî>}ûõ¿Þüîãǯ|~—òi¬P¹ÿŒgüZ?ðáï>ØJ?}n¸~ÒÂŒÿáž²îþüÖÿGýüú«¯ÞýþÓë?üë»7Ï=à™¿û“ìo?àa Ç?½ÝŸ×_ùÿ÷8–|ÿÏ¿z÷õû}_¿þôÍ»7_½ýí¿þæíû?=ÚýÛYœí°l -}øðoo¿úø‡Ã$òú×7ÿåõ§?|×вMÿòî× CŸ÷2~|ÿaÚ7¿ý××x«Óýæ_õÎß~cüÕë¯?Ý(܇ò³Îï¢g—$É`>hýbÆ#é{ñâ;hb¿¹ûpøó_}zýå»Em—@ó÷>¼~ÿöË›ßôËÓSТñõæîËÓ?þ·Sˆëú¿N?ç`ÿ øƒ_øôŸ×JÝ=ÜÝßïîînïæ]¿kwõ®Üå»xnnïoïnooçºúm»-·ù6݆ù8æyÞMù³Í%–Ì4à ãq<œÆyÜc´±ä¿‘Öúc¿_×¹ßõ¹®Ñ{¯ë*=õØc{lëºowm=§Ö×ÕZYW>µÜR -ÔÇú°®óºÖ$ëm]£ËµŠÜ¹®¼®¸®PCy\×úÎëº/ë•Ê­^£ŒÓv=¸èg -¿®È+?îËVê׃^ûçõÿ9œ£~—+žÓº"þOç¼.þl¿Ë=ñä€xñgûý;þœ×ñ¹t=ìç“þÚüª×5”¿w\ã ¤ŸÐþÄËÿtxÌŵV*¬µº¯ëj¸tçﮉë×^g\üzðëQ®ÓýãCÀq%¿²_Wõ«®î×8= ¿æáº=\w×ù꺿¼NëÛ羟¿ôT­cÞןëØß­õ»_ó|ìa!EêyÒº0A¾ÆBšÛ…<çµ”ýq„±–²Ð >äkŽÛÓ¾³®ôÃx\Hj¦™ŠÖuµ…|‚œsáôÂ÷…Æ÷úÞ·a]q¡w^W¹]صq=ñvœnÇÂùº»=¯K6M–çñ.¬+®+­+¯KÐLPs½È¢$ýnÍäNŸ²hËí}ïÎ'Ûñ 4"ê?û¡+Upâ>ïëáp=/¡‡+^\I®“ý·®|u•«ëú«=¹”˜ì?¿Æ³×üìu{}ž€îþÔµVªÜüÅwŸ„ .Š¬ÿùÕ}QQûn×¢“úWÆw»Òºì{2È ?$ÿ³\—|ý@ôß…«®¹éñYï++q»Níý"#1Æ¥ÁǶØÏŒ·ëÀÝÇÇõ>)åu$Zê mn×ɾ_æ1ÇœrYG£ç±ä.ß/ž°Ö*–¼Î‡°“¹¿œÌG=kIM[»-[v^tèq­w\œ¬¬Ó"ø.ؾp˜^ËO É ÅÁ½‹"öBjÅhÁfÁdÃbÁ`ÅÞ…·IqVðu(š.Ô<)NVÅÆ©x´ÓÕ¸ e‚ˆ‚ÓB >’b -½À± j›7 >]ü!‘X Ù^ô[ä½Òwà¾Ò}ãB«„?§¨z)bŸÖ·µÌë{º_[s¿6íü¸®‡5ÊYÿõ^w~ •ZK~E–·¸cV²BC†õ¸”dž«â"-¡pE½‚]NÏùåì`/.X.rrŸ~±äd[\n_ÑVšÜË‹‹\ˆ_\.¶]ó°äã„uçÚcýít PÕ È3mïuÄ[¡ëí²G²?ÁwæNWßV^ä’,òËI×û(iŽƒ¬™TÚ|Tyó ‰s¨ÄY!sFH÷*wÞÎyZ<¬CôÌ +¢ ŸëµDú¼U鳫üYT*>@½…ÚTÍ"ƒžU|Tô¬BèT!´ãyÂéÿôÕŸ¿NW€ñ=®ù]×ɼý^×ÝŸºNJÍž\G梤ÿQH¦aÃ:“ OùýApv}?ëÿü~qa}¿Õÿù]þ¿=­ÿ¦^ßåêz5¥ÒòÝø7t|—ÿ“þŸÖe_‹êŸô?ü‚ïÁ0ÖpGÙÀ½^g|?‹HsñýNä"û~Â/óp-þjRÜP9NdÙù´(}­E鈠•Ð aàSu–¶¸CÎ"ˆj-Šð÷¦­œt/eã»k)‹é‹ ‹~Ò(z…r£…‹/­gªø"_²£ÿºê´˜Ù­H‚‹±õõHÑu„ÕÅõ;‰’ÝàÈâÛrËc-mõNºD²4\ ‘1 a×Q¢Ý>¬OÉ& Ù{e±e1Xa¯÷‹µ¦5í¾^㼤÷°^±(FÜ)/>ºä¨“2ÑGe Â>§2ÏÇ5»¼0¸/l^‰¢¢:IQ=c¨úpsQv¤Â3XÔf]Æ$„±=ÚQTf'ÏHÊþ2ÝzШúÉÕ©£*uT¤¶ -¥üáBsÚ:“ëJ'W” ¹^tÔ„Žz«5`ƒFŒ=.VyZßT -×˸ê"Àz:TÍ ¢AUÄ—¡¶Ó5¨m¨®ñDÛ8觃²AE㬢Žé®WP/®S»µ ÂÖœ|g±ã{?¸ÍuZn€->ž‹® ~òÕ¦Fj:¨¬Æ%£üé|òtÉ(:Ÿ<]2Êçù¤Ò=±ÓDØiîÕJsIï²RºpRÓÌýb(b”™JãZ©Gæ²6árÄQ’%úîº\Y]š“K¶,Ûj±wn°*#阩jè»g}o¨­?­Ö×Uò~Öíþ’b~’÷“·ëJ½“Ú“î•^ÏEîÚ"æi1¬Ç…Šg!̧¥Ì·E—…"›aju3Ñb»^¢ÅÜEÉ%ØgŒÎø¢p“.*ÌÕñãi¡gRšŸ•úw1(G¼Ð¾¨BPÖ!êNU†Ò•6‹zVrô¨³‘ç”Óz/JB&{Ü)ÙvUŠ¶0%êÈ:¬ དྷ†Åh©F'ÕŽL?\ƒàª¥\ £y7^({O!û -¢Á»¾ùgQ8Ò— ùÚ`P-\¹ÌP/»šLżw%3AÍü¬aét°,=oW:Z•& JÛœdÆ$3%©!é;Ò£Û -ìGf:£U"A¾M-GÅǪ̂B£iÉâl–Ò÷¡”žWóëhÙBlö+®h×Ih龄Ãà:š]sº=ûuw¸ö×<)ë²køÕWóktŽbyöKeµ“ýw«8lZÙÖ2 ?§`•Ë§Šå…Ry©RÊ£2y¾ÒÛ·"9\w‡y:*ð_²Qˆ5ÁõøGˆ>6¾}5xÕáO`jxÞ âŸNâÎO¥‡*>üŽ  qçK¤FX }HHÇ¢=£å›tSÃÍB)à·§¿øâÇp÷õ)¼\îLIn+5Ì¡?Ì,Ì`±€)Ÿ”iŽuëút®/ëÂÌ›Ú_."[|?ÃP6#Þ’ü¤³"?­7H]~X:Özó1ì¥j}Ùâ8L觎¤ó‰ˆ˜)²ŒÙ¢G^.z²Æ”ˆ›ÅbzVˆ¼¾}¼”—³äÃL~Â:YL_^þ +YbÔ•N±¶¹·Ý6y¾~º§ñÓ†Y3¹»w_(}šßÏ͹Ü3žNÞÄõ:;í+ªaÖd…9aªv†ÅS¤„½¹ªN=TF¸SýÁÔùOÌ :`=«)Ô$„´T̪ÒÁbK ¹…|ðÙ ©×`Û˜'• xXq6fRãa& -‡‘‹T2 y¹ù8xZ_ËjN©ànÆßné59ÃGµX2»à /ÃÀBJ?øQÌ“"¾”³òAõ¨œ„ÊÇJÄŸ"y„ÿ…JÁ5ª²?8Â?‹ò'˜Ý.ð^•ƒò âŸá1ÔOja*°HÀÉiÀý’,„ (ð˜ ó‚ì&[˜m iOÐ`Bª@Ù–Ò-iæg•C`pj>4Gj9¨Ä8P -ÒŠM-(†Ñ RŒ†ëài5L½ƒsÜ(ÇÃõ ÿ59¡·¯]Ð¥%§i_·¢rçD„ÅܵÚ²éK„ÄÈk©½—äæHtêA=’Ÿ~^„H¯ÓMºüú,¦HÖ“ëô¹?\Ѹï}~øGþãü¡(nþxàèù€Þàé'øÑÁ½‰àõÎ~DpCnêÿÆßvŸ½Ä¦lÞ¼:‚Ï‚?øüÖV©¯ÂpRmáÈô“+¯‚àÅí„~Š«$pRQ€!ÝÑü(¢?ѯƒ/½!z?Û‡bè­2º£˜ ¨~ìñ -á³;iíOO0þîB’ø,Ú‘ÿôy쿸ž¢ÿñ:Óg¨Âó×5­ø,Íxzýè¯Ó÷¸ç»‰ÑÕuúa·ÿ¨/Qüg4ý‡¯®t¸2²­—UcNhÃ4Œ¹…ó(²MK iFÕ¨©ÜžàK¤Ð’°Á ¡h´g>êL\1j6%ï4€ãAýMé´è˜‰)awj¾°¢¤.¨¢¡CqE¤’%XIµ”²ÈÔЀŽ[%N§ö 4)Ã9ÕS„ø> +endobj +732 0 obj +(8.1.1 It's not working; how can I figure out what's wrong?) +endobj +733 0 obj +<< /S /GoTo /D (section.8.2) >> +endobj +736 0 obj +(8.2 Incrementing and Changing the Serial Number) +endobj +737 0 obj +<< /S /GoTo /D (section.8.3) >> +endobj +740 0 obj +(8.3 Where Can I Get Help?) +endobj +741 0 obj +<< /S /GoTo /D (appendix.A) >> +endobj +744 0 obj +(A Appendices) +endobj +745 0 obj +<< /S /GoTo /D (section.A.1) >> +endobj +748 0 obj +(A.1 Acknowledgments) +endobj +749 0 obj +<< /S /GoTo /D (subsection.A.1.1) >> +endobj +752 0 obj +(A.1.1 A Brief History of the DNS and BIND) +endobj +753 0 obj +<< /S /GoTo /D (section.A.2) >> +endobj +756 0 obj +(A.2 General DNS Reference Information) +endobj +757 0 obj +<< /S /GoTo /D (subsection.A.2.1) >> +endobj +760 0 obj +(A.2.1 IPv6 addresses \(AAAA\)) +endobj +761 0 obj +<< /S /GoTo /D (section.A.3) >> +endobj +764 0 obj +(A.3 Bibliography \(and Suggested Reading\)) +endobj +765 0 obj +<< /S /GoTo /D (subsection.A.3.1) >> +endobj +768 0 obj +(A.3.1 Request for Comments \(RFCs\)) +endobj +769 0 obj +<< /S /GoTo /D (subsection.A.3.2) >> +endobj +772 0 obj +(A.3.2 Internet Drafts) +endobj +773 0 obj +<< /S /GoTo /D (subsection.A.3.3) >> +endobj +776 0 obj +(A.3.3 Other Documents About BIND) +endobj +777 0 obj +<< /S /GoTo /D (section.A.4) >> +endobj +780 0 obj +(A.4 BIND 9 DNS Library Support) +endobj +781 0 obj +<< /S /GoTo /D (subsection.A.4.1) >> +endobj +784 0 obj +(A.4.1 Prerequisite) +endobj +785 0 obj +<< /S /GoTo /D (subsection.A.4.2) >> +endobj +788 0 obj +(A.4.2 Compilation) +endobj +789 0 obj +<< /S /GoTo /D (subsection.A.4.3) >> +endobj +792 0 obj +(A.4.3 Installation) +endobj +793 0 obj +<< /S /GoTo /D (subsection.A.4.4) >> +endobj +796 0 obj +(A.4.4 Known Defects/Restrictions) +endobj +797 0 obj +<< /S /GoTo /D (subsection.A.4.5) >> +endobj +800 0 obj +(A.4.5 The dns.conf File) +endobj +801 0 obj +<< /S /GoTo /D (subsection.A.4.6) >> +endobj +804 0 obj +(A.4.6 Sample Applications) +endobj +805 0 obj +<< /S /GoTo /D (subsubsection.A.4.6.1) >> +endobj +808 0 obj +(A.4.6.1 sample: a simple stub resolver utility) +endobj +809 0 obj +<< /S /GoTo /D (subsubsection.A.4.6.2) >> +endobj +812 0 obj +(A.4.6.2 sample-async: a simple stub resolver, working asynchronously) +endobj +813 0 obj +<< /S /GoTo /D (subsubsection.A.4.6.3) >> +endobj +816 0 obj +(A.4.6.3 sample-request: a simple DNS transaction client) +endobj +817 0 obj +<< /S /GoTo /D (subsubsection.A.4.6.4) >> +endobj +820 0 obj +(A.4.6.4 sample-gai: getaddrinfo\(\) and getnameinfo\(\) test code) +endobj +821 0 obj +<< /S /GoTo /D (subsubsection.A.4.6.5) >> +endobj +824 0 obj +(A.4.6.5 sample-update: a simple dynamic update client program) +endobj +825 0 obj +<< /S /GoTo /D (subsubsection.A.4.6.6) >> +endobj +828 0 obj +(A.4.6.6 nsprobe: domain/name server checker in terms of RFC 4074) +endobj +829 0 obj +<< /S /GoTo /D (subsection.A.4.7) >> +endobj +832 0 obj +(A.4.7 Library References) +endobj +833 0 obj +<< /S /GoTo /D (appendix.B) >> +endobj +836 0 obj +(B Manual pages) +endobj +837 0 obj +<< /S /GoTo /D (section.B.1) >> +endobj +840 0 obj +(B.1 dig) +endobj +841 0 obj +<< /S /GoTo /D (section.B.2) >> +endobj +844 0 obj +(B.2 host) +endobj +845 0 obj +<< /S /GoTo /D (section.B.3) >> +endobj +848 0 obj +(B.3 dnssec-dsfromkey) +endobj +849 0 obj +<< /S /GoTo /D (section.B.4) >> +endobj +852 0 obj +(B.4 dnssec-keyfromlabel) +endobj +853 0 obj +<< /S /GoTo /D (section.B.5) >> +endobj +856 0 obj +(B.5 dnssec-keygen) +endobj +857 0 obj +<< /S /GoTo /D (section.B.6) >> +endobj +860 0 obj +(B.6 dnssec-revoke) +endobj +861 0 obj +<< /S /GoTo /D (section.B.7) >> +endobj +864 0 obj +(B.7 dnssec-settime) +endobj +865 0 obj +<< /S /GoTo /D (section.B.8) >> +endobj +868 0 obj +(B.8 dnssec-signzone) +endobj +869 0 obj +<< /S /GoTo /D (section.B.9) >> +endobj +872 0 obj +(B.9 named-checkconf) +endobj +873 0 obj +<< /S /GoTo /D (section.B.10) >> +endobj +876 0 obj +(B.10 named-checkzone) +endobj +877 0 obj +<< /S /GoTo /D (section.B.11) >> +endobj +880 0 obj +(B.11 named) +endobj +881 0 obj +<< /S /GoTo /D (section.B.12) >> +endobj +884 0 obj +(B.12 named-journalprint) +endobj +885 0 obj +<< /S /GoTo /D (section.B.13) >> +endobj +888 0 obj +(B.13 nsupdate) +endobj +889 0 obj +<< /S /GoTo /D (section.B.14) >> +endobj +892 0 obj +(B.14 rndc) +endobj +893 0 obj +<< /S /GoTo /D (section.B.15) >> +endobj +896 0 obj +(B.15 rndc.conf) +endobj +897 0 obj +<< /S /GoTo /D (section.B.16) >> +endobj +900 0 obj +(B.16 rndc-confgen) +endobj +901 0 obj +<< /S /GoTo /D (section.B.17) >> +endobj +904 0 obj +(B.17 ddns-confgen) +endobj +905 0 obj +<< /S /GoTo /D (section.B.18) >> +endobj +908 0 obj +(B.18 arpaname) +endobj +909 0 obj +<< /S /GoTo /D (section.B.19) >> +endobj +912 0 obj +(B.19 genrandom) +endobj +913 0 obj +<< /S /GoTo /D (section.B.20) >> +endobj +916 0 obj +(B.20 isc-hmac-fixup) +endobj +917 0 obj +<< /S /GoTo /D (section.B.21) >> +endobj +920 0 obj +(B.21 nsec3hash) +endobj +921 0 obj +<< /S /GoTo /D [922 0 R /FitH ] >> +endobj +925 0 obj << +/Length 240 +/Filter /FlateDecode +>> +stream +xÚ•OKA Åïó)rl›N2Éü9ZªRA¡27ñ°´[)¸[ºÖïïlWË‚^$0ïý˜y[Š *Z—BTK +ÛÖXx+Þ½¡oFÔ¡Šsåð‡[ LÁ+T\@1M±_8±Eo=C¥BÈÌ~À—Ù,C yÄŠƒÂ•Ë»—Ùrý´š——ì,ãf׺Ãǹ¯ÏÇ~”ž›}Ó7ݶ™¿æ a$/¾äKc¼\óXwŸõûà›Û| §â1'p®äðqH'`Ô ð3‹zšüßÚ±y±n VG³1°™ž07l(%tî[þM^Xúendstream +endobj +922 0 obj << +/Type /Page +/Contents 925 0 R +/Resources 924 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 931 0 R +>> endobj +923 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (./isc-logo.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 932 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 612.00000000 792.00000000] +/PieceInfo << +/Illustrator 933 0 R +>> +/Resources << +/ColorSpace << +/CS0 934 0 R +>>/Properties << +/MC0 935 0 R +>>/ExtGState << +/GS0 936 0 R +>>>> +/Length 843 +/Filter /FlateDecode +>> +stream +H‰tUIŽ$7 ¼ç+ôb‹‹¶«Û†OcàƒP°}©`ÜÿÁLU7Ð6 +ÈT¤$.Aëå·×òòåµ–Ÿ~~-Ç£–±¬tµrãâŸ??Ê÷ãåõ÷Zîo¥ŠÏgçsF)owlÿŠí¿ßŽEKÅO‹õ!ÝZq¼[oQîßî|;ÂÅ`¸–ÇáK¦GQ—¹ð²²$h¿ûñ×ñõƒ=¯KZôUà_*Oƒ·!ˬè‰Ï7ŸÒ*WYL¢›D‡m‰æ°zá[“˜Šnâ>?|°%6Kø +›Øiê?ÃÒš)0*¾ßƒ2!} j´rS…[2 1Z“ÞGA¨u£r•~îωãÞeT䲎‡¦1'ïÇIŒ‚HGGŠ`´kf ò¸—wa±FÚFBA[c)L‡4SzZŠÓ¼ÄÓSF¬äDZÊІ9ù¸> Hº¡ +J‚xi†þOá@½-M†xôÉ‚î³_¨OC8³Ä:JXl 0$‡(•vàª~FC¬žm†¢Ëj£4QzÐŒT³«´$Ù‚±³ ¬‘î5Þ[š¸FÚ3föòùˆÏAk€¥ûl0,¥·'XIo Ïy*æ#Až‡?+E#;™J¹–ºp”UQ–§Â< +F ‘åReBC[¬ÐWçz %A2×¹NôØVš‘æ +BqÕ•l9uš× ^D5 ™]ÀS—÷ã‚H¯X4¾¢oÆØ ŒÉÆÞõcUÑrΣe©úx"E]æ†`¦Øº:AcÁѶÓ}¸oüxbˆ Òétž^‚fO„€PÈúÄÙt“ÍÚ16 +Ì‹<{a˜ïºõ4ÖØ(®)tAtR÷´[bvL·>³o [Õ³ü˜“ÓÓ–²\AYŸ`IõÌõ„ˆ‰sz£“$Œ‰ýÁ˜˜IO +!=§ ¨Œø†vGc £I#/'~<1‚ÀÔRPy±´ýl1½Ͷw1 чd }¡þa#fßËþÚF¯ÞƒÇY}ïAô +Ë9b :žÎÞF" ‹>64”~0IGD˜Ë Ø°$ÙtMâ¯%Z½Gð¾¥Úñ§aÑÌ‘ I¼ ý—/øýzü+À0huendstream +endobj +932 0 obj +<< +/CreationDate (D:20100303120319-08'00') +/Creator (Adobe Illustrator CS3) +/Producer (Adobe PDF library 8.00) +/ModDate (D:20100412113401-07'00') +/Title (ISC_logo_only_RGB) +>> +endobj +933 0 obj +<< +/Private 937 0 R +/LastModified (D:20100412113400-07'00') +>> +endobj +934 0 obj +[/ICCBased 938 0 R] +endobj +935 0 obj +<< +/Intent 939 0 R +/Usage 940 0 R +/Name (Layer 1) +/Type /OCG +>> +endobj +936 0 obj +<< +/OPM 1 +/BM /Normal +/CA 1 +/OP false +/SMask /None +/ca 1 +/AIS false +/op false +/Type /ExtGState +/SA true +>> +endobj +937 0 obj +<< +/RoundtripVersion 13 +/ContainerVersion 11 +/CreatorVersion 13 +/AIMetaData 941 0 R +/AIPrivateData1 942 0 R +/AIPrivateData2 943 0 R +/AIPrivateData3 944 0 R +/AIPrivateData4 945 0 R +/AIPrivateData5 946 0 R +/NumBlock 5 +/RoundtripStreamType 1 +>> +endobj +938 0 obj +<< +/Length 281 +/Filter /FlateDecode +/N 3 +>> +stream +H‰b``2ptqre``ÈÍ+) +rwRˆˆŒR`?ÏÀÆÀ̉ÉÅŽ> v^~^*øvD_Ö™…)p%•é?@l”’ZœÌÀÀhdg——ÅçÙ"IÙ`ö»($ÈÈ>dó¥CØW@ì$û ˆ]ôý¤>Ìfâ›aË€Ø%© {œó *‹2Ó3J ---Sò“R‚+‹KRs‹<ó’ó‹ +ò‹KRS€j!îAˆBPˆi5Zh’èo‚Öç@pø2ŠAˆ!@riQ”ÉÈdL˜0cŽƒÿR–?1“^†: üSbj† ú ûæÀÆOýendstream +endobj +939 0 obj +[/View/Design] +endobj +940 0 obj +<< +/CreatorInfo << +/Subtype /Artwork +/Creator (Adobe Illustrator 13.0) +>> +>> +endobj +941 0 obj +<< +/Length 981 +>> +stream +%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 13.0 %%AI8_CreatorVersion: 13.0.2 %%For: (Brian Reid) () %%Title: (ISC_logo_only_RGB.ai) %%CreationDate: 4/12/10 11:34 AM %%BoundingBox: 247 367 366 413 %%HiResBoundingBox: 247.0869 367.5654 365.0859 412.583 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 9.0 %AI12_BuildNumber: 434 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0.658824 0.8 (ISC logo blue) %%+ 0.372549 0.376471 0.384314 (PANTONE 425 U) %%+ 0 0 0 ([Registration]) %AI3_TemplateBox: 306.5 395.5 306.5 395.5 %AI3_TileBox: 18 33.1201 594 786.96 %AI3_DocumentPreview: None %AI5_ArtSize: 612 792 %AI5_RulerUnits: 3 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 0 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 1 %AI9_OpenToView: -381 793 0.92 1268 743 26 0 0 117 75 0 0 1 1 1 0 1 %AI5_OpenViewLayers: 7 %%PageOrigin:0 0 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream +endobj +942 0 obj +<< +/Length 11082 +>> +stream +%%BoundingBox: 247 367 366 413 %%HiResBoundingBox: 247.0869 367.5654 365.0859 412.583 %AI7_Thumbnail: 128 52 8 %%BeginData: 10932 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FD1F52285252A8FD04FFFD05A8FFFFFFA87DFD4F52285252522852 %525228525252285252522852525228525252285252522852277DA8FFFFA8 %7D7D525227FD04527DA8FFFFA85252275252522852525228525252285252 %522852525228525252285252522852525228525252285252522852525228 %52525228525252285252522852525228525252285252522852525228FD21 %52A8FFFF7D7D525227FD0752275252A8FFFF7DFD215227FD2A522E522752 %2E5227522E5227522E5227522E5227522E5227522E5227527DFFFFA85252 %27522E5227522E5227522E5227522752A8FF7D5227522E5227522E522752 %2E5227522E5227522E5227522E5227522E522752277D7D7D275227522E52 %27522E5227522E5227522E5227522E5227522E5227522E5227522E522752 %2E5227FD1A52277DA8FFA87D2EFD11522E527DFFA853FD1D52A8FFFFFF7D %28FD285228525252285252522852525228525252285252522852277DFFFF %7D522752525228525252285252522852525228525252275252FFA8522752 %285252522852525228525252285252522852525228525252277DFFA852A8 %FF5227525252285252522852525228525252285252522852525228525252 %285252522852525228FD1852277DFFFFFD1B52FFA8FD1A527DFFA8275252 %FF7DFD265227522E5227522E5227522E5227522E5227522E522752277DFF %FF525227522E5227522E5227522E5227522E5227522E5227522E52275252 %FFA852275227522E5227522E5227522E5227522E5227522E522752A8A827 %522E527DA9275227522E5227522E5227522E5227522E5227522E52275227 %5227522E5227522E5227522EFD17527DFFA8FD1E527DFFA8FD17527DFFFD %0452287DFFFD155228FD075228FD08522852525228525252285252522852 %5252285252522852527D2752525228525252285252522852525228525252 %2852525228525252285252527DFF7D522852525228525252285252522852 %525228FD0452FF7D5228FD0452FF52522852525228525252285252522752 %2752527DA1A8A8FFCACFA8CAA17D5252275228FD3C52A8FFFD145228A8FF %53FD0652FFA82EFD0C527D7DCAFD04FFAFAF85AF85AFAFFFFFFFA87DFD05 %522E5227522E5227522E5227522E5227522E5227522E5227522E5227522E %5227522E5227522E5227522E5227522E5227522E5227522E5227522752A8 %FF275227522E5227522E5227522E5227522E522752FFA827522E5227522E %FF7D522E5227522E522752275252A8FFFFAFAF603CFD041413FD04143C60 %AFFFFF535227FD3A52277DFFA827FD11527DFFFD0852A8FFFD0952A8CFFF %FFAF3C3D1414141A141A141A141A141A14141461AFFFA8FD045228525252 %285252522852525228525252285252522852525228525252285252522852 %5252285252522852525228525252285252522852525227A8FF5227525252 %2852525228525252285252522EFFA85227525252285228A87D5252522852 %27527DFFFFAF603CFD07141A1414141A1414141AFD041460FFA8FD3D52FF %A8FD10527DFF7DFD0F527DFFFFA9611414141A141A141A141A141A141A14 %1A141A141A141A14143CFFA827522E5227522E5227522E5227522E522752 %2E5227522E5227522E5227522E5227522E5227522E5227522E5227522E52 %27522E5227522E5227522E527DFF525227522E5227522E5227522E522752 %A8FF27522E5227522E5227522852275252A8FFFF3C1413FD191436FFFD3C %5259FFA828FD0E52FF7DFD0D527DFFFF8B1414141A141A141A141A141A14 %1A141A141A141A141A141A141A141A141460285252522852525228525252 %285252522852525228525252275227522752275227525252285252522852 %52522852525228525252285252522852525227A8FF7D2752525228525252 %2852525227A8FF52275252522852525228522752A8FFA93CFD05141A1414 %141A1414141A1414141A1414141A1414141A1414141A1414FD1552285252 %7D527D597D527DFD065227FD1852FFA8FD0D52FFFFFD0A52277DFFFF601A %141A141A141A141A141A141A141A141A141A141A141A141A141A141A141A %141A142E5227522E5227522E5227522E5227522752527D7DA8A8FD09FFA8 %FFA8A87D532852275227522E5227522E5227522E5227522E5227522E527D %FF525227522E5227522E52275252FF7D522E5227522E522752277DFFFF36 %FD2314FD0E527D7DFD07FFA8A87DA87DA87DFD04A8FD05FFA87DFD15527D %FFA827FD0A52A8FF7DFD0952A8FFAF1414141A141A141A141A141A141A14 %1A141A141A141A141A141A141A141A141A141A141A145252285252522852 %525227527DA8FFFFFFA87D7D52522752275227522752275227522752527D %A8FFFFFFA87E52522752525228525252285252522852525227A8FF522752 %5252285252522752FFA8275252522852525227A8FF85FD05141A1414141A %1414141A1414141A1414141A1414141A1414141A1414141A1414141AFD07 %52275253A8FFFFFFA8FD045227FD0F522EFD04527D7DFFFFFFA87DFD1052 %7DFF7DFD0A52FF7DFD0852A8FF8B1414141A141A141A141A141A141A141A %141A141A141A141A141A141A141A141A141A141A141A1427522E52275227 %7DA8FFFFA85252275227522E5227522E5227522E5227522E5227522E5227 %522E52275227527DFFFFFF7D52275227522E5227522E5227522752A8A827 %5227522E52275227A8FF5227522752525227A8FF6113FD2714FD0652A8FF %FF7D7D28FD22527DA8FFFF7DFD0C5227A8FF7DFD0852A8FFFD06522EA8FF %61141A141A141A141A141A141A141A141A141A141A141A141A141A141A14 %1A141A141A141A141A141A14285227527DFFFF7D52522752285252522852 %525228525252285252522852525228525252285252522852525228522752 %52FFFFA8525228522852525228FD0452FF7D5228525252285252FF7D5252 %52285227A8FF611414141A1414141A1414141A1414141A1414141A141414 %1A1414141A1414141A1414141A1414141A141452277DFFFFA87D28FD2952 %287DFFFF7EFD0B52A8FFFD065227A8FF7D2752525227A8FF8B141A141A14 %1A141A141A141A141A141A141A141A141A141A141A141A141A141A141A14 %1A141A141A141A1428A8FFFF525227522E5227522E5227522E5227522E52 %27522E5227522E5227522E5227522E5227522E5227522E5227522E522752 %7DFFA87D275227522E522752277EFF52275227522852A8FF52522752277D %FF8BFD121413FD0F1413FD0914FFFFA8FD3352FFFFA8FD0952FF7DFD0652 %FFA8FD04527DFFAF141A141A141A141A141A141A141A141A141A14613C3C %141A141A141A141A141A141A143D3C3C141A141A141A14FF7D2752525228 %525252285252522852525228525252285252522852525228525252285252 %522852525228525252285252522852525227A8FFA8FD045228525252A8A8 %27522852277DFF7D27522752A8FFFD051461A9AF848B1414141A141436AF %AFFFFFFFAFAF36FD04141A14141461A9FFAFFFAFAF601A1414141A7D2EFD %3552277DFFFFFD0752A8FFFD05527DFFFD04527DFF3C14141A141484FFFF %FFAF1A141A141A85FD09FF841A141A141A14AFFD08FF841A141A1427522E %5227522E5227522E5227522E5227522E5227522E5227522E5227522E5227 %522E5227522E5227522E5227522E5227522E5227522E52277DA8FF52522E %5227527DFF52522E5227FFA852275252FF60FD061485FFFFFFAFFD041460 %FD0BFF36FD0414AFFD0AFF60141414FD3A5253FFFF7DFD04527DFFA85252 %527DFFA8285252FFAF1A141A141A141A84FFFFFFAF3D141A14FD05FF603D %60FD04FFAF141A1461FD04FFA96136AFFD04FF141A142852525228525252 %285252522852525228525252285252522852525228525252285252522852 %52522852525228525252285252522852525228522752A8FF5252285252FF %A8FD0452FF7D5227A8FF3C141AFD051485FFFFFFAF14141460FD04FF3614 %141460FFFFFFA91A141484FFFFFFA91A141414FD04FF611414FD3D52A8FF %FD0452A8FF525228A8FF7D277DFF8B141A141A141A141A85FFFFFFAF1A14 %1A60FD04FF3C141A1461FD04FF141A14FD04FF8B141A141AAFFFFFFF601A %142E5227522E5227522E5227522E5227522E5227522E5227522E5227522E %5227522E5227522E5227522E5227522E5227522E5227522E5227522E5227 %522752A8FF5252277DFF7D2752A8FF2752A8FFFD08141385FFFFFFAF1414 %1361FD04FF36FD04148584856014133CFD04FF60FD0414FD04FF851314FD %3D52287DFFFF525252FF7D5252FFA8527DFF3C1A141A141A141A141A85FF %FFFFAF1A141A60FD04FFAF141A141A141A141A141A3CFD04FF61141A141A %3C616061361A145252285252522852525228525252285252522852525228 %525252285252522852525228525252285252522852525228525252275252 %522752525228525252277DFF7E2752FFA82753FF7E27FFA914141A141414 %1A1414148BFFFFFFAF1414143CAFFD04FFAFFD091461FD04FF3614141AFD %07141AFD2B522852285227FD075227FD075227A8FF7D27FFA8527DFF7D7D %FF3D141A141A141A141A141484FFFFFFA91A141A1485FD06FF603C141A14 %1A14143CFD04FF61141A141A141A141A141A1427522E5227522E5227522E %5227522E5227522E5227522E5227522E5227522E5227522E522752275227 %FD04527D7DA8A8FFA8FFA8FFA8A87D7D52522752275227FFA8527DFF277D %FF52A8AF13FD0A1485FFFFFFAFFD0414138BFD06FFA860FD05143CFD04FF %36FD0B14FD2852A8A8FD07FFA8FFA8FFA8FD06FFA87D5227527DFF7D7DFF %7DA8FF7DFF3C1A141A141A141A141A141A84FFFFFFAF3D141A141A148BFD %07FF8B141A141A3CFD04FF61141A141A141A141A141A1428525252285252 %522852525228525252285252522852525228525252285252522752275252 %A8A8FFFFFFA8A87D7DFD065227FD04527D7DA8FFFFA87D2752A8FF52FF7D %A8A8CAA914141A1414141A1414141A1485FFFFFFAFFD071460A8FD06FF8B %1414143CFD04FF36FD04141A1414141A1414FD2252A8FD04FF7D7D525228 %5227FD0B52275252527DFFFFFF5253FFA8A8A8FFA8FF61141A141A141A14 %1A141A141A85FFFFFFAF1A141A141A141A141A60FD06FF85141A3CFD04FF %61141A141A141A141A141A142E5227522E5227522E5227522E5227522E52 %27522E5227522E5227522752277DA8FFFFA859522752275227522E522752 %2E5227522E5227522E5227522752277DA8FF7DA8FFFFA8FFFFAFFD0C1413 %85FFFFFFAFFD061413FD0414AFFD04FFA9141360FD04FF36FD051413FD05 %14FD1D527DFFFFFF7D7DFD1E52A8FFA8FD05FF601A141A141A141A141A14 %1A141A85FFFFFFAF1A141A143D363D141A141A14FD05FF3C1A3CFD04FF61 %141A141A60AF85AF601A1452522852525228525252285252522852525228 %52525228525252277DFFFFA87D2E52275252522852525228525252285252 %52285252522852525228525252285228527DFD06FF3C141A1414141A1414 %141A1414148BFFFFFFAF141414AFFFFFAF8BFD04143CFD04FF3C143CFD04 %FF60FD04148BFFFFFFAF1414FD1752285259FFFFA9525227FD2352A8FD04 %FFAF141A141A141A141A141A141A141484FFFFFFA91A141484FFFFFFA91A %141A1461FD04FF3C1414FD04FF8B141A141AA9FFFFFF85141427522E5227 %522E5227522E5227522E5227522E52275227527DFFA87D27522E5227522E %5227522E5227522E5227522E5227522E5227522E5227522E5227522E5227 %522752A8FFFFFF60FD0E1485FFFFFFAF14141485FD04FFFD041436FD04FF %3C141484FFFFFFA8FD0414FD04FF611414FD16527DFFFF7D5228FD275227 %A8FFFFFF3D141A141A141A141A141A141A141A84FFFFFFAF3D141460FD04 %FFAF363C3CFD05FF141A1461FD04FF853C148BFD04FF3C1A142752275227 %52275227522752275227522752275227A8FFA82852275227522752275227 %522752275227522752275227522752275227522752275227522752275227 %52275252FFFFAFFD0F1485FFFFFFAFFD0414A8FD05FFAFFD05FF36FD0414 %AFFD0AFF841414147D527D527D527D527D527D527D527D527D527D52A8FF %FF527D527D527D527D527D527D527D527D527D527D527D527D527D527D52 %7D527D527D527D527D527D527D527D527DA8FF853C363D3C3C363D3C3C36 %3D3C3C363D85FFFFFFAF3D363D3685FD0AFFAF3C363D3C3C60FD0AFF6136 %3D3CFD16FFA8FD49FFAFFD11FFAFFD09FFAFFFFFFF %%EndData endstream +endobj +943 0 obj +<< +/Length 65536 +>> +stream +%AI12_CompressedDataxœì½ëŽ]Iv&öçÒ?tM*î—¶1@æÉLY%5º[ @±¨ÇE²Áª’Ü~zÇZëûVìs2Y]7Æ@ç“™+÷‰;"ÖýöÿÓ¯ûâöËÿüöE~nNñçOo_óñÓ¯nzó×_}õí×ß|Ð/~óË›¸îZ7Ýþõø7þÃÛO_¿ûøáWú§—iýñQ>ý‹»Oï^¸ùÍÛw_þòæ¿\àß½ûæ«·ëýÛó_}üýÇ/>~øê_üæ¯î^¾~÷K>xtÿú›u[ù˘þ2†›•ËÍí߬î>~ûáËw~÷ñÿþÕM*ý&7ù×nJÌëÏÿû»ß¼ýúúž—a´)7¾¬­–õC]:×GÒË:äc÷ß|ûþí‡o~ýéã›·_}þøÕÇO_ÿêæüÇ5û¿yýûõ—×7ÿçÛ¯¾úøï7w_½~óÖË×/ß}õv½çû×ßÜLY‘Û¿Žé‹»oß}õåß~ûþŸß®(¹8¡#þý×k¨5ªü,àþÅ_¿_ß¾ýæ›5Ûõ~õZWL¯ˆÿÃM°~÷úÓïß~³ŽÂǯ¾ýFæøÓÚšW¯ÿøV¶7Úþîo?üîã?èü^ä×lòZÀ™nbj㦗|“š='ö›^ñȨŌd C÷µÐ¿^{ûwŸÞýþ݇_abý‹¿úôî˽ß=Ý û¦o°vwÿ›üg“\ïûÍ7o?`ÒëœÿæpnÂË¿ùízâÇ/ÏßË‚-¨²¶÷Ã:Kë°ØßügýËúø·°Ùëï_¬½ùõ§wdÌÓßê_Æ¿þêÛõ§¿úôñÛ?üõ‡ùxú…„_¿þæ_&¼ýðå× ± f¿ÞØ'ôÕ»{k°…ÛøåwŽ÷»O¯ß¬ÇÞüÝ?ÿ··o¾Y`ÿôÛoß}óöOôÛ7²LŸnî>}ûõ¿Þüîãǯ|~—òi¬P¹ÿŒgüZ?ðáï>ØJ?}n¸~ÒÂŒÿáž²îþüÖÿGýüú«¯ÞýþÓë?üë»7Ï=à™¿û“ìo?àa Ç?½ÝŸ×_ùÿ÷8–|ÿÏ¿z÷õû}_¿þôÍ»7_½ýí¿þæíû?=ÚýÛYœí°l +}øðoo¿úø‡Ã$òú×7ÿåõ§?|×вMÿòî× CŸ÷2~|ÿaÚ7¿ý××x«Óýæ_õÎß~cüÕë¯?Ý(܇ò³Îï¢g—$É`>hýbÆ#é{ñâ;hb¿¹ûpøó_}zýå»Em—@ó÷>¼~ÿöË›ßôËÓSТñõæîËÓ?þ·Sˆëú¿N?ç`ÿ øƒ_øôŸ×JÝ=ÜÝßïîînïæ]¿kwõ®Üå»xnnïoïnooçºúm»-·ù6݆ù8æyÞMù³Í%–Ì4à ãq<œÆyÜc´±ä¿‘Öúc¿_×¹ßõ¹®Ñ{¯ë*=õØc{lëºowm=§Ö×ÕZYW>µÜR -ÔÇú°®óºÖ$ëm]£ËµŠÜ¹®¼®¸®PCy\×úÎëº/ë•Ê­^£ŒÓv=¸èg +¿®È+?îËVê׃^ûçõÿ9œ£~—+žÓº"þOç¼.þl¿Ë=ñä€xñgûý;þœ×ñ¹t=ìç“þÚüª×5”¿w\ã ¤ŸÐþÄËÿtxÌŵV*¬µº¯ëj¸tçﮉë×^g\üzðëQ®ÓýãCÀq%¿²_Wõ«®î×8= ¿æáº=\w×ù꺿¼NëÛ羟¿ôT­cÞןëØß­õ»_ó|ìa!EêyÒº0A¾ÆBšÛ…<çµ”ýq„±–²Ð >äkŽÛÓ¾³®ôÃx\Hj¦™ŠÖuµ…|‚œsáôÂ÷…Æ÷úÞ·a]q¡w^W¹]صq=ñvœnÇÂùº»=¯K6M–çñ.¬+®+­+¯KÐLPs½È¢$ýnÍäNŸ²hËí}ïÎ'Ûñ 4"ê?û¡+Upâ>ïëáp=/¡‡+^\I®“ý·®|u•«ëú«=¹”˜ì?¿Æ³×üìu{}ž€îþÔµVªÜüÅwŸ„ .Š¬ÿùÕ}QQûn×¢“úWÆw»Òºì{2È ?$ÿ³\—|ý@ôß…«®¹éñYï++q»Níý"#1Æ¥ÁǶØÏŒ·ëÀÝÇÇõ>)åu$Zê mn×ɾ_æ1ÇœrYG£ç±ä.ß/ž°Ö*–¼Î‡°“¹¿œÌG=kIM[»-[v^tèq­w\œ¬¬Ó"ø.ؾp˜^ËO É ÅÁ½‹"öBjÅhÁfÁdÃbÁ`ÅÞ…·IqVðu(š.Ô<)NVÅÆ©x´ÓÕ¸ e‚ˆ‚ÓB >’b +½À± j›7 >]ü!‘X Ù^ô[ä½Òwà¾Ò}ãB«„?§¨z)bŸÖ·µÌë{º_[s¿6íü¸®‡5ÊYÿõ^w~ •ZK~E–·¸cV²BC†õ¸”dž«â"-¡pE½‚]NÏùåì`/.X.rrŸ~±äd[\n_ÑVšÜË‹‹\ˆ_\.¶]ó°äã„uçÚcýít PÕ È3mïuÄ[¡ëí²G²?ÁwæNWßV^ä’,òËI×û(iŽƒ¬™TÚ|Tyó ‰s¨ÄY!sFH÷*wÞÎyZ<¬CôÌ +¢ ŸëµDú¼U鳫üYT*>@½…ÚTÍ"ƒžU|Tô¬BèT!´ãyÂéÿôÕŸ¿NW€ñ=®ù]×ɼý^×ÝŸºNJÍž\G梤ÿQH¦aÃ:“ OùýApv}?ëÿü~qa}¿Õÿù]þ¿=­ÿ¦^ßåêz5¥ÒòÝø7t|—ÿ“þŸÖe_‹êŸô?ü‚ïÁ0ÖpGÙÀ½^g|?‹HsñýNä"û~Â/óp-þjRÜP9NdÙù´(}­E鈠•Ð aàSu–¶¸CÎ"ˆj-Šð÷¦­œt/eã»k)‹é‹ ‹~Ò(z…r£…‹/­gªø"_²£ÿºê´˜Ù­H‚‹±õõHÑu„ÕÅõ;‰’ÝàÈâÛrËc-mõNºD²4\ ‘1 a×Q¢Ý>¬OÉ& Ù{e±e1Xa¯÷‹µ¦5í¾^㼤÷°^±(FÜ)/>ºä¨“2ÑGe Â>§2ÏÇ5»¼0¸/l^‰¢¢:IQ=c¨úpsQv¤Â3XÔf]Æ$„±=ÚQTf'ÏHÊþ2ÝzШúÉÕ©£*uT¤¶ +¥üáBsÚ:“ëJ'W” ¹^tÔ„Žz«5`ƒFŒ=.VyZßT +×˸ê"Àz:TÍ ¢AUÄ—¡¶Ó5¨m¨®ñDÛ8觃²AE㬢Žé®WP/®S»µ ÂÖœ|g±ã{?¸ÍuZn€->ž‹® ~òÕ¦Fj:¨¬Æ%£üé|òtÉ(:Ÿ<]2Êçù¤Ò=±ÓDØiîÕJsIï²RºpRÓÌýb(b”™JãZ©Gæ²6árÄQ’%úîº\Y]š“K¶,Ûj±wn°*#阩jè»g}o¨­?­Ö×Uò~Öíþ’b~’÷“·ëJ½“Ú“î•^ÏEîÚ"æi1¬Ç…Šg!̧¥Ì·E—…"›aju3Ñb»^¢ÅÜEÉ%ØgŒÎø¢p“.*ÌÕñãi¡gRšŸ•úw1(G¼Ð¾¨BPÖ!êNU†Ò•6‹zVrô¨³‘ç”Óz/JB&{Ü)ÙvUŠ¶0%êÈ:¬ དྷ†Åh©F'ÕŽL?\ƒàª¥\ £y7^({O!û +¢Á»¾ùgQ8Ò— ùÚ`P-\¹ÌP/»šLżw%3AÍü¬aét°,=oW:Z•& JÛœdÆ$3%©!é;Ò£Û +ìGf:£U"A¾M-GÅǪ̂B£iÉâl–Ò÷¡”žWóëhÙBlö+®h×Ih龄Ãà:š]sº=ûuw¸ö×<)ë²køÕWóktŽbyöKeµ“ýw«8lZÙÖ2 ?§`•Ë§Šå…Ry©RÊ£2y¾ÒÛ·"9\w‡y:*ð_²Qˆ5ÁõøGˆ>6¾}5xÕáO`jxÞ âŸNâÎO¥‡*>üŽ  qçK¤FX }HHÇ¢=£å›tSÃÍB)à·§¿øâÇp÷õ)¼\îLIn+5Ì¡?Ì,Ì`±€)Ÿ”iŽuëút®/ëÂÌ›Ú_."[|?ÃP6#Þ’ü¤³"?­7H]~X:Özó1ì¥j}Ùâ8L觎¤ó‰ˆ˜)²ŒÙ¢G^.z²Æ”ˆ›ÅbzVˆ¼¾}¼”—³äÃL~Â:YL_^þ +YbÔ•N±¶¹·Ý6y¾~º§ñÓ†Y3¹»w_(}šßÏ͹Ü3žNÞÄõ:;í+ªaÖd…9aªv†ÅS¤„½¹ªN=TF¸SýÁÔùOÌ :`=«)Ô$„´T̪ÒÁbK ¹…|ðÙ ©×`Û˜'• xXq6fRãa& +‡‘‹T2 y¹ù8xZ_ËjN©ànÆßné59ÃGµX2»à /ÃÀBJ?øQÌ“"¾”³òAõ¨œ„ÊÇJÄŸ"y„ÿ…JÁ5ª²?8Â?‹ò'˜Ý.ð^•ƒò âŸá1ÔOja*°HÀÉiÀý’,„ (ð˜ ó‚ì&[˜m iOÐ`Bª@Ù–Ò-iæg•C`pj>4Gj9¨Ä8P +ÒŠM-(†Ñ RŒ†ëài5L½ƒsÜ(ÇÃõ ÿ59¡·¯]Ð¥%§i_·¢rçD„ÅܵÚ²éK„ÄÈk©½—äæHtêA=’Ÿ~^„H¯ÓMºüú,¦HÖ“ëô¹?\Ѹï}~øGþãü¡(nþxàèù€Þàé'øÑÁ½‰àõÎ~DpCnêÿÆßvŸ½Ä¦lÞ¼:‚Ï‚?øüÖV©¯ÂpRmáÈô“+¯‚àÅí„~Š«$pRQ€!ÝÑü(¢?ѯƒ/½!z?Û‡bè­2º£˜ ¨~ìñ +á³;iíOO0þîB’ø,Ú‘ÿôy쿸ž¢ÿñ:Óg¨Âó×5­ø,Íxzýè¯Ó÷¸ç»‰ÑÕuúa·ÿ¨/Qüg4ý‡¯®t¸2²­—UcNhÃ4Œ¹…ó(²MK iFÕ¨©ÜžàK¤Ð’°Á ¡h´g>êL\1j6%ï4€ãAýMé´è˜‰)awj¾°¢¤.¨¢¡CqE¤’%XIµ”²ÈÔЀŽ[%N§ö 4)Ã9ÕS„øІdµ,˜½3[¾ÒEîúš4øµ-*}™.R©s«†E ÒI ƒíjˆ;[ sií`u°¼òߦq´ÂšÖ‹|²t¹ ̨èdë•5v»^îá¨5÷‹e¾ØëX‚m³‹éœÔ({ðÀ 5†6ÙÄ(… gKS7”ÝÝ!XL«‹Òxš˜²“?.S?>Ÿöñá8§gãq¾#"ç³9É9ýð˜œË¬š‹œ%…œ•cbÏs‚ÍOH9]ç|gôæhp«E&?"ê‹‚Ô¥:¶¶8u¨¶HuªÚI§f“Óé«£he= W6Ý-^Ù¤Ï'7$¬+Ë¢s->÷ZÄšˆÓ}"bDÂë"oÐräî5G.)ù3Ï’xŒÕø w’ÀH’9©Ÿ­ìk)«(+uíî+ñ¸²L{Ö%¤Ë°^þÎcqåMí°®M¨k-n×v=ªõSÂ÷ïî4t_÷‡š3×Ѭë˜ÞÞß/|Jë0u¸"ç…æ]&z=>gŸÞ¶Mé¤|Ö´ ~£C%ˆô¯EýÄâ1DqD‡¼pr DpÞ>ãǾŽy9z¯Ý›¥Cþ©mØ>ÄkCjŽ*/?¨¤|§2ò¸¯ád1ö&[ bíˆ'+ëÀÊEþ*b˜!„*¼¬Ÿ‰Lû±C!Tn}Jo襪è…q%â.J¸ŸÄœUh¨ýdnùåÌ©gôS‡Ò%ó³ñd$Ùyð%‡Ië÷0ž‘)Ú0?IÂLϪ¥«@5¦׋ÿËáÿç‘/sŽãÖN.öÿLå>þ;9ÔŽ±ë;uúÚ…vAhM/âî,ÞFbm¢º°*œð[°dlM÷ ñM¢JšFµä¼“ @@ -1466,7 +1790,7 @@ s Dx^QÜ×}Ì'Bñ[ :à)B½R, S´èšðfB×É4ÂèìÙasÌÁ(ͤWYĤ1,]©±¤ÉãÊ3’ÞÔo`(g¾w,Qì(Áê|ê”­[àŽ%hXTMw®GKuQ*´b‹½Mˆ˜ÓZê[MYŒåA_qjRdÒGq¥( ŽüÕw”ÄH‰Öç-튵¨ù‹ôk¥ kÄu6™i^T6_÷òÂïµÆë¶Rί¥_¡zÐ$SÑW¡ ×$JÕŽ;ÚcÂíPQþˆýš²Ü‘~Ê Ìû ›Žhq•hMâT ‚oÁá¡ä‘ ³µ%±ÓêÒ2¢'­[ÝDJÖ@n#Œ ¡‰G€’HÞt‚ $Ö¬X®:[ôM¥àkiº U_wÂÉ„ßs¬‰Åw)Õ!ºRbã’è #öp £0?Û9B“% «¡þ­! MÓ³a¾“ܶrh%[íZyGÚ­ ˜ØyY‰Ÿ‹© ¨zŽ…N¬V¥%™­‚¨™@“£=HU˜ü¢³l0¼Tq_PIÐ/u,dÆö¶fý"íŒØ¾MMæu [endstream endobj -728 0 obj +944 0 obj << /Length 65536 >> @@ -1708,7 +2032,7 @@ qlÞ¯ ¶“¬ûVG=# [ül&wJ΂fkíY”&{öñß1øÀ ÛÄ%'DSì]-†ø,^¥·ä †¸ùì²WU`×z0,PZ“Ny}7/ì%ñ «×­Ð  F?؆Fß®U E2,„Ò -[‰Ðð~Eô׈bˆ¨<Þë‹uAhÜš:®—Ú[ɬëxÏ*}ñŠ–Ȥ”=cf身O©½S«!Ikà•O7C/¶ž[\ð9³Y%“׆Œ95ToÂK‰ýÐ2ïmñ\¤•_afbµîpe"YRC+ç°>…JÊò`u81‡¸[å8¼ÝŠ2#aG9u&«`æÚ3Æ KÞH¨ÃNk“‹:6÷ð¦/F ²ÈO}|}3RÖ$Yé…u:²—wENú쇦3,I=¡ÔwM{ æjˆ¼=ßî úÑýSTÛT¿}0GjÏŒ—©;èçæŸYÕ#•ÈGq •›«NÙÔo¾äØvöM¶¼¼ú¡ÜAWDœçoHÈ Í'L“…ÓÔöÌ\Kôæ4ûÉœoYäÍŸ›¦×ºð<ƒ\qùßôFs¦ç¹¨'¬‡~ž kS_LÓ`%AwMÈFH«ãÏ‹Òˆ‚¤*»Ra6éñ‰RL/㤨RœD­R«ï¥&ÐÍÄýÇF¾«h¾vxïªý«¢Š~¥A$kïKDØ×+2 ÂHþòúvŸûA]„‡~çË臖AÝõ±VpÞû¡Þfêýàíд³endstream endobj -729 0 obj +945 0 obj << /Length 65536 >> @@ -1931,8545 +2255,10840 @@ uAL ]×g1ͼ‘ôAÚF¥5³ò(ª®Í ]0_†ì›ðÆ„e @kB“0€«ŠÕ¬adóŒ‘qìsê‹ ²¯dy1‹y†KôëP¦àpµMõ˨º¨õH¥ôèÅ2#pÃC¤€Zraeü$JÔSÂûkbüDÁ@fÞèÛ6¦1Oîõ)VÝå¶K m6o°Êwµ˜Íô‰iƒMlã!Qáiªk´ª²endstream endobj -730 0 obj -<< -/Length 53114 +946 0 obj +<< +/Length 53114 +>> +stream +xøëÓ˜§¸„®Éžu Œ¶-)ª%ÄÛ_“šÚÍ¥Ú4³XØ+-ëmT†Ÿ`°]üÍå¢ìJE½X¾ó˜&ÉI›fßúà“‘´OÅÎFæ(­í!LÎÖvœ §*‹bu‚ÛØŽpdЖ˜Ã:2OÍö fÜæËYÌS¤šõ¢{;‹ýîY(Wp@0R«wlâ­j£jJõ¶8ý)åY½½ôhC`w-qŠãÔXÞ@tôõ}âwÞ˜Æ9â<î°6èI[„ú5%ñΗ+sW¼ZÇIïµÝ„o²Øº[§±œ£Òs5­7s,ÚóÓÝðª4ûx¢Þ"%áú¼¸5²NÞ¢!å'(2©Ž.vŸMà²æÚù&lûªMåئ{mË9ÆÜ5ÈäácŽÁ'½s×0E—šê „ȑהæZ¹F—ã–b ÎÐÝNhyç!¾2:óM(É*';“=çå4–&Ø.½@q†I±:ûU…¢Â°#+!j¢8Ô óœ óÜÓ4IÖ¹”´²òø®a©Í¦€:ãòºäpÇ{ÖF&B¬†ÿ^Nd«yˆäù0{+†ÀÖB¸&æ‹&ÏC±Y +¸/ßCEV”‡0 ³ +/:¥ð£Ùv«¢Àç2^’=š‚Ý¢÷6„× ø~c"[]`%†/qÆJ´G$% ƒæIÙÎw +jž¤Ždˆœ0ü*¥Ï&ÀFèÿ!R¹9€A&\3u ÌÇæ<–žwl]á@9M~·ž 4R"2vö»Â’­cc,+Ú‰S#4…ržÐN(ï#Â}!Pä8£ZãxFQ¨–ìÎõúH ¬ObžÊIÏÕ†ÒG{ ÜêWí÷ Rr.älk&ïa|¬W™IypR2@ Ž÷E¼nÇÇ.‘´iàn™#Ò ˆXŸ¥`Ü*†2ŒÛ4ÜþÐ9ÄÔùðT¡cç™gpɵ„Û® Ž §Â`ôP]Ý¡º |·ß-^u2Âî*Îk +ÁíâC\.>ºA ÿóR'$P"vBÐÜYc¨šz*R*+mNæûÒºt}˺‚7ç±™¦¶$ °b#‰âJ2d™¦ƒVœ–‘wÈP¯k¬'õw°B4BÌIöƒ#ú)Æöµ-À+!¨mX!Á ˆkY‚ì›kÀ-rj/tàþ†FÆz½&hÞF€Þ`^űD-_æ9 Û1r0‚,&7FX›Æ6ÂW`BÍ .ÄxÃŽçnD\²;=F0Ä¡Ô'°aî¡)ò*ØïóºÛ°É^–©R†´2®Íbs2Hü¡1Ñ­Æ,{3cû¸OA†% ›áëU‡ðÒbÅ…³Ç°&¸j³ +mu‚QÌî"Öb®Dkó˜×íÀ–©g;&éõºiq3ŠYK„|F›¨»síïp¸Å®›žu 6 Ùjóµ£Yä¥*ú Ÿ{sÓ$'ðß=™‘‚‹˜1…µX;à4ç£Ò¸"Rq”Ž¸ _jÔW’M¼æL/iPк3™q óô0õÿµzÏ»êʽc'/?vÍÕ †^pôú›HÈKj¥Z†Wo‡4DúZoPôJVÔÐýj%f‘ÎIRópíÑ fÐ{#ÆÕV²¨³!œ¥Q$Ì=)Úà°`æ[õ kÎ1'Qn·Fæ¹Î"Ðê'Ná%6|¤™™–8Æ¥‚îµ%©Y¯"¤#÷à 7sÃH]…3Ø¢i\ÇYêJPås9ÂIÏSÀÏ«§&ä7,†Ú$ÖABÆÊuM@Ïæ®ÊÎö ðkeô!iId¬¶Ûè–w`ÔA2@¡$2%ÁIü9TDgYÿ}Õ' À Ü—¤(VrUº{õÛ"AÀ­ðó¢ä;W^Ro®ëÝÊÆ\¼ÃÞÄ );Ê ãºÜ‚–ÒÑËÍAÅg‘B“–*R0¦¢jƒ_n¶iU‚¾Uñc¤¨%PR¾Êo†8ƪü}Sc’•{XõDWÆHÑÆnJ뚎§RbGX>-:…´‚’BŽ V¢±`E”åû®ŠŠ–ìON• +¡Oä+ãZ–Þ«oâ „²ybÏ‹[*!‹Ñ%¯Å9«…(Œ›–7°úækôS•i‘’ràù)-[t¦CÈßÃUmÒ«‡z-nVï!š"eUƒU|”Èî!%cJ<d€]Twù­—$Ð!Áî$A8ÕÓ&ê;b.û4èïSh"d!E 0X°‘ÅI‡#lBÝ\‘Q#ÓðgÊ^+QÓ`S#ïor}k›«8(sG%!_XeŸU'E®¯Ä®MªªL£&Të±gHB¥ÌÙ®ryCQ S´h¼vôø9GO^uÅ£ØH=rÆYgêðãW^µ']jž®lØË®|ȱKÎ8«_²ºóO^wüØ%㲓KÆç…—­=ÄðeW?vwü ÛØ?|ôê•¥¾jZ]j5—3Åè¿×±k¯Ø=¶zB׼܋I÷‚pPöÙÏæ£.¼®õçž|Ö 7<û‘¼óWþZi÷‰/ü…—<몳o÷¿ÔíwN>ç^qÃSŽÕ¯ø¥N9íAá+^öüGßK£?ìé/yù‹Ÿò°#_ùGx»s®yîK_úÜkÏýî¯ø¥N9õÂÇ<ÿç_øÄÝå+©ÕëzÜϼè¹×Þûf¸Ô)§?ø±Ï{Á3N|ÿWô"j8ºø'¯Þ“¯øÊ.ø¯þjþ¯;?ðš§>ë§/K_Ñk}í×òÝö̇?î)9¿¢×úµeÒƒù¸G]ò%®õÿ•zà_Ïÿ}êyäÕÎ_Ék}ãínÿ­ü?nsÏí¸äŒ[ïû˯þ²Mâ[ßñ{ÕH;õìK/¿ô¾ß³ï/¿æ˵ˆ¿õNþn:•[¶ó/yð9‡öýéWý—y±;¤»ûÛêÿ¾ý=pñù÷øïûþöë¾ñ˺حÃg$ÛØï|æ“ö5پ替óûÖþÈY÷ +¶nÕÎûÑ‹ÎÜ÷ý†oùºÿú¥Â½Ï9猻}›5ÜéÌ‹/½èÈöûý×~Û·ÿWgv›xæyçÿPŸ†¾õ÷_pÙC/>|p¿¿ø–[ßê›ÿk—J÷=ÿ‚óŽúö©í.ç{Ä•—Þw¿óòëou‡;Üú[þ+—:ëž¿X +·9ük{ÝÃιÓ>ôÍw¸ëÝîôŸvšV—zàE¼o\Û'ÜÅzÚ³ž|õ÷[ ·=ýîßÚ­þ+—:+Ýf­ý;ϽæÙ/ùùçÿÔŧoÿ»o;ýðÙ÷Îÿ)óçVñ¾Øv©SNùÁG<ïW^ÿÚ—=íŠ{niw¾Ïݯÿ'.v wŸ}.uJ¸üù¯{×»ßñÚ\{Á]·ýéϺäòËзüå>ÿ|ÏáûÓ¥n»¥ë».}Þ›ÞûñoyÙOÿȶòÝg;yÍ÷¿Éëmï~¿‹.8;o¿·û]ÿýÙ?|ì#þÎ_|Ìý·x}·¹÷Ãó„G»×MœØ-ÓÎEžS¶ÍjõÏÙÏ|Ûÿí³ŸþØ_¼ý†Gô-ý?xüI×?õšÜD‡ðÔûþèƒøûíçg=ëó™oüì?¾ï5O~Àwlö¹êY?÷¼Ç]rÓŒ ÛÞó¢ÝKwöÝaϾþ]ùü7Þø‰¼åyG7_Ëw>ð§^ð 7<õagÜâ¦\ë´\±wé½öy‚§œòCÏùÿð…Õµ>õ׿õ‚ÝÍ“Óí>õ¥¯ü…gî¾)׺ý}/ä5GÛ¾ýç<ÿwÿé‹|­·?÷âƒÝýÄséU/æû0ýüè'=öK8tçýÜ{>¾ºÔÿþ7=å¾›Ý÷¾î†WýÚËž¶{S ÉÛï\ýŒç?ýÄÝ÷ýÁE/{ÿ¿ÑµþùþÏë6õ½zê+^óêŸÂÅ7å;ôà'¾øå?÷¨Ãûõßåäk>ð©Õ¥>÷÷ï~Ñî÷ntßã'~öU¯{Õ ¹³e…nü“þÜ_}ý+Ÿzî~ý‡Ÿò¶¿ý=¿|ã6¤Sôä—¿öu¿øÌË÷}³Åz÷“/yÓ;~ó¥W†}~ûÀ~ÿc«¥ñù¾ç®Øø.ÞïºþÚ^ý¢Ÿ:ÿà>þU_=ýË=ýÊw½÷÷ßøÜK·G1]ýê?ÿ÷Õ´>ùÁ7?õ¬Þïß{ö/¿á ¯¼þaû®BõDäŸ3ûê÷|àïyÍ7G¢vžõNz„_üøüâñ}þ®—>å¯ãkVÓÚ7<öõ³¥uø ¯ÿ£|ôC¿÷KWo[µw;ñÊ÷ÿËjZŸýðÛŸ¾q3§^øø—¾þÍ¿ñÊ/ñq}íÙÐ:òÄßøóò_?øÛ7Fûîçþæ7öÖ§¼ûœ×ÿîûß÷?^ýÔá¯ZwÉnñ]ß5Mì{ŽÞðî 3ãÓùŸ¿ôËWvÖÓßò!Ú3nüÜß½ù±ËyÝáO|Õ»ÿìüŽ—¼ÇhÝpÿnyÇ;ÍÝ}žòæ¿â?ù¡w¾àèü•Ýåø+ÞûO4­¿ð¿óœå¾[®|É;þìo?üÇo~Þôa~õ†t«Sï6ŸÁ«eý>zÿ7~ñ_þüן4/ìûâ.n¼ñ_ßÿŠ-§üÄ׿ÿ#ûÈû_÷¸#£qñáò?·¾[¸ó·Nÿ~Þsßñ·Ÿá'õïùÅÃæ¼Óå/ýý~^®õé¿~Ëãgcã{òsïúпþû?¬¾ðiƒÿº é–w«aþ ¾ÿ'_û§|jÜø©¾íú‹m/ÿÁǾá/>!—Zíïÿ¥Ÿ˜ö×ÕŠúÃ~æ³}Ï‹/šFúÆ éÀ]àžq2±¾÷Ø‹ßý‘ÏòkùØû~õ:‹@Ýï¹ïú»ÏêµnüÌßýÎÏ+ç{ßÿÛ¿ø±÷Üð€iZß>?.}÷8ûÌ<Ù÷~üëÿô_dbýö眧­w~ø/òw¬ÿ|òƒïºá„íE÷zò›?¸úðþå_rÁç›n÷߬_ë»Ï8ÿ‚6Lð;]ú‚wý ¿±/|ü}¿|â.öÿòßíR7~ñßþê]/»öl]t÷yúÛþf5çOüé+/ã~ÃwÜé»çm‚þùÎ3~äè%÷ocᇫå}ÿ‚¼±·À¨8çY¿õáÏŽkÝø…O|è÷~åI–µsæ3ßñwŸ£%ó¦yÉÜÞå»®ùG·¼û…—ß=gZ@;+Û–W÷>úž—^Îfûw?D¿ñ1³OþÝ{_wý._ì¾ÏzçGV×úÂ?½çe»áwÔ#g„5cû´<üäUGï;CÇ_ñž¤“þÆOüÅëËA8ñ²÷|ô 7.þùôßÿÑŸw™ÓkÑ|ê¯ÞúôsÆûsÏÿ¡ºôîxîî{ÌÉ£÷ëãÌ'­v{î³ûÎç°íQñòkÝø™þñ›žóÕqpÖõï¤g¸zÁôk×›×=xéƒïß®émŽ{ô“~úä…ÃƸóC~î·ùƒþâÇßû²‡Ò'æ®xÉ»ÿþsk׺ñ³ýã_æÝñ”³Ÿõ[lñÜø™¿ÿ½—íÁ–ÿoýÂ+N»ÿi‹‰¥?ú©Ï|•S<<]óª÷ÿ3­ðOü髯¥ö?öÜ·}èSë׺ñ3ÿðÞW=æ>+GémþŒ~&ï|áØ—O¿àÄ£®}èY‹£ó.<ù´ç^ÿøËï5ží=óíüןúÀo<öžÔpø1¿öþ­?ÄUÿ‡Þõ¢«Î;úLl•_¤Sö2ÝÙî|Þ‰Çþô£Žž÷ÛÛyü‰ÏûÙg]÷£Îšîú¿úÇÿJïÿƒo~"o§wÚ}Áo}ðß7®µÚ[^óÔKÎû©WÿÉ¿jÃ?ÿÙo^ÿà;é¸üÓŸ|Í4,½{Ìs^ø³O9~ÖH²žóœß¦eü™¿~Ë“Åæ¼ç£~ù÷?òé‹}â/ßôôsO¹ðç~_Äçþé^ûÓzÊ–ÝÇ]ÿì'îÝw^‹·ÿ¡ŸxÆ _ôœŸ¼x˜§_óÚ¿ü$]ë­O‘k}ÏEO{ýû?úÙõk}êCoyÆY§~âoâ¼¹ñ3ùŸ/ß“§xèâÇ<çgŸý“-¬ûtéãŸÿ¢<ùŠÉ¸àÅÿ÷Çy^z­SN»ôú7þÉÇÖ/öé¿ígžr×ã+ó»å'ÿŸ·^ÿcl ÜþÜkŸý¢<å¡ 'ã;Ϲú/¼áúkÎñÞÏxÇêû\½¯'ÝK[N»ìùoþÓ­-üÏ|ø­O»Ï)§œûì·Ëºúçóÿô‡¿úh^P§üà‰g½ø%ϹæÜE<^úøŸyÑó÷cã!zä?ô™ÿ_öÞ;Ê«*Mþýugîw?ׄ^=s;Ø]=ÝÚtO'u™ +P‡ ˆ²¨$CQÂEP1‘d©¨€€¥ bãRAÁ,.IJ € ˆ„¥ ¡¾ý¼aŸó …hßžoÍé™îbÿÎÙgŸß½ßç}žïÖ?}ÍšäÕM{‹_¶÷Óç®7»š“®xD{¦]LÓPØoâœ{g\]¼E:þ¼ú›fN¿±_nê¬}týw‡ö|¸ht–æô½cñ‡;Š¦ÅïÖ?1ÖTÑ¿]rÇ«›µ¶¾ußÑ­.½~ÖÜY7\Vl …µ×Þ>cêˆó²SßÇ>ùîàÎ5Ì8~ßÛôMþe{>X07#ûЉoÖ<2šÌÄßt;ýÞÙêŠ ²ßvj˜:ó¶«/±•èŽ{þ‹ï~³òîü²næª/®Û•­™;WÝÕƒ~é<ýMÛ;vøø8n°3êo½kÖ„º’#ˆ¨ïÄ;gM`­ˆÎw¼¹íà¡ïÎ:¿è¶ ÿŒe¾ÍÞµã¥l‹7êïù艫¸•O|Ó¬××–lç~×ëú9÷M·»W·aáG{ÕÌËÝx÷›_fµøõÛwÈ&´ïãŸ}o¿kÑX¶I““¦ßvÍ¥Nq…sÆÏ}tþd5NzÌ|3Á7ïÞYºKˆ‡?´vwþ»ä†þÙ»v®Y0’+(îãmSÇ\Pºs<熇—vü³tfþ~ã‹“yö=þ¼&_USzÖ~Òóëv|÷íŽÍë?X»nã™pl~é†SKm¹~õƒ'¯j‹}öšZ±ß}òÔ8þ”V]9yò••t ³¹z÷+ ü{¿ývo6íZûHC~ÿû—vOznCnm9ðõÚgï{ûS«·Ù‡v¯}` ›Si¿ënž<ª{ÉN󜉋7”¯ñØô½=$÷ß?ŸzÖy=GNžksþŽ;?]ùúŠ ;²ò}³b6ïã;7ÜtÛ䊻>«Â߈åèG&Ô^Ð¥ë…C¯žtÛÝ —­úb÷¡¢;íÛõõ®½¹´¯ßš.ã»ÆL|“RüY¦µ*˜.tíýjí²GæΙ3÷‘g–¾±jݦoöU¾/»¶/¿Ç÷Ão¹kÖÄ~aég­ØVñ³P»6¯[³jÕê6lújçwe†[ùe¾‹Æ÷.º~μ»n¬)vœ3¡rkÉuà»Ý;wîþvßþCMß“»L{ÑôsÆÈ™ ½çÚî¿É¿êÏæ¾Óägýeö+—"×Ú›~öÉ{¯,>kwóŸ|{ä<š{íýüÙñfœœ{ÝCK_]ìàöó†eû¯kï|uãOöaßnX|ËE™A_}Õc«·ÿˆ XѵË[óFŸkÏSN¸dÚ’õ?UW<¸í½E/ÎN¥Ü!÷¾¾ñ0Æͱ\ßo]¹hJm’þ¶¹êáw¿üI^vp׆×æ¿ÐÍÞõ‡^“_ùS¼ìÀ®Ïß^tˀ꼙ݪ÷”ÇßÝ´çGîù‡ön_ÿæc· *µ¬™òèòÏvý¨½ñûo6®^:BŸSKŠ­z]sÿËoÿñÆÙ÷»6­}uáWôlU(»Nh?bÖó«7íþQ>íྛ?xýñÙW_vf剠ïͽññÖ=Çú¶Cû÷lÿüýמ˜uuß6Mz[_|ÍÝϾýɶoåmÌFxÝŠeÝyMŸv‡Ã9ŸÐ®ßõsŸ{gÝ–{ÈëØ·Çì¸W¾üÔýSÇÔV QÝâìç>óæÚ϶îܳ÷ûý6o:øýÞ=;·oùü㕯>5oÚøçÚ-ý{û˯ýØ’7Þûè“Ï7nÞòÕ×ßìùîûýªøÖC‡îß÷­yË>zï­W—<~ÿ­W è|z³#Z´ë3fÒŒy ŸYüâK¯¾ñŽÙQâÛ¶m/¿¶mÛºeÓg¯~ëÕŸ]4Ö­Æ^Þé´£ +9á䳺^>êš&N¹ù¶;ç-zîÅ—_}íõ7Þx³ôzã×_{yésß?ã–I×нC›“›SuåïKÎhsÖÙçœ×}ÐØ&O½åÖi·U¸¦ÝzËÔI×îß­ÃYÕ'ý!-Nªn×¾ý9çVºÎ9§ýÙmÏŒÿ +$³âIÛîƒhR„Íž­ñ±&ÍFǶ«‚koÏhŸVµùþÏè*åÑâ z×’ÝX’œáõ|“£9´ÜP7¼^ƒwmrõÀþC‡öÜ·$¹Mÿ5— Ô»O¦\Zòj'Fhñá™qˆ;§6®H¬ÓR˜ìˆÄGÈv˜{ÂâY¼ì96*=lGÄ/‚¨yP©( ‚Ï!ôQÄ\L ´²æ©Pˆ0¢@U Àggl~ 0«É»lè­DÚ ¤=±#*ŽÄéËÏû­’ B±8`ÒŒLÊK¤ Âà$ªlù,«5þŠ¥UŠ˜Ÿ‚>ËÉH~ŠITÝ,`–>¢AP>¢þ#JP.$žñ{–&låã.VìÅÂG&üY@‘Ä©%Py‹8“±Š•+Í@CÙÞ$r8_IXÜ.rÀ3—²_ +ïƒ>‘5HP,aZQÒ®’ Bˆ?DIñ'„¾ÌQÈÔçÙbÌ ²âç=KV}âòÉšö»¢€M ¾¤TµR‡¤ Ô:Ž[\€lêÍeŸ£r÷ÚÕ'ÿ."N¤½Lïô·h>L(V¤B%%òHdî6ŒÏJþ&LHa"$< °õ0Í1Üç&Ô»C‡)÷ùñXIÖ‚@Åa@ç° CÙòJ„8Ìï¬tdb—ønFÙXfý(:-¨{$Â]ã‚ÉóR +æc]ÇE{ƒÎö̾ÇAéšÆ&Éu@Ôíci3·qÒçb‚ ŽÉ3ý˜ÙÉŽU§ÙåûožcäÙÑò¡¯:£y¤]\:U©›qëánüÈOð7ƒM'0³Ðß™Îÿú»£}¢ðz¤ë¨íŽ?jÊ +¿úh7Ög\Øî(Ÿ8wø€£ ïzý=|WþºðÖ9c+En5}õšþàÍ]|[îê:í¡éù¶ÜuÒ¸{§÷>ª' +ßr[Ÿ£{âÔ±S¯8Êú½ôÆqB™wu»ª¡M¡ð?â‰Î#êüÂÏä˜GœŸ×¿S¡ð»#ðBüsƒÜ꒾Յ‰GèÁ¿ÎÊŸYw±S(ü¥©à!¹ŽÏªÏí ']tÖaGÖ¯r…öëúÁ7zJ&C¯ÌõÛ0Wèó‡üíÔÚKµœ”!yÛ^qùæ[÷һɸ³Vm3àÔÙãïœÀ³öÃFtlâ°Ûùö#ÛNZ¸h"ƒŽÜÞ£.¯±æöœ…|xvÕÒ+åï“Ž*ôñuÎè«í»`á†moë…Ãë+–낉“u&h7óÃï¼?ξ½vtßÒØ\5·ß~‰üÙç¹o?¼ÚþtòÀ!殪!wÍÑ!7äµ}_“ýØ}X—ò' +ýî?Tþ¼üå½ëÆg¿u=¤Âhì;ÿÉ©kíøØ×ë¯Í~ë1Ạ+¡sµó—̽Tþž¸¾±ñÓ³ßjnŸVa"ºhî‹ GÈßõïhüò¶ì·áóï%(^ñ>ã¦Å‹gžÃwz|gã·OYÌã9³—.ˆ?~Ya0àÑמ"ßôyã¡·†ë/#—~ð"ýãߪŠžhç+¯Í<õ«MõN‘:=òéö·®À_'dÞšF-Yñ¤¼¤û‹û¿yBêg슽ûWÆ_Ì·†`ù> ß_>[‚zæïnÜÿö0ú³óÂí«è-²÷O˜CκoíúçúÓ¿{¼¼ßëj~Å{÷¿A‘TÉy9h)¾ñ½/¥ÇNø¸±±qÓ-ø³ãÂmßë+üºñÜõTgS9ó6’{çÁ&qÒ'û^£Êm×ët} Eá7lh<ônƒy×*Fµ½w%Óôü­ КAŸãuf‚HÞ±¹±ñóÙ…þ/ €ú£‰…ÂÐå­ ¯;ô0»¼ËúãáîÏrñÙ+q½ñžS W}Ðظ}!À4éÈëéÔuþÿöCº/B}1û”Â-Ÿ›ïž„».š4Eûv<üÀ©/z¾Ô½ýþøBÇE;÷/GŸ>yÜœ[zÉ]nœRcê}Þç%ì}eHáòWö6îX„¹®ÇmóíúÞçöi +cÞ.uYnyè¼Â°7ö5~:wõ¿ûëBzÊø¹wô*œûÐÖ’ö¿mz_ßvî]=ÖÜuê Ý;@^ÑmÚ·u+ zu_ÉwozÐL í|ñÕ+hÈîw<›K£vÌ+ïЀï=cf?mð §ÞbêùjjŒO͸[HÎïÝÏrÛ¯¬^lMŸ·ôÐ'ºOœÜKŸødB¡ûKÔ©>¸Ž½rùæU˜¹†ß3Ñ‚ô;ŒŸpazƒéUS +c©xû—]È¿Ž_»oç‹ ½qã§Í{bíUúÄeÛÄWËÚÜÍÇÈÍh¼¯OLiæg4®–/ïòT3;‡Þ½BFÙ{Í|Åw/Ñ]8k~3kªñ˸—Ô<ýuóØ¿R,®‹–N†M\[‘PÍ3o¿Y@Øo_·½ê‚{×6ž³oõôÌXì~ÏÊoŽôÀ÷kﲺÉUOþ¶oí]Š®Kî_ùõa€ûÞ¿»W¡ä:ïªGß)ãëÐÎU³/,}À\®zäÍ6–y¾ßñéêÅÓÊ7èê8ôê›måšµk?àkíÚ5+_]xÓؾ‡Ûäu4jÜUWëuÕØQƒJã]þ×»¶‹\ÛÝJÕb*:¾Åà‡¢g‚câAâ@p“X„&“X} nêˆ0c¤îè—º¢§Búkê€H!‡ò‰¸â ªÊbà‰E;VW`d%¾Ô7“ª÷Y|·PÈpYSÍmå³?ÜÂKﲫZ29_x0Dó +¡ü²8§.*[~”f$‹r|Ÿâ!„’…ÀѯÚÆPËðÄKšîÕš(—D,ÅÞ!'%›(`o"Ÿ¿§!ÕvI''´N«Ð¾ÌúœT°´"<¼lùEŒŠ1 ÷ ¨…±ÚôX -U-Ïûi‘4¬Þš„*@íŠ^ê@CÚ1¹0V¡¢ZTè'HqܪÂI©›t 4ƒ8ŽD˜Iz©êñSÍ +h¤…€k=ÀÏãkÔ•IPÇ“ +LÄï ùŒÄªÚ«ãܤŠÃ<`qÞÄcQI®”PÀS™¾~¯0Ë@&BøÀEXÞE:…©HI0Ì@´¹ ììª.I8ÒІ” +¿±Oh'Ss‰ëôIKV‹òKìù"W¥žr©!g`)0i¢÷bû~QŸO¡ýê (Ãcdôl´–³£ +¬V%‡*'/ÈœP@<䤗 HOîiÀ_U-`Ò]¥l“ÀUhPÌ™"QÕ{ ˜Ãè ­ÂLZ6-ES4Q³( ´ЬJ¥UUr-²Ë [Õ‹6ÝÖµ sm•J¬w=qìrA^[m/‰D.ÚLG3ð=ÒÖÄ7:©öÍ5´`X%œ@Ö@óÙR®.Ø0ÜÒTÛËsc]odeRýc²yr_€9€† œL2Û´ÝëÛ™ JÃ< CíÇQs=†ç«ÈáÞ)^q¨Xæ "ΕÀŽY7&½:XMAà¶Ë§‚Ë12”1õ(¹ØÐ@ˆ\‹ÖB7€ fTGõeSFƒ„0\·4ƒ0¶ú€ÔÏItÃÈŽO¶:ˆWËi "¦´UYˆG¡bˆ…AÎ’0U$šN&9ŽbÆ“&:m…± +R"’%ìé‚Z)KF +d¥Õ(eÁpªZô¤¼O€î™ RÁ\©îȵ€R¡o»¢••*¬Š,o•ÝCi~ƒ½Šô"h€±‰ lªŒ.@W#Ov* }‡û1æ +™K ƒbNêbHxË@$ÂiÈi%’9Ï%>ëöš~"zcÆpÐ^-IWKŒT¬®/󹩟Č]i˜±¼%H¬ö$Fµ¨C‡\Õ¢×J –dòRƒ6vÌ“4”qÍ°ò­=e’uñ€1ƒO‘È †ÕËj€Qm²­n 33-²¦Gè³9­R +…ʘãŠéHf*}@êV'Év`èщÊ/ëlZÑ9 ½RûPoç&dTW­¯Äª¢Šòb€‰þEqxÆvSXÐaäÚŽ%k—´ [©¨_Ø*˜&`3“•#ÃÀ ”ÐuE§{‚È-?Œ8Zü5ƒ€K`jˆ Mî^D"è!¶Ë<—!1 Ùß@6ì +M^0¬˜sõX‚5€ª[4¿<ÁùMùžÈ%« „.0wÂÐ긅Y/FÇà]‘IL\Ý„‘ZZø1`Qá2mX¥lÓ1R‡´»MZ ¡ÍjiÂÈ¥ñ:vù#ôa&S‰÷ë y-€(:˜cí°!½+0¿F®ö‚„t2IÞÎËÊ/‹oà[ûÃT€džµTàÄísÙ|Ñ6”3‹ÀÑm™éD2?û™F" ¶)}SP×ÏéA²µçÇÜ0-):ÀÉ*ÒkŒ–n“˜ /Hkä µ"Ï<5ø‘ÝVÅ}@J|äu1aüuè<#‰ )_€-˜XÕ‘F h¢î‹¤µs÷bô{´×ð­‚«Çë½Èª ãDº IVã#Í*Àç)¯%$…4_˜;É0V@0Ý89V0«£0e? „ YùÀerŧ"áŠdÁ#QŒ_Ï%.ë͸¦J £~¤ +¸Hô³ILD×׉µ š¶¦S Î QH·é"ë +qb1¿¨º¼ØXñ¹­9’åpzŒ k9ûj@>ˇrbDÐgRÖ1DÉ!5¬²#gÞ˜±.†HLS[ìÖÊÓnâÈØLùˆ²Ñ®Ëì¦ÀcJt\6SÈxâ ›X‹ÆñäÞP¦‘POIäZ2HØJà ô0ÎØ®øMbƹWë0fLxb¥}irà-'Ãx{J}X6ó¦"RQ€E¾zDàèö4% q2pHɧ礲ÎsfþˆÉºdæz9åÄËÔÒµ#4éÅj|ÙÕð÷n ñHÚÚNlõëÍË©YêºT‰f”%~d'ÓÀeÝæ$‹­ué‡U¬5ªýŒã&5‰ÐŠ±À§v‡ž‚nD¤Yµ]RÖÕ¶E(KÝÓëùä3àñ¢Ï“=¤G·öõ|ô£Ø•oEŒ”#'::7à¼ÎÑ!GÏ8¾ÂKŒñJÀ3ãË1¯ìíÈ[D­ß íê㊓Íh”ˆ2„´ð‰ŽyÞq¬H|Ì3&¼u5#7ÏÄ8#ÓÕÌŒgÞàC®ÜOCIÔÓ/Ó–òùèäƒ.=Ž=Uà]Ž8ÇPNhrÍïêZJBÛ,Û23c\±-€DYß5~RƒUTÊ;ÉÖr/·{ÐåÕ׳Lø^ì:ä ä/–¡mãZ¬ckJžL fÚPtŠÁ‰©¢ÌóŽ#ŽµÔº "V›çDÇ°ÐÒ ÆŒaã ’gq$úÜþ8Y cÒ}çÃLÊÃb¦±Ý‚šKÎ ÓH€“ +yAÖgõ÷ɪ ?/Å”+…˜ÒjØZkØZ,f¶– ±UKŽH邉&êAa™Ç³¶q-žó'„®8±éò8­¢ðÓÕ%À¬Ì.¬w!Mæ(2ßíª ‹oÚÏtkr¸ˆI  fª]vóðäøžXÖ‚Q&úHåú¿ÈÒŒªý/É’hl +bµ86Å,ÕfôUŒd©p7~ä'ø¿›Éš½äß@$˹ÊðÈõÃ$²Š¯ü1ÄgÑ|u¤&¯ŸW»–ð¯þxìù]TQêèò8³í±‹ŽºÚ»ÄgtÞ)Gß×JHÏ?¥ð÷|?Š˜­|`Êß›Oíq÷Ø< +E²|‡A›ÚÎ…àê¿nRѤìú§¼`Ò¯M'ë8jÜÅmÀR÷ÛÖMk_ÿò›œ Ü¯Z›—wŸzÏT"ú¥W.þSéúõ 'ä?¼´Ò.½ûé®pTð—#Äàpmžp’—/ñ g4Þï‘×-þõw…°œþéòÂv?‡°B«óÚø´î€lXòþ # …?žÛù‚ÒX•ãŸ—7¡h ¿\Ø¿sþ–Ö5ƒ4ž°rËÊ …B‹š†a%*E¿KÃ"Ý?üδeÃuyEÂYc'*ú.Þ~ð«û +§^unq&Qû(ÿÏ_y' +'Ìšœ§£ìzë¢Go¾ HËí/Ý6iÞý7žS”ljºE¹ý16™ô˜öÐœaN¡ uÕ}ÎòO>ÝÄ$‰»?[óæ±E/.œtÉEEâ= ÌÇõšñèÜQ§~Ù‚ª:N_‘ƒ0ïxoî%öþŸAi´Mß^ù‰æWzÀ%3ÜÑ×)´H©;üÁ+ [’ƒ™nYrÍérûï[ýÓe·aE\œ¿wQË—Íœ3ÖŒ5ç ôñ–]/jwñ½ë-Hw÷›7+ô3ìÒÌd§Ž™T“Ïäô¢hì¬›Ç ÎÄDÖqäÈŽ…‹žøJòØ»òvAp·î6j ýÙîÃ7手[žlÆH§Éw7ëÄ6§V™GN›Ô½P'AëïVVÊ o}èÓà…žóß~ûþ<ÔmçD¼Þ|Ldz°rþ-ße +ÛùqF¬î~þ’Â?ÑÈòÜõ…6ýj©ú.½oÙ"ßoÝȵ:ÓôOšNz-X¿çëU,^³ýPãÞ7òuÒ©ûÉ…ÞZÿêÌ{¦ È¬~O¬^Ž€¢) ,ß6§PðiÎïóì¶ÆÆý;¿%¥œ÷s1G…B»ÁWÞðò×û÷lzÿiúôÂæ-¯\ß½0‹‘Á߯š<è2âÝ­y6×ì›ÈIÒå·/&°òîwX<ø¥];?|aÁz¡8޵⡱~rÖ9Àñ7‹³¨ÈŸÿºpæõ˶Sú·™å»P¨{q7P÷™”Ä–çÆñà¼yc–Éž—3…$ÄžwÿÜ!Þ¾¹¾wP8wa &zËã}ùæ雲Ä]K³æi….:ú]îß~ü Óg•À¤×ÏæÏïñlþåãþR8¡Ý™¦õÎ_$ï>°éù…N%ño_Vø™ùÌ3ïø(ƒ«ï~gª•Z:©;I¾Ü¤Øô}«ÆF¼SŒ"þlnÇŸ“ß.{j{–ñû³íLxb—^í ®{­Ø8½0³8ÈfßòQfÊ톼jqÚß®½'‹£Mzv£Y< (Ø¿þ©uÅtÛ;u.´º¨Ïé…‘ok ¿ûàžÉëé—ràÇ-_äÞ\\«›n7=¤¾áœÂŠàÿþ£¹ùÙä섯¾li¹¾ˆ½¶Î0Ãwâ ]²L>ŸŸŠº\?m̨q7½ôUÓy4~·ìòÂ÷MïUhx—»ðîçŠ5¤.¾kñK¯¯úôð¡ ;Þœ·ìõ‡.+ _Έñ S‹ò(ô{tÅú/H|»oÇŽÏžêSè+½öšâLF>ýˆ–7×WO÷.œ³€¿zõ•Eytœñâ7O{aûr0×–yí +…Éèï÷Æäó8åÚg–N3ßôÚ‘Yƒ×Oκä{E%éyߪµÏô.æ®q$ùÜ°žþ^s]>“º§6îþâ‘Þ…¹GŒÈiÜd:Kaæ—ô÷º;òK¿ÅæéMo<±áˆy4îý`ÎÔ»×ðxøàæüº\ó,Šp YÜƾڸ…óØûê°üç´»ÿËæ<_rmkjÆOpc3£Š®Ïo6Ožüá_ÅrµâðL~fZ;ìÚ¾…ššý—fô6u}5»pîÈ‘™…wΛŽüPéupí} Ý™=…kVÿ€ï9¸cËÇOÎõ”%?ŒÄwÇk×eÕíæ–F>6ïúæåñ¹hñú—›3”^?´.×ßΞþÞh ­¯LΩé™Åï®æDý_›^¸¥C¡èê>÷££$!ßôôè2Ëîs×±í¶G—fa® þ´ù·¾1­¢êçÀÇ>iæíÛñá³7WÖ_M?¸æë#æàž­ëW/ff¥øx¾ºÞþÌ;wîkZ‡âûÍï½ôÐÄ+‡÷>=È™}®™÷Âòï­^½z\ïøé¶=ûè’ñ7üm\ÿ:U:UñS[œû§ªÖ]ꇛ²TµèÒ¯fhÝ™ë÷é\S߯ëè¡uüÞmš¼©}›²¢)8 > ‰ñƒV©ïGßh$˜–„hêà'×fà±o¨Aü1(‘BgS7VL ðI »$76cšÂ”á°ê ^ÇÈKÀ¹*Î)0qF/þáHIã‚_ÂWå{¼£…%€¼å{„Âgl' Ò≓08ŒñKlàÂý8T)ö8j[ƒø¢@!: èC ŸðÁ‘§Ñ7©âzc X-}Þ¢mQ‰Pˆ%ò¼¡äÞ£Üjª]Ð<„BV.òH‚¹K- \K¼—Õ »†.3ŠÃ’T¢çupP®ž d2É + P§ ÐÅb*xÛ £Û À…°:%V”FF í7Øé³Ø0ákVÛ¨%E0y"g\ªR(–=ÎBád|e÷­&·ˆ£˜âj—D“#¸Lcù6©˜ÛiG‰Bš_# óX‚€&d´“%'¹è“8Ð@´0TRü¬i@,ÌÎ@I¸–¬ÔZÝx¨Œ?V‚Œƒ %±£@][j`gmøˆ²~S®¾„Œ)ôµ!@hY»83.ãÔ-¶¡5:sëbJ8ò5"Å>¯0ެà ^Ša´:ur²pÈ,eqš~Q̈ PåIðs±…Œ ‰ -Ù?°¿\߀Õ:GC,a¾¬Ôð ^Ä\‚”©@GÄÅ\­oÖÆô#,$–`sGqö¤O‘꘎4Ø&qtS%¬Ý/ÄcÑþà¡æ;™¾žBðíúš&ˆ7"ƒ…m`ð©Ä‡Žî²è&¬Ò±fHb.Z'Ë@¾@[\¢Áì +rKŠO“=(þe6ˆ2n„ü†a£‘{ òæ:”’ÜlZ»hBËJkÞŠ•ÎÂïÍÀ¬F_lqE)âP* +^®â.'"!ØbýYÂ3—$JÞŽ8ŽË Fá¡'+¨¬?Ye­•YÍ"”Ë·Ñt.ïÕ&|*æÏ@¢£y“« âÈ-¶¡Ýüh® Mç¸Q~½æÚbmƒürŸå`r³Þ%‘ÔËqŠEcIc^Z²z +›l/ÊÏGb^R¢:‘èHtŒ†'Jàû¹x:ðpƒ+G¬qThÐë)0SyòÏgÛ Á/'-»JßËèëËNsš…<õ› dpgâ™bgxScÁ˜ë ~0ãÆô&T‡ùœÊˆ)kV:ö3T,ÓnÇ8­\œÿë0ÓæÖã)˜)÷ +3«ÌtX˜iîn‚™ÒüßÍ!LwÃø¿(Ì´äúû#ßr„ëgÿÚÌ›þÃ?ÿ±™¨Æ¿o¢´ÿûø‹ЕMã› ÛþW÷ÏÿŒ¼*cÓHÚ&Zý—§$…v]2‚èÂ?6]1ÿoé§_Ôs@Ÿhê×EóyÐÝÏ›Àƶ:v\¿ í÷þñ¹_«ò2è?;±XÃ^¯³G\ÓpA‰öëÔÉåÑvÿ9­¨úxö€=Šh´ã³´Z¤gU·ÌÿÔêœ6ÀÈþ%ÿE>éünÕÅàÅSz]È ûEÂ"¹ÄßwèÔï¢ 3ÙêìžÝN.e?eÀ•P½Þeõ5ná·¿ÈÿvúEçŸXøÕiçØluIÃÈrþ¾VýnºelûB¡ëu“z +¿pþ’«Ã¸×EIáøvÝ,kÛ1·NèV–E¡ÛÍ?|S—Bý¼y@œtVî;ÿØýSÀ“zu×ú?oÂ=·U ¦>ùÚEo¾òøœçßy}vׂߣ{”Êç\h*£Å—µ‘Ÿ;aÞœ¾åYjX¹ñËO7n\÷ê¬Áƒ.ïÔ\îÖ8Š/•–ÇÌ7¾eùi_ߺwÏk?\ñìŒQ—žnЯŽzê…Ï;wøÐÎ2¬zN{ð¶Kʳ(tyðãíŸ,¹ëÉ¥ONíA•ÿ[»÷ ä[‡‘õÝÑAþÎÔ˵G¨³«ªÁY—^Úº@—‘ƒ?ý`ÁëîzlÎe²õÔ’;Î-œ4|ò(þÎ3ÅŽjG½€ªÀëÛPcþøMkdÜuÚ¢Ç&µ-ËáÌ©O.‡ùiîìCÿÄßœ~¦ ãáØqä°³M'%¨¡ôŠûžž7î´Ò,úÜÿÌ=„tê}“K½:õ,tàï2óê9Ó[pûÈq£Í×Ä ó—>uËù…Bÿ‡–>D_Ôæâóxú¸dÎ KîÍÊÙ3Öìþn%Ävœòø’'çÝ{ÿt $ÚÞ²äíe3.(\ÿÚÚçé‹ÚÖ]ÌŸ“®zdÙSr£áÕ]f +êï[òÚãw\=cÑÂÛP©ý¬\ÿîÓ÷¾¹õ›U“é—_*У³o\ôÂ=*ò‚ÇýÙ¿vÎí‹Þü𣧞_è?ÙsSÏ5M=ùÕ/¶}ùéŽÆÆo^0ÅN/»¼‹Î5æ,}v²£Ó½“{ÿÀW›wìÝûùÃÝÑ@/¿÷­Mß÷Á¶í›7îmlÜú̵CG ¿0›e¯}é …½Vߺ"äøŒÒG¾¸áÓW&™V¹réÚUOß·ÚÜñå«÷O¬Ë‰L]ùÁSÂY]÷̶<ª`QZ_öäæ=7eôг³/*ܸæûÆo×>2Jš±}¿‘WO{wÛ–h3veÞpרǶljÜ»Ü4ó€93LÛtyt㾯—OAêI ½öß^ûÅÞÆo^fÖù¶ó6æsh<ð.é&ÚØøÉôB§©wŽ;ïyíóæ>œ^ùÀKïÉÅ[½[û\ ¼æëçSžøØhï}è‘4»Ô<ôæójë5ïýo[qpÛ;pçør)lË3ã/(Ü €éþ/?Z6‰Fäi7>6ŸX€(Öz÷ú''\ÓƒBI½\Ïù惥¯ãWm{^ð°—NŸMx“°/‡6¿>ûÂÂ9<àkžÝYšEc£EÚn] (÷S¯= CóŠÈûàºGG·/üAØíÛ>¸¥< {m¼U»Á€¹^m:ã¢?þt>æ–à<ªO8&íËéšÅå¼ü ©qï£÷FÒÉÝ¥ƒ_ñîa\ß.QÐæÐ%¯¼·cá:À®Æ\&Lºý^¨PöúôAõŽ}wçŽ×îˆÜz'%õ¨¯áUò칇ãò>´ñ髹v»¹kÏÚ'Ö£È{_‚vC‡«'‘UmÄ+‡… n{oÑÍ×ß0kó ˆ¶¼|Ûu7Î~`Æ`¸íço<\ûw|¾î“ÍÅP¨o¿øhÕÛÏÝa²#„ìÐΟgm¾ Ûñæ͹eàü9ï7 5™¿ö­]d.u¿÷ã„ übATØXJ÷|pTyürñ°BÉuÁÜ£)ÇÞÏO(‡[u»gm3ëãÐÞ¯V?8´`ë‚{×6£]¾ÛºnõOO«`5âê:ûݯööù½_­yiÁÄ+‡]vFåLÛN{nõæ]ûç$’ãvaÿÐÊâ³j¡ƒ7 SsN,VÈm¥ZÊp.¦ +¨Q]v賿ÝXáyŽú—L±”þ¯b +œ ÄJ ŸXš: $0Á] Þ™Ðr +B Z8ùœ£-|sÌ= ÊLáž‘®O)lKaÔ&÷±µ)W(¯Y8G+6öÂÃéšalDTäÕ;rÔ2>cÆxH©Ø› "´A#¦åüc5¹sI‚⚎’_[»«¾Ëç "ÌX9€jàÁI¾M!_N-ïªÏœÞ +ÜÆP.)Õ;ü‘pàgŒÎ©€Àõªp±Üó s1fÁe_o$4, 2Q.,8ÙCW°ÊeX¿0"dœòdX[œA˜#VwmÍä:7X£}éq +`*¾2š%±ŠÀ‹p©šÇ––=rBáy°=Ù+Û’`âoÉ×Rø÷”ì0ÇU(/v®°ÐJˆ3¾#øˆX±VäÖö?/ƒ1rs‚P̺,Ï÷FJa +V `âõTvÁ—¾‘q¡Âù¯DkðÕ +Ÿ<Ô ôg¯® O@Ê&néP ÑÂá#A¬ôèß ‰nV-® @jj%šá&eøk®kEëÔE„%äÜ1‰2îþéPÞ/ôwù¶r”WZ9uj <‚À–óS¨×€¦¨AL¨ÞQî.`¼”>1¥ø”Eû;É‘[â ¹kB­à†Øòôfµc̼ϣidÖR¶¢³1‹æ|áX…›Vý×Â!Œ€¹gt²¨L“Âîè G]ˆßå«W:ƒÒñ®(WPzÊ1 /2i +‡ •KSâ;€qñƒüðhÓ<˜À2*O¡_Ó%™›@้€ðŒò‰sˆ âŒF DQ ƒ¶Jãaxúâú–?^iÇÚ°ÐØã$ÌŽÙ`¿5Js%æfÔc1«>ßé1¸=ÈÈòŠB0x ° =–ç7?ƒñai"Ë(V3+)+‡€vT—ƒØ²vz61›Š}?‡ÎÖ9xûa€ðêmš#å\]?±# ¸ósœ“06+² 1/ÅòD^Áèo\ f/wà,xbš “ k j.Ð’º­yÄÃOUˆQ›TA +'põDd™¢»åÿ/ÑÍ®ÆÿhHýÿqjÑQ•éfÑî&´=ÁÿÝ ´€ïùÿeÑÌ´TMùº›} ;Påë—•ýÜG¾þýúß4Ÿ\¨èÊÊ^õ»ÃÝ×ô••ýßN<Ü}M\—/ûâßuÿð³¼€øoN;õ¨¿ãW¿(NÌ<þñ9Éan.¡“¢úÿÅ~^(xm-"!èv~ËBé¥-UÊ^Ç/þ…N{uÓ€ï:÷>ÏâÔo~ÜñìºþÕñEþõŸLÝ·‚êú)ýG\¬0†Óz÷R¾‚¶@O9 ¥¬*ÁDüÆ´á šà _¯nùï~ÑÉòÅU¶]~w~mV¦€Q1$æ¿/üÊgÈCŸI×ØÃÕê Lÿ€/nØ~ÒùÊ1]Í;O9-O õ›¸Eáß*üÉc§‹r¹¹Î@ÔÇZœb¥¿{Þ<ûšS ¿ÃÙ9”…{ú¿~QÅ÷švï+ØھשÒÇ~Ó¦­–ºfî³óû +¿o×££Õo>ál ýo©¾î¾û¯×ÞÓúÕb>œJ{Z'E |ò½7§·5µÔ©w7Í‚à +­Û9…¶ãî^pçpáz8gôSùq•ùGÛž +Shxm˦Åð;]Þ½³NÍå`Ž9ñ‚þ¦Ì]0ç*þˆ¶Cï|lîåø€3L×Lúô9]r¸ñÃýû×Ý G§aýØãÕiôªý®7ÜõÈÂ9c»“ëç¼i‹×|ø Ò¶©éuɈ+ˆ{ì‚g¾nlüúy8®;ŽFN ~ÚD:ÜïzócOÏÃD6g¾½mß·k'Ró›<õ¦k.áÞ~Ö¬u‡@ƒÏè4f$jwšrÿÄÃÒñ¦GL`2«3¦,‡í›gà5¾xÊ왓úKï¬$)‡Vƒ,äâñ Ôù.¼óñ{zãøÊ{g õÎ¥‹˜æâ“—Ú\që­×^.¥¶wo >¾Ö4Ï•S‡Q]:wñCLZP{û4ñÐ ÇèÏ]=†tQotís̲yz¡0èîÙ Eé=ÿ•'ع|É´[ÅOXÿ¶ø6ö¼àÆ¡3>¥Æù~í]ÓŸ{í±Ë)ñÂyË_ºš_0kf-ß8j¥º46̯5=ûýÉÂ)ë¯6oßüÃDªg­øàQ*ý¨…¹Ó•kÔòÀ?·ÃjÄ[9Ç˾U›rãšížÛ¹Ðû±Õ+ær[\ó‘ÍázóÏ?Ú14äµ¼ïoÃdNºáÐÁí+ÏyÓ·_¿Áª­Ó,ŧ·›žÒV§‡>Kò¾Ò ‰ž ó“¨ÞCßí€[òËÑ={gœß¾\W8£oosϺ?/k»ÿrÂ_•óâî{çS£æø=¶/½õŽ©#N×Ïÿ~ÞmôõbSõ}ž+¢yÚ³bÎK7çïÚùÁ²ûFX@ØÀeE”Û–Íœýr ãÌ÷_m-qÚm'§îÚ~n±dðw_m=²îËç®ÊÁC†¾xd~š’kÇëSòtm§¯>:'é¡íoL+bÉ+t›sT¾Ú=Ÿ.™RœA¡pþÝ«ç@/º¾ûâõû†žU(½ºÝ¾ôóæ|ÉÁÝ_¿ÿŠsËžG]Œœÿ滾?¬òó¡=›×¼tßÈ&]‹ç6Üûüë+?ܸ«2%Æ=[V/{`üÀòòçËÑgø˜\º|å{– |ŸlÙ¾mã‡ï.›?~`Åâ—¥nx1ÆUï|ÑÜëúƒ_±ÍÅŽÈãoàúo¯äQx%›ØÚÒÞõϼyíd·°|òš €ºŽ + ýA¤F@//!™8ä÷YS¨ÎåH•cmSÖ`­Îr)È"Í"çËß×ÝÜýŸ²³v«Úð³åâPR¬ÊRRE§*Tq•Ô¬š½*“ÈâpôI0¹EøðË\QÙJ؇³\ËzN.0­GX@k òLjA÷=¡¯—‚E"˱U¦žs9ø~,’JApwFÁK-+‡rñgT üª"VN¦Y4|V¨ÖÓÞ]1¬­b\i¬œæPXW1¯<\O² Õ,O¢ÐŸÝ[‘£qh¹ãÚ°4ö¿C''—Õ6 ÑLM¤YùLØô ¹ÛŠÇUˆPÔ,ħ›Œ´Ü,œüí©" B ¯G¬bV†8UM +Xƹt艪fs¢ï±R…Ïlš<©è2P€)'Æn"5a£/uÛQG§Šš8´&D¾i©/=ˆˆpºÛ›‰Þ…j^ý1iF–©Ÿag:Τ“pRˆ³…:™Q\™R¹RvÉVœg´Ä±z˜ÑýH£E|1 3‰>Â.ÈÐsáË&6ñ‹ X#ˆE'0áù¶c³F)gÙê†À)S„â^¨\KuÁÌ\dD ÃY8âG‡ñ%”‚y"7¶Ä9Ú©k¾†+ú!{¹©»Ò¾,»x1(5ØŠs/äÑI0-AÊ=6Þ˜„†`Ê}‚8l²Š#_5w–@KÌ~`ô*?XO @T]k!RôÓüÆdK` i•t„Í€ž`=žÃ$‡T! øfü†9‘;Džo—AèÞ“3ò¢¢, T”é`Æ­õR¬¦‡ž)SEêÈ`jÕŒdîài("‘ïY)Rô)EÈtiZæH„§ŒeØ*CY‘פE* —РH¨³$ì’®--„ãÚ±›*§†­å|¾j‡kPpäîØå +ŸÁ,Ir)‰WÈš°îø6?èªB&-5ÏAi¬:£ ÞQr°XÚƒÖ” [º!ëã„2·X¬@æ6t+QfÊiEH2³+U¬¾ZQTåùr¯À.ŽhI‘ˆ†¹¶›Ù+Šdè(¡K"AòÕYLD_("OŽš QmTU–íÒ L?I¸–U€Ðqd$P¢%]•ïKD›NË*² aÈ$¿ð±Ì²Š T€“´±2±½ˆTß<V2V "¡IÇjRQ\?†žˆqjã1cº¬ˆSgÆÈóxÙÔqS– £3YÌ.ß :eêÀ’Ùe6C]ˈÊa§²åÉH¡€ä”uX2GiÅ…<¥°æ[ ¤|¡•RN™`° Ñ8Í¢‚Ä\E1º +ÂuœE™1å¯s|½[ÖYI $?" +³^+Y)Á):±b¦U`]ÔêÄ$â ¹uML\MLTPècȶõ}-IY&âv¥Û§<ÄV«öb)Y™ !G¢…ä +H!rwdëN`.™i±„#‘bsÙâ©Ã;èjÛ³B‡ð¤Æ-¨)£ËfŠ2kzV 0²9 ·„;žûP97fO{· ³hê«ØfÌä”XX£8DcȾÉAmê GrÅœQ°2´McÝn” Æ™]ó4Ã9‹H¬–ÖF–0„”*ó€0Æ8Õ2'ØsËJ"g?¹DlõSý ­Ú›ô±ØÂÒb>È@•ëñ…a” +4t”5ö/+"ÖY5c Î?ÊUê(„ØÔñB­¸2éR­¸ +B§%QËÕSõ3`lU‚M'ZXmi*¨[êe|g*k è±ke:A",.©ïÄRõAê +LYXIHW„»I¸6WôjRò%ÍÇŠð£žÙt‘ÂÃâg⦎˰&KAŲ”‘$zˆEÐaè"î‡j—U Gɦ{±€Žì ŒŽ„β|P˜ñÅر+ €š—È"»c6}-ËšŸ£”ƒzº+‰±—d˜=³×ø>ó,¶$hnìP“ø.w²–•ifx“„3O cºû&av)p*Ø;ì y®G"¶ºÍò¸!¨†h{&›lÆ%BHZ¹¤À(+WNV‹sCMO”&˓ψ¬U‰mÇo•qóTdñ©ÄøÇlö´py9ÉB´I@tc~jA›~ªBíi¶ÑòÓ§®…膱i& ŸÅÒ¨•ó­JðZŠ×,èÅóÇØSO”åeöƇs](Z´š‘ ŒÛX€–))UvNÚøq¢™ÖüIôžÙ‡!^% EÆ“==# ôH‡$¤su(‘b(ça-+q;õ´wÓ!(ÿ ‡È"ä…±Pà!7 Ëx«­/DÇvç®[;|= |#›Xš-9fÏCl+‚qKq»ÙárEo ¸§½›Öô½„MÏl¿†˜È5ÔyeÌ; ÿ‰" “åó(e³^:pÇ@9(Y.7Ò‘:­tÏB[OŽT‰PÌÕ…%·µGWeÌ8¸ +eˈ6Qd…ï9ñY!Ôî&¸^P}Êî^NȾRî!©GŠ#N”̺Fa° ' +ÿ@ &~ˆY™½øî$Ì t¶ú\Ž×É,1™pÍÖÆdžȓDbGlY™v\íÁØr@JȨӅIÛ±Fnäe:^¾®'&*N¹êØfëZÉî’ª¨•ÚjYAqvP¶ëIb!õ¤µOG¬q=ŽÃÖ3õ$:¥Ô-«ù!v„ð-ÜáZ*ÚÀq$”4*ÖD~èÚu9MxÛ4ÈþÀå8­ }6 +G‘Ë^:Oj)!;øÈœׇ`^ìÉÝN¢Î,ß¡š†^…t†ØŠ1¤I|芘j5T'†ìØçÊs•¿›ŽË(‘ÜÔZ +8¼h Çl'ÑSHäó†4óÇ(µV’r\–…D,“”ÆÊxî±6|Š˜naw”Ÿô¹“}üÀñ8wW~óT¡P£Òõ²É:uJ¾žOvÊý ¾rW¥R˜ rˆ#‹"%F6‹T"Í<Çaž;5H}9þ¢ùŒÍ>Ý…Ý$9û%Q-ÐÁ§jgÐx¢C£T\åd¨· +Y¡ãËÝÊ'Df%§f³"²ÑJ¤+æ²ðBùÁõãÌr51m)ŠuT2çSÕ•2…–žö…Q t‡øáa1¥ö&·?çTHßÄÒ†ØC4ÎÍ¥ÿô¨)÷5‰ +4íæ#Â:{%…uÄÇÑ*O…8ànßažö :|Ìî™ÑçDâã&,qcx ‹ +Ðäì´R¿&Ã7XNÂX»ö΄ï¬V:ÂôÀ®Úžè Al&l~ “hd²ý€ýéy‡Êì¥røgßX|VB3:l¾-™ñU(T‚˜\A%EŒ#è „ÿr¾‹PFªÐ5ÖcæÁc–Èîˆ8KècQ1¡¯ÚOûµ¼Ô–ÁŒ©B´W·êYmùõ'âÐ…Gµí`,n‘€ë}cùÚ óó‰r8.!~N¶u,CZÂôËûK5"CÍÏ8¬r &€ÿÅ@™íºH4Ä`dŽÍ6ÊÞôPn¸8ôeÒ¡ðAB'A:äør„ìµ…×:ÀàUGÁ؆¯ªCåœ;÷ŸÇ<ÆñA Ä6¦ÔØ8ÃB3Æ–ÞLz *‘?ø£ý@œhÔ-Ñ~ôѾ#mï“á‚NèIµ4Õ3½TùeÏ +ØÐؤ…(õ³\ÍUGf­” ”‚¹Ù½®-­g‘Y埀.À£CrF'²ßÚ]ƒäBCAž:QRÏò…ÃAÐh|¡5€Š¯}Þ Ì:C.;rTºÜQ ;æ@„¾7íÄOÃF¸¥zoD‡c©Ý'ú*—FÉ/ˆ–ºC]Ä*iЙ²Çܽ§ h‘W +Ñ‘èU“ÑW-EŽÚш2½{±Ny‰“ÕK¬ÀIMÔÅŽ"‹ï…RU"Y$‘O yûÃdɉÅÌe¹¦ŽÒåJ ‰zr±Æxþ^Ä¿¸7Vv’|¤LQ^²è8l‘$¬¤Ê‡ƒxœ;¹-³^(‘CA&dŠ6ô¸i±¹[íî;¦ ´ ð°Z& +ÙÂëÛ>0,¬„5š…gò™‰ëràéæ†+E¥ÈŽ$Ä)èî´ $|d@¿@=DnÑI?ÈÇj‚Äå;qLjóÆj]bÒÐp³Äl*«»ÚÎPä+K#öÓˆ‘—¥6Ïîÿôì­t¶¶K¬‰Ì¾u²DÇ®°Ù†$;SChëh'ïŠ-Ïh~.SºVN>¹€Äe6Ý;v•× ʧãc…=\tÅ3”Aö‡c8Eá,|Ù±àuøfˆ= %ªË GA-† h.®н¾µd±H¹JHù©fˆïE<6·:d?”…¨!ÑãÀ%O‘@÷SœÅ1í¨Øéu,{*…2ÿð]•"ra_ÅYËΪcýƒöV”í8‘°> {Ǩð&…aÄva÷yï,²&í¡#¶Óà` ½°©é†³éV™ò"µb‰˜­lΕ¨pEჵ‰jc†gšTž¡SÇB>!ô6(1ÈB=|—Ñìò90Älj /œpcƒ€Žt…¤£ÍÇä<Ë®I©«aA„iYñ ŸO­+Ã3(‘£MÈy$šªë1¹,RW¶¢YŽÄ„qHt¬' l³¬YÄ…ˆ®&eËÁ&È5‘©¡f›‡ÔÁqàºzÞšò0ðkÆÌfÚ²òÎU³fp˜‚q¤•©âˆu‹9‘VÉ +q-â,…T¨øéÖ’Ï DFûoöÊøÖýIžó\×N5ª“žZnÆlÑuLöÅ•Ö1ÎÂãøú!‘í!dÕ•À:ë—CE»“R1v šBYD‘¨°,øN%šªÂF^§»cØÊk?|3o½ß?|;OYTÚÐóÇ´¥·K›ÇÕïsH‹$J4½©zq·#‘ÉÕaœ„Aš[yK|3R¼cóΰ—úoÖAýýê†Wµ2°MßRÿt'¸³2ùäôÙÿ‡?á4Õ‰ØF/&ÆÕؘÐÆÚ±îk¯îk"ÝfX©FÂþkH¨RèZ€- œ =tÉÍhà ždLÔ ï‹éÀC<Õ™ò•Õ$c„í‡ãêÂá[ŠpÄ%ÈUí0^’0YsB¬˜£rÖĦO1Þ0fÞ1jÒ Gœ²z¥dâ”c¾3Âct~ +íB`¥ò#‡ 05ñè†%Êq$6±ö¸â{=a…¦¹r©ä@>¥ù³¨\ÀH‡–M1@|F°J2ÒˆNX¹´åÃ`.# +íÁqÝ.âöS…­™žãñôR•Î–Jt2Ÿ•m:Ñ0³Í;1ÁññË$(ˆX=¼Œ±&hŽ ǦðÔ©—•ÀuÏn9å³nœž[’JPNmq—Ë÷N_qØ/$®[Üå`_e™êyòp ­%#¡<ófõAøŠÙËc°ÉXD)Ζq§ç†8óqê…ÏÜî$<ŸÏ†¢n¼ˆÉb8'I·p˜JÂÍ ’p@¿¤ý7u¡Àa!õb_øOòá•°ÈÎ|÷ì¡:‚”ßeh¿Q锩2À8" @Ã-´=h²TÈ;û‡Â|"ÓMÍdæž„°äß +sŠA%Ɔ½#ú‰d!˜p ÿU´B–‹Î†›BË+–Ž-[E<[Ò> …zL)Iˆ©ä­tÚlIØ@¡6æ·YKRn*쥸RȲ>D¬£@%JqúÙ Dè¥ î|­Øj'Gg9j\™Fîž)>Þ4Mhq¡†‘FârçÖKc Î*zƒÈ¨˜†5ö‚Ê %@Ê”DF”w>a¾†ÀcÒ.NôÊ׸ ðd2c„/6Þxâ_i „ %²Ãf‰0€|-m–ŒÝ˜ª¾„R¦½›Ã[Äi‹'™ƒ•x>}“ÔƶáÏ€`¶^`CͲDc:Že®/mñ?Á€;b5‰€ì@)Iý{ÌR$–ND0Em¼SƒLÁÝécc¢‹+Ç­F¾ ¸¹¥T`EìI•6RžA|OYÒp–΀ïê‘Õ3Å•a½ ¬HNÈÒFKË™èWbêÆÀU;Ë@2òÆ\ÓYhh%±¼k¡vUßc…»VAF‹ÀØBi2,„“çêB Tª –_IK3ÖSÞ\c õ‰)ÂWª²6a§G.ú@ñÁøa| ±õPc‚ª€g#BJC¤ @ˆt–(‡ÄŠè%ÂÉF¬¢å"7M¬N£1u;îd:ô…â†݈«#ùBÌ…H÷" +6Uµ%Ðt…žÜë;Œ%:|RÕP|¯o÷ã¹—ù±£gÆ Ç: +Ù)ú°Xý q°3Š*i”Wm-ã¤î’ ¥“Ò ™,)䤸hÙ'» Gj ænøêgÀ`‹„ƒÞk1l<^c©gÐɽ"‡h»M£U†úBº5ˆy ÓÁ*vXÚI +1då @j:tܦ¦ÖJêÇ–ÃT)Ûü”ûRlcÚÊ+FÖ@ê&!¤?uᙄ % ‡õ]a%DH‡JzÞƒÄÁÌ&*L.á}"¥6f¤òerg·P%P@ð#GbŽŠƒš°_àü‘¹="§Štµ8 +J+~I±n©”žJµ©s/fE1l£•Èˆ§HŠ)I;W\=Â9ŧ[!ÇR§®2ò¥¼îŠWC!ª8dIù$Íã0aÍ€WÒ|¼DØ©‰ƒo()l¤ôVìƒQl…°áÌC”RàÖÕMþÃPWì.qcUÞ"6-3žFÇ•(ADÄg Šáˆ# íáãF¥'G–‹Ç6 úþ²ÖFØ—)Êã@˜ªª‹+²zNÆÃã(cŸç”»AøóŸhÔ'œwUóeU©Ð_kü…•q˜$*ÓÞ qÀ…1·tÄÁdÜzÚU1M‰ ZÚqÕY&nê‚Ž#ÝÊzQc&b`ækŒcÝ:Ó‹{¥´åD<#‡%´fr¯ôey¦{S€èëLð¢‰\Vœk:~ñ½¦lJäK€M+·éW©kUÄP_1Ó×äjg̾ú+Kj¶yË1>ÓåÐoÄ| ;H>SÂâÒŒAvkeÂÍüŸýL9„WÆËXúdv‘±ËZ©„5ª \HièIÊâØ]t=1 C…dšúo™­ ɉ憎^â©áÿôÅ/΀p)VêkŽ,y”,'ÀH÷‰X:P9xT¿Kg‰oDV´Y½Pæ/O ¡ž§‚c@iªÞ¾L"áL`=‰œ&ÚØÇž0D¢Ö•¯ÙPdt”)’Q±ÂØSÈ<‡•›k]–ÐLA´ó½!G%ó¨’P¬òþÂ6zL$av>ûÉ5®#ð"‰8¹{™ù3>&níH3¥^æFŽ,:ÀÍð ö@Îi=©A5 +»¸›SÛk41Pc–Ö K…ÞÆf{¾¦:„˜p†f‚8–Ò†ÂOˆ—åüÛ~Ä®ž%=Ê9–¼L_Ÿ+b`È áBõHi”S^·<;{f>¦)–uôäÏ„§`QK!`E!OÎÌ”8ÑiÄL°”‰Ív7 ½¹V°1ba? +¤Í3ýáña¦Êý%Ù™œÃ´$x°/Ûø˜·Ë¼FÒ¾EKô¡+XÉ$!ß«Û/"…P=ÌŸOÂÌZDdÛÇ_Eçó…X\q´½O%1ä~sS™à‰â½¹±Š1oäÌ1\&:¨eõâó¥4ÑHPQÕ5mfg;f [Rž9С!D>±›>väa¯éi$…{Ó¢µ:Ùós ¸ÇË7‰Wl\î5œWeË{,–y:;'Xš€ÐBögšo ü2H, &ã†SZ{ +š4R€;mÅä(ZqßrÄ`áµS›JçúiJžpØw•Hç’ PÌ! BW¹Öp\QP¹¢ XT0Ëæ¡'‘®H §5.¥VÏ|fï.Ó¤Êéï\AuÉ¡ð-™Þ‹÷ P”¿Ë;.×åc/v¬1ª–šı›tÊÄŠŽ*XYËü¦Ãt€„sÅ%gbÀÄ|`*ƒ‰¡NP7b©AjÄ‹hV€­a ž(ôâ´JM7'Õ½"Eþê~&VVr¢öˆ2K_Ú)¶„¦é’œÙT+{²X,ÊXI`N‹N$EìzÖl—ÐM0Ê2³Þ¯T錈å…Y# žæ² +Q/ÂÉN‰è\¨¥@^«”ˆ©=pØa¨Z቞ :™™ë¡=aCbxÃ%JŒb¶âø˜IcËXA‚í|<E÷kÐ>NqÅåX{\;]ˆÖ'¡â 9^ÎcÞ\šœõÐ_ü¡gë‘Žy)09"¦-_¦[ŽXǦßrÛ#€Ý¥gˆNxÍ,³Xö*]„¾¨L^1pÆ®Á]’#¶ÈªRà4¹W¹ܼx—²´Sð;¼ãL G™®q”áǾ}s áD™8(y!cË‹S +ivY½6ÓXÇY9O5ð9$DÜ!ûTÚþ`°³J(z4«€ˆ¡¯«%æ¢D¢|bëÌJ@ýêëÈ"õlÆ€á.‘F39Æ‹0BÞW ¼¥‰Ãøà›_&2$ºo=¾àÃUl‚Ãij#€eÝávSF$L¶\Ÿ.X¿-c æ† º°Ä†I›ûø4´/`®Ž5«P¯rp;^pT•F¡Œ¥È W'öýtÜ€¦&|–º4Ñd9@_ãÕ%ÊÍÑ‘L ƉÂk“ÄÎ…¡+á¤LRÕ€É$Q߀+ì—šŠ6†utõ`µä»Ä4`—­8šÜ¼QiªŒŠn{K Væä¯ (ƒdlµå@ƒrPBF4Z†`¨u¨‹àªwe†u«r +àgé?ä Ž‡+S£*œœú¢ á­ ŠÓŽÌäÎÐŽUéð„™Z*Ê”àè‡T:î)?RÝœˆ¹ÕÉÐQi)tU†é„Šæ'|CÊfZL+„¾.n ¤‡¾õÜÇ›OrÊÉiÊöÌ(®Z[o".Ö U ÙO‡´íkê„L«MÌE8Ç…ä ³.Ghx¡%èMÈUæÊÞ(ÉH…‰pÂñyŒfTjÞg?åÞɉtM6 ’dL‘Êd“i‘ùŠÅ¦ŒþØ:ð€tä8*àÓcœ ¸¼ƒ/?¿ÈøÜËO;*ŸŠ”ŸpO[*žËT8Ãá, ÅŸ›«[þÔµzCrXîDªÛCèǹO&SŠ½¾x c2x=SY‚2+Sg-A^j"’p9êöô#Bá|î*ERc®IäLYE,Ê›Zí•\¡ånSÑ+©ìd­èŽ-sÝÖÚ8ˆrGo¹SXŠWÙ…\ÉÙ\É1]ú…™»¢»»‚k\kT@ëi¶‹Æ~ÓÕ}áˆù X¼ )Ê…Ñ( r ¯Â–D>‡"y‘²6— › …=Z5´«¸‚c§Ò\/dE€8QO0ù¬ÙëÎaqEV(ñqèAEB !££+ƒ?Tp=+]EGu—vE÷7—¹¢³¼‚S½ÜûÎÏWòÔ7áÒ/qÿ×f3ž ÙžúsGÓp q V©GâÙ ¨ ¤‘rÅöÀÅsÅ&ÏÕ{ÙžXIõÄ=€hVvE‡_¢æsœÑ!i¸“xæ2ŠÞÈrÒƯ4ÁÂΉ[£â¼¶~Åãû²£þžö…M¸JÜ µ¶9ª¥("V!s1Òç…a¤TIªë³Ñ¬ßìå·d7C±¨I^~„×LÙ¦)-3›IöˆpŸ *­ 4©ÆJƲCé9DfEìf%œ'$”3BBèI*âC™Õ©ÿÊ‘'Ô¨t¡ß¢\ü´aXÓrþž¹TG·ViR´‡¦ˆ}™ó*QdôNãÅv=EË&‰Ä‹Î< b"Ú{å!™l¢pã{¢u¥5J“ +e”(ci‰ÃL³©è^«äˆ«ä´ãÝ“Ò‚:X žÈ´qÐ9È…“€‚½4·36J,ãGQ e |)sEÄ~¸?»¹B(@Å  +œEÅp„J •‚t[U1$¢ ¨žR1¥,æEr¨ SLÓ³ìî,ô¦bN¥€K¡\~L9ÈþĶð '’]Ɖ*¤>…#//ÅÈ:M<=Ù3vMÌõ¤®B¨sUÞ'›ÒDk•Æ'z¡'h¥‰OB,> +Ú9dYH|¢·=«@iþ©8–çªxd›qM—B!2–øÀOuô‹¿ ›L;¸êöĆ5a¡_ßËë#Çe4Ç1…N4QDL´.[‰ÕsHŠcê#Br(¡"Ý-£·p—}ƒ~ßß9mˆ^zÞÁ‡÷\ßpß–-9™"ó?wÞPü’ð/Ž4ÿÝé²ËëjëkqFŸ!—ÕU9|äˆ~Uk×ô­^ÕixSˆÃÿVÅ?V× Ø¿ïðš¡ýú×Ê]‡ غʯZ_õ¨ˆÖnýSUK“Eþþ÷·XS_Uéþ¢[M%›{)‹&_Pü@ˆ:5Ô ,¾•²¨p¿çhaŽ˜5eá;¥ù›>Òi°iÞ~E7W÷«8 ªKíðþ—]6°Nï¥,*?ÐÆt°öƒ>WS”Eß~xÁðÚ!G*FWóª:× ®íŸÝÉuQéö jL'­2pÈðª.õÇ ¨k*wÊ‚Ÿi7²O]ë?UµângúiQ§û‘;oc:)÷ê$øzýÿ?»‚èWÔöfÛåøÅ!þ/r²ÿc/Ôÿâ¬ïÒ‹Í?=þRc3´ÉýI¾×/©èªÐVsbþÇcÍOòf§¨¦Í?}úæØ‘Zw¢OÎf,z±Y/¤µÄç¶læ7ÿ˜¡Òp7e+žvÐGÌÛmðàšAu}ªüÖUúôÖUâ=Ö¡ÑDYdF+)„åKå—œ?ua0K•”$úëV‡1¹i»´VþÊm“_JŠÂ÷‰½ò×-UÙòSR´¤¸ëŒö=ºRõ LùSä.õ£Ö8®õ¹ƒ‡\1˜þaLÂm†Œ¼ B:æªZŸg +k̺Ög˱¡Nol]-Öb»þÍgâQÓú®â8õOô­å–¿Tz¨K}iºÃ>tf͈þµù'P—‡}Ä£¿v.÷šLò†¯ù¦!õÿQW;ÄX„}ð#ß&ŸVÕ\ݺ£Éºî?«N®:®ªE.Â'WÑ[«N>®ªuçšáõ¾¥zÈà>#û×7ñùPu—¼ urøWKæÆ3MÇ®jÑmD]Û†ºÁúôÁWRMgUG\UüÿŽ !@Ö𺌱ƒQHG¡3ûŠêÛ¾¹™µÍ£µëðšÁ#þsÈðA¢÷f_ßÂþÒª¦ÿPÓóy°™ßëd ´È=ÛºkÿúGìZ¶ÒêõI™ŠFü)ÿëðºÿhFtÏJ‰=s¤õÔÕ˜äµ5ëº_ÚÙÌ-uƒëéÇ’ŸÚÕÔÖ^”ýÒÁìÕFTÊíì¦s;»87þeøz3·]úÿµ÷Ýý‰ãÜÂïà; .˜’j +©¤N’ILI„±a÷™ýã~öW’›lK¶ dÊîìýÝy‚-«®stÎåNO6Wb{Ué¾(Ý®c‘ò 3|ïýƒ¶+«[ž#ÀR‡=mdÃLÞËÃQOû¼`ôü>ü .{Œž®ÚÀàoú.D0ÞRñcLhÀ‹&€v/ÂJÆ“æHnmcµóÒ=ù««ôåÑ•¬ôdØ3jv~æxÍ™ÛgÌÑÙ@r4€H¡Ò‡ÏlLÄá®{ñ+Ü¿+Ï’ô”`3XK‹šÔ¹bXxÕ^åÍ«D2¯ÿðª_žWý$¶3ëUâŸÆ<`Sêwé“AßU¶­™[ŸS§ÊTÿ×mOàÐ ô­ËÒQ†£˜Q󵫴ºãðÅ÷ѯhîx˜˜NV¡·ð%•€FZ?j/Õz`ºvúžóÍàæ+Ø͸>Œ‘7#w2;ÓÑ(ëìÞPASìãüør¤ö:Ý +Øhüiì4ÆûÃöÛß=µ«©}t¾MÔñ»%Qô/€ÝÞûÇdF®…B£L*¯ôÔQ_þ®ýLÌI@~i@Ô°°!¤oÞò ï"Ös2%þ¶R±?P¾føf—Lèú(…ÿÝÌR‡”’7|ñwW~së<ð)]ßѾarõš’aàÚëPù=1å.fhŸÈƒö«íÁp2¶ IùUÓAò–0’ÿêÚÕ¹¥û“q×h »òƒdR0‰Rjî7\Z/ +P³%Yù*ÖaEé|U*Í Ÿ6w;òüx¡ý¬·úç.<©ËUÚ^¸ÔŸ(T|±µ +Œ7/C½RÏh·Û,ïï¤ +hÛÝÄ"à¿èúþ·×·v í˨tQjÅáÃÈÿmµÆ;òXF*‹¡^ÂM]åd€ÅœÅ0ä%sÄÿ!ubOî)á’ 5ô_N‡øoºL’JŸE¢©ôúÄfž¥”åaP*ÐŽ²1áÝnÚ}¼YÔôg¨ô?ÅÐs.;S$¨|¼¯¡É{›™N#Òie62yv“ hhz»Cî ÿv¾Ó^Qmûœ Ö‚S¿ê ’B­þ ckÐBâ¨7&8:²ò¦.oÂn@oSŠF€R(ĸtÖLDÎ$S4³”!úÏ@ j»¯à«j«JûçÈÕŸ%öÛÝ_ƤŸ•€¬°îÀE5ús*ɘß1»B !˜¶Áà5 ¢É¢:cÍò4€ùþcwJêÊÜ,Jÿ/nþ£@„¯Ñ¯-/ ©/iŸ×.ÅN@sºï®`ØÿEí$”fÛ‹ŸbÙÿ9Vø L=É~¬`{äXaî–cNÒ­üÏ0çÔ;<ôcd±ËÆ)¤›ûCº?‰tÑ¥/“®Õ‰©0~iÒÍ}&åþToÃÕVŒ3¼…ÕüÓ8,hQGæ­òDöºÿè>ÿ©"û'˜ySM0Öþ¥Úq¼ýUN7’¹eDŽpPg‘ž§k˜^"Û4¾(‡M<Ø4þÓ8ù†¯/·Dõž‚Vß^‰‡îi€~k@˜ gŒhР·€`DÒ@ñ9?'DC©‹æµ²8æUÝy`ÄŠ¼vAEö·…©Í™X¡ã ¢ íT:gÀ+¯§–P ñ9ñæ?  +X96lPª tìÈé5±) ø«÷·Eþ÷…Î5Í„+Ü b8೺p5keP@Qø½A¡³Š‚dˆR‹kšrÃ<€€€è\³ø[ƒÂHÁ1U)(xã6Š‡ÌÔ¯¸Ÿœ§óŸ0nLÏøYïO[‹ÍZk œ5ÝÞFà,)L–pÞÇèy3~L¿f°ÿÀWкýªEöý|Ûð_‚Ä›ÑàF’´hgþl~±¯?×ÑÆ7ïãfsŒýŽÑ¦jÀ6SÑòMϱabÒO +ÚÚ fàþø׌ø"9Ø?,6FE `* 9Øæ­Öe¨·ÌêG¶ÄËøûèg9y5Ö|åÆÏT&½Ä¸¿ +D†õós·}/Q-÷•=—ÀCw!…÷äþóx8覵¦DÁgoÉ*ý¯N-÷6Etkj"·ÐØ虿£øû›õ{[í£KðwßúþØ~ëjaÊ[WÝÀST·ŠWV¾«cXíoÈYÍ>ëÚÜíð~ß‚ï¸{–ûEîžæÏõKîŒ/_ Ò»ùëøÃ:~2ëÈþazˆ–‘ãd^5¨GqÛâØK‰ÝÊþ£xüá?€{¬ý¢Üã3ïø‘ë(ü,³ú®Þ‡/J﹇ŽIÿƒ3Ê12fD£ÐKÁ:ô*]ç1Q«ùBÊ1.•¸Ùœ¿ÑE=ë!-95X>³},ÐÍ“o“2˜Ÿë;'gæÏÊúM=þYÚõÖ×é_ÈÓ}þ}QÝþ¹4—ónÿla~ÿl¿ÿ¯qáçÏsdߧò¤?~À„q³÷>ê›Â˜rtp>spW{‚4[âH£1¶T¡¼:èìšõÉ}‹œŸ”D„VtÚb//¿;Ÿ«€!<7ÿ„œÏC§m7´âׯ½qW{7sDØz Õè±^£>»íöa¦Šö]ÐÓUð}£÷n,aʘÐÉqïåu kh™]÷6[÷rhyÂœ¦p›7q„ãûÍr¸?|†[ðsmÞBŽÇ:Œ|\³Zžd$" F·h)ˆ²áøéîñÅÉq5œ¤ð¥5ý1è´d"œW¦á(:iÈŠÞèÚxƒS åXÉ¥6ãY‹Žˆ9ë:R¬¦¥z%~1Ž# |1œÀ ^3/Yå¢;´_Ò#„ç´WÍïï­avóÿ`Ñ ¹ÕU?àfÆ!¦„†Êèu~•å÷Ñ J5?ê`ÉÝp¹?QÇ&u (áÝÑͶŽšþÕEåÀüêý-‡€y)]UôÚSßRcV¾wǯ݉ +L”„€ ~àÁ9°R”pmØï¡Ñ–/€}ÿ+Ãön^X³¡ØcÆø ˜-ü…I ð;~wÔíô&ïáó.J÷Ó¸YdL€›4»ãÉ(\ëC=概u‚톌Š wï†ølµœ®Ø£È™Æö¨—Öž™¢Wî÷TÇ#u4;½£ðYÔ™)^G²¦ÈÅ×á¤Ã»“ñ0|.ýÓ%9Ö€Tx„h@í½OúfuìѬÈZ9‡°5܆ž}}7GcèX Œü¿÷þ¼^ˆ=wõådvEÖZ}vsèkÕ~íõ;JW‘]n¼…ÿŒÑÅWðm|i >þ%+ê:†@xÓ¿dÄYQ[ø\¥´˜ø¤ÏDµýúM¡3ÐÜ‚~€bºÈ-焘Ӯ«ÕîõÂ3¬ `!»ð_ÞzNÛ?#$xOH0­¿'qÇ‚ø¾»ú“ ½ ãðý³Hýwâbk1/6eGåÏÃÃ5U†6Ô‰±¢ã§Ó˜Ë/4••ªÏÿÂÒø'“Úïµw^,æòi)g¼ÓÖúew¿ÿlæ+dói®+ú­æL¸ú³WÃóùt±è»˜¿µ¼Lÿým$pþÌEe¥4½8>‹zíB«—eUFËŸ¼W†qH[Pk8úN£û<>QzÚQ¶ïÒÜßüÂq½æp¢´»%èÄøéÒȨŸ=…÷îXÖ¢f›GqÆy,ttW vaî žïÂo`&'ã0ôl̦º›ÃíÝiȃ—‰üÒ ŸGFûœ$‰Õ5æÊa‡JBV(Ð[ +axÞ2ðœpOöåq7Ü‚Gz~=FŸ¨1r<)uÃÝÿÃÕNo,·zýÞø;ã|[&È}'l5å­¢Ó°åQW}5]Lȇ„ùÐì,6G§l# Jû;€B¯VMÏ”ï$Løú® ƒ¯ÈÙæ{2xÏØ¥ØØR³Ûß“Çaöa-ÛýŠŠÞ’X—Ù²1lË}hÃãmñPÛ†£ÚAö¶»*+à;0zýÚk¿ž*Ãç^¿{Øýn§y[Ëê{«Ûqµ´akÜœ´Ôî¸6ŒÕs¼k ÙlÍaü‚îØõjvZ©Á– C%³Ø¦éTHÝg¶ 7ºuûnLçÂϦ³udà<ô9 ãWõþ Ýï^@Cïƒ^À¼}¾êU*T‹àtÅR j-ófÚZ*åVÿêƒÚpKî˃¶ÉÆ2Ø©¥ÿœ‡šN–Q=mš¥9.ÌYð8sCM<à%„w÷å=T%g‚FÉX"<ómØJ·á©ÊØÅðÍF€Ã†ðÒMxö¦´PÔ.V±¯ÎÙR}ëZ°o&…éŒi [ûƒçaØ"3Ž"µN0âìPkR7‚¾a¾©ÆüGô‰ÆŽ2Wn”pÜà©›mÛ(w³2Dü²Žøç4ÄGÃÓ›²ŒÀÁcÃ.A zõä4¨ÀÑ1Œ‰ô”:ZŽ]¹ª—róZãrÞÔ†„‚m-ðÒb* ‹…jæ¤ê™= ú™ rw© 7] €Ã8+ÌQ›¿ËÊ›jGc†Æ&}0´Å°‰†çÁ8Ýé”ç¡©¹2têàónàöKqªÀ6º4Ôǵ.­t¶Ãö2_¤¶Â]¥”­lº MBÙp‡&ŸºÞ E_ÃÏÜñV¯ §‡Ú…×|ƒI{ÎYoó—Ëêw¶B‘ÃF_¾íþò'j{Ôo§£Ö¦=P½ ÚŒ{}ÓÛE¥gÕÉõhƒ(ÔOb(…‘¦¬ÑŒmKˆmÔIËX•H}›_ƒÔ¢…R·&:È(ß §•Ú#Ê +-#…ªH§Ã~Ï‹WŸéÌýA»?q~vâå óIìÖèBÛ,訌õî0ÏD>`ªRÆö; /=µÎo”áÀkÐœ»€QµäqCþÞU¼3ÞËAZ~WÍÑbÁƒ¨Ÿiå}kÊð}Wÿ=TÞ.<µêgç–4 öaÉOÓ¢~Ù0•®¬°†ƒaû&c.îÃÞ@"Y¢€\þ=Ð"Šö¡•¼Ûþ…û¤¶z °¶@ß[óöú°ÔïØbu7¼ö P˜ù%}½d{Šüm•ê|„<á\€-ðx/}7í:;¿Ûïøz`ˆŽ¹¿æ­ÅJ›~raÆrx~xå¾étñe”%OÇÑœCKc}Þê©>¾&vãø]ò&P~]Ñ4#üZ%—Þˆ‘«®h—ª˜€ó\ ½}1¾˜4Š'K–Êu·uÕëþÍ° È äq÷âuòÞȽ¾J·¬ñýsx·9$*CäǦàBh9%€ñ +^iªsÙÇLF%iR€ÃôÕqüO6q3Ò¬ð¦º÷•®Õâ­Ø+’®ck ävÌî7 ØÜ<èf7xs`8©–ºFdfxóg¥û1±H–ÈÎðd£8‰?¨{jûý»o·õÛ·û +¨µ¨µhðì|žíƒ¬.ÅY´D×#þµß)'ÞžLYǽÞ•Ø‘W +‚¼†¼$>fky¥`È+C^)(òJìÈ+Ù‘7Mv”Ûº€¿’Ó¼ÿÌí(Ì1~àDáœ(0 °…% +{ P{8aÃ^ŽÑ9;¢û5¶á¢wË ˆÎ9–K÷Þ .®sAqÃqÝoò5ѹ@Œšs`9[kÅ•a¨áòwyà‹á\ çî Mžwy;îzc$á®à×2îò.ÜÍ=øp—Š»<;îòAp—„»| Üåá.OÁÝ#`Î l¹´ïÙÑ—„¾;ú +vôõFJC_’™ak}úò>è+C_!(ú +ìè+A_!ú +ÐW„¾}õ‹yü0R€½B ìÙ±W´c¯7NŠözëÒb0ìrÚÇ6ƒ!¯yEväƒ ¯yÅ@È+B^‘‚¼ÚeT~ø(À]ѻƑüþà- /ØÁÎâ}®•]nJãh,¹ÝÚ+™“½âzMŽ)›¥æóÑBcc·‰lˆ‹ÿì¬ìŒ¥ÉZéäŸÊZÿþ‹DO•Hde9‰Ä¢¡êèë?xImrG9ÛçÁ *üÙÜÍ?¼ôÁ‹çðFÛ|½´Ó­£yÄzð½´sõð‘,¡+n¥êÓÖükiþÌ”„×–6ÐÏ‹œôÞ£ŸÕ§öþüÙGß–ÄÂú6\aý Åv.¾´×àƒmô V~~Øü'÷%7z­¶.¸hm£º6Kñ`·Ð½$K+g)ÐfƒOî.îÝWž/ž UY^^ÜMõ/8´´B!­ Ê¡ØîáM'—Û¿ÄRqéàç¡øÁBîòY‡ÜÊÛí!øoGM¼P§ÑÈÃòóöÀÈñý6ú[:‹\x~/¸¨ñ0ú­Þ|)ƒ‡'#óáöø}öÀ /ÿß–‰;‚•B§Ÿt‡+úͱG)gÐ+¹¥å}\w»Í¬+èìw:A„Õîz‚ÑùÆ»r âOˆ˜›Ü’žòÉí«V†Ë$V’Û¯cþ%d7ÎÖDóÅ™ùz±.n_ŒK•çbýmoá|S®"©×o{æÉv:I=vî")¡ÖŒÄ÷Ôüy›ÅHrks˪ââ>»}ò´Åí=lÃÉ’[¹•…JW)MªÉ£Æuåp?Ò4ÞVÞÒUÚ+>]Ô7C±êu©{¾“Q_62{»_+_jWÍ̘‚–ïà›Ó2@Š”#}¥›·YmÊ¥¡z¬ý¥¯´¡*J¶Òã27oy«I(f­P¹—ï²`…Ir«Yʪ‚zdLªP&·O-ð³Þç:K·¼ÛuõFyHTŽ¸L¶Ç×üØ-ƒ/“_À(Qam|ÈàlO°A.sê Ò™ø¦Ð}R>Æ—Ö `|Ør+w.¯ +ÄAÕÂ5Ot/[Œí¾‘݈.…bêòâpDZ«2yJ/Æ[‹ç÷¤A“Bƒ¶ÒÜÂÂÕ—cÉ`2¾o·_¸Z)wBp´ö­°8×OIƒrµçöuÐPlIÈÞVÉkÍÞv¸z]¹%ïjíãR(_´bà³ìе§Ëïkú §ËË`_ì»**W™W4(¿²ÛªÚwõNy¨\ÂAnTÊ>dÇéËUÒ ¡˜ò0Ú;°†u š;æÖhƒ¶•¯þ†<èqueá#79BƒifV]•j´A÷¶…ÿ…pµ‡½s4(Ä1'*©ë±·ÌU“8h=59¦ºÜ}Ù9! +Ö¢lD2Š::]„î¸|V[ÙÎïD €ó#ç |éVôv5î4×l¼]¡AC1¾zÿV³­õË׸«JÄA£{jþmá,GôhEé‘ Åа;oå]m­®Aï\s­«’=\½?ìtScâ ÍÇíu4(”bîµßï”hƒ–¹«å›yÐƤùÒꃂQаW ~Hðe=SïÓ=ä®FâeÐíÄÕ×ë§ÝPŒ¸ÖëíÖ +uÐÇÇÝñ5eÐû,÷pr‘p +Fц=>yùvSÙX!ú0NŸQ}?M.ÝЭqg`âZOvÊÝ®Z&Zý¶š£ ZØ‹\s mP9:®£Aá(š¬‰l+“ë»,4é"š“…õÄ×Éû#tSqú´r¾¨úV\± *½.qGÇÒ”ê}ay+¾gp‘´¢¾,ÀAWÝì¡‘ŽÜ/äj`ÐÕ%Sï‡EmÐíx5…E£èŽìÖN–µAÆkvVx™\ßÛ<€ƒfÜ2õ’_Í7–¾Akç Joð1}ص³´}­{—¥ØÒTܾl4l+]¸S¥Ö’4œ›é—¢7ã³}0¨piŠ²Û\&câ†õ[*,ß^6îˆo'rdƒÛ¿OŽIo!ç——·xY=] ½{PKEb¥Å +|K`k­A._[äá[ÒD÷^G¹ÁrNDTIz?Pò'{åíx\à·¾äÉo÷—";'×Õ3ë­M‹î×÷TòׇÜC#™”&”·¹Çã­É2é-ÐÇ¢‡‡Ï§kù«Uâ×…ã/|"¾}÷ߦܜŠ[4wÒñÜÒ¥|WÝÒ Fx¿¿*o\ïPÞ–V®•^‰òv/õXÎ]Ü[oí;Ú­}ÛLˆ ò×Çç¯ßÔÇj’òöæÛ»¨fÒ[±ã÷áê[·@þúöáÔÐ oVîLìv¿}ü¸BÜ1ùFØŒ¦ò5òÛîÍqm=é’ß>s¯Ëßö£ˆÅ®Ï:WñÈñ6ékEÙ|<wÎâqø6í~+”öOÎJïð­“ Af÷ñ]¶uÅz¿5JlŒ0 ²™­âÞâ7Ä4û¬¼ºrxR#O3=uãråpveªr~I]}mBkò"¿KLà_§À¦|+GV%Ì~ÛÚ¾Ù4wÐxÖÈ™£Â`˜‚7ÈÏã€9>o˜ƒ?ÓÛl%€–­ª…ÓŒ÷)QayótUSm¡ƒ1Ü­q™žHŒ@;çÍb·ø ÙÄ=âÉø°Ø ÑÚ×Uê ÈΡ +T[`ç<âú˜mØÛ¯ƒÖ#}Ph瘃Š¶A ÀÞ‡úÿ½1l½oð>h¶¹ˆƒ÷lç´³´´` Š´kP(+m†Úÿˆh´öÂQT õÊZs PûoÑ•=­sk6}Ì>,Ò)¨ƒBâ’ÞuPÈÇjûKŽ]åS@_@ã¿ô8žt˜Ú,tí€eAj=ÙŒ0ô¨Lßb·€k¶9„tÂÕ5%ðu*ŽùnÀ_e¨Ãí#ÀjR|ýäÀø(¥ÿ³Íí[Æ:„öYVͦÎm:ÿÖé`qËwe}òy Ltm¸5Šw.œ¬ _ʼv+1øÏ‚9À +>€A‹`6w~¥ô­¦éÉ¢ÍûØÞÖV5†ý8£¥1Ÿéî2«ñéÒ‡ÑD_®5aî@ŠÅÀ(ð :ØŒ}f'æ +*É­–¸‡ƒ|ýòü\‚æÃd…4%Ë£MJõžT¦·°–BÿhðÔ|.O òÆÄ9Òù‰@Gÿœãv5a}ÛüaÃo}àh%É7ï·¯.Žüö/u¤ã‹fÓØÖ‡FA+\_ñûþÕ›~~K*°<:»bFvÜâ#‹{^þ¸™³,ÈjT9äåÅå½Y oÂ=C‚»¾/A!ßRqݧDb>`Ê©“õTïË#|sõž¬GóÂÙwãk•¯>¨u³ ‘ Àúá’®”`W½?Û©Ò5ÄÛSðŸ;Ümê‚]ZÁ‡¶M¡ÊѾVÅÅõÃÆ,KCþ±ûP/i4D›ו/©« +ÅŒu%–Ъȼý65B‚bʦz_IÛ0Ý$CžsÝÓô’]WÇ·i«~ÿA Àä@€y^‹¡Ié3i,)ôÀd¾ Þ™êZÂêcvº“£ ⪃Š|¹f65žìÞËT5¥ý£ï•vHáF‹–eØN]îë\9¢ ”,Gxjg™×arÓ=¯µšÜo BéKñ€Œ°©Rœ …ymÉ[a„6Ä´^Á¤À×—Š'¯ee=u–šµfD•–`ò×±ýíÔí\Õ-– (†b~ûûV˜Ì¬=é´&ߊx ®/ã;¥bÔCVZóaPéÀx¯ ´)íX4kí²’(;è£Ò=N–Y÷/óSéXéó­ ˜¢ÊÙU(6Ege¹h^&·twf(3-ÊJ6œg茪ÕM1‹×ÎbvŽp‘º_ËôÃ¥›ÛU»áºI¥:³vœÜoi|Ñ‹¯)A¦ƒ—=Võ:£é +{NK|jª|Ù{˜”ÊÚy,:Û1*WÕe%tØÍ>7l4M n÷é;«±@Ûi•ÊB1†©a7ñÑ,qm*~\€e"vÝÒ˜ˆS·ô‰Ù;,Ö˜0u»ˆ*ÝWþSâuz™Î¯wà qŠ‡$±¤{HȈÆ.z¬ú;Г× £ÀÏ(fpÉ8õwsiˆöñÅy.->¥{óŽ¸Äò~Ÿ÷®«¾];¤ŸYXÐÁ$¸Î%ÅÄÅâGvJÀØÀò¨øøú¬ I‡Ž‡¿gÃ} eÆ"svUúЩJÓ°hŸ¢L¿0+쑴Ѿs>ÌšðèÐ. + ×Îæ@/‡NHãJx¾v± ?Ñ®[²¹lÅí˘|A¶Uwn|ìž `tèv¸| » £0CÐÁÝ7´Ytò ÐaÐe‘n™ˆ'íñ`U7Í@tçaÂìô*LáćÎ÷Uï5‡˜åì,Â^o«‹'ÃθYùJÀsg“=qí»È³ŸX9û±’ÓÎævŠÍ£òI…ÕKˆ±ŸG%ˆïß)÷,¹:³ŸêÌá¯7–¾irKðÔi°ºÐ`Wvqc÷ór¼ÀÙzúPÎøhJÄÍ#(qõÓÎÑìTù”X!p´Ë™9šµ/WÃ9p4õÈ„pë•£©oôCGC'ïdS +v&ÌÌрЌÎNû— …ö/gæhÈ~Aý̬S ^æpöŠúy¤ípÝñeFÇ!›.€q~û–­sTwƒíèÐåqÃÃBõ‰,£“÷­GP×”„Õ_!3ÚSg8’ÛÉÀdC166 :óÔê½™¬'ƒÎfŽ~€q:N“?{e&çê}%ˆ)Pp ôã£È1Î&íðöLÛ‹&bè‡N9þ*9~š€:ãgèÌîÈJ¤²Pãc×sÓïï?H²0 Åm,F’…!w²±Þ“ùèM»Ê:|°S!ší.Î.Å®gviY»?»~M•…Á¤Ø5ƒ~OêÏ®5ú™FR6ìHðð'—†0$<å…Vä‹Éù§–†7^Ne=tJ‹èÆ1¨ë3û:¡m‰ ”AROß ±à£Q2kº «,çg¡îµ¸äçU``ÜÄ ê.Ñtbò #{žRp¸®ž+ÿp:ç”èDŠaDˆU0¥ FÚ-«X +ù†Ñ“ÒÃHcˆ\³Ûû·ÎXz(Yˆ«tóS´-ììÃG´`òÅûôv6ž‰Ýcñ'c*†ídÀ¾“Žà[šVb”Óà[#2‡ñš”ãtªXU\OÖ‚Â ãáùrñóÅ<¼Œ¥ 3ã‘ÕÂê#Ê¡óΠ Åæ“CçAŠÍ'‡Î;ƒÎq{ÃÔ9tÞt¶lÁrè¼3èìÙ‚ÓçÐygÐ9³§Í¡óΠ Åæ“CçAçÈœ:‡Î;ƒNÏ}›9‡Î;ƒÎÊá-‡.é™AGõÌ¡óΠÃ|žÉô´·ƒÑk§gí£ÏX§dZ¯§KŠ_àöf+ÎHŠr±ÛȬžüÓ%ŸXrvO/€ÓiXrêÖ-Gýâ”Xáä̲±‡…tÏ– – '«+—ý;KÍi}fÞœIû®H:Öõ¥¦%2äì‡9§„e>ú¸Á<àä›2‡üÉ>¾c6„½M)T³öK ¢§'û…‚8,¾¯ÕYÜƶ¥­b1ŸQj>K  +B‹´¿MHÁ AuñLžÞ*ë±a%‘Iæ§Ñu~ÆŒ*Y 3tFÍÏBg¾ÙC°€ÍZOÚ•ˆš·M€'ËѪOÉÇèuÆöÔX“L}SLåšÅþ ž<½m_ó<ËÖÜ$„HÇaÒí&éÔˆO¬Þ +ôÄ~†,0GßÝØ[`Ïã³9[1ðòÀ|s‡Ž†x ¼Ç¤ÆÛ1ÉžZˆ<ð`RôxSdÚ¿â"iÿ¦‰"py0}÷Ï+Ï7'†ྸïA˜³()2Ø™EÎ<¢êƒCŒœ33%ÄèG!I¾ +bvÇo^q†ÖÃL¿L.6ûeÏ7Q'vªßÒ?_ŽÒ…Õ•áX™¼öu·‰Ôí}ÔA>u¹v=Œ=¢*&”n£Kv¯uð.nY¬ëXÃ3â™*ǺCÍCOqó£}0ˆYiB p0äÈâúLpxi.{þWž,xùÆíz¤ð ¶Òv=rß/+Ö¡EÒ1ùAq[ø¥Çyd Ù¹=#Š!=™M“bÉø¢nÚô±‡q|i.pZvLÉAÄ +'o÷Ž<%°û>w¹ñ’6%1˜óÊ° ä‘¡F§[iqÓÀÉî‘ÙæT×ÝâbqäcÓ±xd¶ùCç (SD©÷ÈPcàßæä‘K[ž=‚è€Á#bIC›Ù#³‹3x{d°ŒT¿ü¼<2†&Pz=9À&Ç„ÉlQ;WêÚYÄ?nœEYÎ#'qû’÷Ž`54-—ÉÈ©3:dˆœ ù§¡m&fNƒ±£^7‡±¦yßb!]˜96Sþ¨fñN¯çÊ«£¤Ø3…ýDPrý’* +õ⺥#TŒ¼°ì8IÏâÞYDAG°_ê§ïó·#ûùçÇtÿØÌùpz´##nÞùpÁ"T§Í‡sÆõ5ç’=â̇›%[=N…8§|8#Ùž7ï|8Ý£8¯37J>é–€¥¹çÃ7·x…ZN•ç²Å(Ç:З2‡”Ž•Ýšê“/Æé¸d˜®[²ÄDº¢$¦£ýËÙÓë!bŒ„dèÇ}­Eà^ØÃxžr6P‰Ÿ9“ öã{©ïñ|ééóI'Ð æ CÂQLb @†"´Y`#f¾¶ì¸!»óÆiv2¬Þ_1PŽQÉ°zUt^Aûev2¼Íå6`ÔO2¤E©Á~æ@†°·-ô®­†ìp›bOå0°3û3~·Myx¥¡¯&qEð™c3¨aÒ<2Rï?昑 +:›_FêýÇ2Rù¨3éfªŒT9z” +Äï(© Ÿ9ðMÐ v22S?,æ“oF*û5Ð.-ç ÄãÒÔ AF=¤,"4GY‹ûl#Sá,>4['H*œ¡ÁÒüƒóI…à ÆäÏ™..˜ßrÚT8»rN©p^è’v^©pšW!Ót¦T8Ó?Ævåç7ÂS%rKµHL‘Wg-RåôQ´ŽÎ¨1Ž»È°3ÊE†Áu˜–j¿dxÚÔ†ݨãÛE8À¸ºAŠ1ˆ,¯Ž #œÂÁðŽjâA÷iUãˆèl+ž¾{εÁKªòuóqó¢òÆ—K™ƒëÊB÷ YÙN6/B±ÍáS2þ®Ÿ‚–ËåÚÍ}­#,oE+š8Bî^ÌŸ|åÎ;+oã¹XŽrq W·§¶U{ +ØÖZùî––ìvCMvS&Ok¼cP<ÃŽ«q+G”As ‹ùóÄ-ÙÍ3Ãn$zeØÕ¾\R]Þo¥_h¹X G.–£Ÿ$`ƒÚSÀÔåü’UêÕ™ìK\ö)Yg Ï »hMNSåj‡§”As ±ìq剞a÷è•ì¶˜£Z?[øBÖã‹ôŽdZ†Ý¹G.áñá}Ðjõ²fóÀƒaµ Œ¿ô\¼ÉÊfƾû”vb™óngTa~ZYÛeè1¹6W-Ñ Ö|›u*¢æŽ%N±|ä²W̽oÈ­#L~eWJX'DšÜ¯ p¢§ölËœglE¿ìš°ÿ”È1W`ReŸxRÆ,?Õ?æjªJr„)ÅB¬N^ßJr¬^8tíÙ\à4´‹yÿ¸¾ Eä|½pÓ‘cYŸQ÷5V×oJ¾µ˜Îš+`M‰èU`¨Ç>%è¾ñ¬,I +wªËÓ;s6³f¦l:R.±9eÓ‘–š{6^æ›M7kæãôÇØ–DžW6I®›¾ñ¹eÓ±Ý2k6]‰‘]¨³À‰µxž¸3±–pE1x¶é-¥Ùo„•é+4<[Wc!LvQAù­»â JR½W¯j ­%œ‰ à™O‘&§%N¡¾d­Qí™r5œ&¡u5¿ +†WCÖDOÚWߦ¨Së Õ_Ù]_ Í¡Æë–â©N«Q?3åsu¬\WO»*{rºý†CÖT‹@%2øðBÝkÅ•O´üᳬx½ÆÝlGäF…;ψf2ô«p nõ 3—E'V¸›¶R^0ò¡WÊ›K>ge.yIŒîX|ã³W¸sÖ{uÖ¸Ûb©pÇz«9 Ra*í—EטâÞQØÙ#C.,¦æÝ’šX+G[,.OÓåÅ8Í!ó‘á²ß{®´~fôf!ß8èg‰µ°J “Ãóï‡~/œG“™™â,—7u~»û :±ªï¾ of&C3?óàcÔ4& +(ï”3†)éfJ³¸/7s»ÚvÌöéý–vˆyÛîìJ˜è9eæƒi†WtÆL1„SrÆ*¼•ß©–Ó«.Å°œÆ&L»µ‰É>»e(÷ˆÝwá_‘î•zSƒO¹G‚>VNû˜EÌWS®$?ˆ±ç¸–Óλù¦Öa\ñAìµgÏq…EòÜ"œõ̘éyÇ›S8xÜAdÑ/—©=®’Æ3Ò̺eEÙæcZŠÞÅvþ¶ò¥v{QùRUvv÷r¡X¹”n—Ë¥Ì! ãlŽ ÑëÛ§§{—uØ.Gý;r>ÜFäÎÊœÒ|¶Ü¿³µS•lùpÉõö - Oz]‰mD†¤AC1˜°EÏýS£µN†:(W»(QÍ-X9búî۳Ğ<­¯±AuØÖ’ª9(–šŠ!go^ë”Ü¿hœšš¦Lžxz^rcý¿Ì™†çQ]/{{ç•ù÷NL74²ÒjË ÒZÑ Kîk‡6h×+ ïìÆÆ-ixÇwuÊ …=[ñBç g®=EgâúÀß&¦¯‘ZÚ­3µËÞ7ìù•ô–‰S­.&9‚ÒinmÒwÕ~òôï¢Ê½Â&“îÛåN—†óªbF …¡zHèù?SNÉq¾&(†žmeÓtg©ÌrWñ‹kÃnjõñ$.û„ 1l²Åî*ÁB«<²ÒÈUÓd¥ùEhº±‰v̺óDÎ뻊ôXŸ7j†‚Lʯê uJöÓ˜wç§Å6%úˆe#wêÂ1X"YaìÐG5S˜S¿zßs(ÇÊ/.Þæ¥L yG»Ô{´q|Jw§9%¤L´ó{–TNš¦ôVô5˜÷ïjÕß²`ócÊ}öΈgëÞó¢TeùÿeŸ?OˆÑ‹lM1z‘Ÿ) –¥væJ¦k‡z ]¾Í¤”+Ðëj+ê9¬×€Y€¬9€:çŸÒŸÌšè¡[2d²æ2U1£À„½¢žG®(C k K– = =ÇŠ +Ž`×Àx沑i§oÞ9€fÆk“ÚÓ¬Eù¼+²Í«(_0/Ü´EùBDm€6©i‹ò*²}BQ>2›wQ¾?œKQ>¤õÁ +xŸZ”^-kžEù¨õ+g(Êç˜R#{o?Å#B.™Rƒº~ÖHUý¦ºŠP×oŠX¸)êúQ ¦Wõ›ÇÝP°®ßìѶ,uý|ã”æR×Ï»ªóÝP>uýX­®Ÿ•Žèy7ÔŒuý¼Ca6Ç<êúy+줢iêú9—k¯êGô)MQ×Ï;ž)äïÐeªëç½´Pl>uýæQÄ¿®Ÿ÷‚t)6s]?#áÎëVóÙëúyGœ‘s§L?ÂCOÌä#xͳ¶–Ùëú‘rÛ,ª›)+Í· ë T¬uý¼M]CSšµ®ŸmrU¿àõøæó>u]?ïª~³Ôãc?P¡çŒ«ëç†2RçQ×O?P¡TõÃrxgMOñ¨êg‹»˜¡®ŸçQd’¾/Áêú\ #;UΣ®ŸwU¿ùd¥Õ¼×¼€ñÍT×Ïû Ë•+:e]?ïª~3Ôã P$Ø«ßÌ·x˜UýæRÏW‰gÈæp×õcÌ{ FÛÎT×÷€])Š2S]?uý¼A ëŠÎ£®Ÿ 1¢7Ç}/KΓ»®_0¿å´uý¼& 7ON‘óô¨xWõ =èQ×Ï[1ÄøØLuý¼C×Iâ”uý( Ô«úÑNF‚Öõó>± ÅæS×Ï;˜˜];E]?*ÄP¦€ÿY[ =ï{víôuý¼…ƒ3‹sÚº~dáÐȦ‘p°ÒÈzLY“ ^—˜"×®¸X|Ë8»¡é“5ðÞž¶ètiY>,MV.ÙÈ>þŽ»¼c6 ‚ 4#ª€;»í–(Ì‹Äï“ÈjfùåXF UQu7²ò¢œeVckKâõ‘´+å’êë~f8‘—÷º…âÊöÝâ—hdœˆìÖÎ3ÑÛ¯¹µÅæõB%ö6h6–»¯£Õ\³ññ˜ë4^vÞžŽ_C±Ãn³X<¾ßû¸jò£ÃçæëY¯YÏM®ë‰øãc9™øv+};y?M®?’_vÆJ¬_Vq1v‡™·øºžøÒh_%‹É£øÖÇâ{ƒëÄEÙ^;¬<ÔÁZ"B餟\ogw¸·½ÅÕ.®k\}axÌÕOŽ_¥·½ªL^·–ÕåÔq .<¢gZn}T“›…ã;¸%”öÆU¯òŠúr°ÀeNºØ6áž^}_P~é–:®|©í6j›»›m«¤VGp¹ôqNVŸÏ6_/?”Aî8r}|˜D+ ňk<¥W–b7§‹…õ~)vÚ¬,?5÷7³Å¥£\ÒLÛt_]Í7–¾´HÖÔhm5¢ô20óˆ–Åf‹iTbiWO±¾Í· +Õ ÝßZ²–fIÛùåµ¥¡­^—>®v2ã• +à0Ål+Sª +{;àéÑÁÎóåÅñî^îé8Y”6·kÅÅóNùá`a­T(Ý&«a£Kݶê×qxÂOVR±I-¾·¿ÏW¿®m”{r†‡›3¨¶ß>Š^nÞV…ǽNŠËÈ«PÆ/ˆˆUø5˜›Ã7qû2šFÇ5o_XFÆ—‘² ô@lg~®%ÑO@ÌçàçΪ~Êzì¦ÐßââÆÆSí1qwÈ=ÝyÙYoD0ïC|¢)nðd¾XÁ_”c-óE +qÉwB1óUõ²ùl¾à°«‹û¯Æ‹ãZ)_oDeóYk\ÿšn£ÈF>^Å_Ö8ø,£‹阃 Kïü^®!ÀŸ‚ÖwëkÌìû,©5iøUøsÕd8‹Uâ{h”³´Ö¨+Ã~Î8tm<ßÞ;A?õnÛ_îxd¦p™ÛZ2sÔ|ÁÛ‹z+$rkcЋ´6 +—X,pB¿ ¤X5UL|ÝYç®q”,Sc©ÈÂt[¯:ç=f=’úC–8sÖ#ŸYP7’—ëJnë2{¼›èÄ5jJ|iFþ‚5ß »ïÆŠí^_?Yè%$&7céײ•½M¨ ^kØ-T¾ìóÚWÚ'’þWÿRÐÿšÜ}E¤.Tò£+vT“gX®ìæ(†‘½I•¬dh;»‚I÷;u´h¿2‘OOˆd祥«càÁ»fJÆœ@ËÜëQjÒhrõ,ñTn àÒ½ +ßg’Õ«›=Ê{=’Yâ㨼&ªƒ ~æW4Š—£Í,êÚ4únŠG ÖPø¤ù•¢[âàŸü†Æ2Ÿ/×îˆ.Àîu1ÿ/øÔòkRo'ëâzz5" Åô§$¤§ÃU6R_ó]“öAù«½òÓÛn*(ýR?:¨9¹D>´u¤…Êê]’ËÔw’p׎ðø1M7±Û0§e:»œi–¬°¼i*Ä®…‰žóY’†XXíY´¼žaó+[¦·ÖEu¡wêU$Ë‹ÛUÝ®DE›…xñV´d3znm×u5as¸‚+Sk\¬i~BÔ˜ëF¥Œ£ƒ››Ó]­x¯Âf/Žépè@ &´CÕûõUqiýŽøTIA6«i°èP ¯ÒÚ³õQDHZ« +Gð×ãØ‚{H“Iú ÂË™Unê+Qëf(ù¢ðÅ­=K~Ù\ÐëÊ"¶Œ«và Gôhñí»0ÑlÝyK‚žÁ÷%{ûÅR’ìE‹Â0Ú…Vuèówá+~2¢•ªÓTQ›æ‚•¢“”yÛ Uk hr‰¯hr:Ž!`᱇¨,‰¦3.¬{3v®Wd¤Ae +RØéÐ]ë¹ò¦)þ次v¡Ïû+¾ýËcÚFd6± ÎÛçV°.b‘'£‹MÁê"ÞZ<¿§ìd‚T€Éž³°w‘šr¦-ö”Xui*(Ž±,ƒ£t±)ØÚ¥ès b*ÅØ£9y­rú±qMÈ goLJbô™™¬¡4<×ï^9,;Î÷3+ؤâú©ãî¤ ™º£jde÷~7Jô1MŒ~ªJ®sËOVÉ5__ç“UrKçÿL•ÆÃ¥ü“Ur°/4zŽ*¹Åa>S%Ú8TÊ?Y%û•rÓ“7·lIÓ34%xó6®)ÁÕû]D+Z4Gz@fàç­v-ç2ãx©HÙ@fofý|À‹Ã!³ÛK <€Âè'øçv˜Ö m'ò SSi3§@}™lìgz7ã´vvÞK­%·׫¶ètó Aܾ:>4tgýøâR—ç[ù„ ãÀkò€ö·6“Ø39ºö­2âq¡ôår;Ó¹ÍÖ~†“Z‡ÛZŠñöÕ¨¤7©¯%Ö‹ ˜KAÛ¾~/uáåD׃wÿo+”/¤pA*äÙóI¿«œ(½—Þ œ +­‡2»û<9è kJ·{Ñý߸2lOÞ»ƒqx-œÙm–÷÷ R¥Ûvº 9õ“µ+ºËO÷É4Ý:¬áRª<ëo{ ç›rå™»ÝrºïâÞ&t߇b‘äÖÛF$Öå#©×oMø³¦)mšýæð kÊûP;s+ •®RšT“GëÊá~¤i©öHõ•ú­êGåKM&üîž´«l'_ïJOÇB3¸³?Û«š…†Œ»›rþ¼é=¶åI!ý~¼Ilgá2®à¬‚Y¬2‘Tbg>=ˆ$ϢǑd;} _lGVwÅN$ut³YùXP ¦ Ku“Ôv˜YëúÆ× "=Z$ÐÆý²…lG»½EB/½ï}ÌqñtF³»òc\ÿë[wE§8F/èçZcO3×à±]#«w¬Ä±aTîsVs{ò¸h ±¬8è`±¼i¼(¯b¬éÑ„EÖ @—/»Æ‹Þ|ñU7Ýê›+Ö3|äz9…¹#¾âc×÷ÓPXVÍ=’É ‚¿MÀ‹sýB=~žîX}?¢8ð¬†Dõ +`aÝÂ6hf[µQ@¾IÐè$-õàcü¼DÝ®h›“9½MIÀ¿°±€ü`€4·U‹c£ Œÿ VÉÈKk/ƒåËÚF5ûÍ$¾¸n×oÎðcRŒÐ(‚iÊV·ŽN± ‡`Ý>Ômâ pV,Ôk;ËÝ‹Ê~g3¢ÓÕí oaò…€‰žDÿqÁ\rÖ‚Œ#ZëñДÎf[—Z7ßjì'À_@äk²¤õU€IsûØ·–,¢¿ìÇ0$·±ÁLúôg«@:߀À¶5.ú€ÉatYÒÍqM$ ôeœtW%¢Ë%šÈé“BWÁ!U"§«¢×UY“w€ì¡ÜÜ‹k±«¾AuoE'v>šÑ*ÒfÊ°ã!í£dF𴜆ÇÄ7¦ûÇ(ä"Õ2ä£EÀ ,haà Ù,w7·€àâñ5ƒŽ×V4Õ7Ž«Ý[;)MÊù¼t~oå\wÝ[êù§(çÙÔs‚r^²¶.øI*:GÕ®yüÄ“T´*tœú™'©¦óöSOR Xý¿­ Nè"z¬:¸{(‹'Íîx2‚ ¤ÇR÷¥7hÈß»JˆkÿÇÿƒÿæ‹a^(„I?$ø´Ñ +ÅQÛ0Ÿ7c~Ìì*ãJ¯=î ²ò=¼Ý5.÷+áµ°Öö´]ÇÁl¸GмJ@ŸÔ#˜ácˆ ï‚ÿ¿ùüsâÒ9A”„b˜KK"üþÁ \ü!ˆ¼˜‡Oļ e‹è\6ÏÃ? +Y‘φ㧻Ç'ÇÕpV— ´Š›·§/ óü8|þgÃGá».Ü38 ¹<_ +‹à¥œ” ¿‡DžKù¼õ¨¹|:+ÃbGÿ+ä‹ÚWù|šËòaW/åÐ3ø¨˜–²9ðU^­À oŽ×á9Ð^ á,'¦‹°ã,è°¿)Hi tc=°f#䤴À$Û³VFSð̆áPyÔ +¼‚}»çƒf V[³è!ü_8Çš“X„€9Áb y)œåy0˜½&Ççòè\˜¦ã ˜˜o|•ç ¥òÙ4¾Î‚þ ð!WÔŸë)†Û`e…´˜ËŠRQÊ#È +ðkØH*Š ÐFëFJgÅ<€"z»FÌçÒ"j‡æ´ox!-D®è‘”CS¶€ŸO‹"k^ÐÖƒ‹Á¼x´|þx@…´PäÑ3>ˆP’¶EÐ-ìD( õfQû-ré<ø"Ëñ›Ê!øö—å8кˆ&ãø[<ì ~“Uˆ¼Ž©Å,\8 ÔP°‡“‚@Ä‚CÁ!¢hC8¡IÔ8¿/¢þÀÆ#R}Á¨þLä{¸¼”¾!àu 9–aÐ3ðC‚ð¹BNÈkÔ›ÎI…‚9A!ßo–ÃýáË0ÜêOº&¥Ã%ò + 9mDc=+ä:ºÏD>]¸ùö­Ð °!Û#¸p c¾—%Pæ²Ö`ÚEÀšà“BQ‚lBH£ÅÁdÁ 7Ÿ5ðg`|~ ˆ˜ã ዘY€â|!g=i‡Ä¬.ft°Vb:—åµ9ð|AÀŸÖUÈkß™ÏÕ +œ;ø# ñ<Ý°'€å‰íö Ð"W€­Ü$IDà Ù,šg¾˜/ZOàxÿ9{«<˜9zºÌòè Â_ȬÚIJRÞ|ÒÀŸiÀ¾òhq€5çЄ8È8|Ž$ë ʈ€f+Þ¬ ÀIŠ€ŒÛ¸ýY -×x–4&äôi#¸A6%ˆØ!ÍÁÝ£éÀžÐÜÀAÐ1%+äá´s`»à„,q$`ZÈ¢·pLTÁç´¾²Y¸¿è‰˜G EÛ°œ¶Oæ3°À%¬•¹R—·íS0<”Ñ*$‡_  Üúœˆ¹X@Û"B\…s$À‰¼õ¬?3…dBÛl +Ö^IYïc­çBô“Ïsö_²ù  ¹(äÂVO&q˜ãa$fUD{bµÒ) d ì)ÏóÚÌ Å‚ÆåÈ#¦£iú³þŒKgóB l[m=àdpw5‰â°­7y.¶õÎ#Y!*™¬±n×EQ^“.N>ù+QWã™ýÁXSÎÂíáûh8tÂê«<ê†ß‡.¦©5JšÂÔG¤Ö­k&v*¿t/¹×êã‹*ÿÕ ËƒÁp,»#ð&ü¢tÕñP邇Ã'à£9PDOj¡ÿIHÈ”endstream +endobj +926 0 obj << +/D [922 0 R /XYZ 85.0394 794.5015 null] +>> endobj +927 0 obj << +/D [922 0 R /XYZ 85.0394 769.5949 null] +>> endobj +924 0 obj << +/Font << /F21 930 0 R >> +/XObject << /Im1 923 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +949 0 obj << +/Length 1063 +/Filter /FlateDecode +>> +stream +xÚµV]“ª8}Ÿ_ÁãX5D’0ûÆ *[.àÚÚ»ŒâHÕŒXÂ\kþývHQwj_¶|H‡»OŸî|`Í€Ö˜…,N¸fs13móñ`ho°6À +c2Š˜I)Lî¬ê&#ˆB5šhÞ.Q7hf#Š)×t›qdQø ŸÓ‡ñŒ#nKKwšEáŒh*Ýþõè–ǯSñ¶¯G§¿kÌ@¶Á¢†!±0žaó“Nmq[Ó/p?!S ÅA®"O"†a>t a²Þ´zÓîÍIoòÎÄFobiù‡:?òZÎ’¯ªÎ?*9qËCUžêâóã©ÅnÐH§ØÆÌøIˆé'®`ŠE^ÚI‹)A̲,Í61•³oëСõKøm!0µ¡ø6ï½þ[%ÈÿY‰^G÷&éMzWÝrWŸ³ÓOók‰Ñµ~Ðå„Í&xZ“ïÛXõKô­zl‚ˆApïS¤³ÊOEUåArªK9~V¹ÊgòŽ0ÆjþQn‹ÝàKvØŽË“´·EUŸŠ×ÏZåXï ÕPÕMþ»öOÙáKÇÏÓ±¬Ôò¹¨÷ÒjqâKù©ôÜå +Dá1F„Boè`pÛU¤·ÏeÀWàí”AQ¶Šø±Y,Û|ÛÒÍêÖRî³×òWÞK!;­™ʺØä× ¯¤ÀÇ;#奖çw^«¾·í+…â|{.KuþºE=¸œÜì½€‹æPd“ÁÃÞô©#ÝSáž ‰íëúøÛx|>Ÿ…¨¨6¨lH½onmõ€¥ ‰'ê~¾þN!–Éendstream +endobj +948 0 obj << +/Type /Page +/Contents 949 0 R +/Resources 947 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 931 0 R +>> endobj +950 0 obj << +/D [948 0 R /XYZ 56.6929 794.5015 null] +>> endobj +947 0 obj << +/Font << /F22 953 0 R /F14 956 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +959 0 obj << +/Length 2886 +/Filter /FlateDecode +>> +stream +xÚí]wÛ¸†ïó+tWûB(¾ ^:Ž“u·ÉæÄÎé×ö‚GflõX¤KQ¾ €# œÍn²±tö´¥áÌÎûC†Í¨ýÍŒ"Tär–å’(ÊÔl±zAg×ö³7/˜ûŽT‚()„ý%òé\ C”áÙlOòòòÅ_s6ã’d&c³ËO£/Å ç"Ÿ]^ýãè´®Ú²j×Çÿ¼üSo“\sÝ}ŸÎæši„é¿ÉŽçŒRzt^µM}µY´Ëºê¬^œ]†`”DS&gÚä$“”u¡ 6׳áàÃVìîûshàcCÙ=ïÑŽ{— +x6$a»N9pšÛCcÓ®³ŒhÉ\HŸE.õ]y<çö°þ4ü|U/6+›Íã¹2ù±?l¾žå™Éÿß$5>Ó;²}Ž`¸+äîù?CO$ Œ"Ôy H«î*ÖŽ"î(ú©9fæ躨–ÿ-ú+j ¨Ë›åú1ZRdûÌ$)>›É¤CŒ”-µ¦I‰„‘‚:¤Øñ^ÚAß‘")v¤¾·XF×åÕp´¬¦qJ?K@&ÉðÙK&bdl©3MF$ Œ Ôy CZdæî~D:2.oJ¯úªð,¼+Vî¯ë¶\ Ç?Ûï¿zwaØÛ×fŸo6>™É C (Ÿ% +êœqNLžYç<'\_³È¾já6Vü„×›êªè†ˆâ¶3ŒØ»*䉘øL&c 1L R&‘00LPç#&,#LQ0á“~$q7“¢ºŠ/ös¡å³¤bŸ±d€!†TÁ!†ê|ÄÚ)¢â"à ¯«^lÊŸõ¬æŒ.>ãÉ8C '¨(‚S$ 'ÔyÀIåœäJ†r¥/X:œN6íMÝ,[;ã¹/wÊ•²¹/›þž”íc]²–Š4DØREL" AwΔ$Y–å3e(1JuÉP™Xžo–«¢y~y[Øâµ±9|¯†¨d +€!F¡ Fê|¤@’©L +¸£àⶸ<(nöçNñ9.|ê’¹†P„‹H¨ó‘ ¥‰V¹\ÏE[·íÍ#24Í5DÈZ2ÀCª‚  Cu>ÖR¥ÙXC(WCœ‹›eu=Y=Ãö®Øœ$Ä'1™`ˆE’Ó„DÂÀAƒ†àDj>–*”¯ëæ?E¿À~Õ£"¿“ùË×¼Ÿøì%£ 14 :‘004PçãàÁ)ZŽu†vƒGl¶ÖÑßnnÛåÝ­ûʇú¶›üæB?÷™‡OW2 ÀcÊ° caÇ9Ü9ö›Þ2ÏH&lÃDxØÊ~yþî•Ó¸\×›fá/ÿ½Y6åÊoŒG³ÎøÔ-nh€lqoEª&³φdg×ilcAÚ4i!ÜZuØâþÁ žnuÙŽ» õC–æF~Ы+ä8õꂆÈÕµ¥!ÂM$ ŒÔyà'D ™;~üæöéûð‚‚¸dÔÓòyNfb A†"a` ¡ÎCÚÞ¡…v+ßaÛûm¹ªýbÐ.F2—pžŽOn28ÀŠ‡€ uÀ‘9¸[{Ø\ã Çç]»Û:,;ŸU÷Pu5´KôßY¯7]Å÷{jâúµÚ#B²’A†P „H¨ó‚È÷ͼ_)èõ6wwuÓúf™ŸîʦhÃÒÁÐÑ/†‹ ¢Ïd2%À£*¥§)‰„Q²ã<:`vHuî–³†™@|°8­«Ÿ)å×›¦@»]Ã)Ÿ<ØT†šM§ œ KÏŽÓèEDí•CM6¤gìv-VaBü(-ÝHIõá6ü”ëÊ'7ùº†ØuÅC€‰„ƒ:«-"§D2*=9¡çèÄa3¬ØÎëêö!¾lkÓ®ó½"ä,hˆ±¥É4±0 pç#™!Âþ€ðÝE'nm«åBIñìz˜Cz’µ†˜ö0ýˆö‘00íQçþ.b‹v™{ÆD„?×…«Â^·Eµè«0ÃÕ¡èKYòùNf b,A=Í4K‘00–Pç%% cÊW$߹꾯Jäóyç7ºûøÌ&S 1j rù45‘00jPçãÝGrBYæËÊ‘ËãœÕõ­ÛôùT7áyŠáà/ÇJ-}³A{SNÝ•úžØ¢\u툜}g·ŸŸdñ!&>Ì?"~$ L|ÔyØÜþ‘å|?l +¿Z×U½n— ÷Ð̈ƒ2fûHBÎ’†PˆH¨ó–Ãi€ð-g'W«eµ\· hGPü.6¶¾Šþ>EÉúCL(¢$ LÔùx7 Šdœ‡""ÌE.–×U1\üìP†~IÜÍ)“ýD’¼ÝFHÚ9ß×1Ý’‹CiÇ{lýA¨É¥ëbÖO®îítÆ/1Y•E»iÊõd¦ÂÉ>³r2 "+‡;çí34½O‡df×k¬Pç%yΆ^†¥Ãwu»üdgööJÝ£§G¾ÕŒ0àÅH½¡!r n‰‰# õHSÆëÂæW^=TÅÊ—uﮊÖÞÍM¦ýß¹<'34Úa1‚vƒÀÂ\‡r€KM²\fž qrèg{ÿª7- ücÓ”w»æÀÍÓ¸ñéMbä@ùØôb,ŒÔ{|„$:×®ëQçÕblMñàtN†=jŠjý)´›vãŸÿõõ‡ái|gÏœIT|6“Q†*P- •H*¨÷€ŠoTn|Eä[S.în—-,>ÔB¿åpäeHf bŒA™1Æ"q`Œ¡ÞÇ{£Ä¦/÷…{ÙÙ/`Ó~ý˜¹îoe»¹ëJ$±Ïpøô%à 18 ´êuÛ?ö©¿®Ë ÏN²öÀÓfŸÓií#q`Ú£ÞÃÚ:Ëì Š*>j6[N6m½*Â^‹ƒaxÏÞ— ߧ'Y|`ˆ‰Ó‰‰õ>Š¯íä™f@{¿¯ò¶¨6~…όگße(YþÑSä7L{Ìõ8æ+J¨ï6ì´÷{*§õÝCh°ûçÇþ‹ÒM˜]YÚÖ®5¨ö[ïoûŽÁ®_ ñø>7ɪCLv˜{L÷H˜ð¨÷Qy‘‘ÜV’Ayÿ¢¨óÊÞÇWíác¶þn>µUÀÜgg¿,×mYuObfL}gšû¬$k 1ÍaÖ1Í#q`š£ÞG͹"Æ·všË ùºmŽÍQ÷Jè á·/ðÐhè¦#úù,k…l%³ 1 |ú=¤±80Pï# LŒÉ€‚)Ç0¯ Šžá5µ'‹E¹^‡gÚáÁ«¾BÐÏ»á.¨æò– Åh‡1TÁØ #s=AѾӯ#¿iá¬TÆþÃëež|Ú“†QPV ©HS¨w¿ver¢Xæk í—®~<û[׬#KW_m‰Ô+‘J°C ƒ:#ŒE‚@C]{²ŒHßh§³~wæüM·3G‡m9Iób_m@󊤒ìÒ Þ|úm¨‘ °us=¾ÓŸîÞEŒïWywqqvj':ûñÌ7ƒÊ%?•©Ñ A +‹µÁPá_ù™óœ˜ØûÆ»Õõ Î…~‰‰&Áº"15s_êb["_ø3yoÿ>ªendstream +endobj +958 0 obj << +/Type /Page +/Contents 959 0 R +/Resources 957 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 931 0 R +/Annots [ 962 0 R 963 0 R 964 0 R 965 0 R 966 0 R 967 0 R 968 0 R 969 0 R 970 0 R 971 0 R 972 0 R 973 0 R 974 0 R 975 0 R 976 0 R 977 0 R 978 0 R 979 0 R 980 0 R 981 0 R 982 0 R 983 0 R 984 0 R 985 0 R 986 0 R 987 0 R 988 0 R 989 0 R 990 0 R 991 0 R 992 0 R 993 0 R 994 0 R 995 0 R 996 0 R 997 0 R 998 0 R 999 0 R 1000 0 R 1001 0 R 1002 0 R 1003 0 R 1004 0 R 1005 0 R 1006 0 R 1007 0 R 1008 0 R 1009 0 R 1010 0 R 1011 0 R ] +>> endobj +962 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 688.709 539.579 697.4212] +/Subtype /Link +/A << /S /GoTo /D (chapter.1) >> +>> endobj +963 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 676.5858 539.579 685.5919] +/Subtype /Link +/A << /S /GoTo /D (section.1.1) >> +>> endobj +964 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 664.4876 539.579 673.4937] +/Subtype /Link +/A << /S /GoTo /D (section.1.2) >> +>> endobj +965 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 652.3894 539.579 661.3954] +/Subtype /Link +/A << /S /GoTo /D (section.1.3) >> +>> endobj +966 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 640.2911 539.579 649.1477] +/Subtype /Link +/A << /S /GoTo /D (section.1.4) >> +>> endobj +967 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 628.1929 539.579 637.0495] +/Subtype /Link +/A << /S /GoTo /D (subsection.1.4.1) >> +>> endobj +968 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 616.0946 539.579 624.9512] +/Subtype /Link +/A << /S /GoTo /D (subsection.1.4.2) >> +>> endobj +969 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 603.9964 539.579 612.853] +/Subtype /Link +/A << /S /GoTo /D (subsection.1.4.3) >> +>> endobj +970 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 591.7985 539.579 600.7547] +/Subtype /Link +/A << /S /GoTo /D (subsection.1.4.4) >> +>> endobj +971 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 579.7002 539.579 588.6565] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.1.4.4.1) >> +>> endobj +972 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 567.6019 539.579 576.5582] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.1.4.4.2) >> +>> endobj +973 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 555.5037 539.579 564.46] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.1.4.4.3) >> +>> endobj +974 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 543.5051 539.579 552.5112] +/Subtype /Link +/A << /S /GoTo /D (subsection.1.4.5) >> +>> endobj +975 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 531.4069 539.579 540.413] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.1.4.5.1) >> +>> endobj +976 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 519.3086 539.579 528.3147] +/Subtype /Link +/A << /S /GoTo /D (subsection.1.4.6) >> +>> endobj +977 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 496.5559 539.579 505.288] +/Subtype /Link +/A << /S /GoTo /D (chapter.2) >> +>> endobj +978 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 484.4775 539.579 493.4338] +/Subtype /Link +/A << /S /GoTo /D (section.2.1) >> +>> endobj +979 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 472.3792 539.579 481.3355] +/Subtype /Link +/A << /S /GoTo /D (section.2.2) >> +>> endobj +980 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 460.281 539.579 469.2373] +/Subtype /Link +/A << /S /GoTo /D (section.2.3) >> +>> endobj +981 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 448.1827 539.579 457.139] +/Subtype /Link +/A << /S /GoTo /D (section.2.4) >> +>> endobj +982 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 436.0845 539.579 445.0408] +/Subtype /Link +/A << /S /GoTo /D (section.2.5) >> +>> endobj +983 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 413.5759 539.579 422.1635] +/Subtype /Link +/A << /S /GoTo /D (chapter.3) >> +>> endobj +984 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 401.4527 539.579 410.3093] +/Subtype /Link +/A << /S /GoTo /D (section.3.1) >> +>> endobj +985 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 389.3544 539.579 398.2111] +/Subtype /Link +/A << /S /GoTo /D (subsection.3.1.1) >> +>> endobj +986 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 377.2562 539.579 386.1128] +/Subtype /Link +/A << /S /GoTo /D (subsection.3.1.2) >> +>> endobj +987 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 365.0583 539.579 374.0146] +/Subtype /Link +/A << /S /GoTo /D (section.3.2) >> +>> endobj +988 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 352.96 539.579 361.9163] +/Subtype /Link +/A << /S /GoTo /D (section.3.3) >> +>> endobj +989 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 340.8618 539.579 349.818] +/Subtype /Link +/A << /S /GoTo /D (subsection.3.3.1) >> +>> endobj +990 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 328.7635 539.579 337.7198] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.3.3.1.1) >> +>> endobj +991 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [532.6051 316.6653 539.579 325.6216] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.3.3.1.2) >> +>> endobj +992 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 304.567 539.579 313.6728] +/Subtype /Link +/A << /S /GoTo /D (subsection.3.3.2) >> +>> endobj +993 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 281.9139 539.579 290.7706] +/Subtype /Link +/A << /S /GoTo /D (chapter.4) >> +>> endobj +994 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 269.8356 539.579 278.9413] +/Subtype /Link +/A << /S /GoTo /D (section.4.1) >> +>> endobj +995 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 257.7373 539.579 266.8431] +/Subtype /Link +/A << /S /GoTo /D (section.4.2) >> +>> endobj +996 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 245.6391 539.579 254.7448] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.2.1) >> +>> endobj +997 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 233.5408 539.579 242.6465] +/Subtype /Link +/A << /S /GoTo /D (section.4.3) >> +>> endobj +998 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 221.4426 539.579 230.5483] +/Subtype /Link +/A << /S /GoTo /D (section.4.4) >> +>> endobj +999 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 209.444 539.579 218.4501] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.4.1) >> +>> endobj +1000 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 197.2461 539.579 206.3518] +/Subtype /Link +/A << /S /GoTo /D (section.4.5) >> +>> endobj +1001 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 185.1478 539.579 194.1041] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.5.1) >> +>> endobj +1002 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 173.0496 539.579 182.0058] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.4.5.1.1) >> +>> endobj +1003 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 160.9513 539.579 169.9076] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.4.5.1.2) >> +>> endobj +1004 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 148.8531 539.579 157.8094] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.5.2) >> +>> endobj +1005 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 136.7548 539.579 145.7111] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.5.3) >> +>> endobj +1006 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 124.7562 539.579 133.7623] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.5.4) >> +>> endobj +1007 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 112.658 539.579 121.6641] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.5.5) >> +>> endobj +1008 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 100.5597 539.579 109.5658] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.5.6) >> +>> endobj +1009 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 88.4615 539.579 97.4676] +/Subtype /Link +/A << /S /GoTo /D (section.4.6) >> +>> endobj +1010 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 76.3632 539.579 85.2199] +/Subtype /Link +/A << /S /GoTo /D (section.4.7) >> +>> endobj +1011 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 64.265 539.579 73.1216] +/Subtype /Link +/A << /S /GoTo /D (section.4.8) >> +>> endobj +960 0 obj << +/D [958 0 R /XYZ 85.0394 794.5015 null] +>> endobj +961 0 obj << +/D [958 0 R /XYZ 85.0394 711.9273 null] +>> endobj +957 0 obj << +/Font << /F21 930 0 R /F22 953 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1014 0 obj << +/Length 3289 +/Filter /FlateDecode +>> +stream +xÚímS#7Çßó)\uo ê¬=K/ Ëæ’ì²ÜÚ{UwI^8f\ñ1ö&äÓŸÆ3­icMƒrû8©Z{ÚÝôÿçVK£±y¯ÿóž6Ìxá{Ö+¦ ®{ãÙAÑ» Ï}{À›súpRŸõÍðà/¥íyæ0½áûžÒš ½y1Ç +çxoxñãáÉ›³áéÙppôóðûƒÓa|U왲zÉß~ü¹è]„¾?(˜ôN÷~¿Œ{/z³¥%ÓJJxdz08øW|AôìÆ4ù—ð‚ iDâOý)Õ“š÷¬öÌH!7ˆbŽñ£>Eqøm9/—£Õd~yÔº8ü¡¼½9ê;#ÙQ_‡ßåýG{±»R!ëVš6Ÿ;Ú,/{õÁ[¬Øõ±á®Z»¯_é%ÄN ~*ŠÒ;°¢,3Ea"+¢ae0¹œGPVWe}ðßÅ<ÙÂì‰!‰¬fƒ )b°jBv“ˆƒ"†ôÄHÍ´q>#bNóŸŠB\®—‘›A¹üP.«ÃåsE¥“Èc6#ÈbëD1’ˆƒb„ôny(9& "ŒjÒŠ)/΃ӓ¿×p¼¸f“q[Xnš'Fó‹úàx½ZÌÂxÕœK’²ê« SrÈJ¶äÈ’g]ènÉqP’“Þ¡,p: ‰MG( ¡´MÇûåw‡‹YýÛd~SŽ×›‡š!fµ¨âǽ•¶t ˆR0`A(qP0ÞŒ÷LYé# ÐUl½çC5¨Ö×£U#ÿ¬\]-Âûßzù<Ƙ«\°!ÁÁ–©8hïÀ³L)‡Ø+¼\O§·Mµß.òn:ÌM€ro”~’ B'µl"!EVE˜n"qPDÞ«™ +½@$B5Dœ/'Bè¯n¯ýëâ?^l~^„&Ò:»o"ï éÌFR¨`¹(TqP¨Þ#™´®D4 "gƒNÿƒ YL§‹zža ±Ÿ’¦Ilf“‚ )R°ZÂv“’ˆƒ"…ô¤hΤjgÌìÛN WÙ CŠ¬ÅA"ŠÒ;p C‡Áu;¸Ø†ƒ;É_ËÛdõÐÊ퇔˜Äl@!‰$é– ']Ä5€œ NOäù‘‡Ço_'á¨ú0ÕïÎ_Yu8< ¿;÷„zOÈP¶úÈR+@©ŸˆƒRŸôêóÍ•Õ÷Z¢¨ØØ^šØÐrÔwÚ<Ù)¤*dHa€¥®ƒD¤wÀ L4áEÕ8>¹ËÁÓÆR•2¤0ÀRP$â 0 ½7hÏw® 8]Ë•Û ™OqÁ2&,lHÀ°%C*Ú;À`ƒþÚ¶C5 çår²¸€Æ±–·ß®Lq÷Ì/„v ͆R°`Á(XqP°ÞcZµ°È4DÄkXo·4oÞ CU0~¿B³A† X$ +D ¤w¸ü©µf…óŒªÁÐw¯x|UPÜáúfÕ\Ëúøõh>º,gå|UÉaŸ$/h@ö²Ñ@†X +D¤w¨J²ÂÄ9H0nºŽW“ÏÑtrög½-oÓЋõ¥ÐûuÍ4,ÐlX! Œ‚% é`‘œ²P-,MWr¼^…J1YV>”x«MhI´Ú÷"w4f#‚ )D°LÂw#’ˆƒB„ô‡î˜÷Î#¼jÎ8iV»ÿV=TüTèâdy{½Zü: ÇÍ£7ëëëÅ2Œ2V=?p:‰¤fƒ )b°h1‰8(bHïPT +ŠSÎa:¯g7õ¿¿­'7“UY­{ºG¼ÙóË Kål‚!EVQÝ%â "½sa˜’\õT`ÉË8ªª(r¡ž|³žL/bó溜¯š…hnãvâãÓó¸ýºlž]Ì럯&óõáE¥ú2mhü#s%Ć„„[I”¼SÂT„„´÷VB'˜/¤ÅŠ¿ áàä¸>0EQl 8XLGËI(!^Š/ZÎãßš­$2¤”Ť”LÄA)Izoʹ²sñÒ7çÐ"n‹øÍwg/ê#_ÿø}²ºªªN¡îŒzý ¤,›†ÖŽ‚ "»oæHA¡@¹nßÓÚ1§ +‰`€²œØœ¿ÃD|s7•W®}wŸVmHJ¶ÜÈÒ'<¥8齕\æ +ÔþÉÅ_¼­ÕÂ9^ÌfñŠØtsžü\”}ìY!d&[udH©Ž3/U·ê‰8(ÕIïêÒ;f÷­ê¦VýízÞÞ <ÍÊ‹»³ˆÎ»8î^2~¾v‰cr%Ɔ„Ä[i&$NÅAHL{‡õbé 3º#ˆz½ø»ó¦éaA¸ÞÕ’h½àû‚rœ 2¤ÂÊî[ºRqP‘Þ¡FXÅ wqd°|||qQ¿×ošÍ²¯‹_××Í/¨Û8ÿÁõMtw3ö1_´ŽyÉÖRšã¼Sš'â 4'½ƒæF0íŒo5šÇ‘aŒ )8›üòË´9çåbÆŽêØõ2C*²eF†”Ì8Ք̉8(™w¼sì½ùP©ÂùÎÔÛ1«»­Š‹!4q;‹¯&—W«ßËêß;û:³BË2HĽ󺛬uï*Ç/GekÇkr$Ž ­j©ôæ~÷ê3b¾ºÓÓ<ýËr´¼ Ãé#¹ðú±ßI¾ìw2¤ÞIXŠ‰D¤÷È7L)6DÃÆV=JQñbTΪ铷z5”„df“‚ )R°X)‰8(Rv¼§j®ð’y!êÍh¦©¹;¥¶]Ë s,˜^¿-ß—Ër>.;3_ü¡õõv+hÙ½¿‘©]¯©÷”pœ9Ïk™L¬·ÉÔ¼œ@oq:Ý좬îîãö¹ÎW:ù€”æ¾³°!ñÎÚ’Œâ$Å é½iZ…ñÌi¯—ø4;MëëÑj|ƒòM…Š±b?§½ƒ +¤3dH¡‚åRÝZRqP¨Þãe4¡-sº– .²Z¹¯Fõ¥×ûõð‡€©ÌR `©(PqP Þ[P”fÖŽ@ (/ÊjšOÚQ(.y¿»]–_ÉËÏqi$f)›dH1€UPÝnRqP Þa\‘’Y£ÚqEÄ»ˆgõýU íì¾j¨@:³QA†*X. +•D*¤÷¶\άí¸"öãÊ_R™ +2¤@ÁRQ $â @!½· žÙ‚sÊ~\Ùe²”Í2¤À*¨îm©8(Hï0¿åÞ2c¼j›ß~»Íf£jõÈÊýôv—˜Ñ\\°!Ë–b.©8\hïMÂØ4;ŠÌf\ îï,ØÈ0Ov… +ª³FãisÎV ÒLðPŸês«ÑªlÛ˜H—ûFjsžÍ2¤xšªî?©8(žHïÀ“•ÌqbS ?Ÿ€§ûÇ2çùÓ«CÛln!Å ÖŽâ&Å é¸1œéЀDnä½ÜŒóÕ²Ú›º ô¬àRÜSŒ´{šŸ£ÐÉä8›dHñƒ5¤øIÄAñCz~”gZ‰vSŸŒŸ4ÒZ<\:9\fs‚ )N°Vª{ãZ*ŠÒ;p"-Ó¼žô½˜Læãéú¢LQb˜õü¾–Çqñ¼ºå&ÃÙð´v;H? +Ý (r(׎ÐLÙvZÅ̧"çþúò¹¯êä-1•Ùˆ CŠ,•êÞü”Šƒ¢„ô˜pÉ”Bó){/&ÕÇÈ&úß0y'ï).RºýÚoÌy6OÈâ kJñ”ˆƒâ‰ô<œ)n"NîSàtÅÑÅœN5©Í¦¦µ£ AÂQÌìA!C¹nˆqžI§d$ÆßKÌtqyYm'KŒS–Iãõ}‹:_ûg}äñ 2œ ²#ÀÁúà$‚ À!]ÃW/±µhK />9èp¾Ì&«5Ó†Tf'SkG}%Ju™F"ê ™(×ñú’ÑL +Ž¨¶+ïÒbŠ0VÐ环Fóy™Zì“Ž)­MsÞùÕrt 0R<«>¦Inþ7*€ù} +Q8™Ývˆ‰_4Ûž%?Æ·ú—sæµÿÿ÷Ú¶_¿« ÎulÖ®`ÚhÝ“¡G—uñœLº·àÖg¡ÐÿÞÄ endstream +endobj +1013 0 obj << +/Type /Page +/Contents 1014 0 R +/Resources 1012 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 931 0 R +/Annots [ 1019 0 R 1020 0 R 1021 0 R 1022 0 R 1023 0 R 1024 0 R 1025 0 R 1026 0 R 1027 0 R 1028 0 R 1029 0 R 1030 0 R 1031 0 R 1032 0 R 1033 0 R 1034 0 R 1035 0 R 1036 0 R 1037 0 R 1038 0 R 1039 0 R 1040 0 R 1041 0 R 1042 0 R 1043 0 R 1044 0 R 1045 0 R 1046 0 R 1047 0 R 1048 0 R 1049 0 R 1050 0 R 1051 0 R 1052 0 R 1053 0 R 1054 0 R 1055 0 R 1056 0 R 1057 0 R 1058 0 R 1059 0 R 1060 0 R 1061 0 R 1062 0 R 1063 0 R 1064 0 R 1065 0 R 1066 0 R 1067 0 R 1068 0 R 1069 0 R 1070 0 R 1071 0 R 1072 0 R 1073 0 R 1074 0 R 1075 0 R ] +>> endobj +1019 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 758.5763 511.2325 767.4329] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.8.1) >> +>> endobj +1020 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 746.445 511.2325 755.4012] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.8.2) >> +>> endobj +1021 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 734.4133 511.2325 743.3696] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.8.3) >> +>> endobj +1022 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 722.3816 511.2325 731.3379] +/Subtype /Link +/A << /S /GoTo /D (section.4.9) >> +>> endobj +1023 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 710.3499 511.2325 719.3062] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.9.1) >> +>> endobj +1024 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 698.3182 511.2325 707.2745] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.9.2) >> +>> endobj +1025 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 686.2866 511.2325 695.2428] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.9.3) >> +>> endobj +1026 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 674.2549 511.2325 683.2112] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.9.4) >> +>> endobj +1027 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 662.3229 511.2325 671.1795] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.9.5) >> +>> endobj +1028 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 650.2912 511.2325 659.1478] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.9.6) >> +>> endobj +1029 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 638.2595 511.2325 647.1161] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.9.7) >> +>> endobj +1030 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 626.2278 511.2325 635.0845] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.9.8) >> +>> endobj +1031 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 614.0965 511.2325 623.0528] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.9.9) >> +>> endobj +1032 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 602.0648 511.2325 611.0211] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.9.10) >> +>> endobj +1033 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 590.0331 511.2325 598.9894] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.9.11) >> +>> endobj +1034 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 578.0015 511.2325 586.9578] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.9.12) >> +>> endobj +1035 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 565.9698 511.2325 574.9261] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.9.13) >> +>> endobj +1036 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 553.9381 511.2325 562.8944] +/Subtype /Link +/A << /S /GoTo /D (section.4.10) >> +>> endobj +1037 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 541.9064 511.2325 550.8627] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.10.1) >> +>> endobj +1038 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 529.8748 511.2325 538.831] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.10.2) >> +>> endobj +1039 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 517.8431 511.2325 526.7994] +/Subtype /Link +/A << /S /GoTo /D (section.4.11) >> +>> endobj +1040 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 505.8114 511.2325 514.7677] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.11.1) >> +>> endobj +1041 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 493.7797 511.2325 502.8855] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.4.11.1.1) >> +>> endobj +1042 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 481.7481 511.2325 490.8538] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.4.11.1.2) >> +>> endobj +1043 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 469.7164 511.2325 478.6727] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.11.2) >> +>> endobj +1044 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 457.6847 511.2325 466.641] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.4.11.2.1) >> +>> endobj +1045 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 445.653 511.2325 454.6093] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.4.11.2.2) >> +>> endobj +1046 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 433.6213 511.2325 442.5776] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.11.3) >> +>> endobj +1047 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 421.5897 511.2325 430.5459] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.11.4) >> +>> endobj +1048 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 409.558 511.2325 418.6637] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.11.5) >> +>> endobj +1049 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 397.5263 511.2325 406.6321] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.11.6) >> +>> endobj +1050 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 385.4946 511.2325 394.4509] +/Subtype /Link +/A << /S /GoTo /D (section.4.12) >> +>> endobj +1051 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 373.4629 511.2325 382.4192] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.12.1) >> +>> endobj +1052 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 361.4313 511.2325 370.3876] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.12.2) >> +>> endobj +1053 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 339.111 511.2325 347.8432] +/Subtype /Link +/A << /S /GoTo /D (chapter.5) >> +>> endobj +1054 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 327.0992 511.2325 336.0555] +/Subtype /Link +/A << /S /GoTo /D (section.5.1) >> +>> endobj +1055 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 315.0676 511.2325 324.0238] +/Subtype /Link +/A << /S /GoTo /D (section.5.2) >> +>> endobj +1056 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 292.7473 511.2325 301.4795] +/Subtype /Link +/A << /S /GoTo /D (chapter.6) >> +>> endobj +1057 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 280.7355 511.2325 289.6918] +/Subtype /Link +/A << /S /GoTo /D (section.6.1) >> +>> endobj +1058 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 268.7038 511.2325 277.8096] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.1.1) >> +>> endobj +1059 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 256.6722 511.2325 265.7779] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.1.1.1) >> +>> endobj +1060 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 244.7402 511.2325 253.7462] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.1.1.2) >> +>> endobj +1061 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 232.7085 511.2325 241.7146] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.1.2) >> +>> endobj +1062 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 220.6768 511.2325 229.6829] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.1.2.1) >> +>> endobj +1063 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 208.6451 511.2325 217.6512] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.1.2.2) >> +>> endobj +1064 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 196.6134 511.2325 205.6195] +/Subtype /Link +/A << /S /GoTo /D (section.6.2) >> +>> endobj +1065 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 184.4821 511.2325 193.5878] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.1) >> +>> endobj +1066 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 172.4504 511.2325 181.5562] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.2) >> +>> endobj +1067 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 160.4187 511.2325 169.5245] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.3) >> +>> endobj +1068 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 148.4867 511.2325 157.4928] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.4) >> +>> endobj +1069 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 136.4551 511.2325 145.4611] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.5) >> +>> endobj +1070 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 124.3237 511.2325 133.4295] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.6) >> +>> endobj +1071 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 112.292 511.2325 121.3978] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.7) >> +>> endobj +1072 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 100.2604 511.2325 109.3661] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.8) >> +>> endobj +1073 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 88.2287 511.2325 97.3344] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.9) >> +>> endobj +1074 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 76.197 511.2325 85.3027] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.10) >> +>> endobj +1075 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [499.2773 64.1653 511.2325 73.2711] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.10.1) >> +>> endobj +1015 0 obj << +/D [1013 0 R /XYZ 56.6929 794.5015 null] +>> endobj +1012 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1078 0 obj << +/Length 3422 +/Filter /FlateDecode +>> +stream +xÚíYSIÇßùz˜xPmÝÇ>­m°ƒ íÁ8vcŽ…hƒb„ÄHÂÇ~ú­VwUeCuŠÚlˆ‰ËX©LåÿGYG³õÿ±U„ +'ÆI¢(Sƒñåœû{µÇÚ÷ Û†ð]ÏO÷þñR˜#Ns=8ý>Ëj-œžýºÿâí›Ó£7§ï~?ýqïè4~(t̨¨?ñϽ_§ƒ3ïÿÇ=J„³jðÙÿ…æ\îI%ˆ’B„ŸL÷Þïý?üëÚ4÷E”°DYn2ß„sðM˜’ÄãF9¢믢 ÷¡~àB÷O/ªú;yK,5%”IãÝÕãѪ:Ÿ/¾¶o„.$%Ú†÷½»XŒ–ÕÁPR»O†ŠÒú‡tîÿ±»¡½â–hNYJï-±çƒæÅ ”/Ø ¡ámùn~dioÅpÈÅÁƒzOðHC´fÂ#îÏŸ×Õâë°Z,æ‹e e‰“V´o~HóñGKM/'!“ÅœCŒ¨”¢ýœdâÀ8A½3ΉuÆ7Bí¨Jœ° ‚k©lõž~^T9*¸!ÂÖ¾ëýÊcqYÍVCî©{µ]^Žõ_ôÃngþZs³‰¦ïbš€!FÔS±~š2q`4¡ÞM\ÃœN4ñû¡é°úR>›¬&óYó“Ñì¬yña9:¯»3涨¯ +y-¦bÔ@Ýï§&F ê=QÃ1ÒH"5b#5—£åªÊöMÂs#½O¼2½ú» +9.&bA 1‚2q`¡Þ#AÚ¹fØ ’÷EÐæ–Ç}Ÿ–§˜>Rb.KI†)­Rrq ¤àÞ)ÖKAS£6‚2¿ªµÎ‚¢ýg1³¡©±ŒíTSR\ÌO²Ãðbô܃sØ1ŠX¡Y‚Gßû.‚Ùý³Éì¼®Áñ˜—±²WÌ0ÄØ訃4™806Pï‰ áÈ…„l´eºÃëÑt¸\Æ4mÅûjñ©¯ý¬x'‰ªb€!BG +ÝB& Ô{â×Ù€ðl<®–Ë‚óÙjÝ^̧u§±CÍD/!qÅXC ‹Ž0™80,Pï ¦ˆ³Ì@,TƒÅñÌO_?Ž<CMÙ£è7¾C÷XŒ0ÄðèdúñÈÄázOxPI(£â¡<~®WpšFãÙÙÙºÍX·"˜§F#æ­˜ +`ˆQÑÑ¥í/Fê=R¡¯×·¤Â4Tü2ŸU §Žî/F³åÇõ Bö„EL\)ÐÁ¢#ŒéŸ‡äâ@°À½',,%Tw¨° ß5P¼›/ÚÄëÉrUc!ŸZ‹˜¸b*’Åô´2A`H`®Úê,,h× ñöªZŒVëIézòñu¹ª.›×'Õr~½îPÆU€årRÓb¥z\«±1ÅÒCL[˜`LÜL˜º¨÷$¯Ò„qÓ­BQ?ˆ³ÉM‚¦·äW¼—€£b€!FÔÀˆ~2q` ÞR¦t§ôÄXCÀ»j1™ŸMÆq8À÷G˶ְž[|MëßiᶽyI*Fb@02q` Þ«n•ê À֢ϯæÓù¹Ÿ*až&‘yBB‹ †!P##û ÉÄ‚zO„pJ8“Ò-!wØ+¸ôƒÆ©.æÖ¸ü|ÅÿàÖ—°j»àê%'䶘`ˆ‘µ3ýÕë\9¨÷Dµ„KÑ©N1Ùsr²¬Ú¹ÄÛf…Ã÷7ÍpÒ>M)b抹†PÓ_µÌÅqz\Hça0¼S–b*ö9tÿzÖ  Åcêq¾[ÿóYJ 4Dhéè…Ð’‹¡÷žh±’Ê:… ¦Zž_O¦«á¤]._‚IËdöq¾¸¥ ÿÏêR¸ÿÄG¹18f¡Xc`ˆi ³lúK’¹80QïIcÉB39‰.¯VmÙú—FPýJPߢO9* ÙaúŒë—ÿv˜ú˜ë$¾/ +M»uÛ¨ÿììl½Éi4 «Üãô+ýb4¾XwNëí)9Ät 1¥aºm•9¦5ê=‰--ÖuK®»^½Ž[Ü^ú_ûvH(„Øá±`ÌX1Àã*bû„äâÀx@½'„&’ÙÎÞ!OªåÕ|¶¬ÂâÃt2móê7ªèÉ»_ü,T+?/&MeZ2ùà»õðõ‹Å†˜¸0½¶¿Âœ‹õwÄJ.‰”—ÌƱí .S, ž ½ñà7Û<=èå(dº˜#`ˆq•´ýEÊ\G¨÷ÄãD JPöž8Ú¼±Úºm(<ÅŒó 1^ b¶¿d™‹ãõžx¡”(ª@áÉmæŃ0Y®&ãåp|1šÍªinW¾UD*ë64B’›-8Ù³XÌ0Ä*Ùþâd.ŒÔ{dDXo d*Bqú-ÙÜÀ(÷‘èc!f«”hˆ°ÐQa!Âî=±`4Q:AùæCî«ÅõrU ÿ¨¾öÝ€Àí¦ÁŠ•[; )-æ%Ùa¸Á0ZnÁ‚¹N¬hI”µ*Îï–Í Wâq >b +‹á†P"Û_¯ÎÅñzO€(îÃà©œÅïr\}æ¥ìDû©´bCk¢¥Ü¾f$$³`ˆ¡ÅÂPÉÄ¡‚zO¨Ô7-)–Ša\Þ+*w˜ÝPóà[´b$€!†C"†ê=!Q‡Q«‘Ø|ýÓ¤úœ»!Eú/äçÖx«¡„Ø…Ô^˜Bº‹a†LPNÛþ#ê=ÁTïì§.Õ߸¾˜6·+Úéí¹¤)¦µ`ˆAeàÉÄAƒzOÐPIŒ×íðÍEÛzq= 5nÓÊÚ^Þ‰é.† b0A9mÿÂ~. &Ô{„‰;NŒ6 Êbï¦Í-Ql{º­˜ÖRh !MG6׿&˜‹÷×¹¥Ä8pɇŲÔ¾^UëSHbWw†õRX 0Äa€dâÀA½'@ü,Ç‚Ãð>ªöÆŒÓÑúë#¹(ãl ù,†%Ùa¬µ\ÿÒa&ŒÌuEib•bq³%‰·ìþÔ€DÑB抙†PŒŠL¨÷Ä…”~Ä!9䢽NãðëltŽ=}¸:óà °ÿdR÷7R©­•=$¦Xv`ˆÉïú§6¹80ÙQïο´B ¸àÄ1Êm¾!`´Ó¼œLë8å}çñ ¯A†bÆ€!Æ”ÙõïeÍÅ1†zO3N‰“<Ô\D=reœv¬5kó}§kOªñ¼9³¼1•ù÷EÕÎnVó0¹ Ãá‹úüµ1âálcFŠõ†˜Þ0ã˜Þ™80½Qï©+¡–8ÃtÒ{­¸Ø,­l'G!aÅ8C (†C& Ô{Ä9C(7ÈÖ8ð‡õqÚêËê:lf¯¾\…‹wbÙ"6 'ëiŒÞºN@]—bžîJAk7„†9 +n~~­£ý;_s àîc/ÀêgÈpg#¼í'ËñuFïŸþ“i!$ÝÉg! C‹†"P#‘L "¨û„ˆ„ÖûÄ"¢Eä}µJ7«œž¾^ƒ ŸF˜å…  1€ ‚ŒöObs`¡î@šÕϲŠüÈ–ŸãY}h;âøitua +§èŽß}òoæVìðd$hØ&±‘d‡$B¹Ææ;á!a,^ï#ê‹!×|¼]]„S²7§¾ë¥”I3(¯&ŸêÉŠl—;¡Åb@€!FT‰Ñþò¹@0FP÷i¸* a2Þä!‰³—»Üíñ¯Ì:%xxC}ú²ªfuÙæŸ~DÌèþ*‹3ÚƒªÂ6É^½9:yV×ýNsÍ“öó<*d<ýŠ?} „L•rì  ™(Pß邆pÇRáÅ´ ܼl$©ÿr}—P}ÛŒÑOsæ¿R2€BT‡Ñþý÷™(°'b¾Ã±ö6‹Èvy¸n\{ûL<ÿyPß÷´üAjó]ÊQ2C0Z2Š> endobj +1080 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 758.4766 539.579 767.5824] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.10.2) >> +>> endobj +1081 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 746.5057 539.579 755.462] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.10.3) >> +>> endobj +1082 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 734.5349 539.579 743.6406] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.11) >> +>> endobj +1083 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 722.564 539.579 731.5203] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.12) >> +>> endobj +1084 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 710.5931 539.579 719.5494] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.13) >> +>> endobj +1085 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 698.6222 539.579 707.5785] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.14) >> +>> endobj +1086 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 686.6513 539.579 695.6076] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.15) >> +>> endobj +1087 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 674.6804 539.579 683.6367] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.16) >> +>> endobj +1088 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 662.7096 539.579 671.6658] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.16.1) >> +>> endobj +1089 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 650.7387 539.579 659.695] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.16.2) >> +>> endobj +1090 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 638.7678 539.579 647.7241] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.16.3) >> +>> endobj +1091 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 626.7969 539.579 635.7532] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.16.4) >> +>> endobj +1092 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 614.826 539.579 623.7823] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.16.5) >> +>> endobj +1093 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 602.8551 539.579 611.8114] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.16.6) >> +>> endobj +1094 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 590.8843 539.579 599.8405] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.16.7) >> +>> endobj +1095 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 579.013 539.579 587.8696] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.16.8) >> +>> endobj +1096 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 567.0421 539.579 575.8988] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.16.9) >> +>> endobj +1097 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 554.9716 539.579 563.9279] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.16.10) >> +>> endobj +1098 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 543.0007 539.579 551.957] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.16.11) >> +>> endobj +1099 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 531.1295 539.579 540.1356] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.16.12) >> +>> endobj +1100 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 519.0589 539.579 528.0152] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.16.13) >> +>> endobj +1101 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 507.0881 539.579 516.0443] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.16.14) >> +>> endobj +1102 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 495.1172 539.579 504.0735] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.16.15) >> +>> endobj +1103 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 483.1463 539.579 492.1026] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.16.16) >> +>> endobj +1104 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 471.1754 539.579 480.1317] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.16.17) >> +>> endobj +1105 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 459.2045 539.579 468.1608] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.16.18) >> +>> endobj +1106 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 447.2336 539.579 456.3394] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.16.19) >> +>> endobj +1107 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 435.2628 539.579 444.219] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.16.20) >> +>> endobj +1108 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 423.2919 539.579 432.2481] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.17) >> +>> endobj +1109 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 411.321 539.579 420.4267] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.18) >> +>> endobj +1110 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 399.3501 539.579 408.3064] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.19) >> +>> endobj +1111 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 387.3792 539.579 396.3355] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.20) >> +>> endobj +1112 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 375.4083 539.579 384.3646] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.21) >> +>> endobj +1113 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 363.4374 539.579 372.3937] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.22) >> +>> endobj +1114 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 351.4666 539.579 360.4228] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.23) >> +>> endobj +1115 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 339.4957 539.579 348.452] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.24) >> +>> endobj +1116 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 327.5248 539.579 336.4811] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.25) >> +>> endobj +1117 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 315.5539 539.579 324.5102] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.26) >> +>> endobj +1118 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 303.583 539.579 312.5393] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.27) >> +>> endobj +1119 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 291.6121 539.579 300.7179] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2.28) >> +>> endobj +1120 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 279.6413 539.579 288.747] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.28.1) >> +>> endobj +1121 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 267.6704 539.579 276.6267] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.28.2) >> +>> endobj +1122 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 255.6995 539.579 264.6558] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.28.3) >> +>> endobj +1123 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 243.7286 539.579 252.6849] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.2.28.4) >> +>> endobj +1124 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 231.7577 539.579 240.714] +/Subtype /Link +/A << /S /GoTo /D (section.6.3) >> +>> endobj +1125 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 219.7868 539.579 228.7431] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.3.1) >> +>> endobj +1126 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [527.6238 207.8159 539.579 216.7722] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.3.1.1) >> +>> endobj +1127 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [522.6425 195.845 539.579 204.9508] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.3.1.2) >> +>> endobj +1128 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [522.6425 183.8742 539.579 192.9799] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.3.2) >> +>> endobj +1129 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [522.6425 171.9033 539.579 181.009] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.3.3) >> +>> endobj +1130 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [522.6425 159.9324 539.579 169.0381] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.3.4) >> +>> endobj +1131 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [522.6425 147.9615 539.579 157.0673] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.3.5) >> +>> endobj +1132 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [522.6425 135.9906 539.579 145.0964] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.3.5.1) >> +>> endobj +1133 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [522.6425 124.0197 539.579 133.1255] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.3.5.2) >> +>> endobj +1134 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [522.6425 112.0489 539.579 121.1546] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.3.5.3) >> +>> endobj +1135 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [522.6425 100.078 539.579 109.1837] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.3.5.4) >> +>> endobj +1136 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [522.6425 88.1071 539.579 97.2128] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.3.6) >> +>> endobj +1137 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [522.6425 76.1362 539.579 85.242] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.3.7) >> +>> endobj +1138 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [522.6425 64.1653 539.579 73.2711] +/Subtype /Link +/A << /S /GoTo /D (section.6.4) >> +>> endobj +1079 0 obj << +/D [1077 0 R /XYZ 85.0394 794.5015 null] +>> endobj +1076 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1141 0 obj << +/Length 3413 +/Filter /FlateDecode >> stream -xøëÓ˜§¸„®Éžu Œ¶-)ª%ÄÛ_“šÚÍ¥Ú4³XØ+-ëmT†Ÿ`°]üÍå¢ìJE½X¾ó˜&ÉI›fßúà“‘´OÅÎFæ(­í!LÎÖvœ §*‹bu‚ÛØŽpdЖ˜Ã:2OÍö fÜæËYÌS¤šõ¢{;‹ýîY(Wp@0R«wlâ­j£jJõ¶8ý)åY½½ôhC`w-qŠãÔXÞ@tôõ}âwÞ˜Æ9â<î°6èI[„ú5%ñΗ+sW¼ZÇIïµÝ„o²Øº[§±œ£Òs5­7s,ÚóÓÝðª4ûx¢Þ"%áú¼¸5²NÞ¢!å'(2©Ž.vŸMà²æÚù&lûªMåئ{mË9ÆÜ5ÈäácŽÁ'½s×0E—šê „ȑהæZ¹F—ã–b ÎÐÝNhyç!¾2:óM(É*';“=çå4–&Ø.½@q†I±:ûU…¢Â°#+!j¢8Ô óœ óÜÓ4IÖ¹”´²òø®a©Í¦€:ãòºäpÇ{ÖF&B¬†ÿ^Nd«yˆäù0{+†ÀÖB¸&æ‹&ÏC±Y -¸/ßCEV”‡0 ³ -/:¥ð£Ùv«¢Àç2^’=š‚Ý¢÷6„× ø~c"[]`%†/qÆJ´G$% ƒæIÙÎw -jž¤Ždˆœ0ü*¥Ï&ÀFèÿ!R¹9€A&\3u ÌÇæ<–žwl]á@9M~·ž 4R"2vö»Â’­cc,+Ú‰S#4…ržÐN(ï#Â}!Pä8£ZãxFQ¨–ìÎõúH ¬ObžÊIÏÕ†ÒG{ ÜêWí÷ Rr.älk&ïa|¬W™IypR2@ Ž÷E¼nÇÇ.‘´iàn™#Ò ˆXŸ¥`Ü*†2ŒÛ4ÜþÐ9ÄÔùðT¡cç™gpɵ„Û® Ž §Â`ôP]Ý¡º |·ß-^u2Âî*Îk -ÁíâC\.>ºA ÿóR'$P"vBÐÜYc¨šz*R*+mNæûÒºt}˺‚7ç±™¦¶$ °b#‰âJ2d™¦ƒVœ–‘wÈP¯k¬'õw°B4BÌIöƒ#ú)Æöµ-À+!¨mX!Á ˆkY‚ì›kÀ-rj/tàþ†FÆz½&hÞF€Þ`^űD-_æ9 Û1r0‚,&7FX›Æ6ÂW`BÍ .ÄxÃŽçnD\²;=F0Ä¡Ô'°aî¡)ò*ØïóºÛ°É^–©R†´2®Íbs2Hü¡1Ñ­Æ,{3cû¸OA†% ›áëU‡ðÒbÅ…³Ç°&¸j³ -mu‚QÌî"Öb®Dkó˜×íÀ–©g;&éõºiq3ŠYK„|F›¨»síïp¸Å®›žu 6 Ùjóµ£Yä¥*ú Ÿ{sÓ$'ðß=™‘‚‹˜1…µX;à4ç£Ò¸"Rq”Ž¸ _jÔW’M¼æL/iPк3™q óô0õÿµzÏ»êʽc'/?vÍÕ †^pôú›HÈKj¥Z†Wo‡4DúZoPôJVÔÐýj%f‘ÎIRópíÑ fÐ{#ÆÕV²¨³!œ¥Q$Ì=)Úà°`æ[õ kÎ1'Qn·Fæ¹Î"Ðê'Ná%6|¤™™–8Æ¥‚îµ%©Y¯"¤#÷à 7sÃH]…3Ø¢i\ÇYêJPås9ÂIÏSÀÏ«§&ä7,†Ú$ÖABÆÊuM@Ïæ®ÊÎö ðkeô!iId¬¶Ûè–w`ÔA2@¡$2%ÁIü9TDgYÿ}Õ' À Ü—¤(VrUº{õÛ"AÀ­ðó¢ä;W^Ro®ëÝÊÆ\¼ÃÞÄ );Ê ãºÜ‚–ÒÑËÍAÅg‘B“–*R0¦¢jƒ_n¶iU‚¾Uñc¤¨%PR¾Êo†8ƪü}Sc’•{XõDWÆHÑÆnJ뚎§RbGX>-:…´‚’BŽ V¢±`E”åû®ŠŠ–ìON• -¡Oä+ãZ–Þ«oâ „²ybÏ‹[*!‹Ñ%¯Å9«…(Œ›–7°úækôS•i‘’ràù)-[t¦CÈßÃUmÒ«‡z-nVï!š"eUƒU|”Èî!%cJ<d€]Twù­—$Ð!Áî$A8ÕÓ&ê;b.û4èïSh"d!E 0X°‘ÅI‡#lBÝ\‘Q#ÓðgÊ^+QÓ`S#ïor}k›«8(sG%!_XeŸU'E®¯Ä®MªªL£&Të±gHB¥ÌÙ®ryCQ S´h¼vôø9GO^uÅ£ØH=rÆYgêðãW^µ']jž®lØË®|ȱKÎ8«_²ºóO^wüØ%㲓KÆç…—­=ÄðeW?vwü ÛØ?|ôê•¥¾jZ]j5—3Åè¿×±k¯Ø=¶zB׼܋I÷‚pPöÙÏæ£.¼®õçž|Ö 7<û‘¼óWþZi÷‰/ü…—<몳o÷¿ÔíwN>ç^qÃSŽÕ¯ø¥N9íAá+^öüGßK£?ìé/yù‹Ÿò°#_ùGx»s®yîK_úÜkÏýî¯ø¥N9õÂÇ<ÿç_øÄÝå+©ÕëzÜϼè¹×Þûf¸Ô)§?ø±Ï{Á3N|ÿWô"j8ºø'¯Þ“¯øÊ.ø¯þjþ¯;?ðš§>ë§/K_Ñk}í×òÝö̇?î)9¿¢×úµeÒƒù¸G]ò%®õÿ•zà_Ïÿ}êyäÕÎ_Ék}ãínÿ­ü?nsÏí¸äŒ[ïû˯þ²Mâ[ßñ{ÕH;õìK/¿ô¾ß³ï/¿æ˵ˆ¿õNþn:•[¶ó/yð9‡öýéWý—y±;¤»ûÛêÿ¾ý=pñù÷øïûþöë¾ñ˺حÃg$ÛØï|æ“ö5پ替óûÖþÈY÷ -¶nÕÎûÑ‹ÎÜ÷ý†oùºÿú¥Â½Ï9猻}›5ÜéÌ‹/½èÈöûý×~Û·ÿWgv›xæyçÿPŸ†¾õ÷_pÙC/>|p¿¿ø–[ßê›ÿk—J÷=ÿ‚óŽúö©í.ç{Ä•—Þw¿óòëou‡;Üú[þ+—:ëž¿X -·9ük{ÝÃιÓ>ôÍw¸ëÝîôŸvšV—zàE¼o\Û'ÜÅzÚ³ž|õ÷[ ·=ýîßÚ­þ+—:+Ýf­ý;ϽæÙ/ùùçÿÔŧoÿ»o;ýðÙ÷Îÿ)óçVñ¾Øv©SNùÁG<ïW^ÿÚ—=íŠ{niw¾Ïݯÿ'.v wŸ}.uJ¸üù¯{×»ßñÚ\{Á]·ýéϺäòËзüå>ÿ|ÏáûÓ¥n»¥ë».}Þ›ÞûñoyÙOÿȶòÝg;yÍ÷¿Éëmï~¿‹.8;o¿·û]ÿýÙ?|ì#þÎ_|Ìý·x}·¹÷Ãó„G»×MœØ-ÓÎEžS¶ÍjõÏÙÏ|Ûÿí³ŸþØ_¼ý†Gô-ý?xüI×?õšÜD‡ðÔûþèƒøûíçg=ëó™oüì?¾ï5O~Àwlö¹êY?÷¼Ç]rÓŒ ÛÞó¢ÝKwöÝaϾþ]ùü7Þø‰¼åyG7_Ëw>ð§^ð 7<õagÜâ¦\ë´\±wé½öy‚§œòCÏùÿð…Õµ>õ׿õ‚ÝÍ“Óí>õ¥¯ü…gî¾)׺ý}/ä5GÛ¾ýç<ÿwÿé‹|­·?÷âƒÝýÄséU/æû0ýüè'=öK8tçýÜ{>¾ºÔÿþ7=å¾›Ý÷¾î†WýÚËž¶{S ÉÛï\ýŒç?ýÄÝ÷ýÁE/{ÿ¿ÑµþùþÏë6õ½zê+^óêŸÂÅ7å;ôà'¾øå?÷¨Ãûõßåäk>ð©Õ¥>÷÷ï~Ñî÷ntßã'~öU¯{Õ ¹³e…nü“þÜ_}ý+Ÿzî~ý‡Ÿò¶¿ý=¿|ã6¤Sôä—¿öu¿øÌË÷}³Åz÷“/yÓ;~ó¥W†}~ûÀ~ÿc«¥ñù¾ç®Øø.ÞïºþÚ^ý¢Ÿ:ÿà>þU_=ýË=ýÊw½÷÷ßøÜK·G1]ýê?ÿ÷Õ´>ùÁ7?õ¬Þïß{ö/¿á ¯¼þaû®BõDäŸ3ûê÷|àïyÍ7G¢vžõNz„_üøüâñ}þ®—>å¯ãkVÓÚ7<öõ³¥uø ¯ÿ£|ôC¿÷KWo[µw;ñÊ÷ÿËjZŸýðÛŸ¾q3§^øø—¾þÍ¿ñÊ/ñq}íÙÐ:òÄßøóò_?øÛ7Fûîçþæ7öÖ§¼ûœ×ÿîûß÷?^ýÔá¯ZwÉnñ]ß5Mì{ŽÞðî 3ãÓùŸ¿ôËWvÖÓßò!Ú3nüÜß½ù±ËyÝáO|Õ»ÿìüŽ—¼ÇhÝpÿnyÇ;ÍÝ}žòæ¿â?ù¡w¾àèü•Ýåø+ÞûO4­¿ð¿óœå¾[®|É;þìo?üÇo~Þôa~õ†t«Sï6ŸÁ«eý>zÿ7~ñ_þüן4/ìûâ.n¼ñ_ßÿŠ-§üÄ׿ÿ#ûÈû_÷¸#£qñáò?·¾[¸ó·Nÿ~Þsßñ·Ÿá'õïùÅÃæ¼Óå/ýý~^®õé¿~Ëãgcã{òsïúпþû?¬¾ðiƒÿº é–w«aþ ¾ÿ'_û§|jÜø©¾íú‹m/ÿÁǾá/>!—Zíïÿ¥Ÿ˜ö×ÕŠúÃ~æ³}Ï‹/šFúÆ éÀ]àžq2±¾÷Ø‹ßý‘ÏòkùØû~õ:‹@Ýï¹ïú»ÏêµnüÌßýÎÏ+ç{ßÿÛ¿ø±÷Üð€iZß>?.}÷8ûÌ<Ù÷~üëÿô_dbýö眧­w~ø/òw¬ÿ|òƒïºá„íE÷zò›?¸úðþå_rÁç›n÷߬_ë»Ï8ÿ‚6Lð;]ú‚wý ¿±/|ü}¿|â.öÿòßíR7~ñßþê]/»öl]t÷yúÛþf5çOüé+/ã~ÃwÜé»çm‚þùÎ3~äè%÷ocᇫå}ÿ‚¼±·À¨8çY¿õáÏŽkÝø…O|è÷~åI–µsæ3ßñwŸ£%ó¦yÉÜÞå»®ùG·¼û…—ß=gZ@;+Û–W÷>úž—^Îfûw?D¿ñ1³OþÝ{_wý._ì¾ÏzçGV×úÂ?½çe»áwÔ#g„5cû´<üäUGï;CÇ_ñž¤“þÆOüÅëËA8ñ²÷|ô 7.þùôßÿÑŸw™ÓkÑ|ê¯ÞúôsÆûsÏÿ¡ºôîxîî{ÌÉ£÷ëãÌ'­v{î³ûÎç°íQñòkÝø™þñ›žóÕqpÖõï¤g¸zÁôk×›×=xéƒïß®émŽ{ô“~úä…ÃƸóC~î·ùƒþâÇßû²‡Ò'æ®xÉ»ÿþsk׺ñ³ýã_æÝñ”³Ÿõ[lñÜø™¿ÿ½—íÁ–ÿoýÂ+N»ÿi‹‰¥?ú©Ï|•S<<]óª÷ÿ3­ðOü髯¥ö?öÜ·}èSë׺ñ3ÿðÞW=æ>+GémþŒ~&ï|áØ—O¿àÄ£®}èY‹£ó.<ù´ç^ÿøËï5ží=óíüןúÀo<öžÔpø1¿öþ­?ÄUÿ‡Þõ¢«Î;úLl•_¤Sö2ÝÙî|Þ‰Çþô£Žž÷ÛÛyü‰ÏûÙg]÷£Îšîú¿úÇÿJïÿƒo~"o§wÚ}Áo}ðß7®µÚ[^óÔKÎû©WÿÉ¿jÃ?ÿÙo^ÿà;é¸üÓŸ|Í4,½{Ìs^ø³O9~ÖH²žóœß¦eü™¿~Ë“Åæ¼ç£~ù÷?òé‹}â/ßôôsO¹ðç~_Äçþé^ûÓzÊ–ÝÇ]ÿì'îÝw^‹·ÿ¡ŸxÆ _ôœŸ¼x˜§_óÚ¿ü$]ë­O‘k}ÏEO{ýû?úÙõk}êCoyÆY§~âoâ¼¹ñ3ùŸ/ß“§xèâÇ<çgŸý“-¬ûtéãŸÿ¢<ùŠÉ¸àÅÿ÷Çy^z­SN»ôú7þÉÇÖ/öé¿ígžr×ã+ó»å'ÿŸ·^ÿcl ÜþÜkŸý¢<å¡ 'ã;Ϲú/¼áúkÎñÞÏxÇêû\½¯'ÝK[N»ìùoþÓ­-üÏ|ø­O»Ï)§œûì·Ëºúçóÿô‡¿úh^P§üà‰g½ø%ϹæÜE<^úøŸyÑó÷cã!zä?ô™ÿ_öÞ;Ê«*Mþýugîw?ׄ^=s;Ø]=ÝÚtO'u™ -P‡ ˆ²¨$CQÂEP1‘d©¨€€¥ bãRAÁ,.IJ € ˆ„¥ ¡¾ý¼aŸó …hßžoÍé™îbÿÎÙgŸß½ßç}žïÖ?}ÍšäÕM{‹_¶÷Óç®7»š“®xD{¦]LÓPØoâœ{g\]¼E:þ¼ú›fN¿±_nê¬}týw‡ö|¸ht–æô½cñ‡;Š¦ÅïÖ?1ÖTÑ¿]rÇ«›µ¶¾ußÑ­.½~ÖÜY7\Vl …µ×Þ>cêˆó²SßÇ>ùîàÎ5Ì8~ßÛôMþe{>X07#ûЉoÖ<2šÌÄßt;ýÞÙêŠ ²ßvj˜:ó¶«/±•èŽ{þ‹ï~³òîü²næª/®Û•­™;WÝÕƒ~é<ýMÛ;vøø8n°3êo½kÖ„º’#ˆ¨ïÄ;gM`­ˆÎw¼¹íà¡ïÎ:¿è¶ ÿŒe¾ÍÞµã¥l‹7êïù艫¸•O|Ó¬××–lç~×ëú9÷M·»W·aáG{ÕÌËÝx÷›_fµøõÛwÈ&´ïãŸ}o¿kÑX¶I““¦ßvÍ¥Nq…sÆÏ}tþd5NzÌ|3Á7ïÞYºKˆ‡?´vwþ»ä†þÙ»v®Y0’+(îãmSÇ\Pºs<熇—vü³tfþ~ã‹“yö=þ¼&_USzÖ~Òóëv|÷íŽÍë?X»nã™pl~é†SKm¹~õƒ'¯j‹}öšZ±ß}òÔ8þ”V]9yò••t ³¹z÷+ ü{¿ývo6íZûHC~ÿû—vOznCnm9ðõÚgï{ûS«·Ù‡v¯}` ›Si¿ënž<ª{ÉN󜉋7”¯ñØô½=$÷ß?ŸzÖy=GNžksþŽ;?]ùúŠ ;²ò}³b6ïã;7ÜtÛ䊻>«Â߈åèG&Ô^Ð¥ë…C¯žtÛÝ —­úb÷¡¢;íÛõõ®½¹´¯ßš.ã»ÆL|“RüY¦µ*˜.tíýjí²GæΙ3÷‘g–¾±jݦoöU¾/»¶/¿Ç÷Ão¹kÖÄ~aég­ØVñ³P»6¯[³jÕê6lújçwe†[ùe¾‹Æ÷.º~μ»n¬)vœ3¡rkÉuà»Ý;wîþvßþCMß“»L{ÑôsÆÈ™ ½çÚî¿É¿êÏæ¾Óägýeö+—"×Ú›~öÉ{¯,>kwóŸ|{ä<š{íýüÙñfœœ{ÝCK_]ìàöó†eû¯kï|uãOöaßnX|ËE™A_}Õc«·ÿˆ XѵË[óFŸkÏSN¸dÚ’õ?UW<¸í½E/ÎN¥Ü!÷¾¾ñ0Æͱ\ßo]¹hJm’þ¶¹êáw¿üI^vp׆×æ¿ÐÍÞõ‡^“_ùS¼ìÀ®Ïß^tˀ꼙ݪ÷”ÇßÝ´çGîù‡ön_ÿæc· *µ¬™òèòÏvý¨½ñûo6®^:BŸSKŠ­z]sÿËoÿñÆÙ÷»6­}uáWôlU(»Nh?bÖó«7íþQ>íྛ?xýñÙW_vf剠ïͽññÖ=Çú¶Cû÷lÿüýמ˜uuß6Mz[_|ÍÝϾýɶoåmÌFxÝŠeÝyMŸv‡Ã9ŸÐ®ßõsŸ{gÝ–{ÈëØ·Çì¸W¾üÔýSÇÔV QÝâìç>óæÚ϶îܳ÷ûý6o:øýÞ=;·oùü㕯>5oÚøçÚ-ý{û˯ýØ’7Þûè“Ï7nÞòÕ×ßìùîûýªøÖC‡îß÷­yË>zï­W—<~ÿ­W è|z³#Z´ë3fÒŒy ŸYüâK¯¾ñŽÙQâÛ¶m/¿¶mÛºeÓg¯~ëÕŸ]4Ö­Æ^Þé´£ +9á䳺^>êš&N¹ù¶;ç-zîÅ—_}íõ7Þx³ôzã×_{yésß?ã–I×нC›“›SuåïKÎhsÖÙçœ×}ÐØ&O½åÖi·U¸¦ÝzËÔI×îß­ÃYÕ'ý!-Nªn×¾ý9çVºÎ9§ýÙmÏŒÿ -$³âIÛîƒhR„Íž­ñ±&ÍFǶ«‚koÏhŸVµùþÏè*åÑâ z×’ÝX’œáõ|“£9´ÜP7¼^ƒwmrõÀþC‡öÜ·$¹Mÿ5— Ô»O¦\Zòj'Fhñá™qˆ;§6®H¬ÓR˜ìˆÄGÈv˜{ÂâY¼ì96*=lGÄ/‚¨yP©( ‚Ï!ôQÄ\L ´²æ©Pˆ0¢@U Àggl~ 0«É»lè­DÚ ¤=±#*ŽÄéËÏû­’ B±8`ÒŒLÊK¤ Âà$ªlù,«5þŠ¥UŠ˜Ÿ‚>ËÉH~ŠITÝ,`–>¢AP>¢þ#JP.$žñ{–&låã.VìÅÂG&üY@‘Ä©%Py‹8“±Š•+Í@CÙÞ$r8_IXÜ.rÀ3—²_ -ïƒ>‘5HP,aZQÒ®’ Bˆ?DIñ'„¾ÌQÈÔçÙbÌ ²âç=KV}âòÉšö»¢€M ¾¤TµR‡¤ Ô:Ž[\€lêÍeŸ£r÷ÚÕ'ÿ."N¤½Lïô·h>L(V¤B%%òHdî6ŒÏJþ&LHa"$< °õ0Í1Üç&Ô»C‡)÷ùñXIÖ‚@Åa@ç° CÙòJ„8Ìï¬tdb—ønFÙXfý(:-¨{$Â]ã‚ÉóR -æc]ÇE{ƒÎö̾ÇAéšÆ&Éu@Ôíci3·qÒçb‚ ŽÉ3ý˜ÙÉŽU§ÙåûožcäÙÑò¡¯:£y¤]\:U©›qëánüÈOð7ƒM'0³Ðß™Îÿú»£}¢ðz¤ë¨íŽ?jÊ -¿úh7Ög\Øî(Ÿ8wø€£ ïzý=|WþºðÖ9c+En5}õšþàÍ]|[îê:í¡éù¶ÜuÒ¸{§÷>ª' -ßr[Ÿ£{âÔ±S¯8Êú½ôÆqB™wu»ª¡M¡ð?â‰Î#êüÂÏä˜GœŸ×¿S¡ð»#ðBüsƒÜ꒾Յ‰GèÁ¿ÎÊŸYw±S(ü¥©à!¹ŽÏªÏí ']tÖaGÖ¯r…öëúÁ7zJ&C¯ÌõÛ0Wèó‡üíÔÚKµœ”!yÛ^qùæ[÷һɸ³Vm3àÔÙãïœÀ³öÃFtlâ°Ûùö#ÛNZ¸h"ƒŽÜÞ£.¯±æöœ…|xvÕÒ+åï“Ž*ôñuÎè«í»`á†moë…Ãë+–낉“u&h7óÃï¼?ξ½vtßÒØ\5·ß~‰üÙç¹o?¼ÚþtòÀ!殪!wÍÑ!7äµ}_“ýØ}X—ò' -ýî?Tþ¼üå½ëÆg¿u=¤Âhì;ÿÉ©kíøØ×ë¯Í~ë1Ạ-¡sµó—̽Tþž¸¾±ñÓ³ßjnŸVa"ºhî‹ GÈßõïhüò¶ì·áóï%(^ñ>ã¦Å‹gžÃwz|gã·OYÌã9³—.ˆ?~Ya0àÑמ"ßôyã¡·†ë/#—~ð"ýãߪŠžhç+¯Í<õ«MõN‘:=òéö·®À_'dÞšF-Yñ¤¼¤û‹û¿yBêg슽ûWÆ_Ì·†`ù> ß_>[‚zæïnÜÿö0ú³óÂí«è-²÷O˜CκoíúçúÓ¿{¼¼ßëj~Å{÷¿A‘TÉy9h)¾ñ½/¥ÇNø¸±±qÓ-ø³ãÂmßë+üºñÜõTgS9ó6’{çÁ&qÒ'û^£Êm×ët} Eá7lh<ônƒy×*Fµ½w%Óôü­ КAŸãuf‚HÞ±¹±ñóÙ…þ/ €ú£‰…ÂÐå­ ¯;ô0»¼ËúãáîÏrñÙ+q½ñžS W}Ðظ}!À4éÈëéÔuþÿöCº/B}1û”Â-Ÿ›ïž„».š4Eûv<üÀ©/z¾Ô½ýþøBÇE;÷/GŸ>yÜœ[zÉ]nœRcê}Þç%ì}eHáòWö6îX„¹®ÇmóíúÞçöi -cÞ.uYnyè¼Â°7ö5~:wõ¿ûëBzÊø¹wô*œûÐÖ’ö¿mz_ßvî]=ÖÜuê Ý;@^ÑmÚ·u+ zu_ÉwozÐL í|ñÕ+hÈîw<›K£vÌ+ïЀï=cf?mð §ÞbêùjjŒO͸[HÎïÝÏrÛ¯¬^lMŸ·ôÐ'ºOœÜKŸødB¡ûKÔ©>¸Ž½rùæU˜¹†ß3Ñ‚ô;ŒŸpazƒéUS -c©xû—]È¿Ž_»oç‹ ½qã§Í{bíUúÄeÛÄWËÚÜÍÇÈÍh¼¯OLiæg4®–/ïòT3;‡Þ½BFÙ{Í|Åw/Ñ]8k~3kªñ˸—Ô<ýuóØ¿R,®‹–N†M\[‘PÍ3o¿Y@Øo_·½ê‚{×6ž³oõôÌXì~ÏÊoŽôÀ÷kﲺÉUOþ¶oí]Š®Kî_ùõa€ûÞ¿»W¡ä:ïªGß)ãëÐÎU³/,}À\®zäÍ6–y¾ßñéêÅÓÊ7èê8ôê›måšµk?àkíÚ5+_]xÓؾ‡Ûäu4jÜUWëuÕØQƒJã]þ×»¶‹\ÛÝJÕb*:¾Åà‡¢g‚câAâ@p“X„&“X} nêˆ0c¤îè—º¢§Búkê€H!‡ò‰¸â ªÊbà‰E;VW`d%¾Ô7“ª÷Y|·PÈpYSÍmå³?ÜÂKﲫZ29_x0Dó -¡ü²8§.*[~”f$‹r|Ÿâ!„’…ÀѯÚÆPËðÄKšîÕš(—D,ÅÞ!'%›(`o"Ÿ¿§!ÕvI''´N«Ð¾ÌúœT°´"<¼lùEŒŠ1 ÷ ¨…±ÚôX -U-Ïûi‘4¬Þš„*@íŠ^ê@CÚ1¹0V¡¢ZTè'HqܪÂI©›t 4ƒ8ŽD˜Iz©êñSÍ -h¤…€k=ÀÏãkÔ•IPÇ“ -LÄï ùŒÄªÚ«ãܤŠÃ<`qÞÄcQI®”PÀS™¾~¯0Ë@&BøÀEXÞE:…©HI0Ì@´¹ ììª.I8ÒІ” -¿±Oh'Ss‰ëôIKV‹òKìù"W¥žr©!g`)0i¢÷bû~QŸO¡ýê (Ãcdôl´–³£ -¬V%‡*'/ÈœP@<䤗 HOîiÀ_U-`Ò]¥l“ÀUhPÌ™"QÕ{ ˜Ãè ­ÂLZ6-ES4Q³( ´ЬJ¥UUr-²Ë [Õ‹6ÝÖµ sm•J¬w=qìrA^[m/‰D.ÚLG3ð=ÒÖÄ7:©öÍ5´`X%œ@Ö@óÙR®.Ø0ÜÒTÛËsc]odeRýc²yr_€9€† œL2Û´ÝëÛ™ JÃ< CíÇQs=†ç«ÈáÞ)^q¨Xæ "ΕÀŽY7&½:XMAà¶Ë§‚Ë12”1õ(¹ØÐ@ˆ\‹ÖB7€ fTGõeSFƒ„0\·4ƒ0¶ú€ÔÏItÃÈŽO¶:ˆWËi "¦´UYˆG¡bˆ…AÎ’0U$šN&9ŽbÆ“&:m…± -R"’%ìé‚Z)KF -d¥Õ(eÁpªZô¤¼O€î™ RÁ\©îȵ€R¡o»¢••*¬Š,o•ÝCi~ƒ½Šô"h€±‰ lªŒ.@W#Ov* }‡û1æ -™K ƒbNêbHxË@$ÂiÈi%’9Ï%>ëöš~"zcÆpÐ^-IWKŒT¬®/󹩟Č]i˜±¼%H¬ö$Fµ¨C‡\Õ¢×J –dòRƒ6vÌ“4”qÍ°ò­=e’uñ€1ƒO‘È †ÕËj€Qm²­n 33-²¦Gè³9­R -…ʘãŠéHf*}@êV'Év`èщÊ/ëlZÑ9 ½RûPoç&dTW­¯Äª¢Šòb€‰þEqxÆvSXÐaäÚŽ%k—´ [©¨_Ø*˜&`3“•#ÃÀ ”ÐuE§{‚È-?Œ8Zü5ƒ€K`jˆ Mî^D"è!¶Ë<—!1 Ùß@6ì -M^0¬˜sõX‚5€ª[4¿<ÁùMùžÈ%« „.0wÂÐ긅Y/FÇà]‘IL\Ý„‘ZZø1`Qá2mX¥lÓ1R‡´»MZ ¡ÍjiÂÈ¥ñ:vù#ôa&S‰÷ë y-€(:˜cí°!½+0¿F®ö‚„t2IÞÎËÊ/‹oà[ûÃT€džµTàÄísÙ|Ñ6”3‹ÀÑm™éD2?û™F" ¶)}SP×ÏéA²µçÇÜ0-):ÀÉ*ÒkŒ–n“˜ /Hkä µ"Ï<5ø‘ÝVÅ}@J|äu1aüuè<#‰ )_€-˜XÕ‘F h¢î‹¤µs÷bô{´×ð­‚«Çë½Èª ãDº IVã#Í*Àç)¯%$…4_˜;É0V@0Ý89V0«£0e? „ YùÀerŧ"áŠdÁ#QŒ_Ï%.ë͸¦J £~¤ -¸Hô³ILD×׉µ š¶¦S Î QH·é"ë -qb1¿¨º¼ØXñ¹­9’åpzŒ k9ûj@>ˇrbDÐgRÖ1DÉ!5¬²#gÞ˜±.†HLS[ìÖÊÓnâÈØLùˆ²Ñ®Ëì¦ÀcJt\6SÈxâ ›X‹ÆñäÞP¦‘POIäZ2HØJà ô0ÎØ®øMbƹWë0fLxb¥}irà-'Ãx{J}X6ó¦"RQ€E¾zDàèö4% q2pHɧ礲ÎsfþˆÉºdæz9åÄËÔÒµ#4éÅj|ÙÕð÷n ñHÚÚNlõëÍË©YêºT‰f”%~d'ÓÀeÝæ$‹­ué‡U¬5ªýŒã&5‰ÐŠ±À§v‡ž‚nD¤Yµ]RÖÕ¶E(KÝÓëùä3àñ¢Ï“=¤G·öõ|ô£Ø•oEŒ”#'::7à¼ÎÑ!GÏ8¾ÂKŒñJÀ3ãË1¯ìíÈ[D­ß íê㊓Íh”ˆ2„´ð‰ŽyÞq¬H|Ì3&¼u5#7ÏÄ8#ÓÕÌŒgÞàC®ÜOCIÔÓ/Ó–òùèäƒ.=Ž=Uà]Ž8ÇPNhrÍïêZJBÛ,Û23c\±-€DYß5~RƒUTÊ;ÉÖr/·{ÐåÕ׳Lø^ì:ä ä/–¡mãZ¬ckJžL fÚPtŠÁ‰©¢ÌóŽ#ŽµÔº "V›çDÇ°ÐÒ ÆŒaã ’gq$úÜþ8Y cÒ}çÃLÊÃb¦±Ý‚šKÎ ÓH€“ -yAÖgõ÷ɪ ?/Å”+…˜ÒjØZkØZ,f¶– ±UKŽH邉&êAa™Ç³¶q-žó'„®8±éò8­¢ðÓÕ%À¬Ì.¬w!Mæ(2ßíª ‹oÚÏtkr¸ˆI  fª]vóðäøžXÖ‚Q&úHåú¿ÈÒŒªý/É’hl -bµ86Å,ÕfôUŒd©p7~ä'ø¿›Éš½äß@$˹ÊðÈõÃ$²Š¯ü1ÄgÑ|u¤&¯ŸW»–ð¯þxìù]TQêèò8³í±‹ŽºÚ»ÄgtÞ)Gß×JHÏ?¥ð÷|?Š˜­|`Êß›Oíq÷Ø< -E²|‡A›ÚÎ…àê¿nRѤìú§¼`Ò¯M'ë8jÜÅmÀR÷ÛÖMk_ÿò›œ Ü¯Z›—wŸzÏT"ú¥W.þSéúõ 'ä?¼´Ò.½ûé®pTð—#Äàpmžp’—/ñ g4Þï‘×-þõw…°œþéòÂv?‡°B«óÚø´î€lXòþ # …?žÛù‚ÒX•ãŸ—7¡h ¿\Ø¿sþ–Ö5ƒ4ž°rËÊ …B‹š†a%*E¿KÃ"Ý?üδeÃuyEÂYc'*ú.Þ~ð«û -§^unq&Qû(ÿÏ_y' -'Ìšœ§£ìzë¢Go¾ HËí/Ý6iÞý7žS”ljºE¹ý16™ô˜öÐœaN¡ uÕ}ÎòO>ÝÄ$‰»?[óæ±E/.œtÉEEâ= ÌÇõšñèÜQ§~Ù‚ª:N_‘ƒ0ïxoî%öþŸAi´Mß^ù‰æWzÀ%3ÜÑ×)´H©;üÁ+ [’ƒ™nYrÍérûï[ýÓe·aE\œ¿wQË—Íœ3ÖŒ5ç ôñ–]/jwñ½ë-Hw÷›7+ô3ìÒÌd§Ž™T“Ïäô¢hì¬›Ç ÎÄDÖqäÈŽ…‹žøJòØ»òvAp·î6j ýÙîÃ7手[žlÆH§Éw7ëÄ6§V™GN›Ô½P'AëïVVÊ o}èÓà…žóß~ûþ<ÔmçD¼Þ|Ldz°rþ-ße -ÛùqF¬î~þ’Â?ÑÈòÜõ…6ýj©ú.½oÙ"ßoÝȵ:ÓôOšNz-X¿çëU,^³ýPãÞ7òuÒ©ûÉ…ÞZÿêÌ{¦ È¬~O¬^Ž€¢) ,ß6§PðiÎïóì¶ÆÆý;¿%¥œ÷s1G…B»ÁWÞðò×û÷lzÿiúôÂæ-¯\ß½0‹‘Á߯š<è2âÝ­y6×ì›ÈIÒå·/&°òîwX<ø¥];?|aÁz¡8޵⡱~rÖ9Àñ7‹³¨ÈŸÿºpæõ˶Sú·™å»P¨{q7P÷™”Ä–çÆñà¼yc–Éž—3…$ÄžwÿÜ!Þ¾¹¾wP8wa &zËã}ùæ雲Ä]K³æi….:ú]îß~ü Óg•À¤×ÏæÏïñlþåãþR8¡Ý™¦õÎ_$ï>°éù…N%ño_Vø™ùÌ3ïø(ƒ«ï~gª•Z:©;I¾Ü¤Øô}«ÆF¼SŒ"þlnÇŸ“ß.{j{–ñû³íLxb—^í ®{­Ø8½0³8ÈfßòQfÊ톼jqÚß®½'‹£Mzv£Y< (Ø¿þ©uÅtÛ;u.´º¨Ïé…‘ok ¿ûàžÉëé—ràÇ-_äÞ\\«›n7=¤¾áœÂŠàÿþ£¹ùÙä섯¾li¹¾ˆ½¶Î0Ãwâ ]²L>ŸŸŠº\?m̨q7½ôUÓy4~·ìòÂ÷MïUhx—»ðîçŠ5¤.¾kñK¯¯úôð¡ ;Þœ·ìõ‡.+ _Έñ S‹ò(ô{tÅú/H|»oÇŽÏžêSè+½öšâLF>ýˆ–7×WO÷.œ³€¿zõ•Eytœñâ7O{aûr0×–yí -…Éèï÷Æäó8åÚg–N3ßôÚ‘Yƒ×Oκä{E%éyߪµÏô.æ®q$ùÜ°žþ^s]>“º§6îþâ‘Þ…¹GŒÈiÜd:Kaæ—ô÷º;òK¿ÅæéMo<±áˆy4îý`ÎÔ»×ðxøàæüº\ó,Šp YÜƾڸ…óØûê°üç´»ÿËæ<_rmkjÆOpc3£Š®Ïo6Ožüá_ÅrµâðL~fZ;ìÚ¾…ššý—fô6u}5»pîÈ‘™…wΛŽüPéupí} Ý™=…kVÿ€ï9¸cËÇOÎõ”%?ŒÄwÇk×eÕíæ–F>6ïúæåñ¹hñú—›3”^?´.×ßΞþÞh ­¯LΩé™Åï®æDý_›^¸¥C¡èê>÷££$!ßôôè2Ëîs×±í¶G—fa® þ´ù·¾1­¢êçÀÇ>iæíÛñá³7WÖ_M?¸æë#æàž­ëW/ff¥øx¾ºÞþÌ;wîkZ‡âûÍï½ôÐÄ+‡÷>=È™}®™÷Âòï­^½z\ïøé¶=ûè’ñ7üm\ÿ:U:UñS[œû§ªÖ]ꇛ²TµèÒ¯fhÝ™ë÷é\S߯ëè¡uüÞmš¼©}›²¢)8 > ‰ñƒV©ïGßh$˜–„hêà'×fà±o¨Aü1(‘BgS7VL ðI »$76cšÂ”á°ê ^ÇÈKÀ¹*Î)0qF/þáHIã‚_ÂWå{¼£…%€¼å{„Âgl' Ò≓08ŒñKlàÂý8T)ö8j[ƒø¢@!: èC ŸðÁ‘§Ñ7©âzc X-}Þ¢mQ‰Pˆ%ò¼¡äÞ£Üjª]Ð<„BV.òH‚¹K- \K¼—Õ »†.3ŠÃ’T¢çupP®ž d2É - P§ ÐÅb*xÛ £Û À…°:%V”FF í7Øé³Ø0ákVÛ¨%E0y"g\ªR(–=ÎBád|e÷­&·ˆ£˜âj—D“#¸Lcù6©˜ÛiG‰Bš_# óX‚€&d´“%'¹è“8Ð@´0TRü¬i@,ÌÎ@I¸–¬ÔZÝx¨Œ?V‚Œƒ %±£@][j`gmøˆ²~S®¾„Œ)ôµ!@hY»83.ãÔ-¶¡5:sëbJ8ò5"Å>¯0ެà ^Ša´:ur²pÈ,eqš~Q̈ PåIðs±…Œ ‰ -Ù?°¿\߀Õ:GC,a¾¬Ôð ^Ä\‚”©@GÄÅ\­oÖÆô#,$–`sGqö¤O‘꘎4Ø&qtS%¬Ý/ÄcÑþà¡æ;™¾žBðíúš&ˆ7"ƒ…m`ð©Ä‡Žî²è&¬Ò±fHb.Z'Ë@¾@[\¢Áì -rKŠO“=(þe6ˆ2n„ü†a£‘{ òæ:”’ÜlZ»hBËJkÞŠ•ÎÂïÍÀ¬F_lqE)âP* -^®â.'"!ØbýYÂ3—$JÞŽ8ŽË Fá¡'+¨¬?Ye­•YÍ"”Ë·Ñt.ïÕ&|*æÏ@¢£y“« âÈ-¶¡Ýüh® Mç¸Q~½æÚbmƒürŸå`r³Þ%‘ÔËqŠEcIc^Z²z -›l/ÊÏGb^R¢:‘èHtŒ†'Jàû¹x:ðpƒ+G¬qThÐë)0SyòÏgÛ Á/'-»JßËèëËNsš…<õ› dpgâ™bgxScÁ˜ë ~0ãÆô&T‡ùœÊˆ)kV:ö3T,ÓnÇ8­\œÿë0ÓæÖã)˜)÷ -3«ÌtX˜iîn‚™ÒüßÍ!LwÃø¿(Ì´äúû#ßr„ëgÿÚÌ›þÃ?ÿ±™¨Æ¿o¢´ÿûø‹ЕMã› ÛþW÷ÏÿŒ¼*cÓHÚ&Zý—§$…v]2‚èÂ?6]1ÿoé§_Ôs@Ÿhê×EóyÐÝÏ›Àƶ:v\¿ í÷þñ¹_«ò2è?;±XÃ^¯³G\ÓpA‰öëÔÉåÑvÿ9­¨úxö€=Šh´ã³´Z¤gU·ÌÿÔêœ6ÀÈþ%ÿE>éünÕÅàÅSz]È ûEÂ"¹ÄßwèÔï¢ 3ÙêìžÝN.e?eÀ•P½Þeõ5ná·¿ÈÿvúEçŸXøÕiçØluIÃÈrþ¾VýnºelûB¡ëu“z -¿pþ’«Ã¸×EIáøvÝ,kÛ1·NèV–E¡ÛÍ?|S—Bý¼y@œtVî;ÿØýSÀ“zu×ú?oÂ=·U ¦>ùÚEo¾òøœçßy}vׂߣ{”Êç\h*£Å—µ‘Ÿ;aÞœ¾åYjX¹ñËO7n\÷ê¬Áƒ.ïÔ\îÖ8Š/•–ÇÌ7¾eùi_ߺwÏk?\ñìŒQ—žnЯŽzê…Ï;wøÐÎ2¬zN{ð¶Kʳ(tyðãíŸ,¹ëÉ¥ONíA•ÿ[»÷ ä[‡‘õÝÑAþÎÔ˵G¨³«ªÁY—^Úº@—‘ƒ?ý`ÁëîzlÎe²õÔ’;Î-œ4|ò(þÎ3ÅŽjG½€ªÀëÛPcþøMkdÜuÚ¢Ç&µ-ËáÌ©O.‡ùiîìCÿÄßœ~¦ ãáØqä°³M'%¨¡ôŠûžž7î´Ò,úÜÿÌ=„tê}“K½:õ,tàï2óê9Ó[pûÈq£Í×Ä ó—>uËù…Bÿ‡–>D_Ôæâóxú¸dÎ KîÍÊÙ3Öìþn%Ävœòø’'çÝ{ÿt $ÚÞ²äíe3.(\ÿÚÚçé‹ÚÖ]ÌŸ“®zdÙSr£áÕ]f -êï[òÚãw\=cÑÂÛP©ý¬\ÿîÓ÷¾¹õ›U“é—_*У³o\ôÂ=*ò‚ÇýÙ¿vÎí‹Þü𣧞_è?ÙsSÏ5M=ùÕ/¶}ùéŽÆÆo^0ÅN/»¼‹Î5æ,}v²£Ó½“{ÿÀW›wìÝûùÃÝÑ@/¿÷­Mß÷Á¶í›7îmlÜú̵CG ¿0›e¯}é …½Vߺ"äøŒÒG¾¸áÓW&™V¹réÚUOß·ÚÜñå«÷O¬Ë‰L]ùÁSÂY]÷̶<ª`QZ_öäæ=7eôг³/*ܸæûÆo×>2Jš±}¿‘WO{wÛ–h3veÞpרǶljÜ»Ü4ó€93LÛtyt㾯—OAêI ½öß^ûÅÞÆo^fÖù¶ó6æsh<ð.é&ÚØøÉôB§©wŽ;ïyíóæ>œ^ùÀKïÉÅ[½[û\ ¼æëçSžøØhï}è‘4»Ô<ôæójë5ïýo[qpÛ;pçør)lË3ã/(Ü €éþ/?Z6‰Fäi7>6ŸX€(Öz÷ú''\ÓƒBI½\Ïù惥¯ãWm{^ð°—NŸMx“°/‡6¿>ûÂÂ9<àkžÝYšEc£EÚn] (÷S¯= CóŠÈûàºGG·/üAØíÛ>¸¥< {m¼U»Á€¹^m:ã¢?þt>æ–à<ªO8&íËéšÅå¼ü ©qï£÷FÒÉÝ¥ƒ_ñîa\ß.QÐæÐ%¯¼·cá:À®Æ\&Lºý^¨PöúôAõŽ}wçŽ×îˆÜz'%õ¨¯áUò칇ãò>´ñ髹v»¹kÏÚ'Ö£È{_‚vC‡«'‘UmÄ+‡… n{oÑÍ×ß0kó ˆ¶¼|Ûu7Î~`Æ`¸íço<\ûw|¾î“ÍÅP¨o¿øhÕÛÏÝa²#„ìÐΟgm¾ Ûñæ͹eàü9ï7 5™¿ö­]d.u¿÷ã„ übATØXJ÷|pTyürñ°BÉuÁÜ£)ÇÞÏO(‡[u»gm3ëãÐÞ¯V?8´`ë‚{×6£]¾ÛºnõOO«`5âê:ûݯööù½_­yiÁÄ+‡]vFåLÛN{nõæ]ûç$’ãvaÿÐÊâ³j¡ƒ7 SsN,VÈm¥ZÊp.¦ -¨Q]v賿ÝXáyŽú—L±”þ¯b -œ ÄJ ŸXš: $0Á] Þ™Ðr -B Z8ùœ£-|sÌ= ÊLáž‘®O)lKaÔ&÷±µ)W(¯Y8G+6öÂÃéšalDTäÕ;rÔ2>cÆxH©Ø› "´A#¦åüc5¹sI‚⚎’_[»«¾Ëç "ÌX9€jàÁI¾M!_N-ïªÏœÞ -ÜÆP.)Õ;ü‘pàgŒÎ©€Àõªp±Üó s1fÁe_o$4, 2Q.,8ÙCW°ÊeX¿0"dœòdX[œA˜#VwmÍä:7X£}éq -`*¾2š%±ŠÀ‹p©šÇ––=rBáy°=Ù+Û’`âoÉ×Rø÷”ì0ÇU(/v®°ÐJˆ3¾#øˆX±VäÖö?/ƒ1rs‚P̺,Ï÷FJa -V `âõTvÁ—¾‘q¡Âù¯DkðÕ -Ÿ<Ô ôg¯® O@Ê&néP ÑÂá#A¬ôèß ‰nV-® @jj%šá&eøk®kEëÔE„%äÜ1‰2îþéPÞ/ôwù¶r”WZ9uj <‚À–óS¨×€¦¨AL¨ÞQî.`¼”>1¥ø”Eû;É‘[â ¹kB­à†Øòôfµc̼ϣidÖR¶¢³1‹æ|áX…›Vý×Â!Œ€¹gt²¨L“Âîè G]ˆßå«W:ƒÒñ®(WPzÊ1 /2i -‡ •KSâ;€qñƒüðhÓ<˜À2*O¡_Ó%™›@้€ðŒò‰sˆ âŒF DQ ƒ¶Jãaxúâú–?^iÇÚ°ÐØã$ÌŽÙ`¿5Js%æfÔc1«>ßé1¸=ÈÈòŠB0x ° =–ç7?ƒñai"Ë(V3+)+‡€vT—ƒØ²vz61›Š}?‡ÎÖ9xûa€ðêmš#å\]?±# ¸ósœ“06+² 1/ÅòD^Áèo\ f/wà,xbš “ k j.Ð’º­yÄÃOUˆQ›TA -'põDd™¢»åÿ/ÑÍ®ÆÿhHýÿqjÑQ•éfÑî&´=ÁÿÝ ´€ïùÿeÑÌ´TMùº›} ;Påë—•ýÜG¾þýúß4Ÿ\¨èÊÊ^õ»ÃÝ×ô••ýßN<Ü}M\—/ûâßuÿð³¼€øoN;õ¨¿ãW¿(NÌ<þñ9Éan.¡“¢úÿÅ~^(xm-"!èv~ËBé¥-UÊ^Ç/þ…N{uÓ€ï:÷>ÏâÔo~ÜñìºþÕñEþõŸLÝ·‚êú)ýG\¬0†Óz÷R¾‚¶@O9 ¥¬*ÁDüÆ´á šà _¯nùï~ÑÉòÅU¶]~w~mV¦€Q1$æ¿/üÊgÈCŸI×ØÃÕê Lÿ€/nØ~ÒùÊ1]Í;O9-O õ›¸Eáß*üÉc§‹r¹¹Î@ÔÇZœb¥¿{Þ<ûšS ¿ÃÙ9”…{ú¿~QÅ÷švï+ØھשÒÇ~Ó¦­–ºfî³óû -¿o×££Õo>ál ýo©¾î¾û¯×ÞÓúÕb>œJ{Z'E |ò½7§·5µÔ©w7Í‚à -­Û9…¶ãî^pçpáz8gôSùq•ùGÛž -Shxm˦Åð;]Þ½³NÍå`Ž9ñ‚þ¦Ì]0ç*þˆ¶Cï|lîåø€3L×Lúô9]r¸ñÃýû×Ý G§aýØãÕiôªý®7ÜõÈÂ9c»“ëç¼i‹×|ø Ò¶©éuɈ+ˆ{ì‚g¾nlüúy8®;ŽFN ~ÚD:ÜïzócOÏÃD6g¾½mß·k'Ró›<õ¦k.áÞ~Ö¬u‡@ƒÏè4f$jwšrÿÄÃÒñ¦GL`2«3¦,‡í›gà5¾xÊ왓úKï¬$)‡Vƒ,äâñ Ôù.¼óñ{zãøÊ{g õÎ¥‹˜æâ“—Ú\që­×^.¥¶wo >¾Ö4Ï•S‡Q]:wñCLZP{û4ñÐ ÇèÏ]=†tQotís̲yz¡0èîÙ Eé=ÿ•'ع|É´[ÅOXÿ¶ø6ö¼àÆ¡3>¥Æù~í]ÓŸ{í±Ë)ñÂyË_ºš_0kf-ß8j¥º46̯5=ûýÉÂ)ë¯6oßüÃDªg­øàQ*ý¨…¹Ó•kÔòÀ?·ÃjÄ[9Ç˾U›rãšížÛ¹Ðû±Õ+ær[\ó‘ÍázóÏ?Ú14äµ¼ïoÃdNºáÐÁí+ÏyÓ·_¿Áª­Ó,ŧ·›žÒV§‡>Kò¾Ò ‰ž ó“¨ÞCßí€[òËÑ={gœß¾\W8£oosϺ?/k»ÿrÂ_•óâî{çS£æø=¶/½õŽ©#N×Ïÿ~ÞmôõbSõ}ž+¢yÚ³bÎK7çïÚùÁ²ûFX@ØÀeE”Û–Íœýr ãÌ÷_m-qÚm'§îÚ~n±dðw_m=²îËç®ÊÁC†¾xd~š’kÇëSòtm§¯>:'é¡íoL+bÉ+t›sT¾Ú=Ÿ.™RœA¡pþÝ«ç@/º¾ûâõû†žU(½ºÝ¾ôóæ|ÉÁÝ_¿ÿŠsËžG]Œœÿ滾?¬òó¡=›×¼tßÈ&]‹ç6Üûüë+?ܸ«2%Æ=[V/{`üÀòòçËÑgø˜\º|å{– |ŸlÙ¾mã‡ï.›?~`Åâ—¥nx1ÆUï|ÑÜëúƒ_±ÍÅŽÈãoàúo¯äQx%›ØÚÒÞõϼyíd·°|òš €ºŽ - ýA¤F@//!™8ä÷YS¨ÎåH•cmSÖ`­Îr)È"Í"çËß×ÝÜýŸ²³v«Úð³åâPR¬ÊRRE§*Tq•Ô¬š½*“ÈâpôI0¹EøðË\QÙJ؇³\ËzN.0­GX@k òLjA÷=¡¯—‚E"˱U¦žs9ø~,’JApwFÁK-+‡rñgT üª"VN¦Y4|V¨ÖÓÞ]1¬­b\i¬œæPXW1¯<\O² Õ,O¢ÐŸÝ[‘£qh¹ãÚ°4ö¿C''—Õ6 ÑLM¤YùLØô ¹ÛŠÇUˆPÔ,ħ›Œ´Ü,œüí©" B ¯G¬bV†8UM -Xƹt艪fs¢ï±R…Ïlš<©è2P€)'Æn"5a£/uÛQG§Šš8´&D¾i©/=ˆˆpºÛ›‰Þ…j^ý1iF–©Ÿag:Τ“pRˆ³…:™Q\™R¹RvÉVœg´Ä±z˜ÑýH£E|1 3‰>Â.ÈÐsáË&6ñ‹ X#ˆE'0áù¶c³F)gÙê†À)S„â^¨\KuÁÌ\dD ÃY8âG‡ñ%”‚y"7¶Ä9Ú©k¾†+ú!{¹©»Ò¾,»x1(5ØŠs/äÑI0-AÊ=6Þ˜„†`Ê}‚8l²Š#_5w–@KÌ~`ô*?XO @T]k!RôÓüÆdK` i•t„Í€ž`=žÃ$‡T! øfü†9‘;Džo—AèÞ“3ò¢¢, T”é`Æ­õR¬¦‡ž)SEêÈ`jÕŒdîài("‘ïY)Rô)EÈtiZæH„§ŒeØ*CY‘פE* —РH¨³$ì’®--„ãÚ±›*§†­å|¾j‡kPpäîØå -ŸÁ,Ir)‰WÈš°îø6?èªB&-5ÏAi¬:£ ÞQr°XÚƒÖ” [º!ëã„2·X¬@æ6t+QfÊiEH2³+U¬¾ZQTåùr¯À.ŽhI‘ˆ†¹¶›Ù+Šdè(¡K"AòÕYLD_("OŽš QmTU–íÒ L?I¸–U€Ðqd$P¢%]•ïKD›NË*² aÈ$¿ð±Ì²Š T€“´±2±½ˆTß<V2V "¡IÇjRQ\?†žˆqjã1cº¬ˆSgÆÈóxÙÔqS– £3YÌ.ß :eêÀ’Ùe6C]ˈÊa§²åÉH¡€ä”uX2GiÅ…<¥°æ[ ¤|¡•RN™`° Ñ8Í¢‚Ä\E1º -ÂuœE™1å¯s|½[ÖYI $?" -³^+Y)Á):±b¦U`]ÔêÄ$â ¹uML\MLTPècȶõ}-IY&âv¥Û§<ÄV«öb)Y™ !G¢…ä +H!rwdëN`.™i±„#‘bsÙâ©Ã;èjÛ³B‡ð¤Æ-¨)£ËfŠ2kzV 0²9 ·„;žûP97fO{· ³hê«ØfÌä”XX£8DcȾÉAmê GrÅœQ°2´McÝn” Æ™]ó4Ã9‹H¬–ÖF–0„”*ó€0Æ8Õ2'ØsËJ"g?¹DlõSý ­Ú›ô±ØÂÒb>È@•ëñ…a” -4t”5ö/+"ÖY5c Î?ÊUê(„ØÔñB­¸2éR­¸ -B§%QËÕSõ3`lU‚M'ZXmi*¨[êe|g*k è±ke:A",.©ïÄRõAê -LYXIHW„»I¸6WôjRò%ÍÇŠð£žÙt‘ÂÃâg⦎˰&KAŲ”‘$zˆEÐaè"î‡j—U Gɦ{±€Žì ŒŽ„β|P˜ñÅر+ €š—È"»c6}-ËšŸ£”ƒzº+‰±—d˜=³×ø>ó,¶$hnìP“ø.w²–•ifx“„3O cºû&av)p*Ø;ì y®G"¶ºÍò¸!¨†h{&›lÆ%BHZ¹¤À(+WNV‹sCMO”&˓ψ¬U‰mÇo•qóTdñ©ÄøÇlö´py9ÉB´I@tc~jA›~ªBíi¶ÑòÓ§®…膱i& ŸÅÒ¨•ó­JðZŠ×,èÅóÇØSO”åeöƇs](Z´š‘ ŒÛX€–))UvNÚøq¢™ÖüIôžÙ‡!^% EÆ“==# ôH‡$¤su(‘b(ça-+q;õ´wÓ!(ÿ ‡È"ä…±Pà!7 Ëx«­/DÇvç®[;|= |#›Xš-9fÏCl+‚qKq»ÙárEo ¸§½›Öô½„MÏl¿†˜È5ÔyeÌ; ÿ‰" “åó(e³^:pÇ@9(Y.7Ò‘:­tÏB[OŽT‰PÌÕ…%·µGWeÌ8¸ -eˈ6Qd…ï9ñY!Ôî&¸^P}Êî^NȾRî!©GŠ#N”̺Fa° ' -ÿ@ &~ˆY™½øî$Ì t¶ú\Ž×É,1™pÍÖÆdžȓDbGlY™v\íÁØr@JȨӅIÛ±Fnäe:^¾®'&*N¹êØfëZÉî’ª¨•ÚjYAqvP¶ëIb!õ¤µOG¬q=ŽÃÖ3õ$:¥Ô-«ù!v„ð-ÜáZ*ÚÀq$”4*ÖD~èÚu9MxÛ4ÈþÀå8­ }6 -G‘Ë^:Oj)!;øÈœׇ`^ìÉÝN¢Î,ß¡š†^…t†ØŠ1¤I|芘j5T'†ìØçÊs•¿›ŽË(‘ÜÔZ -8¼h Çl'ÑSHäó†4óÇ(µV’r\–…D,“”ÆÊxî±6|Š˜naw”Ÿô¹“}üÀñ8wW~óT¡P£Òõ²É:uJ¾žOvÊý ¾rW¥R˜ rˆ#‹"%F6‹T"Í<Çaž;5H}9þ¢ùŒÍ>Ý…Ý$9û%Q-ÐÁ§jgÐx¢C£T\åd¨· +Y¡ãËÝÊ'Df%§f³"²ÑJ¤+æ²ðBùÁõãÌr51m)ŠuT2çSÕ•2…–žö…Q t‡øáa1¥ö&·?çTHßÄÒ†ØC4ÎÍ¥ÿô¨)÷5‰ -4íæ#Â:{%…uÄÇÑ*O…8ànßažö :|Ìî™ÑçDâã&,qcx ‹ -Ðäì´R¿&Ã7XNÂX»ö΄ï¬V:ÂôÀ®Úžè Al&l~ “hd²ý€ýéy‡Êì¥røgßX|VB3:l¾-™ñU(T‚˜\A%EŒ#è „ÿr¾‹PFªÐ5ÖcæÁc–Èîˆ8KècQ1¡¯ÚOûµ¼Ô–ÁŒ©B´W·êYmùõ'âÐ…Gµí`,n‘€ë}cùÚ óó‰r8.!~N¶u,CZÂôËûK5"CÍÏ8¬r &€ÿÅ@™íºH4Ä`dŽÍ6ÊÞôPn¸8ôeÒ¡ðAB'A:äør„ìµ…×:ÀàUGÁ؆¯ªCåœ;÷ŸÇ<ÆñA Ä6¦ÔØ8ÃB3Æ–ÞLz *‘?ø£ý@œhÔ-Ñ~ôѾ#mï“á‚NèIµ4Õ3½TùeÏ -ØÐؤ…(õ³\ÍUGf­” ”‚¹Ù½®-­g‘Y埀.À£CrF'²ßÚ]ƒäBCAž:QRÏò…ÃAÐh|¡5€Š¯}Þ Ì:C.;rTºÜQ ;æ@„¾7íÄOÃF¸¥zoD‡c©Ý'ú*—FÉ/ˆ–ºC]Ä*iЙ²Çܽ§ h‘W -Ñ‘èU“ÑW-EŽÚш2½{±Ny‰“ÕK¬ÀIMÔÅŽ"‹ï…RU"Y$‘O yûÃdɉÅÌe¹¦ŽÒåJ ‰zr±Æxþ^Ä¿¸7Vv’|¤LQ^²è8l‘$¬¤Ê‡ƒxœ;¹-³^(‘CA&dŠ6ô¸i±¹[íî;¦ ´ ð°Z& -ÙÂëÛ>0,¬„5š…gò™‰ëràéæ†+E¥ÈŽ$Ä)èî´ $|d@¿@=DnÑI?ÈÇj‚Äå;qLjóÆj]bÒÐp³Äl*«»ÚÎPä+K#öÓˆ‘—¥6Ïîÿôì­t¶¶K¬‰Ì¾u²DÇ®°Ù†$;SChëh'ïŠ-Ïh~.SºVN>¹€Äe6Ý;v•× ʧãc…=\tÅ3”Aö‡c8Eá,|Ù±àuøfˆ= %ªË GA-† h.®н¾µd±H¹JHù©fˆïE<6·:d?”…¨!ÑãÀ%O‘@÷SœÅ1í¨Øéu,{*…2ÿð]•"ra_ÅYËΪcýƒöV”í8‘°> {Ǩð&…aÄva÷yï,²&í¡#¶Óà` ½°©é†³éV™ò"µb‰˜­lΕ¨pEჵ‰jc†gšTž¡SÇB>!ô6(1ÈB=|—Ñìò90Älj /œpcƒ€Žt…¤£ÍÇä<Ë®I©«aA„iYñ ŸO­+Ã3(‘£MÈy$šªë1¹,RW¶¢YŽÄ„qHt¬' l³¬YÄ…ˆ®&eËÁ&È5‘©¡f›‡ÔÁqàºzÞšò0ðkÆÌfÚ²òÎU³fp˜‚q¤•©âˆu‹9‘VÉ -q-â,…T¨øéÖ’Ï DFûoöÊøÖýIžó\×N5ª“žZnÆlÑuLöÅ•Ö1ÎÂãøú!‘í!dÕ•À:ë—CE»“R1v šBYD‘¨°,øN%šªÂF^§»cØÊk?|3o½ß?|;OYTÚÐóÇ´¥·K›ÇÕïsH‹$J4½©zq·#‘ÉÕaœ„Aš[yK|3R¼cóΰ—úoÖAýýê†Wµ2°MßRÿt'¸³2ùäôÙÿ‡?á4Õ‰ØF/&ÆÕؘÐÆÚ±îk¯îk"ÝfX©FÂþkH¨RèZ€- œ =tÉÍhà ždLÔ ï‹éÀC<Õ™ò•Õ$c„í‡ãêÂá[ŠpÄ%ÈUí0^’0YsB¬˜£rÖĦO1Þ0fÞ1jÒ Gœ²z¥dâ”c¾3Âct~ -íB`¥ò#‡ 05ñè†%Êq$6±ö¸â{=a…¦¹r©ä@>¥ù³¨\ÀH‡–M1@|F°J2ÒˆNX¹´åÃ`.# -íÁqÝ.âöS…­™žãñôR•Î–Jt2Ÿ•m:Ñ0³Í;1ÁññË$(ˆX=¼Œ±&hŽ ǦðÔ©—•ÀuÏn9å³nœž[’JPNmq—Ë÷N_qØ/$®[Üå`_e™êyòp ­%#¡<ófõAøŠÙËc°ÉXD)Ζq§ç†8óqê…ÏÜî$<ŸÏ†¢n¼ˆÉb8'I·p˜JÂÍ ’p@¿¤ý7u¡Àa!õb_øOòá•°ÈÎ|÷ì¡:‚”ßeh¿Q锩2À8" @Ã-´=h²TÈ;û‡Â|"ÓMÍdæž„°äß -sŠA%Ɔ½#ú‰d!˜p ÿU´B–‹Î†›BË+–Ž-[E<[Ò> …zL)Iˆ©ä­tÚlIØ@¡6æ·YKRn*쥸RȲ>D¬£@%JqúÙ Dè¥ î|­Øj'Gg9j\™Fîž)>Þ4Mhq¡†‘FârçÖKc Î*zƒÈ¨˜†5ö‚Ê %@Ê”DF”w>a¾†ÀcÒ.NôÊ׸ ðd2c„/6Þxâ_i „ %²Ãf‰0€|-m–ŒÝ˜ª¾„R¦½›Ã[Äi‹'™ƒ•x>}“ÔƶáÏ€`¶^`CͲDc:Že®/mñ?Á€;b5‰€ì@)Iý{ÌR$–ND0Em¼SƒLÁÝécc¢‹+Ç­F¾ ¸¹¥T`EìI•6RžA|OYÒp–΀ïê‘Õ3Å•a½ ¬HNÈÒFKË™èWbêÆÀU;Ë@2òÆ\ÓYhh%±¼k¡vUßc…»VAF‹ÀØBi2,„“çêB Tª –_IK3ÖSÞ\c õ‰)ÂWª²6a§G.ú@ñÁøa| ±õPc‚ª€g#BJC¤ @ˆt–(‡ÄŠè%ÂÉF¬¢å"7M¬N£1u;îd:ô…â†݈«#ùBÌ…H÷" -6Uµ%Ðt…žÜë;Œ%:|RÕP|¯o÷ã¹—ù±£gÆ Ç: -Ù)ú°Xý q°3Š*i”Wm-ã¤î’ ¥“Ò ™,)䤸hÙ'» Gj ænøêgÀ`‹„ƒÞk1l<^c©gÐɽ"‡h»M£U†úBº5ˆy ÓÁ*vXÚI -1då @j:tܦ¦ÖJêÇ–ÃT)Ûü”ûRlcÚÊ+FÖ@ê&!¤?uᙄ % ‡õ]a%DH‡JzÞƒÄÁÌ&*L.á}"¥6f¤òerg·P%P@ð#GbŽŠƒš°_àü‘¹="§Štµ8 -J+~I±n©”žJµ©s/fE1l£•Èˆ§HŠ)I;W\=Â9ŧ[!ÇR§®2ò¥¼îŠWC!ª8dIù$Íã0aÍ€WÒ|¼DØ©‰ƒo()l¤ôVìƒQl…°áÌC”RàÖÕMþÃPWì.qcUÞ"6-3žFÇ•(ADÄg Šáˆ# íáãF¥'G–‹Ç6 úþ²ÖFØ—)Êã@˜ªª‹+²zNÆÃã(cŸç”»AøóŸhÔ'œwUóeU©Ð_kü…•q˜$*ÓÞ qÀ…1·tÄÁdÜzÚU1M‰ ZÚqÕY&nê‚Ž#ÝÊzQc&b`ækŒcÝ:Ó‹{¥´åD<#‡%´fr¯ôey¦{S€èëLð¢‰\Vœk:~ñ½¦lJäK€M+·éW©kUÄP_1Ó×äjg̾ú+Kj¶yË1>ÓåÐoÄ| ;H>SÂâÒŒAvkeÂÍüŸýL9„WÆËXúdv‘±ËZ©„5ª \HièIÊâØ]t=1 C…dšúo™­ ɉ憎^â©áÿôÅ/΀p)VêkŽ,y”,'ÀH÷‰X:P9xT¿Kg‰oDV´Y½Pæ/O ¡ž§‚c@iªÞ¾L"áL`=‰œ&ÚØÇž0D¢Ö•¯ÙPdt”)’Q±ÂØSÈ<‡•›k]–ÐLA´ó½!G%ó¨’P¬òþÂ6zL$av>ûÉ5®#ð"‰8¹{™ù3>&níH3¥^æFŽ,:ÀÍð ö@Îi=©A5 -»¸›SÛk41Pc–Ö K…ÞÆf{¾¦:„˜p†f‚8–Ò†ÂOˆ—åüÛ~Ä®ž%=Ê9–¼L_Ÿ+b`È áBõHi”S^·<;{f>¦)–uôäÏ„§`QK!`E!OÎÌ”8ÑiÄL°”‰Ív7 ½¹V°1ba? -¤Í3ýáña¦Êý%Ù™œÃ´$x°/Ûø˜·Ë¼FÒ¾EKô¡+XÉ$!ß«Û/"…P=ÌŸOÂÌZDdÛÇ_Eçó…X\q´½O%1ä~sS™à‰â½¹±Š1oäÌ1\&:¨eõâó¥4ÑHPQÕ5mfg;f [Rž9С!D>±›>väa¯éi$…{Ó¢µ:Ùós ¸ÇË7‰Wl\î5œWeË{,–y:;'Xš€ÐBögšo ü2H, &ã†SZ{ -š4R€;mÅä(ZqßrÄ`áµS›JçúiJžpØw•Hç’ PÌ! BW¹Öp\QP¹¢ XT0Ëæ¡'‘®H §5.¥VÏ|fï.Ó¤Êéï\AuÉ¡ð-™Þ‹÷ P”¿Ë;.×åc/v¬1ª–šı›tÊÄŠŽ*XYËü¦Ãt€„sÅ%gbÀÄ|`*ƒ‰¡NP7b©AjÄ‹hV€­a ž(ôâ´JM7'Õ½"Eþê~&VVr¢öˆ2K_Ú)¶„¦é’œÙT+{²X,ÊXI`N‹N$EìzÖl—ÐM0Ê2³Þ¯T錈å…Y# žæ² -Q/ÂÉN‰è\¨¥@^«”ˆ©=pØa¨Z቞ :™™ë¡=aCbxÃ%JŒb¶âø˜IcËXA‚í|<E÷kÐ>NqÅåX{\;]ˆÖ'¡â 9^ÎcÞ\šœõÐ_ü¡gë‘Žy)09"¦-_¦[ŽXǦßrÛ#€Ý¥gˆNxÍ,³Xö*]„¾¨L^1pÆ®Á]’#¶ÈªRà4¹W¹ܼx—²´Sð;¼ãL G™®q”áǾ}s áD™8(y!cË‹S -ivY½6ÓXÇY9O5ð9$DÜ!ûTÚþ`°³J(z4«€ˆ¡¯«%æ¢D¢|bëÌJ@ýêëÈ"õlÆ€á.‘F39Æ‹0BÞW ¼¥‰Ãøà›_&2$ºo=¾àÃUl‚Ãij#€eÝávSF$L¶\Ÿ.X¿-c æ† º°Ä†I›ûø4´/`®Ž5«P¯rp;^pT•F¡Œ¥È W'öýtÜ€¦&|–º4Ñd9@_ãÕ%ÊÍÑ‘L ƉÂk“ÄÎ…¡+á¤LRÕ€É$Q߀+ì—šŠ6†utõ`µä»Ä4`—­8šÜ¼QiªŒŠn{K Væä¯ (ƒdlµå@ƒrPBF4Z†`¨u¨‹àªwe†u«r -àgé?ä Ž‡+S£*œœú¢ á­ ŠÓŽÌäÎÐŽUéð„™Z*Ê”àè‡T:î)?RÝœˆ¹ÕÉÐQi)tU†é„Šæ'|CÊfZL+„¾.n ¤‡¾õÜÇ›OrÊÉiÊöÌ(®Z[o".Ö U ÙO‡´íkê„L«MÌE8Ç…ä ³.Ghx¡%èMÈUæÊÞ(ÉH…‰pÂñyŒfTjÞg?åÞɉtM6 ’dL‘Êd“i‘ùŠÅ¦ŒþØ:ð€tä8*àÓcœ ¸¼ƒ/?¿ÈøÜËO;*ŸŠ”ŸpO[*žËT8Ãá, ÅŸ›«[þÔµzCrXîDªÛCèǹO&SŠ½¾x c2x=SY‚2+Sg-A^j"’p9êöô#Bá|î*ERc®IäLYE,Ê›Zí•\¡ånSÑ+©ìd­èŽ-sÝÖÚ8ˆrGo¹SXŠWÙ…\ÉÙ\É1]ú…™»¢»»‚k\kT@ëi¶‹Æ~ÓÕ}áˆù X¼ )Ê…Ñ( r ¯Â–D>‡"y‘²6— › …=Z5´«¸‚c§Ò\/dE€8QO0ù¬ÙëÎaqEV(ñqèAEB !££+ƒ?Tp=+]EGu—vE÷7—¹¢³¼‚S½ÜûÎÏWòÔ7áÒ/qÿ×f3ž ÙžúsGÓp q V©GâÙ ¨ ¤‘rÅöÀÅsÅ&ÏÕ{ÙžXIõÄ=€hVvE‡_¢æsœÑ!i¸“xæ2ŠÞÈrÒƯ4ÁÂΉ[£â¼¶~Åãû²£þžö…M¸JÜ µ¶9ª¥("V!s1Òç…a¤TIªë³Ñ¬ßìå·d7C±¨I^~„×LÙ¦)-3›IöˆpŸ *­ 4©ÆJƲCé9DfEìf%œ'$”3BBèI*âC™Õ©ÿÊ‘'Ô¨t¡ß¢\ü´aXÓrþž¹TG·ViR´‡¦ˆ}™ó*QdôNãÅv=EË&‰Ä‹Î< b"Ú{å!™l¢pã{¢u¥5J“ -e”(ci‰ÃL³©è^«äˆ«ä´ãÝ“Ò‚:X žÈ´qÐ9È…“€‚½4·36J,ãGQ e |)sEÄ~¸?»¹B(@Å  -œEÅp„J •‚t[U1$¢ ¨žR1¥,æEr¨ SLÓ³ìî,ô¦bN¥€K¡\~L9ÈþĶð '’]Ɖ*¤>…#//ÅÈ:M<=Ù3vMÌõ¤®B¨sUÞ'›ÒDk•Æ'z¡'h¥‰OB,> -Ú9dYH|¢·=«@iþ©8–çªxd›qM—B!2–øÀOuô‹¿ ›L;¸êöĆ5a¡_ßËë#Çe4Ç1…N4QDL´.[‰ÕsHŠcê#Br(¡"Ý-£·p—}ƒ~ßß9mˆ^zÞÁ‡÷\ßpß–-9™"ó?wÞPü’ð/Ž4ÿÝé²ËëjëkqFŸ!—ÕU9|äˆ~Uk×ô­^ÕixSˆÃÿVÅ?V× Ø¿ïðš¡ýú×Ê]‡ غʯZ_õ¨ˆÖnýSUK“Eþþ÷·XS_Uéþ¢[M%›{)‹&_Pü@ˆ:5Ô ,¾•²¨p¿çhaŽ˜5eá;¥ù›>Òi°iÞ~E7W÷«8 ªKíðþ—]6°Nï¥,*?ÐÆt°öƒ>WS”Eß~xÁðÚ!G*FWóª:× ®íŸÝÉuQéö jL'­2pÈðª.õÇ ¨k*wÊ‚Ÿi7²O]ë?UµângúiQ§û‘;oc:)÷ê$øzýÿ?»‚èWÔöfÛåøÅ!þ/r²ÿc/Ôÿâ¬ïÒ‹Í?=þRc3´ÉýI¾×/©èªÐVsbþÇcÍOòf§¨¦Í?}úæØ‘Zw¢OÎf,z±Y/¤µÄç¶læ7ÿ˜¡Òp7e+žvÐGÌÛmðàšAu}ªüÖUúôÖUâ=Ö¡ÑDYdF+)„åKå—œ?ua0K•”$úëV‡1¹i»´VþÊm“_JŠÂ÷‰½ò×-UÙòSR´¤¸ëŒö=ºRõ LùSä.õ£Ö8®õ¹ƒ‡\1˜þaLÂm†Œ¼ B:æªZŸg -k̺Ög˱¡Nol]-Öb»þÍgâQÓú®â8õOô­å–¿Tz¨K}iºÃ>tf͈þµù'P—‡}Ä£¿v.÷šLò†¯ù¦!õÿQW;ÄX„}ð#ß&ŸVÕ\ݺ£Éºî?«N®:®ªE.Â'WÑ[«N>®ªuçšáõ¾¥zÈà>#û×7ñùPu—¼ urøWKæÆ3MÇ®jÑmD]Û†ºÁúôÁWRMgUG\UüÿŽ !@Ö𺌱ƒQHG¡3ûŠêÛ¾¹™µÍ£µëðšÁ#þsÈðA¢÷f_ßÂþÒª¦ÿPÓóy°™ßëd ´È=ÛºkÿúGìZ¶ÒêõI™ŠFü)ÿëðºÿhFtÏJ‰=s¤õÔÕ˜äµ5ëº_ÚÙÌ-uƒëéÇ’ŸÚÕÔÖ^”ýÒÁìÕFTÊíì¦s;»87þeøz3·]úÿµ÷Ýý‰ãÜÂïà; .˜’j -©¤N’ILI„±a÷™ýã~öW’›lK¶ dÊîìýÝy‚-«®stÎåNO6Wb{Ué¾(Ý®c‘ò 3|ïýƒ¶+«[ž#ÀR‡=mdÃLÞËÃQOû¼`ôü>ü .{Œž®ÚÀàoú.D0ÞRñcLhÀ‹&€v/ÂJÆ“æHnmcµóÒ=ù««ôåÑ•¬ôdØ3jv~æxÍ™ÛgÌÑÙ@r4€H¡Ò‡ÏlLÄá®{ñ+Ü¿+Ï’ô”`3XK‹šÔ¹bXxÕ^åÍ«D2¯ÿðª_žWý$¶3ëUâŸÆ<`Sêwé“AßU¶­™[ŸS§ÊTÿ×mOàÐ ô­ËÒQ†£˜Q󵫴ºãðÅ÷ѯhîx˜˜NV¡·ð%•€FZ?j/Õz`ºvúžóÍàæ+Ø͸>Œ‘7#w2;ÓÑ(ëìÞPASìãüør¤ö:Ý -Øhüiì4ÆûÃöÛß=µ«©}t¾MÔñ»%Qô/€ÝÞûÇdF®…B£L*¯ôÔQ_þ®ýLÌI@~i@Ô°°!¤oÞò ï"Ös2%þ¶R±?P¾føf—Lèú(…ÿÝÌR‡”’7|ñwW~së<ð)]ßѾarõš’aàÚëPù=1å.fhŸÈƒö«íÁp2¶ IùUÓAò–0’ÿêÚÕ¹¥û“q×h »òƒdR0‰Rjî7\Z/ -P³%Yù*ÖaEé|U*Í Ÿ6w;òüx¡ý¬·úç.<©ËUÚ^¸ÔŸ(T|±µ -Œ7/C½RÏh·Û,ïï¤ -hÛÝÄ"à¿èúþ·×·v í˨tQjÅáÃÈÿmµÆ;òXF*‹¡^ÂM]åd€ÅœÅ0ä%sÄÿ!ubOî)á’ 5ô_N‡øoºL’JŸE¢©ôúÄfž¥”åaP*ÐŽ²1áÝnÚ}¼YÔôg¨ô?ÅÐs.;S$¨|¼¯¡É{›™N#Òie62yv“ hhz»Cî ÿv¾Ó^Qmûœ Ö‚S¿ê ’B­þ ckÐBâ¨7&8:²ò¦.oÂn@oSŠF€R(ĸtÖLDÎ$S4³”!úÏ@ j»¯à«j«JûçÈÕŸ%öÛÝ_ƤŸ•€¬°îÀE5ús*ɘß1»B !˜¶Áà5 ¢É¢:cÍò4€ùþcwJêÊÜ,Jÿ/nþ£@„¯Ñ¯-/ ©/iŸ×.ÅN@sºï®`ØÿEí$”fÛ‹ŸbÙÿ9Vø L=É~¬`{äXaî–cNÒ­üÏ0çÔ;<ôcd±ËÆ)¤›ûCº?‰tÑ¥/“®Õ‰©0~iÒÍ}&åþToÃÕVŒ3¼…ÕüÓ8,hQGæ­òDöºÿè>ÿ©"û'˜ySM0Öþ¥Úq¼ýUN7’¹eDŽpPg‘ž§k˜^"Û4¾(‡M<Ø4þÓ8ù†¯/·Dõž‚Vß^‰‡îi€~k@˜ gŒhР·€`DÒ@ñ9?'DC©‹æµ²8æUÝy`ÄŠ¼vAEö·…©Í™X¡ã ¢ íT:gÀ+¯§–P ñ9ñæ?  -X96lPª tìÈé5±) ø«÷·Eþ÷…Î5Í„+Ü b8೺p5keP@Qø½A¡³Š‚dˆR‹kšrÃ<€€€è\³ø[ƒÂHÁ1U)(xã6Š‡ÌÔ¯¸Ÿœ§óŸ0nLÏøYïO[‹ÍZk œ5ÝÞFà,)L–pÞÇèy3~L¿f°ÿÀWкýªEöý|Ûð_‚Ä›ÑàF’´hgþl~±¯?×ÑÆ7ïãfsŒýŽÑ¦jÀ6SÑòMϱabÒO -ÚÚ fàþø׌ø"9Ø?,6FE `* 9Øæ­Öe¨·ÌêG¶ÄËøûèg9y5Ö|åÆÏT&½Ä¸¿ -D†õós·}/Q-÷•=—ÀCw!…÷äþóx8覵¦DÁgoÉ*ý¯N-÷6Etkj"·ÐØ虿£øû›õ{[í£KðwßúþØ~ëjaÊ[WÝÀST·ŠWV¾«cXíoÈYÍ>ëÚÜíð~ß‚ï¸{–ûEîžæÏõKîŒ/_ Ò»ùëøÃ:~2ëÈþazˆ–‘ãd^5¨GqÛâØK‰ÝÊþ£xüá?€{¬ý¢Üã3ïø‘ë(ü,³ú®Þ‡/J﹇ŽIÿƒ3Ê12fD£ÐKÁ:ô*]ç1Q«ùBÊ1.•¸Ùœ¿ÑE=ë!-95X>³},ÐÍ“o“2˜Ÿë;'gæÏÊúM=þYÚõÖ×é_ÈÓ}þ}QÝþ¹4—ónÿla~ÿl¿ÿ¯qáçÏsdߧò¤?~À„q³÷>ê›Â˜rtp>spW{‚4[âH£1¶T¡¼:èìšõÉ}‹œŸ”D„VtÚb//¿;Ÿ«€!<7ÿ„œÏC§m7´âׯ½qW{7sDØz Õè±^£>»íöa¦Šö]ÐÓUð}£÷n,aʘÐÉqïåu kh™]÷6[÷rhyÂœ¦p›7q„ãûÍr¸?|†[ðsmÞBŽÇ:Œ|\³Zžd$" F·h)ˆ²áøéîñÅÉq5œ¤ð¥5ý1è´d"œW¦á(:iÈŠÞèÚxƒS åXÉ¥6ãY‹Žˆ9ë:R¬¦¥z%~1Ž# |1œÀ ^3/Yå¢;´_Ò#„ç´WÍïï­avóÿ`Ñ ¹ÕU?àfÆ!¦„†Êèu~•å÷Ñ J5?ê`ÉÝp¹?QÇ&u (áÝÑͶŽšþÕEåÀüêý-‡€y)]UôÚSßRcV¾wǯ݉ -L”„€ ~àÁ9°R”pmØï¡Ñ–/€}ÿ+Ãön^X³¡ØcÆø ˜-ü…I ð;~wÔíô&ïáó.J÷Ó¸YdL€›4»ãÉ(\ëC=概u‚톌Š wï†ølµœ®Ø£È™Æö¨—Öž™¢Wî÷TÇ#u4;½£ðYÔ™)^G²¦ÈÅ×á¤Ã»“ñ0|.ýÓ%9Ö€Tx„h@í½OúfuìѬÈZ9‡°5܆ž}}7GcèX Œü¿÷þ¼^ˆ=wõådvEÖZ}vsèkÕ~íõ;JW‘]n¼…ÿŒÑÅWðm|i >þ%+ê:†@xÓ¿dÄYQ[ø\¥´˜ø¤ÏDµýúM¡3ÐÜ‚~€bºÈ-焘Ӯ«ÕîõÂ3¬ `!»ð_ÞzNÛ?#$xOH0­¿'qÇ‚ø¾»ú“ ½ ãðý³Hýwâbk1/6eGåÏÃÃ5U†6Ô‰±¢ã§Ó˜Ë/4••ªÏÿÂÒø'“Úïµw^,æòi)g¼ÓÖúew¿ÿlæ+dói®+ú­æL¸ú³WÃóùt±è»˜¿µ¼Lÿým$pþÌEe¥4½8>‹zíB«—eUFËŸ¼W†qH[Pk8úN£û<>QzÚQ¶ïÒÜßüÂq½æp¢´»%èÄøéÒȨŸ=…÷îXÖ¢f›GqÆy,ttW vaî žïÂo`&'ã0ôl̦º›ÃíÝiȃ—‰üÒ ŸGFûœ$‰Õ5æÊa‡JBV(Ð[ -axÞ2ðœpOöåq7Ü‚Gz~=FŸ¨1r<)uÃÝÿÃÕNo,·zýÞø;ã|[&È}'l5å­¢Ó°åQW}5]Lȇ„ùÐì,6G§l# Jû;€B¯VMÏ”ï$Løú® ƒ¯ÈÙæ{2xÏØ¥ØØR³Ûß“Çaöa-ÛýŠŠÞ’X—Ù²1lË}hÃãmñPÛ†£ÚAö¶»*+à;0zýÚk¿ž*Ãç^¿{Øýn§y[Ëê{«Ûqµ´akÜœ´Ôî¸6ŒÕs¼k ÙlÍaü‚îØõjvZ©Á– C%³Ø¦éTHÝg¶ 7ºuûnLçÂϦ³udà<ô9 ãWõþ Ýï^@Cïƒ^À¼}¾êU*T‹àtÅR j-ófÚZ*åVÿêƒÚpKî˃¶ÉÆ2Ø©¥ÿœ‡šN–Q=mš¥9.ÌYð8sCM<à%„w÷å=T%g‚FÉX"<ómØJ·á©ÊØÅðÍF€Ã†ðÒMxö¦´PÔ.V±¯ÎÙR}ëZ°o&…éŒi [ûƒçaØ"3Ž"µN0âìPkR7‚¾a¾©ÆüGô‰ÆŽ2Wn”pÜà©›mÛ(w³2Dü²Žøç4ÄGÃÓ›²ŒÀÁcÃ.A zõä4¨ÀÑ1Œ‰ô”:ZŽ]¹ª—róZãrÞÔ†„‚m-ðÒb* ‹…jæ¤ê™= ú™ rw© 7] €Ã8+ÌQ›¿ËÊ›jGc†Æ&}0´Å°‰†çÁ8Ýé”ç¡©¹2têàónàöKqªÀ6º4Ôǵ.­t¶Ãö2_¤¶Â]¥”­lº MBÙp‡&ŸºÞ E_ÃÏÜñV¯ §‡Ú…×|ƒI{ÎYoó—Ëêw¶B‘ÃF_¾íþò'j{Ôo§£Ö¦=P½ ÚŒ{}ÓÛE¥gÕÉõhƒ(ÔOb(…‘¦¬ÑŒmKˆmÔIËX•H}›_ƒÔ¢…R·&:È(ß §•Ú#Ê --#…ªH§Ã~Ï‹WŸéÌýA»?q~vâå óIìÖèBÛ,訌õî0ÏD>`ªRÆö; /=µÎo”áÀkÐœ»€QµäqCþÞU¼3ÞËAZ~WÍÑbÁƒ¨Ÿiå}kÊð}Wÿ=TÞ.<µêgç–4 öaÉOÓ¢~Ù0•®¬°†ƒaû&c.îÃÞ@"Y¢€\þ=Ð"Šö¡•¼Ûþ…û¤¶z °¶@ß[óöú°ÔïØbu7¼ö P˜ù%}½d{Šüm•ê|„<á\€-ðx/}7í:;¿Ûïøz`ˆŽ¹¿æ­ÅJ›~raÆrx~xå¾étñe”%OÇÑœCKc}Þê©>¾&vãø]ò&P~]Ñ4#üZ%—Þˆ‘«®h—ª˜€ó\ ½}1¾˜4Š'K–Êu·uÕëþÍ° È äq÷âuòÞȽ¾J·¬ñýsx·9$*CäǦàBh9%€ñ -^iªsÙÇLF%iR€ÃôÕqüO6q3Ò¬ð¦º÷•®Õâ­Ø+’®ck ävÌî7 ØÜ<èf7xs`8©–ºFdfxóg¥û1±H–ÈÎðd£8‰?¨{jûý»o·õÛ·û -¨µ¨µhðì|žíƒ¬.ÅY´D×#þµß)'ÞžLYǽÞ•Ø‘W -‚¼†¼$>fky¥`È+C^)(òJìÈ+Ù‘7Mv”Ûº€¿’Ó¼ÿÌí(Ì1~àDáœ(0 °…% -{ P{8aÃ^ŽÑ9;¢û5¶á¢wË ˆÎ9–K÷Þ .®sAqÃqÝoò5ѹ@Œšs`9[kÅ•a¨áòwyà‹á\ çî Mžwy;îzc$á®à×2îò.ÜÍ=øp—Š»<;îòAp—„»| Üåá.OÁÝ#`Î l¹´ïÙÑ—„¾;ú -vôõFJC_’™ak}úò>è+C_!(ú -ìè+A_!ú -ÐW„¾}õ‹yü0R€½B ìÙ±W´c¯7NŠözëÒb0ìrÚÇ6ƒ!¯yEväƒ ¯yÅ@È+B^‘‚¼ÚeT~ø(À]ѻƑüþà- /ØÁÎâ}®•]nJãh,¹ÝÚ+™“½âzMŽ)›¥æóÑBcc·‰lˆ‹ÿì¬ìŒ¥ÉZéäŸÊZÿþ‹DO•Hde9‰Ä¢¡êèë?xImrG9ÛçÁ *üÙÜÍ?¼ôÁ‹çðFÛ|½´Ó­£yÄzð½´sõð‘,¡+n¥êÓÖükiþÌ”„×–6ÐÏ‹œôÞ£ŸÕ§öþüÙGß–ÄÂú6\aý Åv.¾´×àƒmô V~~Øü'÷%7z­¶.¸hm£º6Kñ`·Ð½$K+g)ÐfƒOî.îÝWž/ž UY^^ÜMõ/8´´B!­ Ê¡ØîáM'—Û¿ÄRqéàç¡øÁBîòY‡ÜÊÛí!øoGM¼P§ÑÈÃòóöÀÈñý6ú[:‹\x~/¸¨ñ0ú­Þ|)ƒ‡'#óáöø}öÀ /ÿß–‰;‚•B§Ÿt‡+úͱG)gÐ+¹¥å}\w»Í¬+èìw:A„Õîz‚ÑùÆ»r âOˆ˜›Ü’žòÉí«V†Ë$V’Û¯cþ%d7ÎÖDóÅ™ùz±.n_ŒK•çbýmoá|S®"©×o{æÉv:I=vî")¡ÖŒÄ÷Ôüy›ÅHrks˪ââ>»}ò´Åí=lÃÉ’[¹•…JW)MªÉ£Æuåp?Ò4ÞVÞÒUÚ+>]Ô7C±êu©{¾“Q_62{»_+_jWÍ̘‚–ïà›Ó2@Š”#}¥›·YmÊ¥¡z¬ý¥¯´¡*J¶Òã27oy«I(f­P¹—ï²`…Ir«Yʪ‚zdLªP&·O-ð³Þç:K·¼ÛuõFyHTŽ¸L¶Ç×üØ-ƒ/“_À(Qam|ÈàlO°A.sê Ò™ø¦Ð}R>Æ—Ö `|Ør+w.¯ -ÄAÕÂ5Ot/[Œí¾‘݈.…bêòâpDZ«2yJ/Æ[‹ç÷¤A“Bƒ¶ÒÜÂÂÕ—cÉ`2¾o·_¸Z)wBp´ö­°8×OIƒrµçöuÐPlIÈÞVÉkÍÞv¸z]¹%ïjíãR(_´bà³ìе§Ëïkú §ËË`_ì»**W™W4(¿²ÛªÚwõNy¨\ÂAnTÊ>dÇéËUÒ ¡˜ò0Ú;°†u š;æÖhƒ¶•¯þ†<èqueá#79BƒifV]•j´A÷¶…ÿ…pµ‡½s4(Ä1'*©ë±·ÌU“8h=59¦ºÜ}Ù9! -Ö¢lD2Š::]„î¸|V[ÙÎïD €ó#ç |éVôv5î4×l¼]¡AC1¾zÿV³­õË׸«JÄA£{jþmá,GôhEé‘ Åа;oå]m­®Aï\s­«’=\½?ìtScâ ÍÇíu4(”bîµßï”hƒ–¹«å›yÐƤùÒꃂQаW ~Hðe=SïÓ=ä®FâeÐíÄÕ×ë§ÝPŒ¸ÖëíÖ -uÐÇÇÝñ5eÐû,÷pr‘p -Fц=>yùvSÙX!ú0NŸQ}?M.ÝЭqg`âZOvÊÝ®Z&Zý¶š£ ZØ‹\s mP9:®£Aá(š¬‰l+“ë»,4é"š“…õÄ×Éû#tSqú´r¾¨úV\± *½.qGÇÒ”ê}ay+¾gp‘´¢¾,ÀAWÝì¡‘ŽÜ/äj`ÐÕ%Sï‡EmÐíx5…E£èŽìÖN–µAÆkvVx™\ßÛ<€ƒfÜ2õ’_Í7–¾Akç Joð1}ص³´}­{—¥ØÒTܾl4l+]¸S¥Ö’4œ›é—¢7ã³}0¨piŠ²Û\&câ†õ[*,ß^6îˆo'rdƒÛ¿OŽIo!ç——·xY=] ½{PKEb¥Å -|K`k­A._[äá[ÒD÷^G¹ÁrNDTIz?Pò'{åíx\à·¾äÉo÷—";'×Õ3ë­M‹î×÷TòׇÜC#™”&”·¹Çã­É2é-ÐÇ¢‡‡Ï§kù«Uâ×…ã/|"¾}÷ߦܜŠ[4wÒñÜÒ¥|WÝÒ Fx¿¿*o\ïPÞ–V®•^‰òv/õXÎ]Ü[oí;Ú­}ÛLˆ ò×Çç¯ßÔÇj’òöæÛ»¨fÒ[±ã÷áê[·@þúöáÔÐ oVîLìv¿}ü¸BÜ1ùFØŒ¦ò5òÛîÍqm=é’ß>s¯Ëßö£ˆÅ®Ï:WñÈñ6ékEÙ|<wÎâqø6í~+”öOÎJïð­“ Af÷ñ]¶uÅz¿5JlŒ0 ²™­âÞâ7Ä4û¬¼ºrxR#O3=uãråpveªr~I]}mBkò"¿KLà_§À¦|+GV%Ì~ÛÚ¾Ù4wÐxÖÈ™£Â`˜‚7ÈÏã€9>o˜ƒ?ÓÛl%€–­ª…ÓŒ÷)QayótUSm¡ƒ1Ü­q™žHŒ@;çÍb·ø ÙÄ=âÉø°Ø ÑÚ×Uê ÈΡ -T[`ç<âú˜mØÛ¯ƒÖ#}Ph瘃Š¶A ÀÞ‡úÿ½1l½oð>h¶¹ˆƒ÷lç´³´´` Š´kP(+m†Úÿˆh´öÂQT õÊZs PûoÑ•=­sk6}Ì>,Ò)¨ƒBâ’ÞuPÈÇjûKŽ]åS@_@ã¿ô8žt˜Ú,tí€eAj=ÙŒ0ô¨Lßb·€k¶9„tÂÕ5%ðu*ŽùnÀ_e¨Ãí#ÀjR|ýäÀø(¥ÿ³Íí[Æ:„öYVͦÎm:ÿÖé`qËwe}òy Ltm¸5Šw.œ¬ _ʼv+1øÏ‚9À ->€A‹`6w~¥ô­¦éÉ¢ÍûØÞÖV5†ý8£¥1Ÿéî2«ñéÒ‡ÑD_®5aî@ŠÅÀ(ð :ØŒ}f'æ -*É­–¸‡ƒ|ýòü\‚æÃd…4%Ë£MJõžT¦·°–BÿhðÔ|.O òÆÄ9Òù‰@Gÿœãv5a}ÛüaÃo}àh%É7ï·¯.Žüö/u¤ã‹fÓØÖ‡FA+\_ñûþÕ›~~K*°<:»bFvÜâ#‹{^þ¸™³,ÈjT9äåÅå½Y oÂ=C‚»¾/A!ßRqݧDb>`Ê©“õTïË#|sõž¬GóÂÙwãk•¯>¨u³ ‘ Àúá’®”`W½?Û©Ò5ÄÛSðŸ;Ümê‚]ZÁ‡¶M¡ÊѾVÅÅõÃÆ,KCþ±ûP/i4D›ו/©« -ÅŒu%–Ъȼý65B‚bʦz_IÛ0Ý$CžsÝÓô’]WÇ·i«~ÿA Àä@€y^‹¡Ié3i,)ôÀd¾ Þ™êZÂêcvº“£ ⪃Š|¹f65žìÞËT5¥ý£ï•vHáF‹–eØN]îë\9¢ ”,Gxjg™×arÓ=¯µšÜo BéKñ€Œ°©Rœ …ymÉ[a„6Ä´^Á¤À×—Š'¯ee=u–šµfD•–`ò×±ýíÔí\Õ-– (†b~ûûV˜Ì¬=é´&ߊx ®/ã;¥bÔCVZóaPéÀx¯ ´)íX4kí²’(;è£Ò=N–Y÷/óSéXéó­ ˜¢ÊÙU(6Ege¹h^&·twf(3-ÊJ6œg茪ÕM1‹×ÎbvŽp‘º_ËôÃ¥›ÛU»áºI¥:³vœÜoi|Ñ‹¯)A¦ƒ—=Võ:£é -{NK|jª|Ù{˜”ÊÚy,:Û1*WÕe%tØÍ>7l4M n÷é;«±@Ûi•ÊB1†©a7ñÑ,qm*~\€e"vÝÒ˜ˆS·ô‰Ù;,Ö˜0u»ˆ*ÝWþSâuz™Î¯wà qŠ‡$±¤{HȈÆ.z¬ú;Г× £ÀÏ(fpÉ8õwsiˆöñÅy.->¥{óŽ¸Äò~Ÿ÷®«¾];¤ŸYXÐÁ$¸Î%ÅÄÅâGvJÀØÀò¨øøú¬ I‡Ž‡¿gÃ} eÆ"svUúЩJÓ°hŸ¢L¿0+쑴Ѿs>ÌšðèÐ. - ×Îæ@/‡NHãJx¾v± ?Ñ®[²¹lÅí˘|A¶Uwn|ìž `tèv¸| » £0CÐÁÝ7´Ytò ÐaÐe‘n™ˆ'íñ`U7Í@tçaÂìô*LáćÎ÷Uï5‡˜åì,Â^o«‹'ÃθYùJÀsg“=qí»È³ŸX9û±’ÓÎævŠÍ£òI…ÕKˆ±ŸG%ˆïß)÷,¹:³ŸêÌá¯7–¾irKðÔi°ºÐ`Wvqc÷ór¼ÀÙzúPÎøhJÄÍ#(qõÓÎÑìTù”X!p´Ë™9šµ/WÃ9p4õÈ„pë•£©oôCGC'ïdS -v&ÌÌрЌÎNû— …ö/gæhÈ~Aý̬S ^æpöŠúy¤ípÝñeFÇ!›.€q~û–­sTwƒíèÐåqÃÃBõ‰,£“÷­GP×”„Õ_!3ÚSg8’ÛÉÀdC166 :óÔê½™¬'ƒÎfŽ~€q:N“?{e&çê}%ˆ)Pp ôã£È1Î&íðöLÛ‹&bè‡N9þ*9~š€:ãgèÌîÈJ¤²Pãc×sÓïï?H²0 Åm,F’…!w²±Þ“ùèM»Ê:|°S!ší.Î.Å®gviY»?»~M•…Á¤Ø5ƒ~OêÏ®5ú™FR6ìHðð'—†0$<å…Vä‹Éù§–†7^Ne=tJ‹èÆ1¨ë3û:¡m‰ ”AROß ±à£Q2kº «,çg¡îµ¸äçU``ÜÄ ê.Ñtbò #{žRp¸®ž+ÿp:ç”èDŠaDˆU0¥ FÚ-«X -ù†Ñ“ÒÃHcˆ\³Ûû·ÎXz(Yˆ«tóS´-ììÃG´`òÅûôv6ž‰Ýcñ'c*†ídÀ¾“Žà[šVb”Óà[#2‡ñš”ãtªXU\OÖ‚Â ãáùrñóÅ<¼Œ¥ 3ã‘ÕÂê#Ê¡óΠ Åæ“CçAŠÍ'‡Î;ƒÎq{ÃÔ9tÞt¶lÁrè¼3èìÙ‚ÓçÐygÐ9³§Í¡óΠ Åæ“CçAçÈœ:‡Î;ƒNÏ}›9‡Î;ƒÎÊá-‡.é™AGõÌ¡óΠÃ|žÉô´·ƒÑk§gí£ÏX§dZ¯§KŠ_àöf+ÎHŠr±ÛȬžüÓ%ŸXrvO/€ÓiXrêÖ-Gýâ”Xáä̲±‡…tÏ– – '«+—ý;KÍi}fÞœIû®H:Öõ¥¦%2äì‡9§„e>ú¸Á<àä›2‡üÉ>¾c6„½M)T³öK ¢§'û…‚8,¾¯ÕYÜƶ¥­b1ŸQj>K  -B‹´¿MHÁ AuñLžÞ*ë±a%‘Iæ§Ñu~ÆŒ*Y 3tFÍÏBg¾ÙC°€ÍZOÚ•ˆš·M€'ËѪOÉÇèuÆöÔX“L}SLåšÅþ ž<½m_ó<ËÖÜ$„HÇaÒí&éÔˆO¬Þ -ôÄ~†,0GßÝØ[`Ïã³9[1ðòÀ|s‡Ž†x ¼Ç¤ÆÛ1ÉžZˆ<ð`RôxSdÚ¿â"iÿ¦‰"py0}÷Ï+Ï7'†ྸïA˜³()2Ø™EÎ<¢êƒCŒœ33%ÄèG!I¾ -bvÇo^q†ÖÃL¿L.6ûeÏ7Q'vªßÒ?_ŽÒ…Õ•áX™¼öu·‰Ôí}ÔA>u¹v=Œ=¢*&”n£Kv¯uð.nY¬ëXÃ3â™*ǺCÍCOqó£}0ˆYiB p0äÈâúLpxi.{þWž,xùÆíz¤ð ¶Òv=rß/+Ö¡EÒ1ùAq[ø¥Çyd Ù¹=#Š!=™M“bÉø¢nÚô±‡q|i.pZvLÉAÄ -'o÷Ž<%°û>w¹ñ’6%1˜óÊ° ä‘¡F§[iqÓÀÉî‘ÙæT×ÝâbqäcÓ±xd¶ùCç (SD©÷ÈPcàßæä‘K[ž=‚è€Á#bIC›Ù#³‹3x{d°ŒT¿ü¼<2†&Pz=9À&Ç„ÉlQ;WêÚYÄ?nœEYÎ#'qû’÷Ž`54-—ÉÈ©3:dˆœ ù§¡m&fNƒ±£^7‡±¦yßb!]˜96Sþ¨fñN¯çÊ«£¤Ø3…ýDPrý’* -õ⺥#TŒ¼°ì8IÏâÞYDAG°_ê§ïó·#ûùçÇtÿØÌùpz´##nÞùpÁ"T§Í‡sÆõ5ç’=â̇›%[=N…8§|8#Ùž7ï|8Ý£8¯37J>é–€¥¹çÃ7·x…ZN•ç²Å(Ç:З2‡”Ž•Ýšê“/Æé¸d˜®[²ÄDº¢$¦£ýËÙÓë!bŒ„dèÇ}­Eà^ØÃxžr6P‰Ÿ9“ öã{©ïñ|ééóI'Ð æ CÂQLb @†"´Y`#f¾¶ì¸!»óÆiv2¬Þ_1PŽQÉ°zUt^Aûev2¼Íå6`ÔO2¤E©Á~æ@†°·-ô®­†ìp›bOå0°3û3~·Myx¥¡¯&qEð™c3¨aÒ<2Rï?昑 -:›_FêýÇ2Rù¨3éfªŒT9z” -Äï(© Ÿ9ðMÐ v22S?,æ“oF*û5Ð.-ç ÄãÒÔ AF=¤,"4GY‹ûl#Sá,>4['H*œ¡ÁÒüƒóI…à ÆäÏ™..˜ßrÚT8»rN©p^è’v^©pšW!Ót¦T8Ó?Ævåç7ÂS%rKµHL‘Wg-RåôQ´ŽÎ¨1Ž»È°3ÊE†Áu˜–j¿dxÚÔ†ݨãÛE8À¸ºAŠ1ˆ,¯Ž #œÂÁðŽjâA÷iUãˆèl+ž¾{εÁKªòuóqó¢òÆ—K™ƒëÊB÷ YÙN6/B±ÍáS2þ®Ÿ‚–ËåÚÍ}­#,oE+š8Bî^ÌŸ|åÎ;+oã¹XŽrq W·§¶U{ -ØÖZùî––ìvCMvS&Ok¼cP<ÃŽ«q+G”As ‹ùóÄ-ÙÍ3Ãn$zeØÕ¾\R]Þo¥_h¹X G.–£Ÿ$`ƒÚSÀÔåü’UêÕ™ìK\ö)Yg Ï »hMNSåj‡§”As ±ìq剞a÷è•ì¶˜£Z?[øBÖã‹ôŽdZ†Ý¹G.áñá}Ðjõ²fóÀƒaµ Œ¿ô\¼ÉÊfƾû”vb™óngTa~ZYÛeè1¹6W-Ñ Ö|›u*¢æŽ%N±|ä²W̽oÈ­#L~eWJX'DšÜ¯ p¢§ölËœglE¿ìš°ÿ”È1W`ReŸxRÆ,?Õ?æjªJr„)ÅB¬N^ßJr¬^8tíÙ\à4´‹yÿ¸¾ Eä|½pÓ‘cYŸQ÷5V×oJ¾µ˜Îš+`M‰èU`¨Ç>%è¾ñ¬,I -wªËÓ;s6³f¦l:R.±9eÓ‘–š{6^æ›M7kæãôÇØ–DžW6I®›¾ñ¹eÓ±Ý2k6]‰‘]¨³À‰µxž¸3±–pE1x¶é-¥Ùo„•é+4<[Wc!LvQAù­»â JR½W¯j ­%œ‰ à™O‘&§%N¡¾d­Qí™r5œ&¡u5¿ -†WCÖDOÚWߦ¨Së Õ_Ù]_ Í¡Æë–â©N«Q?3åsu¬\WO»*{rºý†CÖT‹@%2øðBÝkÅ•O´üᳬx½ÆÝlGäF…;ψf2ô«p nõ 3—E'V¸›¶R^0ò¡WÊ›K>ge.yIŒîX|ã³W¸sÖ{uÖ¸Ûb©pÇz«9 Ra*í—EטâÞQØÙ#C.,¦æÝ’šX+G[,.OÓåÅ8Í!ó‘á²ß{®´~fôf!ß8èg‰µ°J “Ãóï‡~/œG“™™â,—7u~»û :±ªï¾ of&C3?óàcÔ4& -(ï”3†)éfJ³¸/7s»ÚvÌöéý–vˆyÛîìJ˜è9eæƒi†WtÆL1„SrÆ*¼•ß©–Ó«.Å°œÆ&L»µ‰É>»e(÷ˆÝwá_‘î•zSƒO¹G‚>VNû˜EÌWS®$?ˆ±ç¸–Óλù¦Öa\ñAìµgÏq…EòÜ"œõ̘éyÇ›S8xÜAdÑ/—©=®’Æ3Ò̺eEÙæcZŠÞÅvþ¶ò¥v{QùRUvv÷r¡X¹”n—Ë¥Ì! ãlŽ ÑëÛ§§{—uØ.Gý;r>ÜFäÎÊœÒ|¶Ü¿³µS•lùpÉõö - Oz]‰mD†¤AC1˜°EÏýS£µN†:(W»(QÍ-X9búî۳Ğ<­¯±AuØÖ’ª9(–šŠ!go^ë”Ü¿hœšš¦Lžxz^rcý¿Ì™†çQ]/{{ç•ù÷NL74²ÒjË ÒZÑ Kîk‡6h×+ ïìÆÆ-ixÇwuÊ …=[ñBç g®=EgâúÀß&¦¯‘ZÚ­3µËÞ7ìù•ô–‰S­.&9‚ÒinmÒwÕ~òôï¢Ê½Â&“îÛåN—†óªbF …¡zHèù?SNÉq¾&(†žmeÓtg©ÌrWñ‹kÃnjõñ$.û„ 1l²Åî*ÁB«<²ÒÈUÓd¥ùEhº±‰v̺óDÎ뻊ôXŸ7j†‚Lʯê uJöÓ˜wç§Å6%úˆe#wêÂ1X"YaìÐG5S˜S¿zßs(ÇÊ/.Þæ¥L yG»Ô{´q|Jw§9%¤L´ó{–TNš¦ôVô5˜÷ïjÕß²`ócÊ}öΈgëÞó¢TeùÿeŸ?OˆÑ‹lM1z‘Ÿ) –¥væJ¦k‡z ]¾Í¤”+Ðëj+ê9¬×€Y€¬9€:çŸÒŸÌšè¡[2d²æ2U1£À„½¢žG®(C k K– = =ÇŠ -Ž`×Àx沑i§oÞ9€fÆk“ÚÓ¬Eù¼+²Í«(_0/Ü´EùBDm€6©i‹ò*²}BQ>2›wQ¾?œKQ>¤õÁ -xŸZ”^-kžEù¨õ+g(Êç˜R#{o?Å#B.™Rƒº~ÖHUý¦ºŠP×oŠX¸)êúQ ¦Wõ›ÇÝP°®ßìѶ,uý|ã”æR×Ï»ªóÝP>uýX­®Ÿ•Žèy7ÔŒuý¼Ca6Ç<êúy+줢iêú9—k¯êGô)MQ×Ï;ž)äïÐeªëç½´Pl>uýæQÄ¿®Ÿ÷‚t)6s]?#áÎëVóÙëúyGœ‘s§L?ÂCOÌä#xͳ¶–Ùëú‘rÛ,ª›)+Í· ë T¬uý¼M]CSšµ®ŸmrU¿àõøæó>u]?ïª~³Ôãc?P¡çŒ«ëç†2RçQ×O?P¡TõÃrxgMOñ¨êg‹»˜¡®ŸçQd’¾/Áêú\ #;UΣ®ŸwU¿ùd¥Õ¼×¼€ñÍT×Ïû Ë•+:e]?ïª~3Ôã P$Ø«ßÌ·x˜UýæRÏW‰gÈæp×õcÌ{ FÛÎT×÷€])Š2S]?uý¼A ëŠÎ£®Ÿ 1¢7Ç}/KΓ»®_0¿å´uý¼& 7ON‘óô¨xWõ =èQ×Ï[1ÄøØLuý¼C×Iâ”uý( Ô«úÑNF‚Öõó>± ÅæS×Ï;˜˜];E]?*ÄP¦€ÿY[ =ï{víôuý¼…ƒ3‹sÚº~dáÐȦ‘p°ÒÈzLY“ ^—˜"×®¸X|Ë8»¡é“5ðÞž¶ètiY>,MV.ÙÈ>þŽ»¼c6 ‚ 4#ª€;»í–(Ì‹Äï“ÈjfùåXF UQu7²ò¢œeVckKâõ‘´+å’êë~f8‘—÷º…âÊöÝâ—hdœˆìÖÎ3ÑÛ¯¹µÅæõB%ö6h6–»¯£Õ\³ññ˜ë4^vÞžŽ_C±Ãn³X<¾ßû¸jò£ÃçæëY¯YÏM®ë‰øãc9™øv+};y?M®?’_vÆJ¬_Vq1v‡™·øºžøÒh_%‹É£øÖÇâ{ƒëÄEÙ^;¬<ÔÁZ"B餟\ogw¸·½ÅÕ.®k\}axÌÕOŽ_¥·½ªL^·–ÕåÔq .<¢gZn}T“›…ã;¸%”öÆU¯òŠúr°ÀeNºØ6áž^}_P~é–:®|©í6j›»›m«¤VGp¹ôqNVŸÏ6_/?”Aî8r}|˜D+ ňk<¥W–b7§‹…õ~)vÚ¬,?5÷7³Å¥£\ÒLÛt_]Í7–¾´HÖÔhm5¢ô20óˆ–Åf‹iTbiWO±¾Í· -Õ ÝßZ²–fIÛùåµ¥¡­^—>®v2ã• -à0Ål+Sª -{;àéÑÁÎóåÅñî^îé8Y”6·kÅÅóNùá`a­T(Ý&«a£Kݶê×qxÂOVR±I-¾·¿ÏW¿®m”{r†‡›3¨¶ß>Š^nÞV…ǽNŠËÈ«PÆ/ˆˆUø5˜›Ã7qû2šFÇ5o_XFÆ—‘² ô@lg~®%ÑO@ÌçàçΪ~Êzì¦ÐßââÆÆSí1qwÈ=ÝyÙYoD0ïC|¢)nðd¾XÁ_”c-óE -qÉwB1óUõ²ùl¾à°«‹û¯Æ‹ãZ)_oDeóYk\ÿšn£ÈF>^Å_Ö8ø,£‹阃 Kïü^®!ÀŸ‚ÖwëkÌìû,©5iøUøsÕd8‹Uâ{h”³´Ö¨+Ã~Î8tm<ßÞ;A?õnÛ_îxd¦p™ÛZ2sÔ|ÁÛ‹z+$rkcЋ´6 -—X,pB¿ ¤X5UL|ÝYç®q”,Sc©ÈÂt[¯:ç=f=’úC–8sÖ#ŸYP7’—ëJnë2{¼›èÄ5jJ|iFþ‚5ß »ïÆŠí^_?Yè%$&7céײ•½M¨ ^kØ-T¾ìóÚWÚ'’þWÿRÐÿšÜ}E¤.Tò£+vT“gX®ìæ(†‘½I•¬dh;»‚I÷;u´h¿2‘OOˆd祥«càÁ»fJÆœ@ËÜëQjÒhrõ,ñTn àÒ½ -ßg’Õ«›=Ê{=’Yâ㨼&ªƒ ~æW4Š—£Í,êÚ4únŠG ÖPø¤ù•¢[âàŸü†Æ2Ÿ/×îˆ.Àîu1ÿ/øÔòkRo'ëâzz5" Åô§$¤§ÃU6R_ó]“öAù«½òÓÛn*(ýR?:¨9¹D>´u¤…Êê]’ËÔw’p׎ðø1M7±Û0§e:»œi–¬°¼i*Ä®…‰žóY’†XXíY´¼žaó+[¦·ÖEu¡wêU$Ë‹ÛUÝ®DE›…xñV´d3znm×u5as¸‚+Sk\¬i~BÔ˜ëF¥Œ£ƒ››Ó]­x¯Âf/Žépè@ &´CÕûõUqiýŽøTIA6«i°èP ¯ÒÚ³õQDHZ« -Gð×ãØ‚{H“Iú ÂË™Unê+Qëf(ù¢ðÅ­=K~Ù\ÐëÊ"¶Œ«và Gôhñí»0ÑlÝyK‚žÁ÷%{ûÅR’ìE‹Â0Ú…Vuèówá+~2¢•ªÓTQ›æ‚•¢“”yÛ Uk hr‰¯hr:Ž!`᱇¨,‰¦3.¬{3v®Wd¤Ae -RØéÐ]ë¹ò¦)þ次v¡Ïû+¾ýËcÚFd6± ÎÛçV°.b‘'£‹MÁê"ÞZ<¿§ìd‚T€Éž³°w‘šr¦-ö”Xui*(Ž±,ƒ£t±)ØÚ¥ès b*ÅØ£9y­rú±qMÈ goLJbô™™¬¡4<×ï^9,;Î÷3+ؤâú©ãî¤ ™º£jde÷~7Jô1MŒ~ªJ®sËOVÉ5__ç“UrKçÿL•ÆÃ¥ü“Ur°/4zŽ*¹Åa>S%Ú8TÊ?Y%û•rÓ“7·lIÓ34%xó6®)ÁÕû]D+Z4Gz@fàç­v-ç2ãx©HÙ@fofý|À‹Ã!³ÛK <€Âè'øçv˜Ö m'ò SSi3§@}™lìgz7ã´vvÞK­%·׫¶ètó Aܾ:>4tgýøâR—ç[ù„ ãÀkò€ö·6“Ø39ºö­2âq¡ôår;Ó¹ÍÖ~†“Z‡ÛZŠñöÕ¨¤7©¯%Ö‹ ˜KAÛ¾~/uáåD׃wÿo+”/¤pA*äÙóI¿«œ(½—Þ œ -­‡2»û<9è kJ·{Ñý߸2lOÞ»ƒqx-œÙm–÷÷ R¥Ûvº 9õ“µ+ºËO÷É4Ý:¬áRª<ëo{ ç›rå™»ÝrºïâÞ&t߇b‘äÖÛF$Öå#©×oMø³¦)mšýæð kÊûP;s+ •®RšT“GëÊá~¤i©öHõ•ú­êGåKM&üîž´«l'_ïJOÇB3¸³?Û«š…†Œ»›rþ¼é=¶åI!ý~¼Ilgá2®à¬‚Y¬2‘Tbg>=ˆ$ϢǑd;} _lGVwÅN$ut³YùXP ¦ Ku“Ôv˜YëúÆ× "=Z$ÐÆý²…lG»½EB/½ï}ÌqñtF³»òc\ÿë[wE§8F/èçZcO3×à±]#«w¬Ä±aTîsVs{ò¸h ±¬8è`±¼i¼(¯b¬éÑ„EÖ @—/»Æ‹Þ|ñU7Ýê›+Ö3|äz9…¹#¾âc×÷ÓPXVÍ=’É ‚¿MÀ‹sýB=~žîX}?¢8ð¬†Dõ -`aÝÂ6hf[µQ@¾IÐè$-õàcü¼DÝ®h›“9½MIÀ¿°±€ü`€4·U‹c£ Œÿ VÉÈKk/ƒåËÚF5ûÍ$¾¸n×oÎðcRŒÐ(‚iÊV·ŽN± ‡`Ý>Ômâ pV,Ôk;ËÝ‹Ê~g3¢ÓÕí oaò…€‰žDÿqÁ\rÖ‚Œ#ZëñДÎf[—Z7ßjì'À_@äk²¤õU€IsûØ·–,¢¿ìÇ0$·±ÁLúôg«@:߀À¶5.ú€ÉatYÒÍqM$ ôeœtW%¢Ë%šÈé“BWÁ!U"§«¢×UY“w€ì¡ÜÜ‹k±«¾AuoE'v>šÑ*ÒfÊ°ã!í£dF𴜆ÇÄ7¦ûÇ(ä"Õ2ä£EÀ ,haà Ù,w7·€àâñ5ƒŽ×V4Õ7Ž«Ý[;)MÊù¼t~oå\wÝ[êù§(çÙÔs‚r^²¶.øI*:GÕ®yüÄ“T´*tœú™'©¦óöSOR Xý¿­ Nè"z¬:¸{(‹'Íîx2‚ ¤ÇR÷¥7hÈß»JˆkÿÇÿƒÿæ‹a^(„I?$ø´Ñ -ÅQÛ0Ÿ7c~Ìì*ãJ¯=î ²ò=¼Ý5.÷+áµ°Öö´]ÇÁl¸GмJ@ŸÔ#˜ácˆ ï‚ÿ¿ùüsâÒ9A”„b˜KK"üþÁ \ü!ˆ¼˜‡Oļ e‹è\6ÏÃ? -Y‘φ㧻Ç'ÇÕpV— ´Š›·§/ óü8|þgÃGá».Ü38 ¹<_ -‹à¥œ” ¿‡DžKù¼õ¨¹|:+ÃbGÿ+ä‹ÚWù|šËòaW/åÐ3ø¨˜–²9ðU^­À oŽ×á9Ð^ á,'¦‹°ã,è°¿)Hi tc=°f#䤴À$Û³VFSð̆áPyÔ -¼‚}»çƒf V[³è!ü_8Çš“X„€9Áb y)œåy0˜½&Ççòè\˜¦ã ˜˜o|•ç ¥òÙ4¾Î‚þ ð!WÔŸë)†Û`e…´˜ËŠRQÊ#È -ðkØH*Š ÐFëFJgÅ<€"z»FÌçÒ"j‡æ´ox!-D®è‘”CS¶€ŸO‹"k^ÐÖƒ‹Á¼x´|þx@…´PäÑ3>ˆP’¶EÐ-ìD( õfQû-ré<ø"Ëñ›Ê!øö—å8кˆ&ãø[<ì ~“Uˆ¼Ž©Å,\8 ÔP°‡“‚@Ä‚CÁ!¢hC8¡IÔ8¿/¢þÀÆ#R}Á¨þLä{¸¼”¾!àu 9–aÐ3ðC‚ð¹BNÈkÔ›ÎI…‚9A!ßo–ÃýáË0ÜêOº&¥Ã%ò - 9mDc=+ä:ºÏD>]¸ùö­Ð °!Û#¸p c¾—%Pæ²Ö`ÚEÀšà“BQ‚lBH£ÅÁdÁ 7Ÿ5ðg`|~ ˆ˜ã ዘY€â|!g=i‡Ä¬.ft°Vb:—åµ9ð|AÀŸÖUÈkß™ÏÕ -œ;ø# ñ<Ý°'€å‰íö Ð"W€­Ü$IDà Ù,šg¾˜/ZOàxÿ9{«<˜9zºÌòè Â_ȬÚIJRÞ|ÒÀŸiÀ¾òhq€5çЄ8È8|Ž$ë ʈ€f+Þ¬ ÀIŠ€ŒÛ¸ýY -×x–4&äôi#¸A6%ˆØ!ÍÁÝ£éÀžÐÜÀAÐ1%+äá´s`»à„,q$`ZÈ¢·pLTÁç´¾²Y¸¿è‰˜G EÛ°œ¶Oæ3°À%¬•¹R—·íS0<”Ñ*$‡_  Üúœˆ¹X@Û"B\…s$À‰¼õ¬?3…dBÛl -Ö^IYïc­çBô“Ïsö_²ù  ¹(äÂVO&q˜ãa$fUD{bµÒ) d ì)ÏóÚÌ Å‚ÆåÈ#¦£iú³þŒKgóB l[m=àdpw5‰â°­7y.¶õÎ#Y!*™¬±n×EQ^“.N>ù+QWã™ýÁXSÎÂíáûh8tÂê«<ê†ß‡.¦©5JšÂÔG¤Ö­k&v*¿t/¹×êã‹*ÿÕ ËƒÁp,»#ð&ü¢tÕñP邇Ã'à£9PDOj¡ÿIHÈ”endstream +xÚímsÛÆÇßëSð]¥™êŒ{Ƶ/:–§J'•”éLÓ¼€HˆBM4AZã~úˆ»ãR +eŠNÅHKCg|óQìïˆu}rJ¹ÌŽ¯ïÊ“Sfß\­ŠUÕ®ªqÛÿü²šÙ¿˜œ““S™eŸÛ‹0æýÏò@Ma¬öÆæ)$l/ýËé¨s  v§Ðp_ýów‚ÐLïa厂ñ€ºï`‘t¤…¶¯ 4t,°lóf]¯Ê¥ý)ÏÌgŠÁ''Å'3™`ˆ‘Å¢Y>LJ$ŒÔý¶rpI„Ê+¡r¼*æ¾t”Ë·å2^F¶ –?½…ö™HbBÃL£BGÁ„FÝo…fœð\Q 4sBÿ»©Ð?•³.êqù[j->aõ9YQ`ˆ) +SJ33¬h$LQÔýVQJ ÏT”;E/˶™=¢ÉæŠ=½‚=(·ÏG²ÜÀ“æ•;&7ê>È­Œ!ŒÁB-œÚWÍøu¹êµ½xöão‰®2ñ¨íÓ‘*6°C´†É¦4”:¢4ê{+t®‰}Ùê,ÎçÍ|aE½©fÕê]¯ê}µºë‚³c³s.M„É”  ;ÍÙÅ«ýQ;íAÜhwL¾‡ ÿܺ„ƒ(ô K&!˜a lÅ ”s°†ÁÇ8öãM¥l_>×ùƳ¶d672ß1¯—†ó¦n«I¹´ŒØwÃéò§¶<.QÀ`?âýóöÉâÃÉçÃÒ´ç*¤©)›(ÉìYê>Q›Îkfsñ|<.ÛPúêÕò„æÇͬÿÅ÷¶0nþ&žî çÓ^Ÿðäö ±E1Š‚ᄺ8‰ŒÆ=NÌ•M\[3;šÑZ:¦¸ëª½xWójÜ3õóbR¬Ê‡½[-Õ¡7'Æç4™`ˆ5C‰‰‚³ç>6 +’¹E‡IîG¨›QÐõ‰‰/›õͬlïìõ«+HCù gxì` ƒÈ(^àçCò±ï6Ö‚¤2Ýâa?/‘‡ÁÎy3Ÿwųk4?õj››y7ˆâ0¶InT!Í© +"jGFžH D¨{we—R¡h`(t/Vræºq³‰÷Íòµm]íºkîû7ãÂÁvÑ¿ü'ËØt½Ï•îfíÏpW„ÓÞ»>äôo¶¢ÓüP0(¸ÏI²àÀæ<&8ê>T ! ×Æ+Î\Õ¸¨Ç½d]Ÿ>t꺑j?krWÔÓ¾ž_ ¬ +7òj=¿é¬“'T +!ðiJ†b@P"` îœÛ04uøÎ׿îJØnÏ´ìoýºÂßËÙÂ6[!’G±ä³Ì0ÄX‚j¢,EÁXÚsí–Ùãµfãý¹-æŒ?_,ÊzRËá‰ç`öè¾0Àúb0J‡æàù°$ì¹5(ar¢ìXºOBwÕÚ¦aüºnîgådÚUÕn‰•™C,¹ý„䦶hˆ´Ÿñ0db èàî]LäŠÈ< ät옮 õ¥ölY•·®êVíªYºåæöÁ¥øÅ««×ì~HeôË©¤!YÉ$CŒ(JB$ŒÔ}("ZËŒv(°¾ˆ|[ÖåÒw²‚Ê—å­»V‡í9õm³œýÔ™2_fÅ$Ãç.™ `ˆ‘µ±#¤a2"`d î}PŒª¾F\üôV¹F?™ô4´mÙúq˜ÌžÛÿì+íðõáBò˜ 0Ä :¡DÁ A݇ò!3¹PŽÞ—³êfV5Óe±¸{·#\$®ÖÓiٮʉ/+ÅÄózf8c_G=d.™ `ˆq•A¹ˆ‚qº÷Åc³b̾x\–oÖVù^w{åðÛ#殯êQ¹|yÞö<äükáÁ§,™`ˆñ%Ayˆ‚ñ€º÷<0E¨Î¶<0w1é¶zÕ~ˆÿbYÜvÃ“Ç ã³šŒ 0ĪQ6¼ô Cuï‘¡¢»9JdxÌ«;¿­øE3^ƒÂñü&LúöÃIÙWÒÇð¹Jb @-P"`  îC#c$Ë”'A¸>Æíˆa˜ò}u³,ü˜õj½X4K‹…¢æ0¹áõôMæb¼@ÅP^"`¼ î]áà¹ýÂãâûýº¤À¾YWmÕ-ókz˜K(ä8 hˆ´£!er X @¸{Ö$l ë¬t»ß«™›ë\¸IçƧ6™`ˆq¥C¹‰‚qƒº÷Ü(I´Êxà†ûNn»*fœ/vÏ÷ÂOq2?ÀãJˆò ãuïù‘œ(où=?ÿ¨›{·(ú¢¼-Ç«öÙ¥D/«q›Å©ùl»6g¨•L0Ä(€B DÁ(@Ý{ +%Òþ.P { +Âc&uKÆM} ¢ r}((2>«ÉÈC ¨ej™H 2¨{ 3DR±EFõÈ\óÅÌQó|±˜UcwcÖ©ê°àû€ŸÄdB€!F %$Fê>ÜÓÉ©¶oÝ2ÒoÞ´#évƒÉ_NN¹ =.mµE§]­oúwn¹ÜÙ½^¹{A¥ÐOdÕ.d"Yh`ˆ 3 + u¿:“„Ë +Ív„>-Úwõ8Yn-Žÿ¼³'Ó-v'»sû*›u;{×íÑbï)‘ÿ ÉCL"˜#ʆ7/ÅÁ$B݉˜á„©(Äwòs¶—7¬S˜ïZ-‹º-Æ~x‘gÕæ&)“ñOÓÄüL•Ø!êÁôaâE¢@´C}o¥Ë)¡¹Ò‰]é¦Eå$›–«n…¼ªo›nI«_ÎÚÙ,c¨‹y¹Ä*¬‘›‰•[rùñ5sŸ,Y³­¦ÈªÙ~˜f˜ï­fÊtON3@4¹+ÚzsÏÏpS›À„Öà!ßÒº÷‹¾N—ÅüäTï,[~¨ Âá“$‹ 1•`¦(~BP,L'ÔýV(©IÆ(J9¡êÖ¥÷ÆË4iæEU?«Ã3¢ZðŒ¨ñ]9~í¨jߪ–óvw'ÛåËóþÈ´H¿ËkP'ÿA’u†˜N0Q” o‹‚鄺w£ &1Ül/_ºmì,»ìl³I×™°£(1ZsÇŽ|Èδìömy¸®} š|¾“i†MPO*Ø0M‘@0šP÷&aHn¤§IíÐÔmß6¯»µWID} ¢|Γ‰†QPS*.R$Œ(Ô} Šk’Sî‰Ò;DµåjUuSY‡õápò OÆ b8AA©žÕŽ‚ᄺ81I4wô8#ù.NÕ´þßæ©êBðHï ’Ou2HÀ Ji‹É0H‘@0P÷$ʉƃdzº‰õÉéf"½ßm¤$;ô» ò9N&bA ©~fm,Œ Ô} (£D*÷03B³nôB®ÉCúýù$'# 1„ ˆTß´ CuïÊ ¹ Q@æy˜¡üø3”^ƒTÀ€ÂT˜ÊáÎR$ +„.Ô·‡Kk"2ßï¦ V§ÿ6ëe]Ì˪[ÇJðIÿÞ“>½ÉßzÌ°ï<ÙJGÕð„Ò~Ø÷ Ž·Oõ'~ŸE†;dZ¿ùCjq(Eó‰é}úÓŸðO~{ƒ&Cj?„=¤ÂW)ž2Cò<ú}öJŒ”ìý¿¹qû“Bž}ãÓ†°,Ó£î{¹Üè´z‹ÜÄ°9 +„þ¿í†endstream endobj -710 0 obj << -/D [706 0 R /XYZ 85.0394 794.5015 null] +1140 0 obj << +/Type /Page +/Contents 1141 0 R +/Resources 1139 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 931 0 R +/Annots [ 1143 0 R 1144 0 R 1145 0 R 1146 0 R 1147 0 R 1148 0 R 1152 0 R 1153 0 R 1154 0 R 1155 0 R 1156 0 R 1157 0 R 1158 0 R 1159 0 R 1160 0 R 1161 0 R 1162 0 R 1163 0 R 1164 0 R 1165 0 R 1166 0 R 1167 0 R 1168 0 R 1169 0 R 1170 0 R 1171 0 R 1172 0 R 1173 0 R 1174 0 R 1175 0 R 1176 0 R 1177 0 R 1178 0 R 1179 0 R 1180 0 R 1181 0 R 1182 0 R 1183 0 R 1184 0 R 1185 0 R 1186 0 R 1187 0 R 1188 0 R 1189 0 R 1190 0 R 1191 0 R 1192 0 R 1193 0 R 1194 0 R 1195 0 R 1196 0 R 1197 0 R 1198 0 R 1199 0 R 1200 0 R ] +>> endobj +1143 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 758.4766 511.2325 767.5824] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.4.0.1) >> +>> endobj +1144 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 746.3946 511.2325 755.5003] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.4.1) >> +>> endobj +1145 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 734.3125 511.2325 743.4183] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.4.1.1) >> >> endobj -711 0 obj << -/D [706 0 R /XYZ 85.0394 769.5949 null] +1146 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 722.2305 511.2325 731.3362] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.4.1.2) >> >> endobj -708 0 obj << -/Font << /F21 714 0 R >> -/XObject << /Im1 707 0 R >> -/ProcSet [ /PDF /Text ] +1147 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 710.1484 511.2325 719.2542] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.4.1.3) >> >> endobj -733 0 obj << -/Length 1059 -/Filter /FlateDecode ->> -stream -xÚµVËn«HÝç+XÆRh÷ƒWÏŽ`l3Âà|£ÑÜY›ÄH‰± ¹Vþ~ªéŒ‰f3ò¢«éãªS§ªDÃð#ši!‹S®ÙÜ@&&¦¶}¿ÃÚ+¬-îˆÂ&C¦ÁL¾XÕ #ÃâšÎ 䀳KÐ Øâȶlªé¶É‘Å(èÇìn:§Tãˆ[ÔÒ²Í6m8¦Ö£²Ý_÷^uü<•¯ûfòwö»fbdc¤ÃX¶ba:'Æ…'B@nkúî'$*¡£ „"HU¤)@cãa¢S ÓLk0íÁt“÷&ÁÒ -Mq:œ¥ŸuS¼×râU‡º:5åÇûC‡Ý¢‰Îš&þI©¤ž`Jë;?ëõ$Œ"Ó²,Œ@!¹ù­ø=Z¿„ߪO˜ ·ùàõßä§ÿ§üx” &Lö¥ºÕKsÎOâÜ×£ký ³)ÅŽfS<-ç[ù:°~‰¾UÏtÅ” >E:ëâô^ÖuY$§¦’ãG]¨|¶ ï„r¯æïÕ®|}É»iu’ö®¬›SùüѨ›}©ª¾Éÿ¥ûS~ø”Æñãt¬jµ|.›½´:œøR}(=_ -…ƒ¢ð„ Ê 7t0¸iÒ6½}!>«¯§Š²SÄíbõ«Ü»ŽnÞt–rŸ?W¿ŠA -ÙiíôP5å¶è5¸Nøx%í~<¹ÊªTëùÛ›L„;ˆcËg±Ë¢nšsÄ %'6âŒÚ-$[úªÕâyö4áôÞMÔ— •ã:‰3&gb÷ºi‡3i»Ñ¬ûèIcVè+vÃP*JâFYà«Å§ [J+ñn2“ÛŽ`FÇ)eBýXB³eGñ ò‘nfA´¸ -¬ÖaÐåò“x.Ç•ŸxKX˜Øƽû„Aöç¨`g!n8vÇŽ´ìæAùiŠ:rŒ_ÿ‡þ$áåÀ¨ÓëQQ÷1TöZ}Zº"J–ÆXÒU/Ý„í×^úy¯Tbq:ˆ,(aãU7©ßå&Ý·óŽ¥Ó‡Ž‡]œŒ5w»ÑË‚8—ÒÎw¤Qä/Â`áGž?Ž·žWxP‡ŒË-›1™0ò7éeHåØM‚´—"Þdc&ñk`ùŒ‡mÑïSÐgTV±ñ9#c×~³r‡|æßm™›«„ n[p@šà•|{•ô`ý}{•PJ±ÞûD¿zL\_tmš”ÂvcÖXnª7‰·ÏOàHyiäù]4ªï-dûJ¡¤Ø«J¿^ÙŒ.'/+á¢9”yëÁ0ááÀnúÔ•î™pOÇÄöMsüm:=ŸÏBaTÖ[Tµ¤^§7·¶z´2‰gé~²þpz”¦endstream -endobj -732 0 obj << -/Type /Page -/Contents 733 0 R -/Resources 731 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 715 0 R +1148 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 698.0664 511.2325 707.1721] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.4.1.4) >> >> endobj -734 0 obj << -/D [732 0 R /XYZ 56.6929 794.5015 null] +1152 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 686.084 511.2325 695.0901] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.6.4.1.5) >> >> endobj -731 0 obj << -/Font << /F22 737 0 R /F14 740 0 R >> -/ProcSet [ /PDF /Text ] +1153 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 663.4123 511.2325 672.2689] +/Subtype /Link +/A << /S /GoTo /D (chapter.7) >> >> endobj -743 0 obj << -/Length 2884 -/Filter /FlateDecode ->> -stream -xÚí]wÛ¸†ïó+tWûB(¾ ^:Ž“u·ÉæÄÎé×ö‚GflõX¤KQ¾ €# œÍn²±tr!ÙÒp&ó>Àf3jÿ±™Q„Š\β\E™š-V/èìÚ~öæsß‘J%…°?D>+aˆ2<›ÍáA^^¾øãkÎf\’Ìdlvùiô¥8á\ä³Ë«ÖU[VíúøŸ—ê r’k®»ïÓÙ\s"0ý7ÙñœQJΫ¶©¯6‹vYWÕ‹³ËŒ‚hÊäL›œd’².”áÃæz6¼ù°»ûþøØÇPv;D´ãÞ¥ IØ®Sœæö­±i×YF´d. ¤Ïƒ¢G‹ú®<žsû¶þ4¼¾ª›•Íæñ\™üˆØ›¯gù"ó/ùÿMRã3½#Ûç膻Bîÿ3ôDÂÀ(BŠ´êÎbí(⎢ŸšcfŽ®‹jùߢ?£¶€º¼Y®£%E¶?ÀL’â³™L -0ÄHÙRkš”H)¨ó@Šï¥ô)‘bGê{ €eÄ!ñq]^ ï–Õ4.Bég È$>{ÉdCŒŒ-u¦Éˆ„‘:dH‹ƒÌÜÕHGÆåMéU_ž…wÅÊýöâaÝ–«áýÏöû¯Þ]Ø{ãÚìóÅÆ'3`ˆÅâÓ DÂÀ@A3ΉÉ3ëœç„KãkÙW-ÜæÊ?ðzS]ÝQÜvc†{W…<ŸÉdL€!† T -Á$† ê|Ä„e„)ª&ÜcÒ$îbRTWññÅ~.´|–TLâà3–Œ0Äp€Š 8DÂÀp@8P;ET\„ÃáïuÕ‹Mù³žÕ|ƒÑÅg<'`ˆáEpŠ„á„:8©œ“\ÉP®ôK‡Óɦ½©›ekg<÷åN¹R6÷eÓ_“²}¬KBÖR‘€†[ªˆI$ba HàΙ’$˲|¦ %F©±.*«Ø÷ÍrU4Ão [¼66g‚ïÕÀ•L0Ä(€B DÂÀ(@hC2•i@w\Ü÷ÅÍþ\)>Ç…O]2ÀãJƒp ãu>r¡4Ñ*€ á¹hËⶽyD†¦ù¡†YKFbH@U$"a`H ÎÇBJ¢4kåjˆÓbq³¬®'«aØÞ›“„ø$& 1B HršH!¨óqÐœHÍÇ’B…’âuÝü§èدzTäw2ùš×Ÿ½d4€!†TA#†ê|<8%B˱ÎÐnðˆÍ6À:úÛÍm»¼»u_ùPßv“ß\èç>óðéJfb,@9"a`,ì8‡;Ç~Ó[æÉ„ b˜[Ù/Ïß½r—ëzÓ,¼âå¿7˦\ùñh¶ÂŸºÅ -î­HÕd–àÑìì:m,H›&-„[«[Ü?¸ÁÓ ¢.;Ãû.Cý›!Ks# ?èÙrœzvACäìÚÒá&Æê<ð“ ¢„Ì?~sûôýGxBA\2j‹‡é ù<'3 1† ŽC‘00†Pç!m¯ÐB»•ï°íý¶\Õ~1h#™Ë8OÇ'7`ˆÅCÀ‰„ƒ:àÈœaÜ¥=ìŠ?®ñ†÷ç]»Û:,;ŸU÷Pu5´KôßY¯7]Å÷{jâúµÚ#B²’A†P „H¨ó‚È÷ͼ_)èõ6wwuÓúf™ŸîʦhÃÒÁÐÑ/†‹ ¢Ïd2%À£*¥§)‰„Q²ã<:`vHuî–³†™@|°8­«Ÿ)å×›¦@»]Ã!Ÿ<ØT†šM§  KÏŽÓèIDí™CM6¤gìv-VaBü(-ÝHIõá2ü”óÊ'7ù¼†ØyÅC€‰„ƒ:«-"§D2*=9¡çèÄa3¬ØÎëêö!¾lkÓ®ó½"ä,hˆ±¥É4±0 pç#™!Âþ€ðÝE'nm«åBIñìz˜Cz’µ†˜ö0ýˆö‘00íQçþ*b‹v™»ÇD„?×…«Â^·Eµè«0ÃÕ¡èKYòùNf b,A=Í4K‘00–Pç%% cÊW$߹꾯Jäó¹ ç7ºúøÌ&S 1j r5‘00jPçãÕGrBYæËÊ‘ËãœÕõ­ÛôùT7á~ŠáÍ_Ž•:Zúfƒö¦œº*õ=±E¹ênÛ9ûÎ.?>?ÉâCL|˜DüH˜ø¨ó°),¸ý%Ëù(~Ø~µ,®«zÝ.eÌ÷‘„œ% 1  &ù4‘00 Pç#,#†Óá[ÎN®VËj¹nÐŽ - ø]ll}ý}Š’õ†˜þPDÿH˜þ¨óñj@É8ED˜‹\,¯«b8ùÙ¡ ý2’¸!šS6&û‰$y»94Œ´sü¾¯cº­=†ÒŽ÷Øú!7‚P“K×Å0¬ž\ÝÛéŒ_bo²*‹vÓ”ëÉL…ƒ}få0dDVwŽÛghºiÉÌ®×X¡Î3Jòœ ¼ K‡ïêvùÉÎì홺Gw|«a À‹‘zBCäÜ#,Fê=¦ŒÖ…ͯ.¼z¨Š•/ë>Þ]­½š›L ú¿!ryNfh´Ã*b턹嗚d¹Ìj6[N6m½*Â^‹ƒaxÎÞ—ߧ'Y|`ˆ‰Ó‰‰õ>Š¯íä™f@{¿¯ò¶¨6~…όگße(YþÑSäŸMo³F‚À´Ç\c¾¢„únÃN{¿§rZß=„ë°þxì¿(Ý„Ù•¥míZƒj¿õþ¶ïìZñµßÙˆïs“¬:0Äd‡¹ÇtÄ z•Ém%”÷Š:¯ìu|ÑÞfë¯æáS[üÁ}vöËrÝ–Uw'fÆÔw¦¹ÏJ²æÀÓfÓ<¦9ê}Ôœ+b|;a§¹ š¯ÛæØu„ž~û6€n:¢ŸÏ²VÈV2 Àcª±‰cõ>²Àɘ (ø‡r óÊ èÐèS{²X”ëu¸‡ n¼ê+ý¼î‚j.oÉPŒv@6Ý` #s=AѾӯ#Â?iá¬TÆþÃãež|Ú“†QPV ©HS¨w¿ver¢Xæk í—®~<û[׬#KW_m‰Ô+‘J°C ƒ:#ŒE‚@C]{²ŒHßh§³~wæüM·3G‡m9Iób_m@󊤒ìÒ Þi‘ °¿º‚¹ŸéOwÏÇ"Æ÷«¼»¸8;µý¸æ›Aå’ŸÊÔh† „åùk#Ø*ü•Ÿ9ω‰=o¼P]â\Øé—˜hr¬{ S3÷¥.¶%ró…?’÷ö?ÉþªAendstream -endobj -742 0 obj << -/Type /Page -/Contents 743 0 R -/Resources 741 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 715 0 R -/Annots [ 746 0 R 747 0 R 748 0 R 749 0 R 750 0 R 751 0 R 752 0 R 753 0 R 754 0 R 755 0 R 756 0 R 757 0 R 758 0 R 759 0 R 760 0 R 761 0 R 762 0 R 763 0 R 764 0 R 765 0 R 766 0 R 767 0 R 768 0 R 769 0 R 770 0 R 771 0 R 772 0 R 773 0 R 774 0 R 775 0 R 776 0 R 777 0 R 778 0 R 779 0 R 780 0 R 781 0 R 782 0 R 783 0 R 784 0 R 785 0 R 786 0 R 787 0 R 788 0 R 789 0 R 790 0 R 791 0 R 792 0 R 793 0 R 794 0 R 795 0 R ] +1154 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 651.3501 511.2325 660.4558] +/Subtype /Link +/A << /S /GoTo /D (section.7.1) >> >> endobj -746 0 obj << +1155 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 688.709 539.579 697.4212] +/Rect [494.296 639.3677 511.2325 648.3738] /Subtype /Link -/A << /S /GoTo /D (chapter.1) >> +/A << /S /GoTo /D (section.7.2) >> >> endobj -747 0 obj << +1156 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 676.5858 539.579 685.5919] +/Rect [494.296 627.2856 511.2325 636.2917] /Subtype /Link -/A << /S /GoTo /D (section.1.1) >> +/A << /S /GoTo /D (subsection.7.2.1) >> >> endobj -748 0 obj << +1157 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 664.4876 539.579 673.4937] +/Rect [494.296 615.2036 511.2325 624.2097] /Subtype /Link -/A << /S /GoTo /D (section.1.2) >> +/A << /S /GoTo /D (subsection.7.2.2) >> +>> endobj +1158 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 603.1215 511.2325 612.1276] +/Subtype /Link +/A << /S /GoTo /D (section.7.3) >> >> endobj -749 0 obj << +1159 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 652.3894 539.579 661.3954] +/Rect [494.296 580.5943 511.2325 589.3064] /Subtype /Link -/A << /S /GoTo /D (section.1.3) >> +/A << /S /GoTo /D (chapter.8) >> >> endobj -750 0 obj << +1160 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 640.2911 539.579 649.1477] +/Rect [494.296 568.4873 511.2325 577.4934] /Subtype /Link -/A << /S /GoTo /D (section.1.4) >> +/A << /S /GoTo /D (section.8.1) >> >> endobj -751 0 obj << +1161 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 628.1929 539.579 637.0495] +/Rect [494.296 556.4052 511.2325 565.4113] /Subtype /Link -/A << /S /GoTo /D (subsection.1.4.1) >> +/A << /S /GoTo /D (subsection.8.1.1) >> >> endobj -752 0 obj << +1162 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 616.0946 539.579 624.9512] +/Rect [494.296 544.3232 511.2325 553.3293] /Subtype /Link -/A << /S /GoTo /D (subsection.1.4.2) >> +/A << /S /GoTo /D (section.8.2) >> >> endobj -753 0 obj << +1163 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 603.9964 539.579 612.853] +/Rect [494.296 532.2411 511.2325 541.2472] /Subtype /Link -/A << /S /GoTo /D (subsection.1.4.3) >> +/A << /S /GoTo /D (section.8.3) >> >> endobj -754 0 obj << +1164 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 591.7985 539.579 600.7547] +/Rect [494.296 509.5694 511.2325 518.426] /Subtype /Link -/A << /S /GoTo /D (subsection.1.4.4) >> +/A << /S /GoTo /D (appendix.A) >> >> endobj -755 0 obj << +1165 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 579.7002 539.579 588.6565] +/Rect [494.296 497.5072 511.2325 506.6129] /Subtype /Link -/A << /S /GoTo /D (subsubsection.1.4.4.1) >> +/A << /S /GoTo /D (section.A.1) >> >> endobj -756 0 obj << +1166 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 567.6019 539.579 576.5582] +/Rect [494.296 485.4252 511.2325 494.5309] /Subtype /Link -/A << /S /GoTo /D (subsubsection.1.4.4.2) >> +/A << /S /GoTo /D (subsection.A.1.1) >> >> endobj -757 0 obj << +1167 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 555.5037 539.579 564.46] +/Rect [494.296 473.3431 511.2325 482.4488] /Subtype /Link -/A << /S /GoTo /D (subsubsection.1.4.4.3) >> +/A << /S /GoTo /D (section.A.2) >> >> endobj -758 0 obj << +1168 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 543.5051 539.579 552.5112] +/Rect [494.296 461.2611 511.2325 470.3668] /Subtype /Link -/A << /S /GoTo /D (subsection.1.4.5) >> +/A << /S /GoTo /D (subsection.A.2.1) >> >> endobj -759 0 obj << +1169 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 531.4069 539.579 540.413] +/Rect [494.296 449.179 511.2325 458.2847] /Subtype /Link -/A << /S /GoTo /D (subsubsection.1.4.5.1) >> +/A << /S /GoTo /D (section.A.3) >> +>> endobj +1170 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 437.097 511.2325 446.2027] +/Subtype /Link +/A << /S /GoTo /D (subsection.A.3.1) >> +>> endobj +1171 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 425.1146 511.2325 434.1207] +/Subtype /Link +/A << /S /GoTo /D (subsection.A.3.2) >> +>> endobj +1172 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 413.0325 511.2325 422.0386] +/Subtype /Link +/A << /S /GoTo /D (subsection.A.3.3) >> +>> endobj +1173 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 400.9505 511.2325 409.9566] +/Subtype /Link +/A << /S /GoTo /D (section.A.4) >> +>> endobj +1174 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 388.7688 511.2325 397.8745] +/Subtype /Link +/A << /S /GoTo /D (subsection.A.4.1) >> +>> endobj +1175 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 376.6867 511.2325 385.7925] +/Subtype /Link +/A << /S /GoTo /D (subsection.A.4.2) >> +>> endobj +1176 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 364.6047 511.2325 373.7104] +/Subtype /Link +/A << /S /GoTo /D (subsection.A.4.3) >> +>> endobj +1177 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 352.5226 511.2325 361.6284] +/Subtype /Link +/A << /S /GoTo /D (subsection.A.4.4) >> +>> endobj +1178 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 340.4406 511.2325 349.5463] +/Subtype /Link +/A << /S /GoTo /D (subsection.A.4.5) >> +>> endobj +1179 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 328.3585 511.2325 337.4643] +/Subtype /Link +/A << /S /GoTo /D (subsection.A.4.6) >> +>> endobj +1180 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 316.2765 511.2325 325.3822] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.A.4.6.1) >> +>> endobj +1181 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 304.2941 511.2325 313.3002] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.A.4.6.2) >> +>> endobj +1182 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 292.212 511.2325 301.2181] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.A.4.6.3) >> +>> endobj +1183 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 280.13 511.2325 289.1361] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.A.4.6.4) >> >> endobj -760 0 obj << +1184 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 267.9483 511.2325 277.054] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.A.4.6.5) >> +>> endobj +1185 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 255.8662 511.2325 264.972] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.A.4.6.6) >> +>> endobj +1186 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 243.7842 511.2325 252.8899] +/Subtype /Link +/A << /S /GoTo /D (subsection.A.4.7) >> +>> endobj +1187 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 221.2121 511.2325 230.0687] +/Subtype /Link +/A << /S /GoTo /D (appendix.B) >> +>> endobj +1188 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 209.1499 511.2325 218.2557] +/Subtype /Link +/A << /S /GoTo /D (section.B.1) >> +>> endobj +1189 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 197.0679 511.2325 206.1736] +/Subtype /Link +/A << /S /GoTo /D (section.B.2) >> +>> endobj +1190 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 184.9858 511.2325 194.0916] +/Subtype /Link +/A << /S /GoTo /D (section.B.3) >> +>> endobj +1191 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 172.9038 511.2325 182.0095] +/Subtype /Link +/A << /S /GoTo /D (section.B.4) >> +>> endobj +1192 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 160.9214 511.2325 169.9275] +/Subtype /Link +/A << /S /GoTo /D (section.B.5) >> +>> endobj +1193 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 148.7397 511.2325 157.8454] +/Subtype /Link +/A << /S /GoTo /D (section.B.6) >> +>> endobj +1194 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [494.296 136.7573 511.2325 145.7634] +/Subtype /Link +/A << /S /GoTo /D (section.B.7) >> +>> endobj +1195 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 519.3086 539.579 528.3147] +/Rect [494.296 124.5756 511.2325 133.6813] /Subtype /Link -/A << /S /GoTo /D (subsection.1.4.6) >> +/A << /S /GoTo /D (section.B.8) >> >> endobj -761 0 obj << +1196 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 496.5559 539.579 505.288] +/Rect [494.296 112.4935 511.2325 121.5993] /Subtype /Link -/A << /S /GoTo /D (chapter.2) >> +/A << /S /GoTo /D (section.B.9) >> >> endobj -762 0 obj << +1197 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 484.4775 539.579 493.4338] +/Rect [494.296 100.4115 511.2325 109.5172] /Subtype /Link -/A << /S /GoTo /D (section.2.1) >> +/A << /S /GoTo /D (section.B.10) >> >> endobj -763 0 obj << +1198 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 472.3792 539.579 481.3355] +/Rect [494.296 88.3294 511.2325 97.4352] /Subtype /Link -/A << /S /GoTo /D (section.2.2) >> +/A << /S /GoTo /D (section.B.11) >> >> endobj -764 0 obj << +1199 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 460.281 539.579 469.2373] +/Rect [494.296 76.2474 511.2325 85.3531] /Subtype /Link -/A << /S /GoTo /D (section.2.3) >> +/A << /S /GoTo /D (section.B.12) >> >> endobj -765 0 obj << +1200 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 448.1827 539.579 457.139] +/Rect [494.296 64.1653 511.2325 73.2711] /Subtype /Link -/A << /S /GoTo /D (section.2.4) >> +/A << /S /GoTo /D (section.B.13) >> >> endobj -766 0 obj << +1142 0 obj << +/D [1140 0 R /XYZ 56.6929 794.5015 null] +>> endobj +1139 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F39 1151 0 R /F21 930 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1203 0 obj << +/Length 660 +/Filter /FlateDecode +>> +stream +xÚíØ;oÛ0à]¿‚c<áñ}kŠ¤@†m´¥ɱ ÔJj£Ÿ_Ê2e¦¦µ7!¬Ä<Þ‘÷¶„û N3.Q‹ŠišÔ›‚“•ïc‡14 ¢ñ¨›²¸¾“– C# )_¢¹ãÎ)›§«ŸÊÛ‡òqñ\Þ·å0iœ¸ìfüQ<=sÒøü÷g&¿ýœ¢ ›BiÉ´’2üç{ñX|&ŒÞ݇¦¢¥cÚ ›X‰ÑJÐ_:?•ÕÈŒr¿’jA•Ä«mÛÔþ +Ü[PÍùü²Qˆg›ì-ZHßg9iïvEú‹/qÃCO~:×q0ê¤ (UHÎ[6ýàMYf¬…àMwé¯ïDc…`ªKÑ ê(²úµ}éG¾›Õ³ÆØÃÈÙèY†NMvæÆÀ˜q‡‰Br³é‡R3+ƒCs<÷h‡mµlT‚œÏ¸ó¢ +Û>U˜C·ŒG•($‡*›~@åËðç‘ ¨lªiÚÝ•3vÖt&Ma¿'kŠsšâ~‚ÁqM‰Brš²éM̘ Éõšªí[ÕV›å‚ +3»è'`hÀd^Q`ŽWÜ`°0Î+QHŽW6}àeü…ÓF^ØóògÔ¶j›×M÷ñgf_—€5lýTXq`Ö»Öæ`¥ +ÉÀʧ`9ËC¸¥¼‡õmWÓõ¦ªéWÎÅŸŸoÞÂ,êL¢ÂžOæDÅ=+ÆE% +ɉʦDYÍP™pÓ( Õî–µ\W»õ‚¢”óQuXaë'Ês°âÖ‚•ã°…œÀžQ£8Ó !õÌÿC­Åÿ?’;>8ôwÒ9‘^®äŽ!KümD7W·Ø_£K= Š*ÿ ïK¿endstream +endobj +1202 0 obj << +/Type /Page +/Contents 1203 0 R +/Resources 1201 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1216 0 R +/Annots [ 1205 0 R 1209 0 R 1210 0 R 1211 0 R 1212 0 R 1213 0 R 1214 0 R 1215 0 R ] +>> endobj +1205 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 436.0845 539.579 445.0408] +/Rect [522.6425 758.4766 539.579 767.5824] /Subtype /Link -/A << /S /GoTo /D (section.2.5) >> +/A << /S /GoTo /D (section.B.14) >> >> endobj -767 0 obj << +1209 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 413.5759 539.579 422.1635] +/Rect [522.6425 746.5215 539.579 755.6272] /Subtype /Link -/A << /S /GoTo /D (chapter.3) >> +/A << /S /GoTo /D (section.B.15) >> >> endobj -768 0 obj << +1210 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 401.4527 539.579 410.3093] +/Rect [522.6425 734.5663 539.579 743.672] /Subtype /Link -/A << /S /GoTo /D (section.3.1) >> +/A << /S /GoTo /D (section.B.16) >> >> endobj -769 0 obj << +1211 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 389.3544 539.579 398.2111] +/Rect [522.6425 722.6111 539.579 731.7169] /Subtype /Link -/A << /S /GoTo /D (subsection.3.1.1) >> +/A << /S /GoTo /D (section.B.17) >> >> endobj -770 0 obj << +1212 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 377.2562 539.579 386.1128] +/Rect [522.6425 710.7556 539.579 719.7617] /Subtype /Link -/A << /S /GoTo /D (subsection.3.1.2) >> +/A << /S /GoTo /D (section.B.18) >> >> endobj -771 0 obj << +1213 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 365.0583 539.579 374.0146] +/Rect [522.6425 698.8005 539.579 707.8065] /Subtype /Link -/A << /S /GoTo /D (section.3.2) >> +/A << /S /GoTo /D (section.B.19) >> >> endobj -772 0 obj << +1214 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 352.96 539.579 361.9163] +/Rect [522.6425 686.8453 539.579 695.8514] /Subtype /Link -/A << /S /GoTo /D (section.3.3) >> +/A << /S /GoTo /D (section.B.20) >> >> endobj -773 0 obj << +1215 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 340.8618 539.579 349.818] +/Rect [522.6425 674.7905 539.579 683.8962] /Subtype /Link -/A << /S /GoTo /D (subsection.3.3.1) >> +/A << /S /GoTo /D (section.B.21) >> >> endobj -774 0 obj << +1204 0 obj << +/D [1202 0 R /XYZ 85.0394 794.5015 null] +>> endobj +1201 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F41 1208 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1219 0 obj << +/Length 2174 +/Filter /FlateDecode +>> +stream +xÚÝYÝoã6÷_áGXëø%‘ìãî¶ÅÅî’¢½>(c kK®>’ºý 9C[ŠåÍö6ÀE€ˆ¤†äpæ7¿Ê|Éà/M–2iÕR[•fŒgËõ~Á–x÷ý‚“ŒÊdš))¡3óv•I“fFèåj¼ÈÛ»Å?¾|)Xšç"[Þ=œöʵI­TvyWþ’¼Û‡Þµ7+‘±„ßüz÷NS©6šûi ¶ÈRm™ >Ô}۔ú¯ššÄÅÒ¦6y”Ö0ÔõÒw[K›ÜOsmízì½oöEUcûc±'™Ûc×»=¶ÿÃ2öþã-<¸Ðɺ©»ªë;|Ý<à³ëwǺ/~§Á†Æn]=ŸIÖ°ß³U\ÝW}…£:©nxRcÓO‚3úSqžÚ,Ñt)Xâ"O +ìn+×í 7Éz[­‹Žî‹º3k•¼iPÿ¦½1É°ó›ûE†Î•8þдØ(ÝÎmŠ¾ª7´ÏÐo›¶êAÍ#Ž4ŽdÃáh‡¢¦•h+F +žœˆ‡UûÃÎíÁEðëJ€¢ý¶ðîÒYR¬û¡ØíŽ8¾/¶¢)A$؆F~öË2XÂuëRPÂȼŠ¢eÑ(Vuqå +4¨joßñË`wÖj†Ž‚÷f|SHÚê~èÃ"Ùœ?ü¨ßü¾ZEÌs•J• B±b©È%bž§BÎKn×ÍÁá +<ð|߬o¹ù`&͵KÞºö85ØÓNBƒÅp€ñs°o?||OñoOëP¢ÀG'HM‘Œε"~4à*ÎðRÃþÞÑ<.Xl5ga‚¢È$*x–[8_p$Œ—Ñ&¡w@¿=V¥£÷`ùjͪ…öv0PÜ7MĘ B]KÕ%6ÖèÛ ¨È)£™'ãÎù¦C7¾~iÚ¾öØ÷ÿpûŽ ÞüØSv¤K,>ºæ¡©Â’C±þTl¨ƒF÷r‘ã ]”ûªöp-ú¦E 5Ð3ð9B¦êf6Ø£cz"´×MKAwhê’¦‡øüÌ)Rýe (þÙnŠºúã䑳Ng•¿<2>œ(§">‰zƒ“¥M6Ó2žÃ"Ó  𙽔€ôi‰à !‡¹.nëp׈K#šÊi0B¦ƒ!ÈEkwè#wL”L§,jN;ñ¢v!k`¯¨ù±¿0­¤©á°ÅÍ(ûÛPa#Rƒ–>h„TS×¾Ð'Ä´2y,Úªhž«q±¦«ù0|5ŽXœ|i %Dž+}i™È+và:Š .—´©QŒ°ù #A`O °“ìªÍ¶rþ?ÑËSÆõ,MtÍîËQÔRSm’Ùà¢èaõÜóÜ_*˜¸8LÈç$ã$>J’ö"’`¨ ­ƒe}8ëëÀásâ³”ã ÅÚh‰>®©7 /«M·"˜d"µŒÉi¸Ôn¤,F¥²ç”; º¶²©üÒH°†ž7S¹FÎ8 ât€ªÿˆ½p*¡² °{CE]ιKó4—9ŸÓļ¨É(,ýé©¿‡ ˶iz²ž„"Ï8ŸB‚Jp·;^bç8Ö¶<¹oÊã´üì£Ð¨Ž4DN†ÉÉr¢ P˜ @cRàâH=Åáàê²òÙæðyÊ•ŽÙ;Ò“9Ñvà–ö0ì°=f´‡T©’æ™=µ"½Þu(kÁ»€¡÷3®„ë¼Î£v÷Õý®j6mqØç2 TäLb°>”XÀy¡Ì™j‚Ûâq Ôv$¢ +žD8^øú &®*‚îóSˆÏš|SXuYµ)©Ú„âüѳoSSiùS¯wUý•eg(£ãÜsÙºOëàïg7b¸„%Wð¡Ðñ€^Á;NÀNTÿ¯ÕâÛ»Ó÷›CHᙺQ +ÿñæ·Å/¿²e¹`Ë,•ÖdË'è0°&TŠû…’Ðd™‰#»Åíâ_ÿ㬨ǨP¸ªÎc°5#º§K­â™V܇3üôEjŠfø +–Q£­¢+O(Ÿèº³ß…Ù¤ÆáÜ,Ç[|Ö§%_P[B騠ò™ªýó`ÉU¸týqwyˆLä©Ê³ì¡”YÌ'}šûÿƒ“©ÿ‰3ÅWá$ h·Vž?pŠY8I ”‚lSø´£à2Þoýçˆk¥$\î™Ø¹Ó€H~ú÷oPrÛtýHx-Tà3Ÿv@¤è]’·`ºç×î‰ àÚýô•¯×=:å×n„èç–óÌ!zd¹ïªß=Çæ@¿OUÙo¯ƒ÷Õôý 7:ú¹AA¨²ü%ðr™2)"ÄúsZVicÎ; ŸÁÏh£WcÄçÊ+3‹Ÿ±ò#ýšo›]yJ¯¦úßJV§Ìrû’\Ó4lqþ²áË’ÈFCÿ9¶x- =×ú +µ¾€Ð5༚ºÜ¸c3Í¡vÃH-Ôø·¿‹ßE `{õ1³?ÆßÿඖúŸgÑ#!¥`jIB¡¿0{üÉñ¼RÜí¿ð\endstream +endobj +1218 0 obj << +/Type /Page +/Contents 1219 0 R +/Resources 1217 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1216 0 R +>> endobj +6 0 obj << +/D [1218 0 R /XYZ 85.0394 769.5949 null] +>> endobj +1220 0 obj << +/D [1218 0 R /XYZ 85.0394 582.8476 null] +>> endobj +10 0 obj << +/D [1218 0 R /XYZ 85.0394 512.9824 null] +>> endobj +1221 0 obj << +/D [1218 0 R /XYZ 85.0394 474.7837 null] +>> endobj +14 0 obj << +/D [1218 0 R /XYZ 85.0394 399.5462 null] +>> endobj +1222 0 obj << +/D [1218 0 R /XYZ 85.0394 363.8828 null] +>> endobj +18 0 obj << +/D [1218 0 R /XYZ 85.0394 223.0066 null] +>> endobj +1223 0 obj << +/D [1218 0 R /XYZ 85.0394 190.9009 null] +>> endobj +1224 0 obj << +/D [1218 0 R /XYZ 85.0394 170.4169 null] +>> endobj +1225 0 obj << +/D [1218 0 R /XYZ 85.0394 158.4617 null] +>> endobj +1217 0 obj << +/Font << /F21 930 0 R /F22 953 0 R /F39 1151 0 R /F41 1208 0 R /F48 1228 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1231 0 obj << +/Length 3187 +/Filter /FlateDecode +>> +stream +xÚÍÛrã¶õÝ_¡Gyf…àBðÒ7g/3oºv'Ó&y EÈæ,E2"e­÷ë{ÎEJtvÛ¦ÓŒÀ¹ß`µð§6q¦³E’EÂJeëí…\<ÀÚ_/ìÐj õíÝÅ7ïL²ÈDëxq·• +™¦jqWü¼T"—p‚\Þ}÷ör¥­\¾yÿÃÕõ o®~àÙÛÜÞ½ýÆ¿H+ßÜÜÂG]®”Š¹|ýÝÕwo?кâ#¯oî>¼ó÷×w×ïo.½ûþâíÝ€õ˜2% ¢üÛÅÏ¿ÊE~!…ÉR»8À)T–éÅö"²FØȘ0S]Ü^üm8p´ê·ÎrJI¡M¬gX¥õ«l&b£gÕÝ£#ò6MU5‡²~ Ÿë¦~ru_6uGùîR¥KÞw® QYÓ·pÝzW¶£ ͆¾}¸áÛë›7Ãá¿H©ö»7þK]¹¿œ²4NE¬$`E"ü¿Š§:‰LNxúŸí +xÈ(…Ȭý hŸ„³xvLZšV‰Ñªè¨ÚÙH^I$²4Y$&]’1‰ëR)µlÆ<¿ž­TªYþt©åHD'üïúçþFY"2•á=.ÿuÈG¶ø?a˜–ÂZ8{VÃÇ4X_d#ϱîùÐxÝ-:¤ý›w‘mÑ:¡¥‡~W~BÍŽ¥\þTýãËÜ"D²?9»$Œ$8Ìße—Òpš$ð”ïÊü¾r(¯FXüyygà£Ôþ>¯$úZKaæ½wwyJM-T$Lñpób8UfÀ9N@Nôvˆ~ošmÄq“oyöö¹ëÝö<=ð¦1Qˆ@žÌ’lUS³l÷»¶éø‡ˆðí½>¤zY4ëýÂ,ÍÓ,¬7ôuŸÚŠ°ò›ø”²îú¼ªBä„™¼.è¸}ûѹöô2ÞÇáFHÊ·n÷ÑUî™f®ëÞíj×#eãH‡´0;²˜™D ’Îì²k6ýᨹтâæîÕåÊÈ„ñ‚é/ß»OŸé ÚýT:N=`‰0†Áf_9²'¯:‚öDA¹ÁØ#:!€Ìô%)RZÓ Qò™F„ð7ÄÏ显½̉d!ZÆ&’OÅúWÑæwcRæÕÇ +”'ŽŽÄÅ6Hfr`vJ,z‚oNë¥Û‘€Öå:¯^á4D²ë!qØ÷Þx‘÷ù}Þ9Hquèiºë)rºŽŽ+ëM³ÛÍøI+Û¼]Íñ¾%©bÚT ~©åcÓõ4_a =§ôGÊ‹‚¯ï© žÊµ#¨'·ërO˜4ÊŠfýÆfß÷p÷ÀæxVÂßÑAøwÆîYMFô µm ö鯶¥B«„|Îëªé{e³Ëªi>ÒhßÒwÊY?A_ÎÞlP%°œKµ|¦!H´âŒÝ‚Ƚ^MRHÞ=#ŽØÌͦžÍh¡1]Œb઄8´{ö ç+ºïJôH·u®.˜šßönWzY XjÍx{ ï–UiK”†ÐYf§œ®½ÊÙ¥<ƒ2ø÷¼:aìj<ó@6-݇<7‘8`&´ )²ZÅÚ’Éá"9Ie|õÄÇáÌ`<^V8åL†Êåô ØÇŒýeƒûÏ$LÌ7s’"ËÀM½¯Æ6a3oô6JÙÏLEyŽ”ª"2ó(ùê°ssü6 dKi@Ý…±!Š‚½UÅ Xãó­IªGŠu_Ö³ä+’HÏië„ÿƒr* ºêšÉŸÀü1y¥Ÿò[úu}ûšá=]¨tRH­Ó©Ò園¹6ß ! huÕäÅ׺Ü¿wà¡€®‹ù\ãë$9ìŒJŽž¹ <¿}õî!‘M¢Àr‹ì°<Ù¹-*È,ÍX£Šàõ ¨ÆJÄvZÿ˜÷4À‚°}Èëòs¸>gĘ¢žÀý|½æ¢Íû7OZC_š_±m*¤ÂDpl>þž|HÎ1ÚqªTlË VŸ81ºo08£ }Žd¶|›{/KuS¸Ò©€/a¦¼+öÑ/™á«Ñ)˜äÙÆžsvš&vdápxH çóÑÔÝUŒ6ª‰gŠ¦ÄQl¦šd©•fç¤Ó3D—H†)ëx ü„8W‡0k´Щªà +Â"×ñ=õÉz›÷45²SŒ8ˆø˜ÂKçœ8Å$Sc¯Ñ4ý oTIœžO¡Š ù”LvGizÄY|IäX Rþ„5}»²ïÿÀˆN£œ÷çôÁøá£6Œ=á[^á4œ<ö4ôLA`·ár0x>;/þé3øMÕÞòj.Wó([ª]¨Q›ºâ„ç>4–ê">%Ô2ìÊÊž]Ë–_÷Á{¢âÍfEï¼]BîS¾m+oLäprÐX³ÆBU± {ŠSIœè ‚T&ÖͶÍë97§#(QMÌñíäúëz-ærD¤± ®qÝì«‚®¹w3Í“ $á‚f¿C<Ó)³9UFØ$Rƒõ“vZ%¤ˆ‰v0g=&TÓF f}:0½ †2 Ž5\e)±ÊsP¯–f*÷„Zà Ø¥„ç((Ï`óïÒo…²° Ô±©ºWsÜEo*…|ể‘©J³*s½Ûßý0¸Í4Id¡` 3Ô)¡£A¸/ƒ}ŒA¯ŽIÀŒ¼"àUšLy5G ™dDͤÁ[‹³Þ»g>‘™[|X93DƒÉäI€Ä9nbtXÖ§l^&÷ᨃŸ‡>߈½èK >ÞûÌGðxxJÈ’CçLÌŒ¡Mª—ÏpÖ\¢µP&%ň¤ó1ÜãÖ#&>‹À»{þ²Ìc0•Äždßy¬ +9›ÂN<\k)ŸÒˆê8­À^ò 𘎆T¡GKG;&H®EaHôú¡§}7DAζ5fƒcéÇ&\A„‡ýslЛq9nGÎ¥/QèL;:*×63ªšŠÈLò ¡~DCèXÒù£ +V ëOÔ÷3—“ø¬1t`(j7}³nª9çnE¬‡"‚GPBeöÄVHIš0Ê»®Y—rá7ÆE±8’Q4K†h–p߉0pž!ûpg0 +ij+PÂé(;­öÔüá3h2ëb6‘O óCˆ­¥:l-¡âeÑò¶ H{÷ÂÈ£)biO\g·oÛf×ýšÁi˜ Ù>Kö¹usÏŽáÁ먰' r€¿‡òTP€ùg"ZÛ=,hðaÒF&ðÕþ¼÷vªï*ºõñíj&¡N‘Á”_)(ǧŸµ²¨/ q~ÚHQue§ÊôœS‡„fè½øJ«pÞo”UbÉ´ùä«/2ÁIA ¼/j®æ6óÕfÌ-•Ì, ´œeÇp„áÆíÆÕ^2¨Ø‰‡ˆ5?ëqšI½tþ9$ѳŠ¢2¨Z¡l]¨T +H•²/hÊ¿o8—Òù¹gºr5§+üe+5ÁçüÙ#@}‹óÓ]9í^xʲ8Õç] Ã]Œ¾w¹Ga3~óÀ/”šœmëvX=à Ž}?ÅhߨÂ9ÎŒœ´È |Åb‚|6;Ê-z’¼æéžï‚HOZg8`à (7ˆÁ†ck½æ›ï]pX !Ð\ ‹d Y¾6£œc.åP§&jÒw|á@_\ByÍVã_jûæɉy_qWèïCë¡ ï);«Ž½ÛŒò„4 +‘tôÚÄ„¶)Ã;Tèu®r£w¦³§( +®£fw"®höx׺©;°Çn|>”°ÃÓ¶PˇýjÎÖzýÁ”rþ!È£+Œ­$üE™ Bö‘Q™…­Ê"ôãÇœ/Áò±r=?5M[ô°ÌÏ[€Ì°u¸Âz ÆmÜo<)¶ó=P¿+{’‘OíRzwdîØPÖ6ôV`0ÐhõðlÓã>§¦|êv=£lÁá“xý1‡š[ÚÍ„C9ßšÞ4â¦Å7ɵkù ’ß ÿe¬ˆ¦¯¸Çÿ¤ùâãý×þ{Ôñ¿Ä T0iª_ð‡)¶ˆÌ€ +@Ÿ!þêó4Ï©Êendstream +endobj +1230 0 obj << +/Type /Page +/Contents 1231 0 R +/Resources 1229 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1216 0 R +/Annots [ 1237 0 R 1238 0 R ] +>> endobj +1237 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 328.7635 539.579 337.7198] +/Rect [272.8897 207.1951 329.1084 219.2548] /Subtype /Link -/A << /S /GoTo /D (subsubsection.3.3.1.1) >> +/A << /S /GoTo /D (types_of_resource_records_and_when_to_use_them) >> >> endobj -775 0 obj << +1238 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [532.6051 316.6653 539.579 325.6216] +/Rect [190.6691 179.6723 249.6573 189.0819] /Subtype /Link -/A << /S /GoTo /D (subsubsection.3.3.1.2) >> +/A << /S /GoTo /D (rfcs) >> +>> endobj +1232 0 obj << +/D [1230 0 R /XYZ 56.6929 756.8229 null] +>> endobj +1233 0 obj << +/D [1230 0 R /XYZ 56.6929 744.8677 null] +>> endobj +22 0 obj << +/D [1230 0 R /XYZ 56.6929 651.295 null] +>> endobj +1234 0 obj << +/D [1230 0 R /XYZ 56.6929 612.4036 null] +>> endobj +26 0 obj << +/D [1230 0 R /XYZ 56.6929 555.4285 null] +>> endobj +1235 0 obj << +/D [1230 0 R /XYZ 56.6929 530.6703 null] +>> endobj +30 0 obj << +/D [1230 0 R /XYZ 56.6929 416.0112 null] +>> endobj +1236 0 obj << +/D [1230 0 R /XYZ 56.6929 391.253 null] +>> endobj +34 0 obj << +/D [1230 0 R /XYZ 56.6929 164.815 null] +>> endobj +1239 0 obj << +/D [1230 0 R /XYZ 56.6929 137.4068 null] +>> endobj +1229 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F39 1151 0 R /F41 1208 0 R /F21 930 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1244 0 obj << +/Length 3415 +/Filter /FlateDecode +>> +stream +xÚ¥ZKsã6¾ûWè¹jÍàAäÑÉÌlf«ÆÉŽ•ÚJ%9Pm±L‰ŠHÙq~ýv£ %Á3›ÚÒ` øÉYa2¡Ë|æÊ<3BšÙj{%fÐ÷Ï+Écn ›é¨ïWß~ÐnVf¥Uv¶x˜ÌUd¢(äl±þuþý·?-Þ¾¾QFÌev}c¬˜¼[|þñÝÏß/>þxw}#¥uØ—sïâ‡÷4üÝŸn?ÞQûîöSï¹_¼ÿDíß„ïîîá!¯_üëêý"r=Ý™Yþãê×ßÅl üוÈtY˜Ù ¼ˆL–¥šm¯r£3“k(íÕýÕ¿ã„“^ÿiJRF™)”KˆJ©”¨L™Y­´Õ˦Ym®o´•óêp-‹y/b¾®Ûú±ê5õ =»aShÄ_Ý®îAz6×óÛ“šnG£÷]³¨«é‰´­OaÒå+OºãE»ê˜/œw9Ù„vE&-aëÈþÝ=}AãWÝaÝÓG';ÏËLçø›†¹ƒ­àØÙM®\–ëÜÎ@+²Òå‡íY¸{O¬x²8Žê:&wgÝ“Ó +¬f~oöTf¹Ð¹ßÓ”°R9È ªÝÊoH‹ùªÛõͺö&æÛ¹œQJ• *–býgµÝ·u¶ê¶ ‰[—•¥Pl›]Õ&Ó9œ¬°§‹ ʸXϤMÅ;Ûu‰å¬Í„ +FÙ—´·¤r™ ½úš©Àã§l¢b+åéykçÕWÛq‘´[S£æ9¡9ö[0ƒU½ˆNG ‰ÃÑvœÝ«t\ǼÛx]„ïIº]Û=òŠ4…QñR›¡y®G.Oìé•l°?>>’îƒqÒQ ùµ;‰®Zùó‡ï{jA¦½!åØ̉è%½†§ìˆòèÅ¢ ¸ð30ÇxItkÀç dãc ¬A›ß„P«c;¤ì‰Îã‡ãrhÙ‹ݾY%ýö‚½…bþÝÇ»wÔ¢õÀ{Wmë-\‚é7pžáŒñ­ZdåØb‘Ú› v¬k8]jî ÄiÇ)\‡'Á3íiÚôæBox‰mÕ^Ÿóc¥ý÷mõìGƒªÖ«¶:o¤…ãõì›qˆ¿. +¶ÜÙ¼Ãî!åUVDÄóhyÑ~_¯š‡WZÏoÂ+‰ õD"[+îÍ•óÿlêÑYã,„&ODé»-Ï`hŽ.%8r——Å™½¢5–FWÝÓûKÓ¶¤Z$tDôhï½á…N“È>|"°xHA-dðoC­6–·<Ä,–ÿyå{å®þ‰YŸ0™5žÙfÅœóCâ#ªòÌÊ\{TÐî%Óà—Uø—³(ÜÔµ\@®ã?ÇÌ^ +PÌÛ#„]‡f¨v0 'o†)¹¿„@`>ȤùÂÊ;\¥9¸À–?>¥è<ÖDóé <=VÁ³­«ž›ø]†¶uˆ~ªSnñ;6chñÁ'"NΫÔrr|ù%À—`*ƒ÷Cþ¢ à|‚s@^WCE-:'IÇdasøPÎq£ 7_\—jŽ~ÂÀ‚'”¯ã8I% ¥këCå" ûsjPi¤LqW/ÝቨUÓ9BO\(ÈûFzµ q¯y~¥—ŽO3LOeIߤjª,!q’áþ¡>Í™å> èŸë~xG ›?»Ýâ[q~ð8€W¦~Þ— +îˆçŸ¡£ë_ìy˜0âöÖW.|ÿÒÇK~~nPšVŒ3³œ=·Ôµ¯VOIQÕÂ¥Ñ%¸2çÏ¿ì–ˆ`¯LëˆÉçn @ê ¡-Ð×õ?¡ +txÕÁ(1Âùãqt0úØÇ‘C×µLm›§:ÂÄ$è’y¦ +sÔæ1eME&Á$£1â¼äc w,°¬’C¼WJˆãV[î<<ΨñyZ­ ão¦\Vk.çEîëÕ -4¤_gª1Rg:“ÙEyJj•A¤_Ìr“ãB.YOŠ£n¦Ã.9¼œe$³„¸ÁfÊg–’U þ%¢30Jø¼õŒŸ|•“ON|—)þpî8' ‚Ý/›:ú°€KHa ´WÝþ•º}¤ã\fè‰AÒQp‹}èQ\½ ˜Ðc„Æ]bŽÇ]DMÛ³¸>Å}'€»}K,à¿Kˆ´CâA;w¹ÏcJ*²©Ò½ÿ•à3ÍS©³ÂÊKçé’Êl,T`À„‰À5,õ +ñ,…¸Hs (5Û®ò¥.^ÚóÙz¡¼‡8àlD®}°EsÀÜD ‘’ëuCu0h/Y€ÒØ,Ïeyj.›ã¶ò£I(ðÜ“jlª=w<Ö;ðQ\YÓóm½ÚT»¸+ L؃7fg¤X›ShFN¡«ˆ>à32o45³™Qxê5½ã¼‚'Ó‚P)¼<`È$­ÍOËF¾Àí'K´Édî‚fuÉ S‚Θ0g0©/ΚËÌHm¢þð‘•€¼ÂœºÍˆoÒ1C +¾ªz + „Ùt/õDוdå’fd>‰²òôW"RZ*)Ööµ…pHãAQc€æ‹@!óòX:«¬>'NybÏúF†Ø=¤¥«òXÈ^¿B<جH¼Ç=ÀQJ¼à>LYÆCÛ×ì2“ í\VäNÎ' ­¤ï) ÿ[!3A³ŠVg"¼ã+¿¥³ÒÊLˆ<¤”^$@ Ä¢' È!/zq®ÍO»îeÇzªh$…ÉTéÆ™ÖiÌ5œN ßyM +¶|üßùò„R!èyìØ5Âiq^·f@ÔÚNGûºI©ž¸9=C@®ˆB +·o¾Àbº¦úž&\Õ=¯d‚Ó÷aŠKѨðÀæ@pðQ}ÿtNÎÅærtÆ–çÎB‡BÎÅNY/…@J9V_•=õ‰aaéspÓ ß±P­×„Û.„ºÎEç_1KŠœÍÆû˜™;>¹(†t}ß,=¶8®(£ÃÒ ¯†ñ±Ëë4>¤QwIpÎEÌ_ÂÍg%§*£•Æ„Ê_MqPÕ }Ýr& Y<7ú“9¦èí73™þ¸äu›ÂÎk‚ôR0#Rø¢¾d¶Ãæo"ÌÏ}(D˜1Ž‚7ÃGŒÔÑozu@f’fùþ%L"zª¢C‡¯OÁÓ'#Æ]^Ⴢ"›âä>1°‚קZ#<öuœ3qÞ——„ÊùK»¡Žgj)-\fT«ëãýl½d¼zñÙø4Ãäð@Ù“du2`ÜŸ¯+Žæ•ûJ>kGAûÁdMjù˜–º±!µÈœ«jrÃX5:yh“®£}XöÛö !¯u2T ‡nOƒ[ˆ+’e–% * ÜUµ¯ÿLß?˜MdoCh P[Éíü_[9®´¬ö¢"Ò(XÜø.1Ñ7Ü ›»¡}ùW_”繪‘´­Ê\nÌùµ ÝSOL_(”bP¦ ×ÔSðL° ásÔLL‚ÑÖp…°Yž¹ ûê¸ß¸`ñ¥§Q ¡Ï9u/gæ· ï{ŽÙb‘çâ¢>J˜êùÔðbNÖnÓ£ŒG€Cm}¹÷3 %0ŠÿzH8ج +–þvA•c«ÇøÀ†û,¤ÆAg€hCõoœ€}¼ew8ýš*çÐð‡#çô/œÿn1]/‚0Péú\í8 °ef´>+sŒBOD‡+^ .ùRéØ{.¿$=ÕõÞFñ«ˆ š‰?½Ž7]áVý:.½¯k¾Y;î©«ZQåoÀ:®Ä¢jè„Ëð+R7`Áór%Õ;ßÑÜDÔà3%<Í«çªi«eHùâ„ mÏ&Áªa7^d5UËuıJ/$ÚôúÕ”S¼|0DÊÞúëä˜ø§DaJÄÿÿý·ªñße¹ËtQ¨t…K‹/‚#Sxú¢þ~uÉùœ”'Cendstream +endobj +1243 0 obj << +/Type /Page +/Contents 1244 0 R +/Resources 1242 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1216 0 R +/Annots [ 1247 0 R 1248 0 R ] >> endobj -776 0 obj << +1247 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 304.6667 539.579 313.6728] +/Rect [519.8432 463.1122 539.579 475.1718] /Subtype /Link -/A << /S /GoTo /D (subsection.3.3.2) >> +/A << /S /GoTo /D (diagnostic_tools) >> >> endobj -777 0 obj << +1248 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 281.9139 539.579 290.7706] +/Rect [84.0431 451.8246 133.308 463.2167] /Subtype /Link -/A << /S /GoTo /D (chapter.4) >> +/A << /S /GoTo /D (diagnostic_tools) >> +>> endobj +1245 0 obj << +/D [1243 0 R /XYZ 85.0394 794.5015 null] +>> endobj +38 0 obj << +/D [1243 0 R /XYZ 85.0394 570.5252 null] +>> endobj +1246 0 obj << +/D [1243 0 R /XYZ 85.0394 541.3751 null] +>> endobj +42 0 obj << +/D [1243 0 R /XYZ 85.0394 434.1868 null] +>> endobj +1249 0 obj << +/D [1243 0 R /XYZ 85.0394 406.5769 null] +>> endobj +46 0 obj << +/D [1243 0 R /XYZ 85.0394 301.1559 null] +>> endobj +1250 0 obj << +/D [1243 0 R /XYZ 85.0394 276.6843 null] +>> endobj +50 0 obj << +/D [1243 0 R /XYZ 85.0394 200.1512 null] +>> endobj +1251 0 obj << +/D [1243 0 R /XYZ 85.0394 175.6796 null] +>> endobj +1242 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F39 1151 0 R /F41 1208 0 R /F21 930 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1255 0 obj << +/Length 2457 +/Filter /FlateDecode +>> +stream +xڥ˒ã¶ñ>_¡[4Ušø¬œÖÞuv\ÞÙdG9¤¼>@$4b-²Ž¢|}ºÑ ’’8Ž«R:°Ñh~7$V!üÄ*N‚$—ù*Í£ E¼*š»põs»Lóà‰æT?lî¾ÿI¥«<È™¬6»Ù^Yf™XmÊ_×"ˆ‚{Ø!\o>~¸q¸~ÿùÓ»Ç'‚ŸÞ}bìó¿ž7>ü5ŒÃ÷OÏð÷B$i¸þñ㻿o>|¡yÁ[>>m¾|~ÿÏ7ŸŸîÛü|÷a3r=¿™²üûݯ¿…«.øó]¨<‹W'„Ès¹jî¢Xq¤”ÇÔwÏwÿ7œÍº¥‹’a U"D%å’¨âžiÐèÞ™ƒ{s|õpe{Sïîé«™Ì]Ûý¦ëvÖ0ÄÀÎ (™•Ž7t „ßø«”Ѿ*KX Šé€ƒ<Ž¥»*³D@žD×—ýª8Zn M=»ùKb€ãðv)!i2F¹1†D¨Id€E6[³5ûª- § …ЭOº®—n¤ÝŠØ©†ÕôÐêmÍ°YŒšnš¡­ +my¢¬hIaë3aN•SNìU@7ؾ*ypêŽu C`ab5r´CþT&£ÆàLa¾¤ ¸á { nx¯g§þž7››+ì%£ DäöÚ8V²ˆ-¢ïj2ÀÔÕö¨•éixpÝ+ð[f{¦oÓõ– î`PsŽögÐHãÖÇkÍ"t,©|Æ’L³@dÀeèXêí°½åié.qDR +^÷,ÊÕº1º9°{m=d˜]=êmg <(¥‚$ŒÔ¥)úÀºêvô…K‚A4tÈdŽ`Ñ”ƒ â0^a˜ š%Y˜žÍ~{7jÀ½_Í5^×ßÆÓ® §»+>ô`÷ݱz¸4n +âôóŠtiLAâ^¬=:)Hã±Å R¢$3áE–ú[¸ó`™»|5MÖ]¡k´d€€ã`é(7FîÍ|ÆÜ*Þh(Ìëe7•Ùòœ³Š + ®%~êŽ'},Q6ÿ³nøðJ&’PÌMfR…ˆÉ,§ë²sn‰óeÀ ·B•AER2Ë0`¡&X]jcyt%Ž S‰Œ™BæSF[ÐÆg¥@|º]ªJ°óI£)¾¢l–RHE„cñÒáÍqW4qüb‘I {ʇ=@ü>*¯p@• +B3¶œœî!k÷»3 vd’ mäbÝìÃ/î×ññ°–±¼%+ NI.5$BBš\ +¬9ÈÂßM%n×újv¡ƒ˜•Ãº;ÓŠ(„ÊÕ¥d£¤Y™Ž™È² RBúÈ“ùÈãc˜#p!-#ºÖ1é)º9=qáü’f»LRŠPdˆ¼ž/"2 F G; }Ôt(é µÂZÙÑ÷ô5ÿÞë¡·~Ïžn—ª7Ýö'§Ìˆ*Tú®Ú»è4gö× º‰e4¾ó¡ÂRèLsßq‚º+Ä»PeG²Â#Q¿§)2ê(ôÆœÏÊ<Ò2 _ªW¿y_ÙÅÜíÌ5‘˜r¡…(,.k]ÄP0T‰òÕƒô±—Pq!§éGܱ5<ÍlbM¥Ø¦;Z +S¦…€Äüœºã2±öŠ 41ÑÍ–,÷úBäí]¨u›«˜úDOâ‚ÙLë–3žatÙ±º÷5vxnïH‘šªmÝóìAߌå³ìž¢Çð²÷CdÔ“õ±0¤RsA„$ÏW¬DŒ‘ß!]ÆZ7]2}e1¼¨„ë1Üi$žo1ž-Û¯N›$†hj¿F&zÂRå§Þ*'MÍ{ˆá`æ[?ס'œUo›rj¸ÂúuquðÏ _ºÚüé®= ×?<>½'È·^³î' Y܈¬8H·† +8hÁ;ÑÍpÒEë”’ÒÙÛÀT©áßÿ?J1BŽ- LÖúÕ\-à´s³¢]¬£¦„ÁÝÚìYË¥‹œ?NóNolÆ.Ðúzö[£«öcw2Sæ‹$ôÉÜzä\ò«NÚÖž†ÎÝaž[oßeãi!ä¶*x@NKø®ß_÷Vo-ó§”k9ÖÝËß3\vÐG(%ñ"BRi‘qêHs_é#J—¯ºµú „0.¤Ø¿e`·7 A]{yÑz}àLãîe\¬Ísk³ð‚ÂyúRìlýSÃìÑÉÙhr-àù«C2I Ñh6Ë•](!•7ºØñÁ½ÐlÇAšå©¯òÜ%Ø á(v³d”"¹nO“›î&˪ÇÍ…)RA)³Ëx;5äT´)òKL¥·U]Ù3!É”ÐPñDSƒöCXG¹ËéAɸÖÈ|)ÅãVWö (çWt ŸçüùêhÒB:[ÐîuùžG3½åŠ2I>½+ŠÝ•ðN¯Kue ÍŒ€Îö¢~K¡@œ&¡ZR(œÁ­ +M­ + ZãŠÜƒ[æž.ÇñS!L%:P–ô˜¥Hé!”·i"®"!G­š¼ü…3Ãø(M¶æÒ?/ÕºðõwÕNïÉzê-çÕÃÿ­@úÂ?Dþ ÇD÷ÿï2ýý¥Ê2¹ü—ŠÌ OÕÈŠ%ºaÜÿ?sËùy;:»endstream +endobj +1254 0 obj << +/Type /Page +/Contents 1255 0 R +/Resources 1253 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1216 0 R +>> endobj +1256 0 obj << +/D [1254 0 R /XYZ 56.6929 794.5015 null] +>> endobj +54 0 obj << +/D [1254 0 R /XYZ 56.6929 717.7272 null] +>> endobj +1257 0 obj << +/D [1254 0 R /XYZ 56.6929 690.4227 null] +>> endobj +58 0 obj << +/D [1254 0 R /XYZ 56.6929 550.0786 null] +>> endobj +1258 0 obj << +/D [1254 0 R /XYZ 56.6929 525.2967 null] +>> endobj +62 0 obj << +/D [1254 0 R /XYZ 56.6929 393.0502 null] +>> endobj +1259 0 obj << +/D [1254 0 R /XYZ 56.6929 363.1913 null] >> endobj -778 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 269.8356 539.579 278.9413] -/Subtype /Link -/A << /S /GoTo /D (section.4.1) >> +1253 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F39 1151 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -779 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 257.7373 539.579 266.8431] -/Subtype /Link -/A << /S /GoTo /D (section.4.2) >> +1262 0 obj << +/Length 2097 +/Filter /FlateDecode +>> +stream +xÚ•XK“Û6¾ûWèÈ©qù~ÇÙõV­k+ž=Å9`DHD  +J–}ºÑ œ‘SÞÒÐhôóƒâ]¿xWåa”ÖÙ®¬³0â|wèßE»Ìýó]Ìk²< ó,MapgvŸ§U˜WI¹Û¯…üüôî¿&ñ.‰Â¢HòÝÓÑŸU”eXäeµ{j~Þ·âläô°Oò(Hþxú7m˲*cÜÁeem7üüñÓ/´ú7©Çy:H7úsV“ìå`´gaš ‹)P:6 ã‡}EQð/15W1±”é­”dW‡u‘,$Â<ÏS+å—OŸa[‘­˜â*@AøEaE-Bâ@Ód+.’6›I4ʨq]w#Ö³”Q°Û°¸~l¤6áÃ>ÍÊà×q¢½x“´EéGäå–ÓEN|¤i…ÁKá5â8¬ó<±×`Uàú|.Pg9h#ŽG¼Â‘G{Ÿ±§‘8åö7³¹µÈ<Ëé8N½“$š^Mâ¹ãuBÓ—L kzEë0‰jòÚS 2Ó(ÅÕŸ?¼'ú(…™Éš8 ¬ýR¨ UÓ§7"Îtƒ ‹3#}ŸyÌFGòýÿG„ šÄmiÇ«=Ê,S§qh2ZÙ'1¨oä +>ã;ÆïÅ‹5T´R\nDΚy㑾¦…È‘Ž»½2rì͸*Ýò–‘¾PA5”bEÐQ„žÜXß´‘½•’ÇqrÇù³ÄùÜ©Ýc/©| +hWü(½½Ylovœ;çå~îŒ2-©,Ù<²÷»n¼ªáÄqˆšêØ|>þA콃ÔzäʱºFä®m3‚XÖ –¤ IeÂïTŒ +Zš\2.6&¾SsîV‹ŒJn‹ëè^]Ð4c5G‚LŒTÍ{Äp’¼È§ŽTVûC'4‹èÅ¡Uƒ|-ÓÊhMË4`šÑßF¿é +®gCƒƒ•wz¼çab\rc:OJK§ rM’¨ Ô‘¸·q&Â&TC´´ò¬“a«ìonƒèQYdÏçFÉk„“âªÒZ¨xm¯öx/ù¼UllÑY6HÆYƒX½ ¾?g9)©}Ys 2¬ù±J9‚þ#ûqºýA”.%0©³ w"j*xÈ3n’Š(Ñ­-±5U9d<ó"_ +hZã|jY/ýE‰áÝN6“dy 8xp]7b~{é0h”~’e±½„3×rÓ,Ã,*r¸2Ư{ë³½ŸØøÎê±×꛼cµ¬Ë"-XÔx¦J’VP¶ØW¶Ö6DÙ6ßNõÊ0«åU¢癶¿À×¹`+åùöj«U +^–@Á³"ÊÍ—üŠÍVzÙtg¾ÀæÊT/šù@1[ÔÞ%t\Ôy§ðÈAvݬipûqA)µ15âë/túK=ð~jVÐ$Žclv ô<›Í0/ü<‰†dà¢ÍÊùC¿Dy„W{÷áÉcÇÐa…0)á–qU!r¤Éé´#â·5Ôtë÷ë 5×Þ+­÷Y|@åaµ5-k]–A8,¸z­mœ%ËE’ç܃Ã~Õ~½ì­Žo¥¡`¥˜ÔPÖ…¤%€%j˜eøÛÌ)ÔpË%qÄßfG™‡e—¯²OµÙÇÚ" ŠkäØšÎ$©&”Kv Ó#øúUrvXÓ'QFê­õŸ-„Y ¢ZyhAéÞÂÝ,øhhµ +Ìk±NãØóƒF¼´ùåA¨ÔjZàêæD¡›G>>V›£ÐfËÕ·;¡ËìþÏýqy»àðÃpQÓ8Ø÷(Ík=ËöÑ™–EPõâµ²Ú<‘JD…B¸t>I³Ø渻2®ËZÐudn±3ã…ƾtš'ÿ¨ÂõÍã<=í€xfQXrÂ{î%URŸ›¬cPwMß%2¨vŠÐ9ÎQ °ÄÂ~ûNbÌ‘œÁ*Î#²­œ.ø„›XbI"èÓ 5ÜÛå™I•ƒz +âþî^̲EÑÅk˜èPÄÍ w®@íÄÿýu¼J×b´ûWdÓ3Ò%©p °{ÙÈb6îׄZáÿ$áÖÑ\Ä`ÄI®ÿÔÁÿ»^l¤ÿsnŽ ¤Eþß…ûìq[ÙÚ«Çž¯çƒ/©K4à ÝTnX®¦Uà¿!„¯¤û#P(þ­zEº%ûeÍ[™Fu˜&‘„×Ëß`l÷÷ìÛÓþ sèêendstream +endobj +1261 0 obj << +/Type /Page +/Contents 1262 0 R +/Resources 1260 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1216 0 R +/Annots [ 1268 0 R 1269 0 R ] >> endobj -780 0 obj << +1268 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 245.6391 539.579 254.7448] +/Rect [519.8432 268.1131 539.579 280.1727] /Subtype /Link -/A << /S /GoTo /D (subsection.4.2.1) >> +/A << /S /GoTo /D (acache) >> >> endobj -781 0 obj << +1269 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 233.6405 539.579 242.6465] +/Rect [84.0431 256.1579 143.5361 268.2175] /Subtype /Link -/A << /S /GoTo /D (section.4.3) >> +/A << /S /GoTo /D (acache) >> >> endobj -782 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 221.5422 539.579 230.5483] -/Subtype /Link -/A << /S /GoTo /D (section.4.4) >> +1263 0 obj << +/D [1261 0 R /XYZ 85.0394 794.5015 null] >> endobj -783 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 209.444 539.579 218.4501] -/Subtype /Link -/A << /S /GoTo /D (subsection.4.4.1) >> +66 0 obj << +/D [1261 0 R /XYZ 85.0394 769.5949 null] >> endobj -784 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 197.3457 539.579 206.3518] -/Subtype /Link -/A << /S /GoTo /D (section.4.5) >> +1264 0 obj << +/D [1261 0 R /XYZ 85.0394 574.3444 null] >> endobj -785 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 185.2475 539.579 194.2536] -/Subtype /Link -/A << /S /GoTo /D (subsection.4.5.1) >> +70 0 obj << +/D [1261 0 R /XYZ 85.0394 574.3444 null] >> endobj -786 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 173.1492 539.579 182.1553] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.4.5.1.1) >> +1265 0 obj << +/D [1261 0 R /XYZ 85.0394 540.5052 null] >> endobj -787 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 160.9513 539.579 170.0571] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.4.5.1.2) >> +74 0 obj << +/D [1261 0 R /XYZ 85.0394 447.7637 null] >> endobj -788 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 148.8531 539.579 157.9588] -/Subtype /Link -/A << /S /GoTo /D (subsection.4.5.2) >> +1266 0 obj << +/D [1261 0 R /XYZ 85.0394 410.3389 null] >> endobj -789 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 136.7548 539.579 145.8606] -/Subtype /Link -/A << /S /GoTo /D (subsection.4.5.3) >> +78 0 obj << +/D [1261 0 R /XYZ 85.0394 348.7624 null] >> endobj -790 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 124.6566 539.579 133.7623] -/Subtype /Link -/A << /S /GoTo /D (subsection.4.5.4) >> +1267 0 obj << +/D [1261 0 R /XYZ 85.0394 311.223 null] >> endobj -791 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 112.5583 539.579 121.6641] -/Subtype /Link -/A << /S /GoTo /D (subsection.4.5.5) >> +82 0 obj << +/D [1261 0 R /XYZ 85.0394 189.9853 null] >> endobj -792 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 100.4601 539.579 109.5658] -/Subtype /Link -/A << /S /GoTo /D (subsection.4.5.6) >> +1270 0 obj << +/D [1261 0 R /XYZ 85.0394 156.0037 null] >> endobj -793 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 88.3618 539.579 97.4676] -/Subtype /Link -/A << /S /GoTo /D (section.4.6) >> +1260 0 obj << +/Font << /F21 930 0 R /F22 953 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -794 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 76.2636 539.579 85.3693] -/Subtype /Link -/A << /S /GoTo /D (section.4.7) >> +1274 0 obj << +/Length 591 +/Filter /FlateDecode +>> +stream +xÚ¥TKs›0¾ó+t3AÕtt’:3Nƒû˜4Ç()SŒ\ÀIóï+!°Iâž: ³«}|ì~Ú…lx„"I%ˆeˆ8&¬7OÆwé‘>&‚‚qÔiæ}º`1HF4ÙãK ,Y~)âÈ7¦Ëùüfá³fɹPŽáÍç°¨rýb (aªêg[Õ)ÆÌipo'F%ì`û€ñmþ.ëKÑ´+3zT†ðB×C„“»mÐê _µÊKì4Ë‚•Íèòìѵ}ò¶'·+RîJÛŸjéÉù¬ïÓ²·Õ»ÀVoRªgU:5/: +ÕºÕõ«3uEó»$hô®ËZ«¤iëâa׺BÿÚ*Æ‘]…#;`ÞþÒþ{ã¿¡0FLzX¦ñÐS‘ŒÙ¾(Klô¡ða3?VþP%6endstream +endobj +1273 0 obj << +/Type /Page +/Contents 1274 0 R +/Resources 1272 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1277 0 R >> endobj -795 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 64.1653 539.579 73.1216] -/Subtype /Link -/A << /S /GoTo /D (section.4.8) >> +1275 0 obj << +/D [1273 0 R /XYZ 56.6929 794.5015 null] >> endobj -744 0 obj << -/D [742 0 R /XYZ 85.0394 794.5015 null] +86 0 obj << +/D [1273 0 R /XYZ 56.6929 769.5949 null] >> endobj -745 0 obj << -/D [742 0 R /XYZ 85.0394 711.9273 null] +1276 0 obj << +/D [1273 0 R /XYZ 56.6929 744.7247 null] >> endobj -741 0 obj << -/Font << /F21 714 0 R /F22 737 0 R >> +1272 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R >> /ProcSet [ /PDF /Text ] >> endobj -798 0 obj << -/Length 3163 +1280 0 obj << +/Length 1159 /Filter /FlateDecode >> stream -xÚí[wÛ¸Çßý)ôh?Åýò˜ûɶM²±÷¥Û}`dÆÖ‰$z%9©ûé Š8´À‘ÐÆili÷ìÚ‰9œñüÂ`@d#êÿe#¥‰vÜŒ“DQ¦F“ù ]ùŸ½9aí1ãpÐõüâä/¯…9â4×£‹Ï#©ájs2K¨µltqùûé‹÷ï.^½»8?ûãâ—“Wñ¬Ð3£¢>åŸ'¿ÿAG—>€_N(ΪÑ7ÿJ˜s|4?‘J%…3;9?ù5žütcšüM%\hžøU8¿JýCÅFF9¢›_DKØÙ˜qJOß”‹rY¬§‹«³1Wôô¯åÝêll5?%gcåx|_¤sßíd÷¥¦>ëFè.Ÿ[Ú,¯FÍ7¡ZÁn ·ÕÚ>­§[qõSq`¬ Þ+ÒM©Ž¬ð–•óéÕ"‚²¾.›oþQ-üw†ê#1(1!«ÙÄCŒ¨FL"ŒÔ{ F(¢´u‘Ñó¢Zü“R~u»ŒÜœ—˯å²c˜8TT yÌfbŒ@8f$ÆêÝ0?äh_¹¯jÂðç¡ž‡·¾ê–ŒÛ››j¹nþ0]4_Ÿ¿}÷²ùÎ8Îï óC -9ÎbA 9(ê= 2ŒùyŽ -eÉÅ)̳ËË峧åjÕò·ªúr{Óþá·Uzžùšï>–“jcs¹™ì˜Ç@À æ!/ÙšCLs˜w.†5OÄiŽzo5×Îi„‹šó!Í×Uóõ]1/q -ÞM?}šµÇ¼®–ób3⸟]昊\™¡!"s/Ո̩8™·½3è½m´1„ù2²q®êÊàsqf˜½°‘vzu½þVÖÿŸçU5óÓŠáì>Œý² qow“55œ5p:,[[^S•TkE˜d¶ÉÖf¬+iÌ×pzÚZË;_N¥|Ê%s…¾ìO0Ä>IPŒ‰D¨÷Ȇ„1Ê[6xËÆÇÛE׺)*^å¼ò“.gÔÁͪI ÉÌ&b¤@±0Rq`¤lyOŽ¹‚K]ƒ©nÇÜ­¡¶ëàŠõ´Zr>—Ër1)‡3N¾÷x °ñÍÍpÆÀé°LmyM~¦˜%Æ´«€:Ž·ÉÔ¼ž†¹Å«Y9/k?QÌj¿2ÈGHiö' bŸ,(ÆI"ŒÔ{˜´RMŒÔ*à2ܨü½XO®CQ^Õ¨hÃ=í=TB:³Q†*P.n‡QIÄ¡‚zg\)˜)aÒv°lpõzÈÝb]üël,œ:.­îJLe.(Ð¥'J*Ü{ŠåD[Á(¼åeYסŴ«BÅâ2ô½ÅU½:ÿ3ÌôÄ*{ÌR6ÀcªÀÝ0‰80Pïm]Q†­< -WÙçõL£]EmG eÍqÔ@Q éÌFb¨@¹0Tq`¨ Þ»áBY¢™3,Ǻòß‚R™ -0Ä@Ra $âÀ@A½w HM”íšʱ®l3²”Í0Ä€*ˆá«·©80Pï¡¿U¢.0:¾_ûfYÌçE½zdı½½‡KÈh6.ÀÃ*†á’ˆÃõ¦!œÅe¨,u]ñîï-ØF¬¥Ò;¨*&³ö˜Þ¤gܶǜ¯‹uÙMc"]†ÛcsžÍ0Äx‚šŠá©80žPï'¸t"âħݥÌ:öô†¡6µÙÔtv4@8Œ™í 0d0×-1ÒY"ul„8;‘™T‹õ²š­ÜG(|Ç0¤¬{’ÃÐ:1ǹì@Cžž†=©8|pïëç¾ÜuL>?{L¡ ¸ rr™Í 0Ä8Z‰áG©80NPï#ë ص“éb2»½,S”hbÛ5Ù±ŒÔ<9d8žÎc臡³Fæ:€£}MÒº›Óè‡"g÷øò£¯ççÍ1•ÙˆCŒ(I"ŒÔ{ÀDQ"è¤ÌNL¾”w©©¯/AΊƒ‹ö¸êsžÍ0Äx‚šŠámt©80žPï'a‰ Ý¨c§Ý#Ž¢O¯“ -©Í¦¦³Ã ÂaÌl!ƒ¹Äpωa2n'2³êêªÞI–(TÆyNíZÏQò vÆg£ 1v „<‰80zPï&ýáNwKô¡øÙc¢óÿÙeõÝîËlN€!Æ Ô -ã$Æ ê=^e’”N¤Ô×#m»myM}W-ìwr],ejÕÏrR)Ý÷ázY¬< ZðÚՄôfà 1x |BÓˆƒõáÎÃb@;UŸ ?\UËÔLGR¢­¹¤ö *TLo.<Ч'ŸÐƒð¤â@àÁ½wðK˜”°FÕ·§î ÏŸ·åòn\.—Õ2µø§,q҆ſ4/´Ô r2™Í 0Ä8J‰áýu©80NPïíLÆ÷ê„1êÓî«š³oË2Å÷ó˜8¨ Mƒ¹Ò|}<¦;%`ˆ¡åÄPJÄ¡„z()I¨e¼C‰?J»gÄ’¹'T¥BZ³‘†2P61¼ +† ê= #9¡Ò©™ÝW4çÅj]&kRÝGI§wöáú°f9!ÇÙüCŒ¨!ÆO"ŒÔ{àGÔsØ]ɇâgŸ>Ü=æ><æ2›`ˆqµÂ8IÄq‚zœ0CœÕ 4í¾¤YÝÔR¯Ò¦¬w¹ó’&;¬©MÈq6?Àãjˆñ“ˆãõø¡Š8%AÒÅÏ>6壮G!—ÙœCŒ¨•¾°™Šãõ»nîqœ[@JXï{^U³²hE}ßÒ1VÂðUɘ®\ !CO9¼~—Š÷ÞÁ`ýˆà`G¤ÃúÝëjù­hžÄ³y<¤üxûÉ=6Bö²Ù†P9\PRq`l Þ;6´#VÁÖG‡å¹—·Ål¼Z“/÷ž'~¾[Û~È R• 0Ä@€R` $âÀ@@½w (C,7½Š!žM&ñ–ùõFÌz¼¨fuÑ8Þß%. `ˆa…Á°HÄazï°Š§ÄB5X¼]øösáÙ8kÊŽ·¹¦ñ ÌÆbx@ÔðFîT¨÷!ˆÑ½Ž„è_ë+7íƒÿàƒ7„1G*bÞ²©†P5Ü}¤âÀ¨@½wTpFŒèw¦¡¢yZq ÅÅ™£§Ëb±ú¼™T(ÃŽXÄÄec 1, 0jxJ* Ô{‡uÄPÖ«%¶Áâ·—*>Ä'жOäQò8\t™Ëæb\@eÔðƒÐRq`\ Þ#Ì¢µ“ ×pñþ¦÷tüó»Õºœwϻݔ•I|îâ|Z#c¥z\k–1¹òBCDÞ^‚ySq òâÞ;y­"ÚWýÞZõØSîÔ0ýÄ›ˆ˜£l€!FÔ@ ïJÅ€zï0‚hÚo"køP.§Õåt'ü´Xµ+›ãk1«?Ó?ÃúäÃ"’”0Ä€"¨áGò¥âÀ@½whF”‘½1žñèÕM5«®|Ã`„9>'MHÈa6!À#j„’ˆ#õÞ"Q’÷Ë„h Ùc§àÊÏg~ΘºÒ% åÌm_éVÆíä1¹ÙèC (žÞð•ŠCõÞ¡# Qý¾‚ɆœWeÛP¼o®s”á](Ç»ñbⲩèì0(€,jxá2†æº#‚+"M¿¥`*–zzÛ>Ž[쳓ò@ ùÌ&b¨ôô~ R* Ô{G DÊ{Šnhy~;­Çáu8+ЯLŸ7¯¯ˆ;$þ]-êµpcÜ£Ü9³­10Ä4îeyxM2¦1ê½Ó˜2"™îIlR¿šß¬ïºW«Õ7~¢%¨‡mAÚeÐÙaúCù·ƒÀÔÇ\Gñ­#ÂJÑß6â?»¼Ülr*fá*÷¤ûD¿(&×›:á´~:2‡läÊ ì™{¹^bNÈŒº/¨2D(>á»çÐ牎zFôÎ{©¹yÊ…Á7^µ‰Î~áUg‡½ï -Ê8¼U*ö¶+Ìuxo€"‚ƒ&Â>>û< ï)ôœm>óßÝÌÐ7·tZaïm¹Á"ñ]¿cî¼´É–øÿqJñÿýÕÂÝe}k‘ØžÅ-%J+5~þ*š±t:Eî‰ÙBÿíÈTìendstream +xÚÍWÉŽã6½÷W}’ˆæ¢}êt$‡ @ Ì!“-Ó–0²èH”NO‘EÊ›2sÈ%ðA\ŠU¯^-¤Ù‚Â-Š”PQ&‹¼LHJYº¨Ot±‡½ïŸ˜—IRAÒD˜ÌìÆ©(HZð|_+ùzý´úŽ³§$ËxºXï&[YXoÞjy4ª_Æ<¥‘Xþ¶þ%$/rfQ0‘V +'ÿ“<(þEõ§pðMw)åû±—¦ÑWÃ%)3žy-#4ϧæ‡æ,2u3ت ,Ÿ~ý’‘>5[…Rƒ>ø­aÜïÕ`Ô§Õ-¯T¶ºÛ{•©q´A]ÛtÊ ítÀ¨ÆÇA‘e,r}X–<ºØŒ­oÖÆH™¦Üyc ¯’ƒîä¦õDd;:[i°ƒJõF6Nôѱæƃ2¦éö™bÁ"’Œ{F2Z2gW¶Œ¥ y8{o÷TLŠd§H0Â3Ÿ hRõêµÈª±îÚw\yýl”yj“ yY×p@d)¸Ý¶úÜØXØéh—,jýî]ìpÑæ…ýÊ£O‚cßHôÁiˤðJnðÚ•Îáuö|ªŠ,ÁØE16^¾jÕ™a.ÀM©ÙÉÓ42Ú~g9µðû£Fè3O¢×ÖKþ>ª¾±±·“úqÀ™ÍàÒÚj +¦ÝŽÄ$ Žwv‹¢ã€4Z@oˆí%"-Á ]Zæc ä}&`iAŠ<^óÐe$ç„'Œ&0å^[Ç„iN +xfŒE_aNX0˜ÀSš¨¿S•/ŽJí‡/bƒ¦Nʯzßœ–±1—²éLœ¥åK­ˆÆV…BIØm +JxI1|«ÄR{}Ö8!S8ÆM§,ývrö‹çf¨qdü)G%§ÀÚÉ®×r›6H–¬Ú‹½‹…¿ðÃJNXV„ÐO^nóëÅ¿_æ’£5é´¼$E‘—·rÁûºÿäøµ“mÓC\4&Å=î˦“}^)S­l9m7Ï.HÉhòd×.¿oýˆï`¢Ñy'øŸ{ ¸@েÌé¿v€F1yçŠÜ…®öÛ­ÖǬ>}ΆÜn{5xB‡ÀÍô§î¼Þg'²MÛóDöGùüŘ˜÷ã„.±~Ö÷]Ó+­®d[ëÁpúùeS§M³óôwzži~ÅôÌ•@2BIOWW‚¿›^GSë +Ó–ÿ¼\g¥» ÜEÕýx€ +¾qÂôrœº=ȘZ\ ö\FØÿxd²ó‘ód¦·$4%9‡‹{¦úÃ9šfؼ!¼‚¦ÿH ËI)xáõ8kØ;ߥo…­<©»çÃ¥ÛŽ›­>L/‰ÁÌ ²”Š,`îö$àžÇV”ðl×ØæÚ,˜Lá5]Ö·[öhLs&¾Ñ¡0ÌC/—U5U}hõö5¡æ^uº…®û]}á¦×=}»ž^êáý-Rb_ósoù _dð!AK"8YXù½±é_Á£µa,Dqendstream endobj -797 0 obj << +1279 0 obj << /Type /Page -/Contents 798 0 R -/Resources 796 0 R +/Contents 1280 0 R +/Resources 1278 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 715 0 R -/Annots [ 803 0 R 804 0 R 805 0 R 806 0 R 807 0 R 808 0 R 809 0 R 810 0 R 811 0 R 812 0 R 813 0 R 814 0 R 815 0 R 816 0 R 817 0 R 818 0 R 819 0 R 820 0 R 821 0 R 822 0 R 823 0 R 824 0 R 825 0 R 826 0 R 827 0 R 828 0 R 829 0 R 830 0 R 831 0 R 832 0 R 833 0 R 834 0 R 835 0 R 836 0 R 837 0 R 838 0 R 839 0 R 840 0 R 841 0 R 842 0 R 843 0 R 844 0 R 845 0 R 846 0 R 847 0 R 848 0 R 849 0 R 850 0 R 851 0 R 852 0 R 853 0 R 854 0 R 855 0 R 856 0 R 857 0 R 858 0 R 859 0 R ] +/Parent 1277 0 R >> endobj -803 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 758.4766 511.2325 767.4329] -/Subtype /Link -/A << /S /GoTo /D (subsection.4.8.1) >> +1281 0 obj << +/D [1279 0 R /XYZ 85.0394 794.5015 null] >> endobj -804 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 746.445 511.2325 755.4012] -/Subtype /Link -/A << /S /GoTo /D (subsection.4.8.2) >> +90 0 obj << +/D [1279 0 R /XYZ 85.0394 769.5949 null] >> endobj -805 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 734.5129 511.2325 743.519] -/Subtype /Link -/A << /S /GoTo /D (subsection.4.8.3) >> +1282 0 obj << +/D [1279 0 R /XYZ 85.0394 575.896 null] >> endobj -806 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 722.4813 511.2325 731.3379] -/Subtype /Link -/A << /S /GoTo /D (section.4.9) >> +94 0 obj << +/D [1279 0 R /XYZ 85.0394 529.2011 null] >> endobj -807 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 710.3499 511.2325 719.3062] -/Subtype /Link -/A << /S /GoTo /D (subsection.4.9.1) >> +1283 0 obj << +/D [1279 0 R /XYZ 85.0394 492.9468 null] >> endobj -808 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 698.3182 511.2325 707.2745] -/Subtype /Link -/A << /S /GoTo /D (subsection.4.9.2) >> +98 0 obj << +/D [1279 0 R /XYZ 85.0394 492.9468 null] >> endobj -809 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 675.998 511.2325 684.7301] -/Subtype /Link -/A << /S /GoTo /D (chapter.5) >> +1284 0 obj << +/D [1279 0 R /XYZ 85.0394 466.0581 null] >> endobj -810 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 663.9862 511.2325 672.9425] -/Subtype /Link -/A << /S /GoTo /D (section.5.1) >> +102 0 obj << +/D [1279 0 R /XYZ 85.0394 201.2466 null] >> endobj -811 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 651.9545 511.2325 660.9108] -/Subtype /Link -/A << /S /GoTo /D (section.5.2) >> +1285 0 obj << +/D [1279 0 R /XYZ 85.0394 170.5419 null] >> endobj -812 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 629.7788 511.2325 638.3664] -/Subtype /Link -/A << /S /GoTo /D (chapter.6) >> +1278 0 obj << +/Font << /F21 930 0 R /F22 953 0 R /F41 1208 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -813 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 617.7222 511.2325 626.5788] -/Subtype /Link -/A << /S /GoTo /D (section.6.1) >> +1288 0 obj << +/Length 1768 +/Filter /FlateDecode +>> +stream +xÚÍXYSãF~÷¯Pñ$WáaáÉ Ë†kˆqB¥6û ¤1V­,y%ÇI忧ç’d#›JJsõôñMOwˆ…á#–ë!/¤¡å‡r1q­x9ÀÖ¬}M32D£.Õ»Ùàä‚ùVˆBzÖlÞá Äš%Ÿl†(l_]χ#êbûÝøj<9»œ|Žq©oŸ}?¾™½ŸªU¦é'ãïÕÌ-,¹®ý³¡8»ž\\~øi:úŽ=»¼ž ?Ï~¼Ÿ5w­"˜ u¿>}ÆVÆý0Àˆ…km`€ Cj-ŽËë0ff²ÁíàdžagUníE‰`D™G{`rH¦ÀCn€ËwCä1Ê$L''ч±=[¤•ê™¶^pÕIøêaÅËÇ4æ»üÔakÊ"7ì”Ô Qøá®ðV%ÊP(Ž©«ÒMWƒÈ(òÈËJÏ-£Õ*ÍÔ`^”{heE±ºâ/Ï™%IÉ+3¡>Â𑾿¹æ{$i€6ÍGb?ŠÊUtdP[÷ŒUÈÔÛU£wUó²÷8æif¤dEe‹¢ª}ÔK ‡•Î·Ï#MöîCá΀\ò= •ªí©›~ƒ6ÿ-Z®2ŽâbùjÊ·«Ã%÷GÏZ{y³sö\Ÿ~1×ffQ×ÏÁÝ4¹¸a<Ñ}Îo$Ôe”Wsþ:ˆÔÍÝÝÒ‹Œ"'!EÄ „5ç´O Cà"—½âò½t3ûì{â/Ñèö%@ßà0»ÔG/BÓ:T¤×„®ÏìòG÷_¾Éov½fß´C·§‡¿¢ªvÂvç”énü~î~Ÿ\Pb1rääRDIhò0d[ ¬®Š(Ñy8Ê¢<ATm§,%Âr€ ¼t×ìØe526¨CP@¨Ó”©; `;³¨ã‚D&àñÑ0bÏfW£|Ï>»ߊ»êøÔžýr5»C¨gOyU¬%þ±¾/ÓÆWÔXÜÑé´½açQí€@Àó°kieÝn¿@š„PnþŠøìúì@åo e 9S˜n6xïøÔ±!Î %̾œÀ”CePò0%Í-> OGðÿ%Áž~xˆ ïFL0† ÒœÄÇ â죂Û`v•Ž¼·E…¼%*ØE¡ã¿ +¡¦cÞ+Aa‡AiŽ&í«ø¿Ž‹ÐÀˆ¬w dÝçù“g:õ¡° +˜8I wÝöÇ?ób +|HÜï\*“Iv‹LÖ»bF¼ÂS‘…Å@ ¢IG<\Û-MÚ„ÄÌ<Ï~w99Wë:ëÊ¢ŽjÞ0Yjé"qwä¯ +3!“£¢mõÙ΢z0«=9ðIF§~(K3ÑFªI ŒUñZÄy-*¨ŠÔ¥M)~Ë ö¥Þ,Õ]i–÷Å£¬Ž¿ÍübAa zð2JŠe¶Õ#¥ —hg¢_ãF¨Q®Tº’ã¾Ç=ÖÿŸNUÛŒuKô¼*šº º?ºÁöGx¶«™Ö&h› ·®tFT +ÊTˆiivíÚÔ«×eΓ=5’´Š£.mÃU;GÝ©ÔE^à9"–JØCàxy¥™Zÿqdkà“µ› jÝ +Na>¤¯xÁã/jY»—|‘´7ŠÂ-Ý M¤³•PQŽŠ2Q£ýëq€:Ž¦­Ö÷£J\„¥r8.ù ¬ "~AªíŪNAÕ1̃`àùFŒ!Mr¡äå‡~-zP©Ä¢VÊKu¦}?N[êÃFÓ=¦SYl‹3¼îb¿§ ”Cˆ¹Ê[öOÂ]Có¬ûœ„èéÌEc½â°õbz|í/×<ÇG,„i¸Ï(ôY«•P=x¢ºù7Û£û_`#~›endstream +endobj +1287 0 obj << +/Type /Page +/Contents 1288 0 R +/Resources 1286 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1277 0 R +/Annots [ 1293 0 R ] >> endobj -814 0 obj << +1293 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 605.5908 511.2325 614.5471] +/Rect [55.6967 61.5153 126.3509 73.5749] /Subtype /Link -/A << /S /GoTo /D (subsection.6.1.1) >> +/A << /S /GoTo /D (rrset_ordering) >> >> endobj -815 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 593.5591 511.2325 602.5154] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.1.1.1) >> +1289 0 obj << +/D [1287 0 R /XYZ 56.6929 794.5015 null] >> endobj -816 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 581.5275 511.2325 590.4837] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.1.1.2) >> +106 0 obj << +/D [1287 0 R /XYZ 56.6929 372.6686 null] >> endobj -817 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 569.4958 511.2325 578.4521] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.1.2) >> +1290 0 obj << +/D [1287 0 R /XYZ 56.6929 334.1957 null] >> endobj -818 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 557.4641 511.2325 566.4204] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.1.2.1) >> +1291 0 obj << +/D [1287 0 R /XYZ 56.6929 266.1213 null] +>> endobj +1292 0 obj << +/D [1287 0 R /XYZ 56.6929 254.1661 null] +>> endobj +1286 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F21 930 0 R /F22 953 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1297 0 obj << +/Length 2693 +/Filter /FlateDecode +>> +stream +xÚÕZK“Û¸¾Ï¯Ð%NÅDˆ9­×·*öÆ–³ÇUáˆÄ¬DjEjÆ“ÊO @$Žìò)5`³»ÑÏÀÐEt‘K’ðB,²B™P¹Xío’ÅÞýtC-Mìˆâ!ÕË›?¿æÙ¢ EÊÒÅr=à•“$ÏébY}Š^üõù/ËWïoc&“ˆ“ÛX¦Iôöùß^áÌx%eôGñâÝÛ×o~úøþùm&¢å›wooã,)|yýÛw¿¼:÷áöóòç›WK¿ŠáJiÂõ~¿ùô9YT°àŸo‹\.à!!´(Øb#$'Rpîfv7nþîÞšOC–“<'2gYÀtŒ.¨ \¤ld;YS)í`Ñ·1MXt¹WvÑêx¯ŽvÁu,ûºm:½XdII!¥a™,bN å™gF¨e·¼¥”Fm»ëѺµ?vV̯·<‹ê~‹OýÖN‡õxYª}ÛXØ "@&‰HÒ¨°ÜÖ 'EÔ©•Ö*Õ­Žõ2ïrxŒË¾«›ªîªéÊ»²äu¹iÚ®¯WÏ`‚ñ¨¬öuSw½¶Å½%*› + XݷǺÙàs«64÷e½3|As­«7èÚ·“¥w]¯ö8Ht–ó&\µM¼¥yÔîvFªù@«£•º;m6~Þso¼a»a+cXâ½;²,‡8Îr~v®wïKo!d3p÷¼2ë"F ’Hª£ZÓTõ&À‚¹<·4Ï\Éó¬°[Ð/Ä¥ <͘ç3Aõ.Ù1X?Ë…%mº]Ûþv:x + )E3Kx@çlŽå^G?Ï£ÒÌhósŠÝgWí~nƒð¤Â‘MŠ.‡9 ;ÁwøôûIÑÃðdË ëØÎxbe¤` G˜ÿѺ¾^k­Ö.êƆGÿ¸S“ jOýáÔû8Ü—=¹¨~ xJ²ÌÁÀI’†ë¼%Š‡T®X]ÖyO5Š¡Ì>É9{Z¦# +ÈÅEá• +9º4é“dQÕîKc!¨uƒ60õE¿Ü ÇÆ”ðüÏD&¡ ‚@´ñoˆràD‘§.lZxï4Úëø6#ítÐÆx (Ðk0vØ©ÞÒ·kÏ ³S6 ÍØ„t@V¤ÑËx[v6–$hžðtRÁZ]ç(¨ö/·± ,êj-ç릇B»rE qdBÌ•øÜA<»ÏL|›Š¢ë/®ÖÒè®ìWÛ)«‡mí&Õµ:õXç©cìØWTU®¶ã$(ñgWw6êõLñ´½C? gKÙ(m>N“èùîò}{À6ŠÜ}=Ы•êºúÎ%݃i?©ßçja¥]f €"–C6ˆŒP‘ñMIÁS ãPªØ01äq™Ÿ4±HÏ’´5?våFÍêÄ%¡¹ߥӀ‡ÑIurT.Åâ¢ìÓ˜j’>Ê<•Ò¦šm‹†lÄ™§„AÚZ²ÏF.¨l^c©¸d$(ÉwŒ>IRdYj LôÄýãAxŠË2™{¥p•!Ý  p–x®veט¦’d’‹ Ó?¸2N +q‡\1Äl3J2>²ŸÆ¦ãòS|ݸõf^PØ(¸ª¿Î-ÕôW]ö9P¯¡6n`.¦9”÷"4HÕSwrå•FœV¾°:E’ªÏ‹§;EF.|jWuúò75)º_ÄFŸàñ‘î&kôg?Œ ¢ë€®°ahža5€Cö¯]ÙÝ·Ã:8îªCô1[ŒÏøzX"»)xÁÒûÌðq.MÂôÊ”~‹åA&r<@œÅEÐÓ Ë`/ö$.RÍã"O5ĹC¡ºh¦(}Zª§ +ˆe“ÒÊ5°ÉòT°§18ƒ‚øŠzèR÷ÛÊHí€:ê[ýGu8eÒ¦^y‹™´m“D0ef «tNdô£%®Ôº<ízí|³ßÄYØBA\÷~u§ú¥|µEXÓX[ü#`ž&l\­|€½Ñ0§Q½ÛºUÖ]§\ÐÝ9ð\÷nC|j̵´K×áëâèÎF¨úÒ«¦RVÊÃåfyXD†¡> DƒŒ~Wò˜‡žê*4àEJ( ‡è×ê4ä1 <•Mlqù¢Ú5ÇnùpïzF¼ +u"yŸ ×çº(+`:mBñÛ«¤©Ú~–ŸßÖz†ýU†3ÐaÜû<¿_¯ó«÷ +v‚_Ñ&-Ë÷–Ðùs’LŒ“é¨úc­º¯ç½¿ªîzWnBˇ¢—ålÊOøQ‚x# £cÇl»„“¬ðܯb¼ocàÁ +° ‡åþßv×ùöKð_×^9ø>KRñt{RÍ·WO5=öµXFO2ö´dOuE4åv-¹œ—}yäøÐ9ézÌ2Ž[r=p[r.³ñ6\¿DçÁ i›xðV÷ÎÜö³!=îµÍ—»]ûàdmí$´¡#öÉ´ ”3ß'éù 3Ë4H„¶n6Äðd­`ds€F>ã¶<ËÎ1 ïLØÂ\yך^ +Ã{˜.u{²ßéh²C»ÀÔ‚V;‹|S¯ÐákÇ©glÀ„IÏ4px€P˜aúp+ÈdÑÛ±Y‘ÐhÍQÌ€Ý*áY0÷ÁÔ¿OÙvÏý.sÙÇ#Lq°,ÓHÙÙI²3wÒþ -ÅBÌ#¬? #XN‰,èwµì!yᩮ±—ò”~—Nó0ÂSRÔ6,‡„h'”ÍíÉ'úZæ\ã¾×µ;…ïžsB—èÿE9±‡©ó9Ü ŒÊ´w‡qjç…‹J™¨„_¥ILXU8ñ°5ظH \à ž_mNzÓÜ §,« °op¨B1€óÂq|°Ñœç - ·±02(¸0 ·2Ç ÈÅxõ*¦kÁ ;b\F:ÌÁ¤/pGÊìéóÉ¥ñ7Þ“†>ïÏê‡]ùè¸Cø½Úø«‰CyìÇWþÔ5ôQá—Ee‚!°JÂ}jŸi涥q)PÅ«­Zý!¸¾@Û@ +p¬xJ´§¹=vrB þ²¡ðÙ£,ˆ†— +N8çŒd¬`—·Àvÿ¤?í.îü›¾ü2õÃ%0'üµµQ†Ìè‘2ÂÒTúÄ„íû&·×ˆã> endobj +1298 0 obj << +/D [1296 0 R /XYZ 85.0394 794.5015 null] +>> endobj +110 0 obj << +/D [1296 0 R /XYZ 85.0394 769.5949 null] +>> endobj +1299 0 obj << +/D [1296 0 R /XYZ 85.0394 744.949 null] >> endobj -819 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 545.4324 511.2325 554.3887] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.1.2.2) >> +114 0 obj << +/D [1296 0 R /XYZ 85.0394 744.949 null] >> endobj -820 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 533.4007 511.2325 542.357] -/Subtype /Link -/A << /S /GoTo /D (section.6.2) >> +1300 0 obj << +/D [1296 0 R /XYZ 85.0394 721.0357 null] >> endobj -821 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 521.3691 511.2325 530.4748] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.2.1) >> +118 0 obj << +/D [1296 0 R /XYZ 85.0394 672.3079 null] >> endobj -822 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 509.3374 511.2325 518.4431] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.2.2) >> +1252 0 obj << +/D [1296 0 R /XYZ 85.0394 647.0603 null] >> endobj -823 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 497.3057 511.2325 506.4115] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.2.3) >> +122 0 obj << +/D [1296 0 R /XYZ 85.0394 136.5325 null] >> endobj -824 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 485.274 511.2325 494.2303] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.2.4) >> +1304 0 obj << +/D [1296 0 R /XYZ 85.0394 113.5963 null] >> endobj -825 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 473.2424 511.2325 482.1986] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.2.5) >> +1295 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R /F53 1303 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -826 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 461.2107 511.2325 470.167] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.2.6) >> +1307 0 obj << +/Length 3388 +/Filter /FlateDecode +>> +stream +xÚÝ[ÝsÛ¸÷_¡·Ê3Ÿ$зÜ]rM;Í]m_;\h‰²™H¤N¤ìsþú.>Eˆ å4ÓéLÆÁåb¹Øß.h2ÃðGf"C™¢j–+Ž&b¶Ü^àÙ=Üûé‚8š…'Zô©¾¿½øî Ëg +©Œf³Ûu—DXJ2»]½Ÿ3ÄÐ%pÀów¯þþúrAžß¼¾¾bþOø1×?ÿòúúÕeÎç·o~ws¹È±âóþòê—[OqžÇ?¿{óö§_|.?Üþõâõmx‹þ›Ìô+ü~ñþž­à…ÿzSRÌžà#¢m/¸`HpÆüÌæâæâaï®y4¥9.0‚‹Ù‚q$aýÉb™€qŠErIa ÊeAù”ô”/ J‰Y ÒÊÿµ-îË"€@’|–óeyN¾F¤ #OŠä©´Hu±-W‹åC¹ü´lêõå"Ãxþ~ñññó?î´Äß½¬Ç‹d´Ì% ¹¬ª}¹ìšý³%–eTG鹦xæð’Ô³\W›R —àòKŠ³ÀñT¡å„d³´&˜X҇ѢO5ÜÆ`¥žêDgŸ›z°¡„IP´àÓª„´¯fgy,ÂíƒSL$-Qˆd¹rŠIˆyÂ[rØDæ·f·¿$rÞÜï‹­õaóhkÇ…ýÙmWîíø7Œé¦´ãuã&Ûçº+þpÏÔ+Ǩ©Û +¬—Ï—„9óLåˆq¦¾Âú,ÆÝ2PuËL +Ĥ̿F¤‹q· T©½s®¸úøûãÁ1—I'‚/ÜŽ.7EÛ&ˆ* ©—\4 ~L@œžasèv‡.Á1&› 1é—GŽÅS‚)Äsýa¿„ %ýo¹:+òoXàê¾nöÎ¥ïÇ&‚$.õ1ÁŒ"ðf}àBR:)¾Ëº¨6 Ûjyú’õ7ø’C{þWÒP¨D9–Ü +ùŸ¼î Mø¯³^KqŒÛlR¹T •çÙKSi~.•f @ãt:•ö©ÆSi êŹf»“É”CN#"Ÿ!P%dˆ’)8=V}"!nªmµ)tcbÞ5‰ÄʘŒ$Ö«TfÍÀ"‚^ï fæ•ùåóbóT<·vnuØîZ;Ý=”vÎÆ|=©òfd³ÛËvW.+…Ë•a¶ ˜#šaÁ~žÖvÞ=ïªe±Ù<Û©ªŽ2üªZk°. °KÛ¿-:mÖhÌH„ÌH'§¤O5n$J¿À¾^-OÍs€:BM/ꉋF›Eá9‹½5{!éÜêaÛtîÚxŒÈ|UÀtmgõ>Yü´±ZÓ)ˆoˆyppÿj'QŒ´@!Ë3Fh0»Ø<µVšÎ Ü>Ôò«mUôÚAh0eŒ(%qg1%è ½õٕͨÀ¥Ò/Ì0Ÿ7kû[Ø«†Ù¼-÷`ô¢Ë hkÅór‡ÛG™dJ ©Ç™¥iyœP„Ù‰Â]µ©:íe ‹òe¹ë dP‘2¦zü }Ûû.±ä"•qŸ¥5ÂN–BÑì”å¾e*!* +¯Ï+mxþôP]¨ìÃO.Ø«bÓj+ÊÙ¼n:'°Ý…reç«zÄø¥ÕSÊÔeŽ +¹ëO­e¿|(êºÜXæÛfU‚q1°ú·kk³ÿe™Èâ´þÜløÚ_Êù!%ƒZ˜JqÆÞ( ™û©êšCçkF›ö W-UîîS¥­Ñ†Õv·)ž£P{0u‡­«ÊöxQ´>æ÷þóXiÕ "M£Ïb¼Z +Tg«%‘‹jTý"õXŒWK*lÛDQ$Ê•ôö­ûÕ}ªˆÉgŒÂÈö,Xv!/É‘RNO9îÎrÔ®”~düžÏòûT¦J PX¨ìÅpÔEÒŽ”ˆE^ŠH'¬íÈBRá–Ih"×8Ò…TäÅ=‘há8æˆQêß´r.hq˜¬í¯Í²Á9«ú~àžÞ’y0]9mî}*kî2aîʘ{¹iŠÕ)“ñ G Hu¡1úM˜TŠBœTh j46PÒm±H¥×G•Nn¶³ [NnOhÝ™)Çl‚ ÄFN;&q$š°Gd`Yu_'”Eöo¨€zd“j D=ž”ÖaNU¤È7e§ë@¨±\y ƒßÝܼþÁŽ]¶vd‚ØòÎRôÐZŠ! –Ñj”j«ÊV›Ë…ëHP( +)(.*°Mc*wÛliËüƒ\Fu+#ÀàÅÉ™@ôö¬ƒ}#×Ö°±¦1bƒÏ1}Ì¢ x²7÷÷3;¸Ž”îèýZð5Áätý:‡J€ì@ ‰Á‹:'Æ€›ï?éVN–éjÛ;æ4_ø¶€¾Ð•qU’jo‡»ÃݦZÇwÙ•ûªY]ÁPú÷¡ù[-åI/¸icÉ%lŠn`±ºßp_j91±¬N,ê$2žšŽZÅ¡k¶ðνN«UÕB‡¥råÝÃI¸¬!˜ñs¦ªßÂ/> endobj -827 0 obj << +1312 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 449.179 511.2325 458.1353] +/Rect [219.3839 329.5541 281.1025 341.6138] /Subtype /Link -/A << /S /GoTo /D (subsection.6.2.7) >> +/A << /S /GoTo /D (options) >> >> endobj -828 0 obj << +1313 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 437.1473 511.2325 446.1036] +/Rect [491.4967 274.4996 511.2325 286.5592] /Subtype /Link -/A << /S /GoTo /D (subsection.6.2.8) >> +/A << /S /GoTo /D (dynamic_update_policies) >> >> endobj -829 0 obj << +1314 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 425.1157 511.2325 434.0719] +/Rect [102.5211 265.1945 156.7673 274.6041] /Subtype /Link -/A << /S /GoTo /D (subsection.6.2.9) >> +/A << /S /GoTo /D (dynamic_update_policies) >> >> endobj -830 0 obj << +1315 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 413.084 511.2325 422.0403] +/Rect [243.8464 219.4451 306.1963 231.5047] /Subtype /Link -/A << /S /GoTo /D (subsection.6.2.10) >> +/A << /S /GoTo /D (options) >> >> endobj -831 0 obj << +1316 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 401.0523 511.2325 410.158] +/Rect [425.9845 164.3905 495.353 176.4501] /Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.10.1) >> +/A << /S /GoTo /D (dynamic_update_policies) >> >> endobj -832 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 389.0206 511.2325 397.9769] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.10.2) >> +1308 0 obj << +/D [1306 0 R /XYZ 56.6929 794.5015 null] >> endobj -833 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 376.9889 511.2325 385.9452] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.10.3) >> +1305 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F41 1208 0 R /F53 1303 0 R /F22 953 0 R /F14 956 0 R /F48 1228 0 R /F55 1311 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -834 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 364.9573 511.2325 373.9135] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.2.11) >> +1321 0 obj << +/Length 3086 +/Filter /FlateDecode +>> +stream +xÚÕZKsÜF¾ëWÌ-£ª ÝO’]{òú‘(U+'–öU‰Ô Gâ†C*CŽd¥òã4ºùÒ[ÞË–Ë¥&6Ðhàk=|Åà_Å:`Ò¨UdT ׫íá‚­îáÝwÜñl<Ó¦Ëõ×Û‹Wïe´2 E¸ºÝwæŠÇ|u»ûyýæû×?Þ¾ûx¹š­ep¹Ñ![_¿þÛ;¢ÜÀ+­×ÿðo>\¿¿úîï__Fj}{õáúr1£àËåo?üø®ýîæòÓíïn›UtWÊ™Ä%üvñó'¶ÚÁ‚¸`4±^=à ¸1bu¸PZZIé)ùÅÍÅOÍ„·öÓ)ËÁë äñj#U‡0Åg +l¨"°¯6A(…lì«âŽ}9ƒ± +W Ú·~Hž/7!cëŸqůÞkÝùDj fy/‹”˜zó +ÄqdÓÔ4:0Q:†mžTÕÄ4}Y‹ÓŠP–¿êkdÓ†klS!ºâ"Ø=¥tߨïŠä.OÁ«Âx}zÜ%uZáƒY×%zÜ/y¼.O "ï^Šämé%Z|V†áújO}E”ÌM\=¦Û .ÜAÆŠ¸çÑZX•²_éî[`7ìºGë$ÏiÐÓžQFåxì+”û¶h¦_ß>X €¾MN•ÿ¦§A•ŸÒ£#–ÄH“åe²0»Uµºèƒ]Výú­]ë¯))` +)„›rCªUHã­-‘¡Ù|Hö5ê„LV6ÒH=$n‚myxÌÓÚ.U ½~í?¸}ø‡FÞÌMÑd, 6}­ Ñüâ´¾Ï™Ý +Ùm†¿yYÜ[ëÁø.¥¿´Ô=Øô¸v¡‘‹`0]¶ópÑpYåË:Û¿LĦâA¬$ÿ?FŠ³@1kÍ(FÖœŠž9?¦UŠNŒ;{ýáöêý¿i|H«*¹÷ž±/P¨À€°áìö‡"1È]ØþÛÌö{.Ô÷˜nËbŸÝDë(ˆÂpI´ç‹îÙŠÃÛ”é‰þè!C†Î0m×îOǤÎÊ‚ˆHɃ…´à v`QšõÝ©&â®t\¥#ôà +žÓÏYUgÅ};GWjE,8º}¸JŸ,¶³ÎÏMŒëx!ÊCò”mû@Ô[|Õ¡ÇWü¦¢÷û¤²8„4€›‚¨ ö'Àëê‚÷\] +ÇÌí¢]ñu /yéг=?x}AÏæ0îÐrB9÷)Q‹ÓáŽß“=D¨ÁÍÀ þˆ±ðfÏzÈjú›<•Ù®¸~‘¦.`j“ég@Ô"ðÊ=ó¶Þ3ðevðËýDH¹wn+gŒ#Çl)ë²Í˜çB“TuRW#¹pSJ³ ×såö£KA.Éa z‚ÿ‰‰ï1«5šƒÇ úü¶êÛ½1ÝìwÞ|:Š(ÁŸ7_—í¼ù.\Åo§ôø’—çñi^tƒO#Ñ“øÔ}{iĺ¼¿Gä‘<"Upd@ Ì#¸Xÿ4zAl1–‘šäUI¤»”(.çrD÷qúù1϶Y¿}—QŒnk7¥Å— 4˜F'Ô7³ èR§÷åñe#¢0EslZ_€’ 9<À='âZ‘æS¨|¬™1+hÆiÝEðXû ÂÛobÎð–H|¥t&7uç…˜`1Ç) 0uSÃæsÎýÔöh†YqW„Ô6‡ ©Õª+%A,bÿ©õ—´K0k,ù`OГmD½¤Õ_¦V qu-çârÒrÊ„>i*Ñ Õ™9G–#Ìœ´œVB}‰å DŠ"í<ƒŽ«X/å/]¶|ð\(sw:<îî\½»ÚçÍ6Ù>¤lþ?/„y2j–iSJËÁDn©"Øhæ8J-%´œ‡áüJ®ñJû;[Æ ¤Õ½¥¾…¥^n¸q8ê€ôßTD²«wã_˜f»tŸœò†œˆ@½BÇ1‘t 3 Åû¥ÍèdØY%Ú3á\>k£†*T" +¬~9£ê·S‘ñm¢P>ÿÖ¥¾–²9Z“Ã8ÍæJ(ái«ì²÷Á†Ë…Ô±,á”?ëlý8ù2_‹Îùš€:G ÆçWÔpWÔ/cDŒ<Õ_ùšT±+¨•ú¾ƒ…Ÿ Ãx¡'*ñ­]§3å°x·օú;.d]ÔÀA°ÚGÔ¯õ«v M1N +öüúë½Î/nøR†Ôe›ñ>ÏE fùèñïqä,<”Ù(¹ €ç+0È“â z ÁÕ@2¿w,öξ‚­!ׇä×ì’¯mÃ`oOÞxÈ/4pùNZÔôL¥SE‡d—z1´O§û"´­!æûs4†ý£ÓÎ@ÛvíºÎÕ¿ÞDìôÃðÝãXÕø®+(ãvDG‡æ&òèBT¸ùrÂÝÈ–"øqÃI*¹y,èXN ôØñ,B€‹ØxØbpÏã + X…ó®tØfpÅsÙœÿ˜lÓ³«y¹MÇj$wºcÕ|UP‚˜zõ„õñÊoÇÝÉõYì­Jú”ºôìÎåq³ÝtÉ@Bª»`º.ÛyÓ5\=ÓÍÞº’¾Cí"„ƨí<×X»¾c€é˜Å}õnÒºš´k“ÕÏ[ׇCRø>-5¬\jœä§9«+ªóE«wØf¬î¹ÜÖ¤ËAÅ${®±ä¾Eu5S}Ñÿ+‹²»!B³tõ×e›±›çBå÷ù©z8èór›@Éôžà÷(8ýÃÙfÆyÓð˜’EKm¥.ÛyÓ4\iÁ§Šù0qÜM£G +p¥å‚‚žk¬`߆²X4œ¶á}FWRX£bTŶ—ï_io¨ B®—rÙ.ÛŒ½=—¿%9¯I”Æv¨^ì¹Æ‚Ì q_òÛ¬zÌ<6˜ðjر½Ob>µe¢SÓÚâM­¯ËÚ½ª’Ú©¹4ƒ)h*ÑÜHÁ0+¶ùi矚¯²¢ÍR†ÅŒŠ€|¯ù.+v¯Þ|?‘`àL𘸛óð½võ¨I8!ò$£™?¹‚WW×82S>ñyÈüéÝŠÌÚ˹n×Ä·eènöìÉâ»2ÃYÛËb;çLû…³ñÒý^—mÆs=—»@?+w;0Y€ÍËn +°‘ìé¬'ümÓm¶2Ϫº!êï&V&6ñ•±ú=ƒe“Ù {aÕþ”ÅÛÃ%bç7%Š…K-±×Ì/à“í&y¶swĶ:.‹?Êý~î.@è@‹æbë+ïDl@(‘çÖ×0Ö×,(Ï„V¦·@ÿc4ìàûNþ.«ZâÛë››wohÜZâ#Ôšðñýëµ+ª*ݺß_MbŒÅ„\ÐE§¿ÔQw͹S7/ÆÆÅŸŠªæ2î%­¦ñFµ…Öpþtn¸Ç{®§Ôw†ëÐ 4k~w梾ãÏ:'öþ;ˆýê_¶?ªÿ’ñ9 ,ïƒDÊ)…à|¨¹–q cM¨þ'[–Cendstream +endobj +1320 0 obj << +/Type /Page +/Contents 1321 0 R +/Resources 1319 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1277 0 R >> endobj -835 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 352.9256 511.2325 361.8819] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.2.12) >> +1322 0 obj << +/D [1320 0 R /XYZ 85.0394 794.5015 null] >> endobj -836 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 340.8939 511.2325 349.8502] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.2.13) >> +1319 0 obj << +/Font << /F37 1018 0 R /F48 1228 0 R /F55 1311 0 R /F22 953 0 R /F21 930 0 R /F41 1208 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -837 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 328.8622 511.2325 337.8185] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.2.14) >> +1325 0 obj << +/Length 3852 +/Filter /FlateDecode +>> +stream +xÚÝZÝÛ6ß¿Â(¨ˆU~Jdó”öÒÜöpI/Ù¶èZ[k ±¥­%g»-ú¿ß ‡¤$›Þ,zo?˜"G$çƒ3¿ŠÏüøLçYn…Vešq=[î.Øl c¯.¸§Y¢Å˜ê‹ë‹Ï¾’ÅÌf6ùìúv4—ɘ1|v½úi.3™] lþúÅ¿^^.„fów/ß^j=ÿþÜó›o^¾}qY¨ùõÕ›×ï.³jþå?^|s(>>Ç—o^uõêÛažË_®¿¾xy¹sÊ™D~½øé6[Ã__°LZ£g÷ðÀ2n­˜í.”–™VR†žíÅ»‹Ç G£îÕ”ä`8˹‚$·I¢"G Å3žÛ<ŠW™‘x Ï´µz©P¼åjõ{ÛTÈìg_i="WEf+` ¤ˆ&s +›SXOôSbÙ¢È=Ár[v]b©3“ÃkOœæC]ݧ6#3‹š!¢_~ILËÌJaÂvÚæ¶^öe_·Í±¾¥±6’WJö‘êTøBŒ9”<ËQ“é¿X­.’³yINÊ Éìü~So+êì7¾ÑUûÕžÚuGÿûK3?4M}ÉçÍ:Cf !LÆ•R³ç™ÕZ¸µ®7øŽÈ `{·+›>ä07óê×CM O‚k:é >–HXë"è©ÜnÛûESÝ/pß^¯® ¾PAmí“3-ÐÒò7=wUO0pªY0]kL0³‡äZ¤Ú`¯pÞ%œ÷ëÀ‡–cCÑ™by~Î +Ž&ÛŒ¡ayy’cêú}ݬaÓhæ®ZÖ?3&*”jÁçŽÍÂë;™Cï¶n|·SɘŽ,»`[8cܘî«ßúðFÙSß}{Øú‰[§ÄUÝ”ûzû@Ã7NÀëÄî¶åÒm\_í¹Vc]+Ç?Š¼)wÕ*CI%¤mVÚDÉ;#äLd9S´L¦rP !Ú²ŠÜÙ b¿³køïÊ ®|¯Åc"íß܆‰À +‘S%sc3-lp›²Û$ØœúŒ¬ù=Å )Oô MKÀ ­èÈ$Ö–9¸Å(‘aéé¬E&0 Q`ܳ¸Ü?Üõíz_Þmê%„iÀ ¸raŠ©J×US(V­™ßºÝµ;z"ƒj’ZííÑs«VàÙØ4ÿ~S5 ' ˊܘ±e$¸ƒÀes>æ—ðN¦/÷°Ïg#ÿ†ƒA­Ø¾¯·[j9a‹ù¶-W·º!7¾Nª¬¬˜žMšLÛ±äZGÇéõv-ýûÓ¤ÉwÇ÷AÕî bf8:˲¡Æ]µïêΓ—·=úiפ¿ßY<Ž“sQûE»rw·M9_­³¼`ÁiMâöDð_„“Î-ødÃ{ +â!0Y Œ'—E¦Œ Æ_ýæö®`—X;7™PŠ{Ú¾=ZbUÝ–‡m?¨æóÄ‚`Ýà9¤”S ý-& `߬à äŒEÙ¸‡ñ†]ǧÐÿpçIveúzN·.îbë“Ñ«ÙêæOðçóOSAÂïe²çŸ™f¯Û¾:Ã;\¾¯z¯ð¨®ÚÕ‹e»m½I•t€MRS)£öt#2Xš#š€uQ@X†£ò(˜S“‘ +ù]UÛÿk09¦€i­’K3RŠs @@¶ÐùTž¯¶Uï¡qqpa@ˆ&"Dèì!Rn|;‚D q1úHD„¸PFÏß4ˆÄ»;7 º;ŠÝJeJ›#À3u‚í¾^ÎØ:˜1uŠê29ˆ]Dç@ÇÕ¿yÆ•åiÙˆA¢¯½‰îÅ3€J‚'Ý•=ºaHç.ÇÂ3ÓCú¸7‰£$ Ÿ{ˆâäl­!ífÆ@¦¸œwu³¬ˆ¢Äè…¯ ÿ=4õ2N +^¸î7Ô"dTQi†ÅEÊ 7=¾Š<"™{3æV Š¾Äx)ìbÝ”ýa€óR†H£Ôí”ýÎe@oIݦôù©ª%=÷.eî}•›p0 t"‡ÿ¦¥áûò:zßqG¾ìC½òo„ÉÑ"4Òº¹Ã¶›)¿Þ!ôÓÆõ|y‰ûÈB?! +̘"쉽C‚¶í2¾ æ·ížéö˜mjà `Йå£$óxcj€:Ю»D4E&u°üϪ~ù.v Ih."@uæ® 5å*ŸšÊÍùVvS¹…CSQ÷HÞ@w8rÓD¼*”$6ÅׂeJDزHÉ‹ƒ·QÑÕR–˜6¼º&?ñÔ`;œþ¦õŒÞb}–P¦ÃŽ&gv*¡sJ•™*DØ$ÁSÀá ?ÄØÚ¶í{j%ªBe:çúD¥ï«‡tæ\° H´{šüNN…Þât‰Òm©ÂKÝC‡æ²ª÷)×*0g †|_v4ùªBY6Îḵª†Z䪠ñÅÕë¿YH®ùô¾9Ôc¢»ÂYÅÄ·’wAp‚‘ˆ‰!AWÇ…†\)9:ggä¤À•¼ˆrò†à5.>N‹ ûæþ‡˜˜,th€¯àú ”åÅo/ÊÄ^@«p +‰yi·Ü×7”$Ô +B]}R~²  S(@N +Aîê4¶_Ϩñv4ùbLŠ3NfÅÅßUËáÈç™ÈÔñf8ÀÆe>ÙÍ Ø‰TÙÄél£ºA’犧ʹóÏ; 2—.ž> ž†p Šµ‚\Qh…ÿ®ÞÕÛrï_o‰"ö´·)G¦áü*Ο^±£zdÕÎóâô[XB:®Ž‘Ë/K ÌqyØ{kß(ùQ¢id_ítÏ«ÖA2fŸxÕTÝLâ +|:ŽOˆ"±æ—>…’VOÄÃÄ^„Wë‹Í*u6m¦lŒ¹¶‡U +<ÊáfˆÂƒÌ0²hWì\íQŽÆðYùÄËÞPdí²ÆHIh˜6X_JTL>…5¦@Áu4â0þiáÅáG}@ÅÖ¦^nˆH¨sØ<쪲ñÓ‡IoÂòÊ¡£åÖ£ ô5B‡±€ÐUð…±€ŒPÉ1Ò¤¨Š@P¦Ε4ª´ö´ÍõÇ­²È„ŒZŽ›ÃòÄJ5ú 1YÑ#d„‡®ê>OztÈ«òXù÷pqÖs @ìq‹†ØÇæ;¤D¦ ¡GþàhÚº!ð l‡YïÚ}ŸšV3`4K¹À7„Ù¼gPxµ4q-çä¹yacɼ/߻Ԓž’þ6­+~A˹˜;,$«•ÏFÂ;îq}ðÅ—X@ƒï<½7G.ýaÁ$˧J¸€O" ×— ¡uãéÀ5÷å’Â><Ö·~wmªä¸›åEw«ZfŽo4´òÀSS… V‹rÚ]¤tÇÔƒsO³0ð¯Ìˆ#õhÖÔA-Ðr'^SîïkÁgÏ@ÝûwÇjò9…S69d«qozŒñÑA-øOUr¸ŒãLT±™TʼnH KAPàÒ<ñÜ™2¬=¤4ž šÄש«¥rÉ©Úlµˆ7çS°Ú¸î&ÜÛh4Ö@=8S…ÿÆ—¸¥4]õQ"ç7§YÌxÖõ‡Êƒ¸X +Ò¦QØ_?¹"δx’¬Û•±¡\öXìæyôìSma´TT~ZŒP6ÿ˜i@z«áÁÈh†=–ôGv +•ÞSÀ?„ —4ØÄnÀT…6OЭåÁ)or‹Uº-42–qNŒ`±ˆgâìÅ +ˬ•£{NÅìüª÷Ìvàö~ © +RM½Z¸8÷䶅i,ç„‚ýeÌéÖ e,çSIÁXB%nµTF¬±æÉô_¹b\(Ë}V›‡ Ý{X“¨ä‚þrcw5‚ƒècÍ8Èè¶ÅnÕ9eŽñ®ž“=á3nüYH‰ ‚£˜pœ0óÝÁEIá *•uñïC¹­WÔ\µ»ÒG ¢©}Á¬=¬7Ô]÷DÚT•‰pηì¾(;ZeSC +ì´Ü ÎŸS!¬ß\ +!eØG¼Ô†—·õûäÕñÏB¨„˜!•3\’I “0¼Å— ÌIæú)ŸÐ¼ø7éhqÆÅxÊÓË +Î 3Ãʘñä3Ç뤮TÒcP˜"%ùrUÚŸYôßõgÌ +žðg°Á]tç÷-õ<taª\E(Pn×íüMê¶ÒpÉã¡:›mIÓCLjªTH98!F_€4¾§ŠQqp†•mòܧ”¨êåó»rß9¤§ò€ï U.—Õ]ïÛÍ5¢Ù*M`D…ôJåÇhSù G‚pð¨b¾<ì x6ýÖÏLIùd>¿Ø_<›]¹\ìV:­Ñ%™7=Íý¿xµ‰Ýæ«ó7ˆ£œs„ ü%ôMÙU‹ÜOZ5Ë6ÞØDù!q—*õŽ@ÂÛ¯¾ôÕie|xGXÈÄ“‚»æ–?’oØ\êÄlÈÄ;òT%uS„‡ç1…þCGÌÉsá[€ÏEüTäÌ5™±Z¦wä³öa/ž1wùÞI†Ûö‘`…•ó”ôiJWëŸ^8>ô!^7õÎ]àžû¨#ÞlŒÝºÿ§ÓÞ¥>¦a 5.l4K÷ Jà?ñé·ÝðùÅä` ø¾‰ áë“ç©8àƒY螌²”on„n®^}w¸‘ß5å—_ìnäÕú‡w_ô?|¯Ö?4ß±«W|óã«o×?îìÃÕ«—ë•°8öO¿$œßÌ(ɧûü3¹ŸP_<Ï¥H•9V -füyê +z\ŽT0©ßerÚeê«r©3ü> endobj -838 0 obj << +1327 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 316.8305 511.2325 325.7868] +/Rect [91.7912 473.8206 148.0099 483.036] /Subtype /Link -/A << /S /GoTo /D (subsection.6.2.15) >> +/A << /S /GoTo /D (controls_statement_definition_and_usage) >> >> endobj -839 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 304.8985 511.2325 313.9046] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.2.16) >> +1326 0 obj << +/D [1324 0 R /XYZ 56.6929 794.5015 null] >> endobj -840 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 292.8669 511.2325 301.873] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.16.1) >> +1323 0 obj << +/Font << /F37 1018 0 R /F48 1228 0 R /F55 1311 0 R /F22 953 0 R /F21 930 0 R /F53 1303 0 R /F41 1208 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -841 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 280.7355 511.2325 289.8413] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.16.2) >> +1332 0 obj << +/Length 1516 +/Filter /FlateDecode +>> +stream +xÚÝX[oÔF~ß_á‡>ìJx2÷KyJQ€ (YªJUÆv²^;];„¨ê½¶×¢ªBû°ž™3gÎùæ;›D~$Òafx¤ G¥ÛŽ.aíÙ‚™¸Š‡R¿¬GO™Š 2’Êh}1Ð¥ÖšDëìÝòÉóã×ë“7«˜ +¼dh ‰—gÇ/OüÌ9, ±ü­“xòêìéé³·oŽWŠ/ק¯ÎV±Â†Ãίï}õúd¿ï|õ~ýbq²î½zJ0³.üµx÷G8üb3ZD70ÀˆC£í‚ †g¬›)ç‹_{…ƒU·u9Á4šªè(@G0¤Ä5!lÊ&—yB +ªêpà¶ÎŠ‹Û™Ó4dZCÅ}`—Qí^4iûÒŽzÐz„¡ÐrLS !f‚¥Ûf2ºŠ¡Á€F¬¸¬’Y²ÙË¡³!Ü7ƒù®M +‡7Y¾=;ýÝ?5a? h_{a>´¤«žV´«žv¹ö;Úäc·z•§…0õã$m‹ºjy¹¤ñ³YÞ¤»âƒoœ RW“ÓFeÓªÿPæh®(¯7ynjà€ŠºÕ¾8\7}9žÏˆXÊû8þhsÚL†®’aÞ»kÀдžÈþJ@ÎDHsŸzÂ\{,&åÛvu† `»Ó¿ƒ®ðØ혔´Þ©˜+(† ÚwÔ#)A„q +a¨‘ÒÚ·Ôç§Ïž¿}=ŠbHYÊ×På÷™Ù«œ1sx“ÜᶙùÄÆ@3é³÷ÔÇ}" +e-›ËÄAFàê2B—uöMíÄ”, Hšü€rÜæRðD’†VÐ6îß³~ ô^„¾Âa Íã²ã0¼P¿¼›Ä^%yPt~‰ÄC;ïMâ´Ì»„Ù×ÓŽ‚ùç¢ýËÌÕœeÐbpÃù×h&8Âá» °ìôl}7ÉŒdVΓl`åÁ±óôÿÂ1b(ŠHÀšF5þtuð ÞY‘2öµA!4gs_ºpÔ½o÷wµýçFè ™Ötž à ¼0DЕ‚.ÏÂî±û׉ ŒÿAáôendstream +endobj +1331 0 obj << +/Type /Page +/Contents 1332 0 R +/Resources 1330 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1328 0 R >> endobj -842 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 268.7038 511.2325 277.8096] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.16.3) >> +1333 0 obj << +/D [1331 0 R /XYZ 85.0394 794.5015 null] >> endobj -843 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 256.6722 511.2325 265.7779] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.16.4) >> +126 0 obj << +/D [1331 0 R /XYZ 85.0394 556.3324 null] >> endobj -844 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 244.6405 511.2325 253.7462] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.16.5) >> +1334 0 obj << +/D [1331 0 R /XYZ 85.0394 529.0279 null] >> endobj -845 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 232.6088 511.2325 241.5651] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.16.6) >> +1335 0 obj << +/D [1331 0 R /XYZ 85.0394 499.5106 null] >> endobj -846 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 220.5771 511.2325 229.5334] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.16.7) >> +1336 0 obj << +/D [1331 0 R /XYZ 85.0394 487.5554 null] >> endobj -847 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 208.5455 511.2325 217.5017] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.16.8) >> +1330 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F41 1208 0 R /F48 1228 0 R /F21 930 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -848 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 196.5138 511.2325 205.4701] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.16.9) >> +1339 0 obj << +/Length 69 +/Filter /FlateDecode +>> +stream +xÚ3T0BCS3=3K#KsK=SCS…ä\.…t œ;—!T‰©±ž©‰±1ƒEV.­knj©g`fA‚!ÂVŒendstream +endobj +1338 0 obj << +/Type /Page +/Contents 1339 0 R +/Resources 1337 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1328 0 R >> endobj -849 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 184.4821 511.2325 193.4384] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.16.10) >> +1340 0 obj << +/D [1338 0 R /XYZ 56.6929 794.5015 null] >> endobj -850 0 obj << +1337 0 obj << +/ProcSet [ /PDF ] +>> endobj +1344 0 obj << +/Length 2407 +/Filter /FlateDecode +>> +stream +xÚ¥YKÛ8¾÷¯ðme RÄ·¸{ÚÍ ™:Øtïa03Z’»…±%Ç’“éüú­b‘²d«Ó ÄY,Ö‹U_±Ù*‡lU¨,V®Œ•™Ê™Z•û›|õknX ‘JdJ + «©E¦ +nVé”Éîo^¿çlÅóLk®V÷Ûñ,mT¦ )V÷կɛGwêã:å*Oäú÷ûŸh›ÌLanËá›å’I¿áßÕW×–uE;ÞÞÞÑà}í†Ó±îGLfBj8h“å $C2cë”åyžÜvC³} +[øÊfVsv‘I%éLŠ:¹ýtÿñý/4nzü5‰£Ï}]>º¶é÷ô9<º!¬ïvÝ·>¹Þ+‹ã¾>~­aa舸%‰‹º‰´;÷µ¾Úf’nK“xôC}ÁË¡b¨ +c™UŠ{U¾wmý äB%•\´¹J>¶4u\³"©ûC×ö5Í 7üu£eÏfb\g‚™AÞÁ:×æ”,ÓR˜@¶õ‡tûÈ×ÿDËà˜T\™¼Â‰-VÈ8üÖìv4*ëò¹°}¥÷nÀQ3­ÑzMô¢‘Rb5H0ó’Ò¹]h5¡×ñw\*OG2Z;ÐÄ™?|¸¶z6né<gÚfhÜø¸Ë“†£kû-Ù!‹®ä,c… ¨|ßatä&Ùw$}5í¶;îÝàeÀ ·éN 1ܨ@g.ÍKn69ÌÙ+béMoTu_›ÃY¥b)ˆòÌ0OoŸ»“ÈÄDÝ„Ó"ùÍ»ûsÊ2,ƒ«@ƒ¼€Ü)‰+|žä°‘>n 6 ä+¾(Ë]]ž…ÑϘ†s!Ò˜&§'ü ™þX˜K%¤FÆ +W6©BpÂ]±fÉè œCöBÈIºà#m³BB6$ã»]ߥÏ: +¢I[ÃäÚ91Àáh‰(ü3Ò§Ó ×6¹æ;sªœc®D*°Z̺rM yIˆ N(‚ϱEr¿þPé´1ò/¤P#sÈ”B‡®ìv¤™ÏKàÂþP—ÍoyΡBúÌ&´«z^šŸ>¿Cf­Î.Í2Fã™Ö Ê_n~ý=_U`ŸŸnòLØB­¾ÁGž¾Úß ­µJÆ™ÝÍÝÍGŽÂ +‘éœéçyѾx…!íP¬Ò(]*8à1÷Ȩìve1¿Àª°6“¹¥;{;±±ÒÒ# –gJðèŠOëT³äþçÉ»KËOÉ@4¡TÆò·tõeWVZ+ˆh2öºžmà'^ÜóÕÛ4ZM”ŠŒÓ)g¯”泤 €ÆHÀÈŒ i a…¯%ðÕrÍ¡ ­¹ÂâÀ “|_3Èþ¾AéÚ°.46õ„…9—e˜I™ã¸pB¼_‘]µ˜†8$5 fx·§à¼ÐIÀÝÌ­8—nódƒüŸè´ªÞ®TÊÓn«}ÝVý‰)7àt#.¢þöÓZæÉù†é‹ê·–…ã÷uß»©dâÏõå>jü •}N<^Û"U3Ðï®s•· dÅXr‡tûÔ´K–Ê÷æü¢z>Á`´kwÈðé_ ZX€­…PI”„ ×rpJwêë%9 ÒKk^r˜Ì +SDôçÃÃ@x´»'¡w˜+ "1f¼ù¤È,Üì£ù™0Ž–ïé3€>5áwâ„K¤`Á.ä›&‘¿——0*«í* {ÿvÖœ¦º3±ž¶X“N'ÒqåZ±ÐïðÐï¼}W6%eüÿ*Ÿ/7?ã&mã&?ö%~ýìëá±Cbòd뽄kU‘Ž·P,¡ÔÃΕý~=ÒUõ®ÆY", ÖVá_²&ÇEÿÃ84 ~¼y" ®YÒVľ!fíP€Ld _5ÝŽ>>Ó¨Û^t™1+`Eg¹¯èã7Œ?C?蟰‚ÜÙ×sfóÆbZÀC›pQª9z±!˜¸—%'P?: >‰=ƒ6Åm`eGÜ™ ×Û’Jr +ƒ·¡Å/øx#}o›žž‹$ͳ"·± z_?ǘ«ŒÉoˆazèvM¹„0Ò(SØ@]î|›‹=Ój(íjØåQï5k€cy!£~ý€rP• Œâv^RöÐ÷]8ƒÆGp8³¡QÄA輤’pWµü«ºËÌuG·2_‡p\G{@…IØ:EÍw]évKªÆ/ŒÔßœqú‘ùµN4¢vG›0s¨ûf0ÐðÓ§„Ùæ?ê ŸœS™è16­ª¶_ê4À#F£Ää'U€=M1÷ӷǦ|¤ /ŠDÅ߇º­nˆ7nó´Ø¦b“ÌøuMœã¬¿#Ô‰9âè8œ!mÜÕõU’+Êëø!µP/õD‘>nXhG®øÎ{" {"¨*òJ$Ãá¶Ø™D×MQ zI @© Ì\ ª˜ Ç üªêÁ5»žn?tr.æ·kLuBLbb<9õ>ƒáüÏõqSS§ûæ¡E/ã*ùåT÷CO3#Ù¦¦‰½«ÂhäÊÂ;ÌÝÿüî—×îîhzÞ’áúæ‰~án¦KOqTï„IݤÆñræ³qhb"Ô‚«“>@õ84) HéבX`ËžÛÙ{ ¾ÙªºBqHßPB[74_kÄlxü&ü‚Ðgù6ù$³Ðcr» ]y¬+ÈÍbÂA@Ffævq5^œ‘)¦§GTÝÞ5íRŠì¯ÙLq_±U‘|jK^´/„P_:˜‡ +×j ¤‡ +΄£Màõ¿|ŒÜHÖôA-08×I@t98ÔÌÁˆÏùMã혽B†·Ã³å `æp„²Þ"°q—o—^ÇãsÇM´^„ |UÀ1øXžÆÛŒØ<âr“ü–«üû¦GŒ—¼{÷Ö-m»ðhŽ|€Jä¹ùç_4’ÏŸï>~xEë·°•z…)AÃK,¹pÝ׶½ÿ¬&TdÍ9³à¤Õ‚w:|d…êäÛ£dZK&œÈªVŸ±*Œ£_KSÐ=5m8#<ÌÁ,–JÍ#D±”îI—€-`ñcóÝÓ|Ä—×Ç:—üK³›”Œ üs +ý1àÖº@TÿyÀp.ª…aGØ…~æII¨L>óznvFš¥Â¦ˆBE D¨3SÏ>º^÷µµ^endstream +endobj +1343 0 obj << +/Type /Page +/Contents 1344 0 R +/Resources 1342 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1328 0 R +/Annots [ 1348 0 R 1349 0 R 1357 0 R ] +>> endobj +1341 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (/usr/local/share/db2latex/xsl/figures/note.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 1358 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 27.00000000 27.00000000] +/Resources << +/ProcSet [ /PDF ] +/ExtGState << +/R4 1359 0 R +>>>> +/Length 1360 0 R +/Filter /FlateDecode +>> +stream +xœeU9²,GôûeË@@Q ‡!é¡%bd(dèúʤ—÷ÿ(žÑ¯ +’$¡T¬)ÿ®ïë¯ãïãÇ_¢ýþÏaíÏc‹®½Ú¿G—=ûÌöÓ1ÄF¬lÖ]töö×ãqu‰Ý¦‹÷5š”<8Ç—ý:\;âúãñ‰üéÆ&ÞЇ h—õ:ÀÀX=&02²oÒCó eD3PMtð1CrZûbœ7³}t€mA£d«·íä'ÐWŠ!è®»½KO(°ƒÔ¤‡tÙKb•^¦Ìì »å*’ÎÕBêFåmY¸™`Uõ´™Õ -¿nÜž í½³`*TûÞ£jg“¾=Ås–A½R?Ô =}³Ú§l +¤Ï’ÃigÙ¥—ÇáC6uéíÛ&”\Ê GTœ„Méêö–KòlÜ’Fyu|?é%åiÈ¥K”êNÊq{vˆ*êèJE¢]8hÍò¤p0R±ˆ$Á(+Á nÖN¬ +qª„Ñ«ò^ÿï>‹«>÷— .13×…Óƒ!¶3¢SËAÕ”ih¥Å¨Š^…(€<Îm䦽ªšÛÆlLÊâ³ò7ÙaÆ´Ëdô 6(WðÚºK +г2"ïE9~  +n*Œ1½÷¨¾x¥Æˆpîâ‹&XîÃœ§³±è\íD¤ßä0}#XŒûž˜‹¸À>#^V°¡|2Îi‰9ÊÎr)`˜¢Xh¡Ò& „hb—H°Œe"Ãêʱ„£~Ï“a³tŒºìZDß!#Z¶ÚÂk! e'jÝ=§ _tsÙ¬ûÍ&­Nå@‚i¬ˆ3t%kÐE„\H–YZxÿ/U¥Ç™åë—Φ@±¯iW H +þrÓGçX5¾ûû8‡´ÕªOª«t–Ô³$Ây°‰—BÒ›ÀÄ5©/¨vp÷o`kA“ôr ±ñœÓ4N.4Žæ&F°ÑTÆG%V½ Î'ÌØR5¬BÔ‹`qUžv-UÍ=ëÆåQv2ë_ ”¿­qq‚~èr¯Ú5ÌJ¼ð˜°h»P¡õ‹kÜàéÚýªå>Ò¸D °o»Îi¸CrT]¿MJ¥ ÆÖ¹’°;¿ö‹ûóZ¼¬ å[Ç-œÁ¤ŸBx¿ýpü|üÈÂendstream +endobj +1358 0 obj +<< +/Producer (AFPL Ghostscript 6.50) +>> +endobj +1359 0 obj +<< +/Type /ExtGState +/Name /R4 +/TR /Identity +/OPM 1 +/SM 0.02 +/SA true +>> +endobj +1360 0 obj +1049 +endobj +1348 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 172.4504 511.2325 181.4067] +/Rect [470.3398 467.2776 539.579 479.3373] /Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.16.11) >> +/A << /S /GoTo /D (boolean_options) >> >> endobj -851 0 obj << +1349 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 160.4187 511.2325 169.375] +/Rect [316.7164 455.3224 385.3363 467.3821] /Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.16.12) >> +/A << /S /GoTo /D (zone_transfers) >> >> endobj -852 0 obj << +1357 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 148.3871 511.2325 157.3433] +/Rect [304.6433 163.6578 373.3153 175.7175] /Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.16.13) >> +/A << /S /GoTo /D (dynamic_update_policies) >> >> endobj -853 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 136.3554 511.2325 145.3117] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.16.14) >> +1345 0 obj << +/D [1343 0 R /XYZ 85.0394 794.5015 null] >> endobj -854 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 124.3237 511.2325 133.28] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.16.15) >> +130 0 obj << +/D [1343 0 R /XYZ 85.0394 769.5949 null] >> endobj -855 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 112.292 511.2325 121.2483] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.16.16) >> +1346 0 obj << +/D [1343 0 R /XYZ 85.0394 576.3463 null] >> endobj -856 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 100.2604 511.2325 109.2166] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.16.17) >> +134 0 obj << +/D [1343 0 R /XYZ 85.0394 576.3463 null] >> endobj -857 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 88.2287 511.2325 97.185] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.16.18) >> +1347 0 obj << +/D [1343 0 R /XYZ 85.0394 533.5444 null] >> endobj -858 0 obj << +138 0 obj << +/D [1343 0 R /XYZ 85.0394 299.6823 null] +>> endobj +1356 0 obj << +/D [1343 0 R /XYZ 85.0394 263.0631 null] +>> endobj +1342 0 obj << +/Font << /F21 930 0 R /F22 953 0 R /F62 1352 0 R /F63 1355 0 R /F48 1228 0 R /F41 1208 0 R >> +/XObject << /Im2 1341 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1365 0 obj << +/Length 3579 +/Filter /FlateDecode +>> +stream +xÚ¥ZIw㸾ûWèú½‡.ÉÉÓmg:/ñLlgy³ ’²8M‘.V{~}ªP”ÙÓ‡<ˆµÔòU¡ pÀ/ܨØ3‘m’,òUªM~¼ +6ÏÐ÷׫Çlí ­;êÛ§«oîd²Éü,ñæiïÐJý MÃÍSñ“ùÒ¿ +÷ñþýÃí?n“È»ùûõV¨Àûñûû[*==ÜÜ?ÞÝ>M‡rOôÛÕO¿›Îÿ·«À—Yª6g¨~˜ebs¼Š”ôU$¥m©¯¯þ9tzÍÔUF†/d,V8)ÂMú™RbÁJ•ù±’Y)|àEÀ­CIgüµ»F×–i¨K<*Žh‚ÍVD~…‘¡tS› ±—tó\öXQÞQ%5-}5}~o›’†Œ}Õʦ IA3‘†Bùy(›¾jÒ(t4$MSIŒªŠdý_›zED ÊIdÔdZæcA“9–Û•·q¿?µÎÞXµ 4 6ðFàjS—}OÕþTæö“,‘ Û0U~–ÑRà-H¯«Š¢lPq¯؉)W¼if@:x»ªÑóy¬în +ÞÔ¡k.7-÷î˜hYT¤dP>êf4ûF˜ò'&~&EjvM›Œ“Yý |®Œ‘BI×}K¥6Ï5ÊUGuÕÀ“1"*Æã ¿„œØ3Xúy{<Õå0ÕЇ¡gÚû‹Á¤ÏUXNqJB‡–ÊN4]+š9p$•5àLxöK<ƒBA¤±ëª\Á¢ætYèéý`Ø}¥Î<~¨Ð&ß°ÜÏõØ3±á y3 +îlgÛR¡¯Û3"s‡’^ƒ’š`í ˆIo¡dÎß™]PÙ“®ÿ6'É›=~lú¡ÔìXȈ™-R…¶¤W”µ~µôŒe›Eèk„ßPÑ÷X5ãPö†ª…S‘‰AŸ.@Ò¬‹¶ÝÓ.ˆljà KÉ„^2Þ‡±c¢©Ýx2m<õNæÌmfkö\î4À °€BðR¬ÞPÚ1 ftë/ì¨á°X0A¬_A±H ¿”3ˆW@lkG-Ô {3?Id:Ü}ZCEégCР¿ ò€;h +ÒÝÐ#XXDË+Ó”Ç~ÐMn$‡Ú§´úË ÊĤ´ÄŸ#`\±TÙ¹ƒÆAâpìÌÚ<¯@ø…íº!$¤§pè…ZX ëõž¬ò¹±ÎüÆ3ç?´¡ †Šx†3h"µV|8uÇÆ+‘w\£qýaŠöÌ[îÌ;ÝŒvÁv곚3mPÙWêaq ¨Là/8ÐÁÝ5àŸNmGÜ4PE*+vcc"ôÌŸÙ” Âðƒ¥¶ýD%cL<‰‘ÍŒä¶Z÷ý°?UÞ‡ª×»zΦ f ÷ŒfX }bÝß²>Œáš›¦É‚õ8uß•åï|?UÊMD>øLÁlDù‡nU8M9°DâtdÜ¡¶Í.Ó=DØkçÚ=¶’…ñWïAY&"dõWà0Ü*„i†w}×^¦K¢Ö= wOÞ@çÚ ·üÛ‚œœ3Öž‹‘¡÷°n"K⥠rú¼"†(ñU$_Cì‡b²+r“68©[]\l˜ô¿¸Ü=áî4q[6“jnEùA„_PQÇ×úÓ¡C[ NvDSŠ“&Áá-œÝð<[[z¼E +j=§’úq’IÇ¥kn5 . '·JíË4¶°AmÞò\y0SS•:5×R*ô5ãOÀ!O ´ .–d¬‡Ò, üÔïÖ ¡¢ ¥hÆcD<Ž#Ô”-r–QjÎð*7%„¬˜Ò:܆, ÒÅñ§,š³Ë\’òîÞSC˜eÊPŽ½Ç²¼ÌøE±òÃLʼn &!æÞ¨³{ÞPáÁIÖMã·îJÖ-ǺȵŸ~ ƒœÀ][DR_Æ™8ì}„ @A®¼è¹ÜtD~Èdøí ßkiÅiÐÖõv£oh9Ž,? ƒtéç( —Qäé|0â6åž¿ôaðJ"ôT2N½o?Þ ®Œ>ýx‚Ðzài$j,ýÅÇ4X䀋p»±jCƒ¸Ð”xÅ4W))Vbê_0´ÝëºS³_à"£V2„»Ê‹†ugTÁ-÷‰®`fH“×cÁ ÒX¶» 1iZ™ •»0°ÄïìPaE}ì0À‡¶Zì'z+áÕ™£=aB M¥³6w)¸WîìÊØL9‚À0اâÝ›œ×æ=#ÙÿP™û;^Å&½·t,ÒØûXá»Ù•Œ¼SÙ¡4$]¡y?š8EF!¡ËÁhG„¼a„ä¬ £…$!âV1s hfˆÃ{¦i»NÔ]øJ¥~L¹Íê3]¶û®=n  ØT‰·õo¡)>r®‚ìØD –<éËéjÈHº\!ÌŠ)½®®f/N‹`.òi¤ÄÚ¥\bZËÚ0&Özn£+07Lfó…ÖŒÆr\…£‡¡<žª˜¸3pÆZ`66qîËÕ@½×ËϧºÊ+ÌŠ™zA1i›€œŒÆbû±]»t¬Ø² лv¨Hô8¿LªòŽzú²¤çÃalÙç]ušéPÖZÙ;ÿe4@¤™•L‡é½~ØMy+"¥|¥2+¢¼æËåWWQ‰a› -9…ò–¼ ü0TV[ûðãÕ€<hDe—QÄÑ#Èd˜Ͼë<–ë’ˆÍ] ¿³Áᥛ_ªòlÒ[¥q¨­¯v¬9]q$óErÆÅÌCú“IœHÎØତ[­´H…Eùy¸½©'± ‘¶¦°ÈLåïØÓ{Â…†Ñ,8Êüx%"Žu¥GøQ¢ø›;™9œŠáf „½ÉXÆÂàuÆF‘Ÿ&"¤=Œ'ŽèŸf÷gÖš+øL§¡|VÄ{Õ=fDi{ u=ë¦úÝÚ +´Úl8 <ëfXžŒ (Ñq–zxûȦÐOžüö^þ‡9žï Ä'“’G³¡ÄÝ?õ‘³ŽÞj¶š %&êÀ*½ñâ Wð]Gjä]$’cä„D"é€ FoŸH¬a™ú™®¼Àè™2i+ê‚ó1/=Ó’ Ü|ꊞW°Òâ“I¿| À)%í6N”+qì­xfß¹¥(wF$Œà ÃpbrÁÃÁÄ'¸M¾ +Gg\ªà 8"À`xbílgC‹›d¬.â)h¨Ký©§¢cDߣɑb ÃЯ¿Tš*%„$¼Âî`ªˆ ™qÄgylþ;4É#q“OÃR¯_^^WŸ¢@&à¼tþ (³€TfRà0‘U†œ²)(,OH=¯4¾1‰?lãq,¶Ìè?–Á Teâ}מÑZm€œ&LÉyV"³tQ0Zõ—Ñ ¿nš¼“t°kΕ/²ù8h¶úHµIMŦJaÜO‹éF(­-š§6è¶sZ9èê…ÚÂq6¨›G+^…¢GLŒY9nãÕ>ˆ$&äJÂ5äJ0L}¥B~h),NøŽ ßÑ6húXä…"Ûô<öÄÇ¡Ä«ƒO%MÁÇêÆ{ñžöôD,ëý’à›7R;°ƒžð±íêb5•Ó°ê` :!£Œ—È}„Œ2vQ*BFQÇÓÁ%« ‰nñHU5›íCݼR“£ZPlÂôaOÃX·p©ÉAó®i1ý¢ÍGŒìØÕuìÿ‰fät"j ŒÃ ;€ýEd4ð)Å‹ Šþõ ›Ëû²6ööÉĦ²­Ìªzíg¡Q;À³å£‹¥4åâqâßHœþ—þ %•`ZI1ÓŸ“þïÿIÍÿ&‹_¦é’"Iý("¼)dx¿Ù¹ýCÕÛ­ÿÓ°H2endstream +endobj +1364 0 obj << +/Type /Page +/Contents 1365 0 R +/Resources 1363 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1328 0 R +/Annots [ 1369 0 R 1370 0 R ] +>> endobj +1369 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 76.197 511.2325 85.3027] +/Rect [464.1993 393.2115 511.2325 405.2711] /Subtype /Link -/A << /S /GoTo /D (subsection.6.2.17) >> +/A << /S /GoTo /D (proposed_standards) >> >> endobj -859 0 obj << +1370 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [499.2773 64.1653 511.2325 73.1216] +/Rect [55.6967 382.2725 105.4 393.3159] /Subtype /Link -/A << /S /GoTo /D (subsection.6.2.18) >> +/A << /S /GoTo /D (proposed_standards) >> >> endobj -799 0 obj << -/D [797 0 R /XYZ 56.6929 794.5015 null] +1366 0 obj << +/D [1364 0 R /XYZ 56.6929 794.5015 null] +>> endobj +142 0 obj << +/D [1364 0 R /XYZ 56.6929 769.5949 null] +>> endobj +1367 0 obj << +/D [1364 0 R /XYZ 56.6929 749.4437 null] +>> endobj +146 0 obj << +/D [1364 0 R /XYZ 56.6929 458.7525 null] +>> endobj +1368 0 obj << +/D [1364 0 R /XYZ 56.6929 425.4132 null] +>> endobj +150 0 obj << +/D [1364 0 R /XYZ 56.6929 270.5184 null] +>> endobj +1371 0 obj << +/D [1364 0 R /XYZ 56.6929 234.9696 null] >> endobj -796 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F21 714 0 R >> +1363 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R /F55 1311 0 R /F48 1228 0 R /F39 1151 0 R >> /ProcSet [ /PDF /Text ] >> endobj -862 0 obj << -/Length 3454 +1375 0 obj << +/Length 3172 /Filter /FlateDecode >> stream -xÚí[SÜFÇßùó°U túªîÞ}ØÅ€R1ö©lm’‡ñŒ *3™ Äûé·5R·Î0­3ô&&®Š1èèœ9ÿŸNßP÷‡ Œ"TX9ÐVE™Œ&;tpé~öf‡µ×ìû‹öáU¯.v¾y-ôÀ›ñlpñÜËj \ŒÚ=|wzq|zq¾÷ËÅw;Çá¦Ð1£¢¾ã¯;?ýBcçÿ»J„5jpçþA ³–&;R ¢¤þ;×;ç;ÿ -7?]šÆ>ˆ†(Ãuä“p> 㜫]tÊ’Lp±ü(áÎqýAÜå \.1†J磾l6΋ټÍöGWò̯g­ _M–Tƶ6çÎ&Ÿäå|oŸ+ºûf:œL†Ó½}Éõ.ÙÛW”>â_ÒÚ‡]yObÅ É8e]×4™^š/ΠJÞn®«´~ÿ¥JÙZ^õX#¨÷Ž©‰R”F8ý39ʦ”—ż¨Êæ;ÃrÜ|ñÃlx™;Qì#"ÑË‚ÏV2 ÀcaE „…H ¨÷Žá$Ë `mda>]ÌæùxÿSþ92Är“m(FÒÇ/©õâÄøœ& 1bV4Cˆ‰Äƒzïˆá‚“±ŽþE‰Ù\6¸O““^@| -“† +!€DâÀA½w€0F•±Û"¿‹€Á¥û@Zm(%Jˆ'SJþÈúò@˜|º“a†L+rê~˜"q`0¡ÞL™µ®À€æI~–6™Ìf_:}Ìø¬¦"ìbV4ë& êºÃÅhÂdG‹ÚHË«2ÓBµÕ›*1Ϲäl¢¨Iv2DÁ ciúZ‹#ñÛ¤Ý0_iÛ!”}„6­Øói¤BZ“a†.P6Mû‰Ä!ƒzgJ­ÝO³ŒëßÂÜljùŸš¥¬{ntûù&Ÿ¹\É'Þay„ZâS˜ 0Äa€DâÀA½w€(êÊ‹0Þrx=œ9$å__œ“M¸ø„&ã 1\ `š÷ã‰ÃõÞáâ c+¸ˆûõäÝMÝvÔèðm ºùÌ%s 1. 2‘80.PïŽÍ]—p!.Ž>—ÃI1j{7c×Ùh¾~_]£¢nu¤RÏVvŸ˜dÙ!&;L¼Vý²GâÀdG½»5B 2æF®R{Õ]!`t¥¼.®ëÉse¿úäIwa½ ÉŒCŒ1(³îŸ´‹Å1†zïÆ=”•©YÝeœ®t[kÖªÍßgù¬ZL÷˜Ùåþ;£jùñìÞ€æÇ«¼ãÌ+?Äñâ«|â†:Z<½IÚ‘d½!¦7Ì8¦w$LoÔ{hJ”¥D‘uz/›¥5‚½ÄžEHX*ÐÁaE‡X¸÷mˆ¤ âÀ[\à»ùoóÅðº¡!ÿíf C>›…É‹PΖc™ì¹6!OÉCŒ¨ƒ¶ýDâÀ(@½‡F@eNzfU €·ÀQ1-"r¿ýw¤@ÈG•ÿ±§ÖC“ †!P#Ó?‘‹#õÞâ -º#D´„œçóyQ^¶­úÅ÷K䶙ÎÏp2?Àã*ˆñ‰ãõÞñ#9aîÚÀlù9)oó©ï¾ÞܘŠ¶æœ¼¿us#¶C‘ÅdF€!ÆTÉ°~F"q`Œ Þ;F%T‹ŽÕ2òn~•Oî~—K*EÓ-Í‹Ûz¸"${ÉíÏb2#Àcª„1‰cõÞõW™&Ö2Ñ1†/nHY±ËÜm™ô‹qÿŒ,×¹¯÷üLÎ÷gÅeé¾dõì -Û¶M!ëÉLCŒ)¨*ÆT$Œ)Ô{ÇUÄR ™â LýåÝÙÉ›“ÓYR»®•ûNsÝJ™ÚÛ·O¬?xdHh2.Àà -†á‰Ãõp‘Vw=¸ˆ\NN¿ÿáè8¶Rš‰>^¸xvmUHe*(ÐeE*Ó¿j‹÷ÞbÑRAPd -(n4Û]’#m$úq–z­CRœ 0Ä‚bEâÀB½‡±Ì,É2Á@YÛ!~urzäGL³¹ïw=âãßæyYÏÚüÍõ†ÝGqc:s *¿3ò/oŽOÏêY¿‹XuÊ¡TÈ8xÙŸ4÷Ó ‚OU2ÀJ‰õÞ ´3`ºá`<^î$óS´¯«éd8w£¡LgÛsH`2Àà -dD?‘80®ôµ3P<9é™ÔD„Ãnf ñÔz…½@ø”% 1  $¦ÿhc, ˆ5ï,ò¢#ᮚ7‹¶õä]™Eôóùh1 TVå¬çÓasܤ7oþÖ.€‡å ¬G¼~ße¾úwÄÁÛayZó›Jõù,KÛ<-;²õ\ÊÁh”ÏB!,ç˩ϪsûÞ•ÉåÏävb%ý©ó O~ê€!öÔAA1Š"q`4¡ÞMLN§)öº7à¶L²¶|^M«j)²BêÆcíeõûÈt¾%BiáçóE1ŽÝʸ޾4íe/üàÈÿC¬5™X`ˆ ¡±ýûôbq`Ä¢ÞÃÄ œ0ž lw$º„¤˜ãÒxæF½øº±b]{›ËŽËÛfñ¨*›sñ"/§ örå3ŸÌ0ĸ‚Êb\EâÀ¸B½®\±t¤ÈŽ+¿Ãü‡YØð_¥Ô™»ó¥oÖ[Ö(Ñ4¬¿^”£æ R¿„ƶªöT¨ !ÕŠ¬T±8¨pï¾yåZ×ßã-Sþ|dï‰Ø®{«U¶«Žãsš 0Ä€šaÀDâÀ€Yóq¥Hû>+ÓŽ.öc»Ójñá:Ÿ]¹Ö«®F½Éiì:Ðé.G†9 &Û¿Ø×Ý -KÂ=ÑgF -"xû¾8‡ÕdâÏø¼oÚf—I=€—r;žIŒ|š“#`ˆ=FPFŒ›HA¨÷®1¯ûsRˆB'ñdþ×v”\Ví„â]5ýäž©¿7ÿºªîš/FCº£ù«~)Òesø´­ÖÕÂßájn{×ö/ÿáŠ83O©¥õ9IVbŠÃœcŠGâÀG½‡ªáÆ–,kߊb–}·ºjœ”£F±ººqáø÷áÕ°¼\éÝùµÀÂïW:]L>ÔË "³Ï  Ò”Ì0Ä€2` DâÀ@½¨&Ô0Ï€ïmýXÍéžÚÃ{Ïõ¿°ðm~}ãZ)· ȃPòÙNF b(A51”"q`(­yõØ‘DqÛv>p•œó݃››¼£¼¦9˜=´ .ØJ8¶]ÞÉÁº×ØãÄ4'R¶Ç1êTk—…ѧ²º»ÎÇ—uI­WX¹Ýv¿’ŸžÜÔ§"OÏŠx1‘80rPï¡ûÅ2JD¦:5<¶~„šJûjZäí1ýo‹Ù¼š~^=»â£Óó{-v³"”QöŒPðÉJFb(@10"q`( ÞC‘®3fÚ³˜u¿¬."oò2ŸúVù,ÿضÔasÎIùq¹K|9Q–Ù—µòr— 0ÄÀ€ÚØþí±800Pï]qQ2|8y›µýxìßæâßñT~=pÿ5'_3¡·[½C“)†%P'Œ’H%¨÷P>¸$Œµç(ê.}]>^®‹êr:¼¹úÜqÚˆóÅåe^ÿR_V†c7Ækœ¿âá3—Œ0Ä°€Ê`XDâÀ°@½wŃq×Q× _<Îò_NúFx×tø “¶³êY9{}8k€0‚¿§OY2ÀJ‚‰õ€¨ †jOA4¯‡Z6&õ&¯Òð¦Ã5ÖòíèCFL’úPbZ³}`æÞÝkÉí_h‰Dð‚ú¸MŒ.¢Á¼Æå¨-@Ñ8øf{›!ˆbϽn´2ùT¥Bì ‘(Ö|Çæx2EoÖµ^Õí€Ø};,ëo†—±‰ž6ìÖvÓ4ÏEwyl’gõžM&ò^o¯µ„_Û¸Ï-‰î¯ÿÏXxB~ßo‰ì~—eýÓ÷ë¹ÕDf\ ê_â%šö¡(ŠþíÍe öÿá§.£endstream +xÚå]sãÆíÝ¿Bo¡3'v¿¹LŸ®9§¹Lr¹äÜ6Ó$3¥%Þ™=™TDÚ:ç×Xì’KŠ’ìfúÔуö°_$_0øñ…Õ)“¹Zd¹J5ãz±º»`‹°÷× îa–hCýåúâO_Él‘§¹fqý>ÂeSf-_\¯N¾üúåÛë«/—B³D¥—KmXòòÕß/9çÉË7_^½¢­WoÞÑà««——™J®ÿöã¬p«´…ç“ïÞ~ûúzxâ×ëo.®®{NãÓp&‘Íß.~þ•-Öp¨o.X*s«{˜°”ç¹XÜ](-S­¤ +›‹w?ô£]÷èœt´´©¶"›à ÎÓ\k1’ÎS#…tòÁ£q8'c,¹úTÜm7%¯Ýnªn"›¶ìî·xh@-"ɳl§ÆÂ"âü¶ì>k/—27I[<â K +ú[5w—<Ùµ_®‹»rMeaäøÎr ¨£çìÅå„‘¼®Wé N¯÷üÂ4# X€d*yЖ„6E®fðé4ÓR ø8ñ|[„Õå®ØÐdÕì¶Í®èJj«®ô`ÝmÑ…'JZ+j$b":Wz±ì´ªº+w5b™Nê²Û7»4ÙWÝ-v—Ü&e[î@‚nåµ{¬D­e&yëš®Y5Šäõ[:ÎÛm±*iXÔë0 ÿòS̺¼«ÀŠ]õ{ ö{S—DѾú÷…;Ÿ¦Ù‘õü"„jZ—8 &µêª¦¦Ióžþ úóA3#ŽªÖƒ=Õ¦¸ Û5Ð/lïo6U0•‘y!‡6Uà>ÆÖ%•=j]<5™ +–³/êÕ+ò¤¢´†Ë«MUö0Èþß”JLÇ;^›ÍæÁƒ +ÀíÛ¦íð®x|N]Ã㽺-êéÈ…ì+p=RÙ4Y²-wáqŒJÀ'>·@ºÏgŒH®Ã2\aRlÚ†FA"0¬úÁ ˜EGÜy€Î?ì/"\­ÊÖíÚ~wUªçl+PX6õæ‘´Ž†ÙNM¦ âÞ®šnÖ€zàÍÆÛ#I`lœ½yE·t0Ö´çr°¯×(YÎð"ëîƒd^w° G‘nªöÖ¯ßV-Ú¢Ð^°6ØWÈ .·xÙq Ü2=»÷Ha§¥%äWÐ|ÂS;T(VÙ<ù¾.'È<~Ýø­ÆŸù™Õ‚“e±·Êk¨jÚ ¹Á`ê¸òäõ[ÚqÉû'˜z§”60ÚyXòs¹ç—nTM;7Eë} ,â B± + ¶z[­n=Þ0,y¨-¹ÍOÎGÍÖ!šÚתð.¬+6Çîè¦q}©SP}]UOl üëœeÑ¥Ô£›3¯`œØ MX¾ñÀ«¦þ…1ñážÎ¾¦UgŽðÿ¾ÙíI*kBP„ç»/wUélÓ*t9å¶íôæ¯ÉRiLp yÚ³}èo­„„ÂþbãRiž2™O¬Ä,þæ,å—#NO§ +œŸå6ïq.UFö{ˆ\Øl-–ƒxö rT—†LD¯è•Ž«h@Ñ® üŠH%ä€AjÀ ÷Š=¬tüáEsã4yO²¿ó80Öã ÊÃ}è‚TAU½Úܯ«úƒÇïB¢^xàxä˜ä™6Ç¥Â}œtkˆ“8qéüwIO'I‡‚‚xЙà#lŸÇ:úä.*»TžÊ\C&‘à\¹¡Õò#¶ Þ—ÛÞ—:Û10)R“suÎdMÆø³ü8\8‚Ä%ª˜„1êpE ŸûÍšN@.Ãq@Õ¦½§ô…'E;Öm¡ði‰ä»òI§Òû^4ðUFÛq 1“õ÷'Gªiˆé\°p÷ûý äHËäçäÊu¼ìûn{§=i£2Ý]åÓG`Þ•Cn4”IBrw¨ï~òù¦d3;~r®±; ‚¯/Ò»OÞÍ*ÎWk5¶Ê3­È †ÖÅQ¹@vÞ Á3ÂÖ©Q<î_¤A÷È ;®J`Rëu…—o°ì¯a¨¦çc2ÕO¸S2eØ!:uFÁRfž{¥ âŠøJÑ1Ú[ºHȺ//qu[®*rv,ùî'Z<Ð;.ºÜÞ÷hxª¥•Á¥ÎÔÀÍ­W}ÒŒÞÍæ_ŸŒKÍ—J¶ D)ráð …\¹Š\9ìzWÁJwQÀcªËríÂ>V®Š{d + °®‚ê¯÷ȃrP1¡N^~8¢¸ƒP‰Áp_„5WÔÈdÓ4éP°ˆ•©ÃáÂ# :}]nª‡€Ãómwp^O4.´Å n’\jPG èújIŒÕ1"&ºx1)¶3!ßuUœß \‡,`®ï4¨MSÝé „²sT/Þ–~4ª»¨6ôµb=¦3î;ð_{.? Ý2¦Œ»¼“ŽÛÄŽ5Ýü‹ì‹™»‹M`ÁÂ’ÿܱ¾0ÇN8O3%5ù™7—KÃ3þsFÿÁPGYÿ\'nŽÜ×´/)uh·ºQùH#ì*mý*iG.aq÷å¶Ø¼÷kþ ÝE\šUu1,ôY“ÔQñ.µ€†¬&¾m€CŸ¹ËõÜ téË“µ;Ëéúô]#f‡ëƒ‹þLýv>Ê~û4p©¬!?=q7 +3ƒ¾ý4ÆEýùa[î6—:¸/íôö99»*Þ€góÊù×#·tÒ¾sõu¤CÞC—rò¤?Þ=ò<¹x¤½ú¼ßJÁŽ¼˜•qC7CKú&zÚvùÜy¤ÿ>×cRw‘‡Þ,EˆOÿÜj<3Ë9Íg]aä°‚ÜoŠÕǾuzDîÑÛ¤HÐM}Ή¶ÇZ«AdÌ8¥srík1n¼U»QCÿ¾K £í¥Ë2(ƒy‚¶Ý¶2–2Àöm}‡‚dÂu0н“>ph =”vÚyœyAéF*m_»îöLö“§ÖÈ’èxTùR>Ê0ÛSöP³O²wo?)5€}âá.Õ)®_ÞNne‰=<ï*XÆCUr|åóà!Q6`×ç 3†pª±î£¾‡ îÚ™KÑ~Bt¥v1º„Á…5ϼ~ÔY +åk~ðú1yAä! Qwìeë»7ÊùÅ/µ¾8ö–YEnT~úy å^ +CEÕ0´2ÂE¥ϦD1ÑÎÊNSí¡ÉNÒv+3&û-¤thÊYÈ6ÙÈ[NÚã3õˆÔ©6Lž¯ñefõj.õÌ‚NgÆ5þ1 J“f"³g4AÐ`€:¯ÁST# NÉÎk0&û¿Ôà™~ ÏŒ}Fùü”# ÌÇ-Æ㊧Q÷œ"#¨Š PçyŠj¤È)ÙyEÆdŸ®Èw>B8*+µ<øIYÅPÇeÕC•ÕIªƒ¬ÈÎÊjDöjè)MjÇðÞox8Ž”£igc¡ÜKùдΘ1ãóë!G>*ÿcYÛ“B 7?¿1gtAÐQ€:¯£ST#MÉÎë(&ûÿZ¸Â¯¡Ä™êb¨ Pç5xŠj¤Á)Ùy ÆdÏß2Ð(}’t^‹Z¤áeOÒ¢yvTù/µ¸XJ ˜³<Ÿ\ö²ÿD!SÔïË”ÿNKEݘôµ4þ+®SVŸ…Îb¦ü—|n¸÷Kÿv¯Âp´.ÛÕ®º¡¯3€ÔMó€_A=’¼iº2 *º0 +L…ÿ1NÌÑlyÙó¨G¯‰ÿ<©EFoc§wòæPdNŠ-Z|lîwçAQÙQ†Î_[–S“V «¤]púÒô1'mî>,hðcdÜ=ü2~àиñ¢ ÞÅ_ÁÉ”pã>3sp¿Ð9¦¸¢WÄÒ²Tkk¦oâð4©ßÇ‚?QÀqâw¬3|³þÕ?ü¹ìàØÔoÖŠy HfR+ò,0…g> endobj -864 0 obj << +1378 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 758.4766 539.579 767.4329] +/Rect [417.8476 110.3446 466.5943 122.4042] /Subtype /Link -/A << /S /GoTo /D (subsection.6.2.19) >> +/A << /S /GoTo /D (sample_configuration) >> >> endobj -865 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 746.3946 539.579 755.3509] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.2.20) >> +1376 0 obj << +/D [1374 0 R /XYZ 85.0394 794.5015 null] >> endobj -866 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 734.3125 539.579 743.2688] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.2.21) >> +154 0 obj << +/D [1374 0 R /XYZ 85.0394 769.5949 null] >> endobj -867 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 722.2305 539.579 731.1868] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.2.22) >> +1377 0 obj << +/D [1374 0 R /XYZ 85.0394 749.3028 null] >> endobj -868 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 710.1484 539.579 719.1047] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.2.23) >> +1373 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F39 1151 0 R /F41 1208 0 R /F14 956 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -869 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 698.0664 539.579 707.0227] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.2.24) >> +1381 0 obj << +/Length 735 +/Filter /FlateDecode +>> +stream +xÚÅWMs›0½ó+˜œà Y€a|r§m¦“IcÚKšÅrÊ Gïɯ@ ܤNÓÉL‚–§ÝÕ{om›Hü`Óõ ÀtvÍ83y!Þ}4ð´QBctHÇfxf¸låò!ò}l†‹3Ë´EdÍO¾|m@\dÏm€}Çõ­ýOÓ“pv*ã +:=øncŒ­éñþì µ¥z8œMí±c…ßNgsû<<2faÓiû4ѪÍKãì™ q¨#Aø®y#â ff8.…®C©Š¤ÆÜøÚ$l½­·jÙÁê =ÖÑãУ„ÖôDqj!+Y•Œ¯¢´Ëù Ŀш8“M0¨‚>Äíàã¤"Ct…FN7=»Õ¥ÿe’¯@².ÀE~1ÎÒÉnóuorTU ` ×%5B¨¶Ë0Ö‡%z™ó›ˆ/dÖ|•ÞMt¨ÑH:è2ïO® +Ư/t-lvWo{‡ Ý‚Zr*4ÐÂ'ºzªë"ÊÖ)“ÏQšæ7 äѪX2.c?‹V¹¢€‰%Ö‘ ÛºÑr%¶õÄÓÈYQò$.åêòŠñ»M_qÌ +-k²l úðÌ´“g.û‹F8‹¯x!>÷d[z!¼§Â@ëcýè4Í„Y” ÷B ]­:^#öŠ¤d²Û:Œól¯mGµ©s€ònÝ©¥¥v™¨†ö²Q¿ÈV9¹2ÏÔ$‰ <*“kÖ(–§We£@åÚ§meg@ûšÀ-Vy[ãm™ž­úÏZ-Š4RÜõ]u® /uy抺ԟLQŒú5´ã"=6ôeD·Òü_Æo¤ð¶Áï °Êù^7½M…É»ÍÒî³óêÑéÍÀKˆÅ» À¯d÷ÿ MÞMÝ5šº°ºûj.½¨cç+öÓÎRß'Íí™Ö홌}èø"ɦ©ªsì÷:Wwñ~ë¿ÈUendstream +endobj +1380 0 obj << +/Type /Page +/Contents 1381 0 R +/Resources 1379 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1383 0 R >> endobj -870 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 685.9843 539.579 694.9406] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.2.25) >> +1382 0 obj << +/D [1380 0 R /XYZ 56.6929 794.5015 null] >> endobj -871 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 673.9023 539.579 682.8586] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.2.26) >> +1379 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F22 953 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -872 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 661.8203 539.579 670.7765] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.26.1) >> +1386 0 obj << +/Length 1364 +/Filter /FlateDecode +>> +stream +xÚ¥WÝÓ8ï_ñÔJ$µóÛ§…]¸åqл@È›8mtiRâd—ºÿýf~3öØÜaðãNy,ÈB'ÉB/b¿ÒÀßã±ÿl釆™!3õø”ùïCõ~àeˆô‘zùŦÞæV;å®[w#;yF]¨Õµ;?è@ ν,Š|Ç%‚êÊó¼qù8ÿ{¹$…Jlwµ$ZÔu{ïöhT‰°"SÑ´D·ÔI8RGÆmKM¼ ,û&@›+…,ÅP÷ôñyÝÞ¸•çR)ÛJ²:5&E³?c‘Yì¤ê»*7&s‘oäO˜t' ¾žÔÅIüÇît2:…[à,Þ"¿îÄwÊǵ֜½bmµ¥jqgÈ  l1i¾–x¢ª^rO~Ñ +¼¼Ý>y¤üÉÑ~¿3«·°Ádg ²¬Fžl—d¤l[màâ'ËúQv­ÎÚŽüÿ €Æú{ñ«%Ùx4~‚Rl®¶‡Cë“9Ç>áÙüi+ö·ïò_ò»Hž´˜ÃyOQܘ.n[šƒŸ€¶0ƒE( {°­ï‘¦´(†à‡!7²x6¶¦ýÈÏCu'jÙLúT;±« [Oc +غ–›ÅØ‹cQRtù†p9³e±•cg<îgþω¶’8/À¸ÃC/cߤú|4ºƒ…Ë{¸·XRÖxB[bµ© úü8ž£ AmÚ®G2š¯‡ªÄí[3+û¾jÖô1ìh\-àâ„õ'r“`‚è‡nÁÓ¹4&0+èžÉ$˜€Äɘ8Õ ð®ú½qÓpŸÝ¼¾òˆ¼ém°Rå]u‹6ÍóhÖㆡG,=k.7C'È02‘SaVÞ˺>álDo1!(bú *˜ˆ‚¸%Ö6EU"·-N7F_)€{j+•ªÉë¡ H$¸ZmEWÕ{úTÃnu‡Š’˜JXó5TZ`¼‘&”ECނωC.·Û¡©rI(‘ Æ2Obƒ™vTPGÐÊƃ^O•úp±ê«r¯Ÿ O­'®(e&½úª€=Yæ΄$lg% .À•ñù[}êCgÇÊOÍqc#ïu,@¢]Nµ@I£¨”†íÖÕºŽVÈ M@FodøF-e„0Û²dà÷S¸¹¡k~MFµÄº•4J–CM³”%`{8ŪÜHì +ÑKL æ—Ä£´ïéãÓ© +ñ¦lÌ.Ù´C]çÚ¦§‚7nœ¿\ê}Ÿ¤fß'Ùƒzä’£4>U¹„J9$iè‰}óÆ5 ÃÆž9ò'+eÆF z{ãq’W°»Š8ƒê&' €n¿ëÛu'vre‚íÙD¾-Dv¸ºüò“ôá &^¦¾ýµ°ØKý,B˜yvêùáíú­ëÿ¨6Eendstream +endobj +1385 0 obj << +/Type /Page +/Contents 1386 0 R +/Resources 1384 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1383 0 R >> endobj -873 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 649.8379 539.579 658.6945] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.26.2) >> +1387 0 obj << +/D [1385 0 R /XYZ 85.0394 794.5015 null] >> endobj -874 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 637.7558 539.579 646.6124] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.26.3) >> +158 0 obj << +/D [1385 0 R /XYZ 85.0394 223.4026 null] >> endobj -875 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 625.5741 539.579 634.5304] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.2.26.4) >> +1388 0 obj << +/D [1385 0 R /XYZ 85.0394 185.2496 null] >> endobj -876 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 613.4921 539.579 622.4483] -/Subtype /Link -/A << /S /GoTo /D (section.6.3) >> +1384 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F41 1208 0 R /F21 930 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -877 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 601.41 539.579 610.3663] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.3.1) >> +1391 0 obj << +/Length 2265 +/Filter /FlateDecode +>> +stream +xÚ¥Y[wÛ6~÷¯ÐéK©“%‚—ôôAuœØm“fkí¾4}€$Jb‹CRv¼{ö¿ï  H‰N²»ö˜Ì|s£ø,€>S‹R‘Îâ4d*àj¶./‚ÙÞ½¾àvï6ùÃ]?//~x%ãYÊÒHD³åv@+aA’ðÙró§Ø(ÞòöæõÜ\¤wy½x·¼ú¦*€-´añòsι·x{yõ’^½|{KƒWW‹yzË¿ÿqu;ÿkùËÅÕ²—oxHîÓÅŸ³ \å—‹€É4Q³˜Œ§©˜•¡’L…Rº•ââöâo=ÁÁ[stR'<`BFbB)BL)E¥,’B¥¬ëªkæ<ñêbîË8õîhvŸo² ­¬éIZÃQÞÂ3 ¼­nh¡=ÜeM^7¨Pa”ÆÞrŸ¡v@>ApÉd‚÷1Ü+8¸ÑÛ9”6T,il7Z©v.{ŽwuÓµ§¢Ýçšãùs ›¦‰°dýœ¹b±Ž³®6tDÀ¢0ìÉhœ&W]sN³ë7‹Kÿöz!”}mԆݽMÖ®çÜkòU¶±Võ}fô‚íò[]í2 ±D¨¥‘Å+M®]fâîsXPÒ[:zÓî!>~åt¦ÛÜm!ǽלŠ¼·ug7w{ݹ‘]*õç¼<”=YµCc#µîÚÒЪÓKnò]æpD'Ÿ[œdNTœ å=zÂdltž2ÈV-D„{BJùšžûR¯}ð{CÒ¼XÑŒlì‰ëßo—öÌÀ=¦7dN^“:¯z£H9„tšwnÇû ÅTªJ%„Û[÷ÿu(À3Égþ±»&¿ŸN ½˜¸Ïã˜ñD¦cÔ˜‹´ý¦¸R—^§¿?«[þáS Å‡Í⧟¾„¼d€¼5?¡W%˜8ÖbÿOJFâëª>××1C<©±©ÔwTTL¤aSÄ]tñ?æ!ã±L2•øÞx®çåñXÓôh#Cæا@Þ5Õ ¬bÜÂÈýÖMD€}Öc0ïÊ{S·–éâöòæÆ66m-ã>:Âä^ùf*ºýP&ãó˜ÄtÛJ‚ ¼îœ\ÇżÜ3œ_tù]1º[âYúä'¸^‘z+˜Y\ƒvÑïšÖî^‘‚iÔj¨­G"%CÓLÜrd¨) –…-aú’ð˜un¸(Úň¹¹t{«ú¡¢aïV0&.00\àÙÌï`׺=Å•Ãn?Už'‚É(u%`Y$&° +Nƽ“š2:Š`ļÐvmÔ#jz #l˜8$R$—!K IœägÝéÉÖ 8o œ'^Öw}ôé]~ØÜ‚ÅœµŒœðü¹/ß@—Ï74KJSID@Mã±68„5b ‹íº¾ËhÍ`žÐÐ3z¹ Ñ¡‡$Æ2MW-ö™´Rf€á*oK{`_ŠãJkˆcLµ<îESPhÚ}Q¿oÀlϯ–ïæ\¤ž­„ÚÖÕD]VdwûºÊì<ëÖßjimsSA3VNX'kîÉ7OšK×Ê}?Wʳï¯>çmgbÜW£ëM©wØÅž·A2a‘ “¯÷SA”ª/6Tà¾RÅr@ÉSô"¦¢¾‹ÓÃóØ£´¤ŒÓ&è¤^É]°é«‡å¬ïs‰Ô܇ýûvêS‚â,”S¶W¶®«í„ìdì(rº e²À¡yLÒ»vh¡¸Jû¯çÕ¬Yù—¡CÐŒºØÕMÞí˳êùǧb1z6îýî©¢â;:êŸ0¤uÿþqUëX“„'¡?´6‘¹!ä";|À©m»|)¸w›Sº†e[÷z†Tâ ߃û„£­¥k æÇ…š&e BÀÁ¹±$Túq«o€ßogyìǸòªºòêƒäQßÊéÕïЛaÁÔÂÁêÚ`åØ ä÷ö#kñK¦KÄ%šŽªCÚàÊhâiHN±W@íÅ¡§½zœÐÎ º¾¨•²8î=‰’»ïÇ9Þ%ê­ Ù³Î+²¬«:Tä>zØä¢âÞÆ»*ÿ§ ô¢´ ô +„®ìNgx8»u+–ª‹8¶3й=¨©¶Õ;w"ßU„¨Ø~ŠŽRâ×êçSîˆ(•AHÅ +€u¾}¤1¡È@w6#aþ‚âçfû¥M´d ‰¯ë5¼=˜˱AãgDdè<¤Õª=¥b¯‰ãÕ™ˆøIitAÞ5¼={êc¼T ¿ O|:ú€÷¨?þ2ÆL&‰˜þÍrˆ=— +/ ‚3ÉÝýsÑÿdiÙendstream +endobj +1390 0 obj << +/Type /Page +/Contents 1391 0 R +/Resources 1389 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1383 0 R >> endobj -878 0 obj << +1392 0 obj << +/D [1390 0 R /XYZ 56.6929 794.5015 null] +>> endobj +162 0 obj << +/D [1390 0 R /XYZ 56.6929 726.8027 null] +>> endobj +1393 0 obj << +/D [1390 0 R /XYZ 56.6929 697.6944 null] +>> endobj +166 0 obj << +/D [1390 0 R /XYZ 56.6929 648.8841 null] +>> endobj +1394 0 obj << +/D [1390 0 R /XYZ 56.6929 624.769 null] +>> endobj +170 0 obj << +/D [1390 0 R /XYZ 56.6929 472.4047 null] +>> endobj +1395 0 obj << +/D [1390 0 R /XYZ 56.6929 448.2896 null] +>> endobj +174 0 obj << +/D [1390 0 R /XYZ 56.6929 356.0575 null] +>> endobj +1396 0 obj << +/D [1390 0 R /XYZ 56.6929 324.2991 null] +>> endobj +178 0 obj << +/D [1390 0 R /XYZ 56.6929 275.4888 null] +>> endobj +1397 0 obj << +/D [1390 0 R /XYZ 56.6929 246.3805 null] +>> endobj +1389 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F41 1208 0 R /F39 1151 0 R /F48 1228 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1400 0 obj << +/Length 2935 +/Filter /FlateDecode +>> +stream +xÚ¥Z[sÛÆ~ׯà[©ÙnÍ“l˱’ÚI%º34‰ˆI@!@Ëj§ÿ½ç¶à‚„¬Étø°÷³g¿sö\Ô3?=ËâHÙÜÍÒÜE±Òñlµ=S³{ûáLËœ…Ÿ´g½^ž}÷Φ³<Ê“Ì–w­,RY¦gËò×ù›÷¿,/¯Ï&Vs/âDÍ/Þþã\k=¿øøæò-½ýxÕw—ç©›/?]_bÊaž‹Y¹üéòŸç¿-<»\ü…gÐÊ"sœýú›š•p”ÏTdó,ž=BCE:ÏÍl{æbÅÎZß³9»9ûû@0¥¥S˜Ä6‹â̤ =Ó:ÊãØŒP‰ó(±Æ*°"rç ­”š_5]¿Û¯úº¹gúuÅ•›j÷¥ÚIgË姮:šõSõ„ˆÀ¾&†šÁ`ät–Ò†7u³‚ùVeóÏÕSǵbw®³9uçón-Í’o«þ±ªnô-WÖm×Ëê¶Ù<‘_AÛXf:aëÛ}×3ý[íÛìð¸öäŸa©o=+\=pY<_Âfph<æ€5ó®ÝlÚÇɺã²(K蔀†»–ˆ;Š5¹ï¶%¯ K>“–Bßc»ß”~G++ðäU9‰ŒŽÒ\§§>ƒT{òLêwèŒ/ïŠíƒwÞí÷Ûg˜Ï¤éHßB©‡·™rz +u?ðÉÉ“L†‡ÚÙÈ(ÃÃѾaÄG8|3ô{.ºc¢xzá¡^>A_¯¸Á»{Ê=˜oj$¼› +ºOlècÑzÐÛ§Q”5—r ‰°ŒqSö G{0\­´!Ƭ3ö’Ü2\äÄ%cm¹©ªã¼Y+Ì•‹áJÛH¥Î`˃»ûW®ƒ”w˜¿pÊrvJ—X‰ãÈ À¬¹–’,Ê3ðBá'¹÷0ë%FR¹1‚Î7”PYw«}× ¼µÇr߶>)•ðØV_k —OE¨c°ÕÆx[Íê¶xh7õj*IOÐäZ!‡0iÚ‰ZÈ¥RK·éȉ&âD/w»v×½ìÙ éTâ®+çÌÐGÇ׉7ŠÐ3h7Ôƒ°Z«¢áÉâJ!½ârŠ¸´‚L°Øp£Úñv;´Ú&Ï0 âÙ}„ZÇ»H|=tu+›¶YL¥Br¦ûqxYÀ¦¤¨©£ ÛäDúßý|ýáòúš‚²l)µ€öÀ¿rÐ%á¹ã¥¤hûEhwüö‚£¬SŽˆp•=ø+È(9"‘uÏb“Y?)ÛTÆ›AÏ}Y„¬‰ ›$ å.À8:FÆ­:0{Æã€ñ!7ÈC I +¨zÝ“ 5aÔퟖˆXëi5eÀ¡8â‰sNä2c.WyÎÄÜÄ|”Î&>]XCÙ%¬-Ö¤¡¶àÀð u¼Âà#Xh,­†±Žæ5\î›ÏMûØð*ŸRáš“lûÃÄŽ—±–ÁÊ’m&ã<ÎZ-$¡"dz*ˆ°Pkn®Ú²âi]Õ ‰–Ë×oñù•S@ê!¡,x…ßB„æ€ Ô´ŠWëAhP<§E¿?¼&ò`U*O*ØG +»¾›m1½U*ÿVy‚3,œU*ÏŽÉgêÆhC!"dž®Y•Ž…AAV¥„섹"œ]Œ8ň±K$çcU¬…»ÃÅÄúćÕˆ¡!'q1Âê­ µû¾«K߸ã’Ï‹Ó1¼¢CÂ"J–Ö$ÿ¶™@Öʃ¬ùËbí!°Æ[êA³TB ý!ÄЈµW^Í&Kuyõáò·È²ŽvÃC teO¸yF'ŽÄ±>àZþFs zミ£Ñ¬Œ1ÀvžPñ´(íº»ý†Ì'ÐJ®I©xLYÂ@P!N;VºÑ¢OÕa{<½Jxn¬ 5D¿wÄnÌЊã ^Ö æÐüy‰ööâÓò½—bÅ~ íô8júzW±DjA¨ƒ/„‰‘p%«DBàø¯?GQ†7y¤ã„ç³ÌQ»<|ßÆÀ ø¬ÖESw[îåúá`˜…c÷US¡›¤€ §ˆG¾Ÿ`÷á¹Öò=é{ +öÒ÷rÜò0F ;Ráû“Œ43€-Ȩ£ìæäÃÇ€q–ï"¥´O2žÁ +Ò*­†'Qg Höî‰kÌŸ­òZ–ç’ìäò¥`E˜ C;^PttÝÏ5-[k`N.0§Å`¸ã%’—!‘¦ +7[døÙ/ÏŽl©\˜G¨Ð½7Þf«ù[Hï4?ÝW‹÷Õf³¥ëèSª¯¨÷•g±¥§Q:xçÙ: ú}‚XÒäfàªâ‹ì]pÇ4 8A„òípc´Œ®W±é×íþ¹³h„k¶ãÆÔ”|+íß8L|[7°?ÒÂ2 +ò-?ÎCño _iòvËõT‚du¹|Hyž¿ª1¾ð¤ Ká$î´ô‘…»‚H½R”hcð|æB±­=„” Wào8¦Í9}‚Aìie:l5œÑJ"eò£Ðú™›g 1O•Ñ/žÝ©tôÎç'ù‘‘ÉŽŒLîo*ÔØ»ù¤eø{”Ljeñðflðe]åÉø +Ÿˆ_–œœž/Ëâ÷âñÌCysI/6ÝÑW‰}wüɶ¬6Uï?J„@>Žù콟㿇­ ™+Šü¥n÷ì UôÜ¿ ,$ÐÖN½G¨!Mÿ¿ÿypø«…K#›eÏ> endobj +1404 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 589.328 539.579 598.2842] +/Rect [101.3082 379.428 169.9802 391.3282] /Subtype /Link -/A << /S /GoTo /D (subsubsection.6.3.1.1) >> +/A << /S /GoTo /D (dynamic_update_policies) >> +>> endobj +1401 0 obj << +/D [1399 0 R /XYZ 85.0394 794.5015 null] +>> endobj +182 0 obj << +/D [1399 0 R /XYZ 85.0394 769.5949 null] +>> endobj +1402 0 obj << +/D [1399 0 R /XYZ 85.0394 749.2913 null] +>> endobj +186 0 obj << +/D [1399 0 R /XYZ 85.0394 546.785 null] +>> endobj +1403 0 obj << +/D [1399 0 R /XYZ 85.0394 519.0032 null] +>> endobj +190 0 obj << +/D [1399 0 R /XYZ 85.0394 364.477 null] +>> endobj +1405 0 obj << +/D [1399 0 R /XYZ 85.0394 339.5007 null] +>> endobj +194 0 obj << +/D [1399 0 R /XYZ 85.0394 175.6792 null] +>> endobj +1406 0 obj << +/D [1399 0 R /XYZ 85.0394 143.0963 null] +>> endobj +1398 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R /F39 1151 0 R /F14 956 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1409 0 obj << +/Length 3227 +/Filter /FlateDecode +>> +stream +xÚ¥]sܶñ]¿Bo¡&>ŒŸ[NœLÝÔRÛi>x$¤ã„GÒGžeå×w»À‘'ÚéLG3°Xû…ý/¹ð—\ê,Î +Y\æEk‘èËj!.`îû‹„q6i3Çúîîâ›7*¿,â"“ÙåÝýl/ c’Ë»ú×(óø +vÑíÛïZø—\m¤ÈU½úáúç»›÷0ÔP ñúõ¿®’$‰®ß½ºyMS¯ßÝRçÍÍõUžFwÿ|s{õûÝ7wÎ9/‰PH䇋_—5°ôã…ˆUaôå# Dœ…¼Ü_¤ZÅ:UÊCÚ‹Û‹„ g³néªlK•ÉáH¹&]Ä™’Ê çng‘ @Mf¨vÔ:‡ýÎO7ÿa¤ù~JĹЊ‘†ÃUb¢¾²ãxµQºˆßvÍÔ”“­i¸}‚D\Ò°jÛMÔïÔŽöðÑ–製J¢®nº‡Åò±yè`çò,.„ÈþRFúp´‡'ÚͤéªöÈ'¨ìžp‡K˜Xgùå&IâBkéÖ– `8 ³°$É#8t$[ÃÑÔS[RãH*d´)K·”1÷`bhŒ`„¨¢ùŒëÓŠqè;Ëh_T¥QsO³ÍÄ-H¬rFÞàX¡~ù±i[‚W}7•MçÉ{.M±dö3Ò”˜0Ø!I“(¬z×ÖxÝ ÈÐur'L‚œË gÿ°O#0/‹,º¾ŸeDvhRسŸª]Ù= ×2É¢m?íháP¦¦j†²›uW~äMm×vmºûþ°/§ÄçtêIg6Éq ÂdQDµöMgi8í¸3îXq5mEãé%ˆRª¦ýTVu÷„vlWóèÖ¸•+FmŠØ€ø+›N„öHû¾¶ ÊTçÑ¿w¶£SŽ£³ê3&z ¶„ý&„´6ôv-„^*ÿÛ¶û²[!/•q’eÅ_’g´Q3ò@‹©È–øC6 +îšöttº(öVPóθpÂñ„ès¹qP!6¼mmÍGË«Ç ³*'‡\ÅBj¹ÃÜÔâ Œ$U +vDw’§Eá£ÐÕ&â, +=pÖ˜ç áwoß½F‚²¨ Æ\¶­#ïô`èÓHT·7¯wð2ÊncDËwô åtdB°’·[5N!5M4¼èý>@j¥y I?ws(¶3Ÿ! •€!fyñŒ*IG«h8nÛ¦ú¼ÁGr£óúWäB¡- ãnr¾ {¸OåƒùˆëŠL¡w£KײÚÑeRw°ôÄŸbþ”¿~ç<ŒåÞR¶Ù9¿}”¶wÀõà—ÔEFšÖ>XFªÐ¨±³å@!.8â ç-kÛ5¶-Ç0ÍkéÒÒAÔ進8lâ,ÏÅ|ç•Æ¨#Á韥@0Á!ÔͲiÂy[²#·xEÐã*ãâ ¢PA¤¾CƒD˜c ª‚í¸íî©%âUÊÄÏú£ë=µSš3`“ßeûtÚe¡!º-"_ž‰ÉNì3É(³~bN“Ýëòp¡)"xt9 ;@IÃNu ÌáY˜‹KçGæ3§<ç´8±ÆEIAç`“ôº#èü%·¼ß}߶ý#:†M +!šs +9ÅZ˜oàwu¾€ˆZb¹óŒA.ÁÑ9'úè‚â6GlxÉ,föñùrûih¡0¡­²°Õ¾Ÿ#Az^6LØÖŸXU9N k v§¿bÄVgÖYqJ¹ÓEN›Æ2-|M³Ù­\'p<ºH}FÛlŒ™ÆàO…HFñšû£ ?ÐkÔ’ÌRrˆ^ ŒC­YŒÒ:z×»8“iïx3>³“e9 é»$™ÇÆ‹O‹03±¼ÞâÖŽt÷¡¦5©:KõqKCf$Y•Òp‚ €ÇþðÈ­ùÈjê] 󮢟/x†cÎ’LÀÙ>=Wˆ4:Öiáë›M½¦ËÄÈ…FÐÒÒœÓT8…ívNœ·j$Š"ÕABÄy–ŸUü«a2–ñ§3PÇ–‡¶ ¹bÐʇfî*in€ªr(9–+ÿ Ó·”iÂ4°¸â\}B˹ÐÄI$;%ÞúDø8ËðjÚÃ<]˜ÈÀØ®²Ëb¢ÜÎœl–kW ²¦43Æç·ëÎ.MµùÜ˦Ï(«-Ô?ÁÆ€Ò¼bìß]T\$i¶0á7Îm¤2ê]X„nÂ)üHpç—° ²D!ÁŸ‡€øPKô‰¦9N´müI2ÚBRf©‹FvCµ6Œ¡’DGõp<½*À6#‘žÅy_kúÿ3è2o^QAbk8^o e‰WnûÁD¼Ù„Ùæ¼n Ù\SØYíiuÉ0dåºÈrŸ>Ç 'ÐßSúj˜Ÿ°D_O§³òAù…Ç椈¨ÙÙ¤ên„›½Æ¡ÄXÙ2M‹dùê ú~yeŽ¡hö¯XN%:Û ËKò…¢»‘b‘°á˜å-…w1RœÞNqæJ¯__Ï® " fÏf©ÇÕª¤$•z¥yK€îò"ºÅIä©šæ'¼X3J÷„‘@ºgÝÞI ´:L]¢=u ‡Dv¯¹É2ÃÅ1_}§ +Þƒv‹è—•ýXªÐãgÛ9üø½.ôV©\çæòK¡7= Ü£áÌ(3"”S¿üýÝÍúƒ·’…w†/h; +ü&„!èmù¤ãÈñÂøÀbÔYA‰ñN@ÞÊ+9ô»ßÛ®¶|'…ÐcåÿVF‡1¨$3/L,•Ñg ðYk ‚jzˆ«»= ¡ôr/„thB"øoR¦{൤LAî¦AÛì‡Ö¡âhëQ°âµÔ{s÷æ%ugÙMë1=¿W¸Þê«œ¿òïo¯o¸N¾øøA…Pp[(Ш^†–®¢¤&Ï ÔÓÓâ¬3'}?÷äÏã«Ψ|^êò¢Ø~*Q\+ÖeÜA_W Š¿åMÍ k£ øO‘ëÃK/ºÉÀÏlJj鸥˜cc;‹w½™ñº“Ÿ‹úªQb€Vä)Ópt1V„rÃMð·'è¹ÚB…ï"õ±²õ·+ÂK2PŠ±8~Z’õµúëDªTǨ•¼%Ïâ\ /{TúJ$ ØË>w„ÿú—ƒÏ>œN÷×+ z +/\øŽó8«úÁjÜ(,ÿñÃ=½•8 «þXÒЙv¦òsð \}6 óiÁ@È»Ÿ¾û¥ü%Èã;VÅ —A.T¥föµ4ó$N井¯™QqfÂWCdµ|ሰrÃÓLYVêõ ‚$  ƒ6þ·×š÷ÑÏæÐþyÒNUe~æfC‚™Šd¹Õt0øè?ü¶ÏŸ,|(þ̯;”Žñ'+¿Å!}þ¿ùqúÉKšÇʹþ£™›85° å>µÉg”ûŸˆ<'ý¿w€=endstream +endobj +1408 0 obj << +/Type /Page +/Contents 1409 0 R +/Resources 1407 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1383 0 R +>> endobj +1410 0 obj << +/D [1408 0 R /XYZ 56.6929 794.5015 null] +>> endobj +198 0 obj << +/D [1408 0 R /XYZ 56.6929 678.9507 null] +>> endobj +1411 0 obj << +/D [1408 0 R /XYZ 56.6929 644.5195 null] +>> endobj +202 0 obj << +/D [1408 0 R /XYZ 56.6929 514.5361 null] +>> endobj +1412 0 obj << +/D [1408 0 R /XYZ 56.6929 481.3387 null] >> endobj -879 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 577.2459 539.579 586.2022] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.3.1.2) >> +206 0 obj << +/D [1408 0 R /XYZ 56.6929 279.5586 null] >> endobj -880 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 565.1639 539.579 574.1201] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.3.2) >> +1413 0 obj << +/D [1408 0 R /XYZ 56.6929 251.1623 null] >> endobj -881 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 553.0818 539.579 562.0381] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.3.3) >> +1407 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F39 1151 0 R /F41 1208 0 R /F48 1228 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -882 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 540.9998 539.579 550.1055] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.3.4) >> +1416 0 obj << +/Length 3255 +/Filter /FlateDecode +>> +stream +xÚ¥]sã¶ñݿ“éLèö„¿Ð·;Ÿ“^Ò^[ÛI“&} DJâ„"’²ãôÏw»€H‰ö9ÓÑÁ°Xì÷.¥.%üÔe ©Mt™šHÄRÅ—«Ý…¼ÜÀÜWŠ×,Ü¢ÅxÕ»û‹/¾Ôé¥& “ËûõW&d–©ËûâÇàú/oÿqs{µcDâj'2xûþ»+¥TðöãõÍ{šzÿñŽ_Þ¼½J£àþÛÛ€(Çöe¼–ÝÝ\_ýçþë‹›{OáøJj$ï—‹ÿ#/ ¸Ì×Rh“Å—ð"…2&¼Ü]D±q¤µƒÔwÿôG³vëWb‰8 Ó¶„á[b#jË–û+-Ü8Í‚MÙ”]>”øf‚¼i‡mÙÑÔÏåA«aK ˜$PŸïJí»+•í¾ì†ªìiö'ËåáJÃ)‚œEµÆ]ëÒn.›áäÄ!ßõÞ²8 Eû2gtL`[¶LЪÝ-P2Àž…R$Ú»îò¦~"~KÒ{@`à—ñKé$ƒÅ¸¦hú¾\-€¬u×îê|YÖ¼gÌc“ +)·‡ù±éòR–UOÏC_4ZznÊ9=øúi°Ï«ŽFk¶›¬[uO{‡c›ÛÅ#=K^ØðQËCU»S·åñdð):ÍÇ1bÌOR†uÙƒÎk%ƒCO¦qèóMIÊA}µ«ê¼£ h†Àñ4Öá?Aíf8™$@h<­L%èp +¤ž‹o¡3ì˺ZÑ÷8RA¿mxq„.yeÕô ¤eáÞ…¸vp¨~kxû“Û°ªEÕlŽ»ì ¢ñ…ÁÄ„–±vW`^ŸÜ3LEb€ïrÌp:åÐã 県p˜Þò‡¯ÿúíû›Ü‹HJaR™Mí ÀÈw`i½ðØýüCÇ°M‘‡@Ÿ‚”RwÕ¦±·¶RÞ²üyu~:à c¡•Ñ/™JR3UŠŽùmiš‚ÜgÍk¤Œl^¤‰¬ž›†F9==+•I„Ž„‰N½mžfD†PB§”¨b`¶çD‚CÎbcÎd*ø¦ŽŒ³ß·MQ_´J3Vá 88ûÕÀóþ°Dby¿WfÉÊ °=c‰‚¥F‰b‹€)VcI@oŽÐǪ®iÄ.ȘÓàEê…ÑÔ)|äÀwªÈZŒyté73è@2í|#bÑs¼ Eš)^„¾ëè Ä0‡èööîÃWÏ!’ΰˆEÀ}ë!QOŒ Ö-:,Ãfä×bM΋KdŽ2CL$…4¡skïïfHQ`CQêæSÁñ«-yf& '(ÄÅóã0«ÈqùóÅæó9Q$"“:âE_¤ß—« +•±,PMt|˜;a¡Y +Žzâ4ž?*’j|dlvÇ#ßx§Á†øžó¬Û[0"ÞH¬û–±5à»cU|dXžü’×çEᦠüòº~²Û>“?NLÔÔuûH^^!­ØÙ`Š/hN= )f˜Ô)r6ïûÃÎï¬~ö´°jè=§‡0xPX³Ñ$‚­>[ÿe™!Ê_óݾžs–J¦"6É1ˆ.Ò( ÞqÈ´Âà ¦Ö]”ëüP,®Üê~ìâ!Ž(°âèq[­¶4ÜæŽáÎÏ>ä,kï»êRKBÁ‹Æ¢=÷Ú£„”}x>°6¸ÐeÓˆ3äi4w&ƒEKÏ)ï,èU-H¡Rª¶±>iŒ¬¨N6¢¿mXïݹÞrà k9V™…ŠñUÎFEì¹p&?_8ÁiÌ丱ªÀ Û®§Y*ápv>ñ µQ”9%Rù››ú~G8 Ô§I±D3Þª£ÃN&—OµRBÀ‹âCpŒ­€x>ÀúÒœÄIðÓffªÎ‡õl>vìáömÕ S¯öŒö¾œkÎÀ¯ÛUbsè|~Wve׿”GÓZ?Ô@¢õÍ3Å…©ñ ˜5ð¹äJ‹Pù:w`¤#A!ÂàÞµº +ü¸ÕsXGëCîµø¿ÊÞf»´“N;“Ê[x]ÕV2of®¢U"Œ¢iq1¹ù¤ZÒ™:‰ôÔzv‡~˜ædœ#‰>ù•˜\ï¸ñçàêÑ Daµo®+á[3/‰+q™Wˆ+U¡‹ >äuUp¿øÚô¨FöeÜk"\#HÑVÙÞ»/s5™J“Wò*ýÌøÕäé0f=Œ–¥;~ ’\‹aÿM ˜´»&HeΤÂè0—)»b%d&'ÆÞGùͨW,’$>)]™§x…ó³3(I” '7eyYËf®š¡ëŒ_¼jn8ôe8»s4pÝ,ñá:oV[£°çEaÖº3„ñ´¼‰ƒ)À¹îØ’!¹]o+NÐMuXºÐ‘¦"Šˆf¹¨L'¯0„ìÈ ¤Á¶},Á¾±ñm!‰cœ”3 u™÷|8Ý ©8² W:6Áê‡.yíʇ0ëÆ ‚rR;ò9[“$t¡SÔ¡¬e±°µÈùÕb#²Ø×ÛNñ§bžS%§ O(ðòÍóˆ“L$‘Ï"| ³0ÌZçz˜Eø&2åËÏäÄ@5XôH 6Eì¹€àuGÆcç8Q…*¼Ô®0#)b\2†jZœ8F ìÜSbòûE¢Žk¦ÔT+_£Q³y¹[2 tŸ’&ŠÞ{uüÒ«vo?4(ö¶&¥›4¾½íi`WqÓa6׳£ N*Cq-ÆIÞ¼s[x*p×´®®šŸ Œ…ýdµç7]¾‡Z™ìÜ]g¢w«mŽ{±íƒ÷°=)6)Û«ÑÁ[êB)Wè®zÛ¶͢fÎõB2—eÙ«FëÄŒ²qŠFÍäàlyI¹3¾Ó2x)Êrçh³ù<Ë_+äp­CÝ65·#B 9e$Ü>uò—¶ *× X>ÛEpiNq’Œ9EñM(7ŸûÑlŸÂåFs +>é|Ê™ ½Ÿjµ†œÏIÞºFxçOF»Ž ';0ÞíÀ#¬¨–¤MûF‡=£m ¥|y¨rÜ~yMƒX*5%‚ nEtŸ|Yƒ*¼fU¾Ä•WÛ» ýß>ýl ãÔù„O{mŸ;JÈûUW-nTܼڵÓEC^±šÕÀ¼nºxðù~Ñ®;Û…§ˆ%"îuâÛ¦®~ædö݇øѼtÆù´ƒèÀÐDÑ–œ‘“k„çjýÄéð¤%F0Jž!L·yÁh{Nø¹‰“lA˜é·œÙƒˆ+ˆiÕ¯rV˜-Z!3ŸVŸoÀŽZÀ§ls-]Ÿ¸˜æû>Ó¯µôafM“QU˜à÷ÓžFPCB¡Qõ[ê9keÛ*!8å+<íÑFè}¼ýœ²sQݶ?Ó¨ow%ܺ@œ a†ÜF´¾k,æõ J'Á›^8  +=º§u|ü¤ 3ìt¹§v½g¸”Óþ=!ãö"È‘ÞæK<‹Ã—xöôÃÐS_hŒ•HÙäMõóÅN·ô\–s7ôîSmìÃÄ»êDºvZl\Û8Ájô:笉oùìP ³2ñ +dlVÕïóU9†ãÂ3ê +¢èêuÏ$º¾Zrôô“‹‘ÛÚ–GÁbB„½žþ0séÄaeø¨(üTŽ=þ(W>€²Úí”hKæ½ý·VvU_º… /Ú21NÅÝP¶fèi²‘æŶ‹U O~šœXŠ0;탆þ[Œ˜É±•%…ŠŽÁ8zjÛtÿ¯=&JEÊ“¨ò…ÂFXŠiºH#M¬?Ú '›ÑÄ­-ºí7üdžض³ôÌvÆ;‚á{¨©<- >Ÿ⪩†*¯öÂ8¥ž<>{÷ñ‡è±û×ßTs½þúO×ß²ûîû§vírHû››õ7zUß.¿Êïïžû‘Žþ÷gæO?Ò· ÿï¿ÿUBÐYÎÿ{Hc54©# +™êSÊý‘ÎIÿݳÊZendstream +endobj +1415 0 obj << +/Type /Page +/Contents 1416 0 R +/Resources 1414 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1383 0 R >> endobj -883 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 528.9177 539.579 538.0235] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.3.5) >> +1417 0 obj << +/D [1415 0 R /XYZ 85.0394 794.5015 null] >> endobj -884 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 516.8357 539.579 525.9414] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.3.5.1) >> +210 0 obj << +/D [1415 0 R /XYZ 85.0394 671.4386 null] >> endobj -885 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 504.7536 539.579 513.8594] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.3.5.2) >> +1418 0 obj << +/D [1415 0 R /XYZ 85.0394 641.1061 null] >> endobj -886 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 492.6716 539.579 501.6279] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.3.5.3) >> +214 0 obj << +/D [1415 0 R /XYZ 85.0394 444.8166 null] >> endobj -887 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 480.5895 539.579 489.5458] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.3.5.4) >> +1419 0 obj << +/D [1415 0 R /XYZ 85.0394 417.1342 null] >> endobj -888 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 468.5075 539.579 477.4638] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.3.6) >> +1414 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F41 1208 0 R /F48 1228 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -889 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 456.4254 539.579 465.3817] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.3.7) >> +1422 0 obj << +/Length 1913 +/Filter /FlateDecode +>> +stream +xÚ­W[“ªH~ï_aÌËê:B](.qbPlñ. +^˜AQQؘÿ>¥h»³—8Ñ•·/³2³²` Ð?X"<ÃKH* ÇIiµ{%—ÒZoðÁS{2Õ^¹êúûŽ…’ÄH<âKúúE—ÈQ„%Ýþ­Ì1"S¡@YL&ÍF¥%Bp¹¡Ê#½9®Ô”)g‘•iBX–¦’“¨T¾xoÊ+ëƸ9©ü®wÞšúÂW/ À7x‡·ß~%›:Óy –DRºÐÀ@IB¥ÝG0C8ŒŸ;ÁÛäMûPøB½‹Fa„…ƒ/aAT—D0* DbxŒð=.kÜÚ^;³È<óma”uÎlSr¯œÑ€YKVƒy×nrÙ¢½{7o©É„TAwq«Þ “UÒÎô¶¶±·áô±ªloŽØÛõƒ0[à,Eó´HœÛ³¡¬è£l’HŽµÛˆS(ŽÔÖ¦Þ³¦§E²eƒ˜ò~³p?‹ç‡ê­«üºÄ»ÞÖ¶²J Ü×аʱå«×-Á³KGQÓ}âÏôùlâóó]Ôé-[ÒduX ºÊ!HæcÜgØŽ—[§HÜ…íQgâÛ».6ÓFxÜ|Ò]n–#“îy¥ºáÅ gÝ?Š<ày·ÙÚ¦Ú÷eåµ1u„³$Í2½Gãv®Šw]hïZ‘uI˜T{]Cßk«Æ‚¬cvJ¼±v¬ÚƒÃe•q›ÅÁTкPÜv¯Ë•¢74ÆuÛ÷´×dóþåÛŸ‰À ž¦ò'Ô|{jC4§ àø|<9vmë¤Çü,þugãFD@ø¬‚½“# O)ŒÀar'üýNx¢|!t4׺Žâ|Ÿ‹ØµB?³N~þíøÁu±b;ÿÈ¢0?=„¥[eâ“,/û9Æâ1 >ÇιZ»}à0«hÇäFòÎHþó‹|iʲuõWctêR›r3ǬóQS™Wc õùÜe iõòâ—ôì.=}Ï iÉãÝÈkš¦ƒ’¿v›çƒ˜lV”V-Ó°›­Á,­vÌì|±?]ÜMëâHˆ¨. «±Ó5–Ë¡¾ê‹ûË<Ø€¦?Ç‘ò>ÝmÔ!Çqn¯Hj[]cÍî‚š¬/ •­;µÂFûa·³‡Ã"„.—^²¡4sƒþVØ,×3Œ]£›ø±®Æˆ´z¤Ȗ®Y}IŒãõ$n˜ê†z„'ܹ4Äëš|ãP$õ~ÝÉSs„€ïêþÕYØ[Åîœíö›-›]úç¤á;wè4Rûì;êy{^`•›÷åÕ¸zõ-¶Q²+²ÅFél,Ög¬7³³aNº¨k|õ£,OlT$‡º$üã£î>’!¯0üÿ/šØIœøè|/&WBÃAþ/‰ÁH ŸBÌíNCL{P“e<’™ASÿOµ¢ à w Ù¶;4öõQ/#7»¬rh"a0 ðó9]‡öÀºö ¨ÌPÓ4y:«~Q {^K­=V£™Ö3ÚY7îLMœ¹…½=ųË@ç·fįÀé˜-ËS²òv… ­5ÄFÖ6}vyŸï·XÇZ· \¤ùè[C{Òa›¯»£ã¥º0í,Xô­"æv§µæúœFݶ—Ùfª¡åB‹7i ëÕAЬax짋®ª.œq2ºn +5kó}p‡Ö¡š¤ølV…×Âh,:ž7Úëp[·Úq¯½Q %s½†ÂŽÃÞ¼ª`=Aí,ÔŽ'› +)ì Dš&›ÉèhvTGiél'#Ó9šEÌJ{œxŠBФ›,=ÇÑ;ÆŽozÛÂ>˜ž4H¼6ÞŠÖo‹þòYbc"ò¥ß~½Úò‹ö·«åßÝj¹4Ã0…÷lx<:«šZËàQp©süV„øÁšXoßï³/ìµB»9ê¢Qò½¼8þ¿šE!b$‰pų(*P¥@­+—T×cù”ø¬êû$/ + 8îcbE裋ё•G” +iÇ!€D.÷upsõÎ)1„§#.e¤#0l)ð;ÇÆ –uú•›_Cu T„b ¹3¥mj€“$œ3½¬ï®~Á}ƒmïPI‰¨C¥ŸžŠk¯šïNñèe §ÊEíC‘†FÌG§Ám>©!A*GëÛ¯X>ym²sûw›ªn¤À¿Y9ÕŸìþ1ßq*”óÙ$'YñCSRA¤|Ë+Úƒ1GÊí0ßß[ôFà@ùä¯Î]ÓGί_@ÄQtÊ·^à<NTà=àts…ÿ¹ç;ѱog…Ñ㬨t¾}Œz½ç;?^iguzZJŸ‹ã…N¹…unv÷W=Ó ã¢Ç(ø¨ÞŸ~ú~=íxXQqèiê1œH•<@ÝîäÏ7òÐÿ¤—/dendstream +endobj +1421 0 obj << +/Type /Page +/Contents 1422 0 R +/Resources 1420 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1424 0 R >> endobj -890 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 444.3434 539.579 453.2997] -/Subtype /Link -/A << /S /GoTo /D (section.6.4) >> +1423 0 obj << +/D [1421 0 R /XYZ 56.6929 794.5015 null] >> endobj -891 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 432.2613 539.579 441.3671] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.4.0.1) >> +1420 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F22 953 0 R /F62 1352 0 R >> +/XObject << /Im2 1341 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -892 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 420.1793 539.579 429.285] -/Subtype /Link -/A << /S /GoTo /D (subsection.6.4.1) >> +1427 0 obj << +/Length 2465 +/Filter /FlateDecode +>> +stream +xÚ¥kÛ6òûþ +¡Àò¡VDQÔ£p7›t›ë¦Íº=¤M?heÚÖU–\KÞ­s¸ÿÞÎP¢¥w@°Àj8g†ó"-¼þ„—© ”yì¥y¨P(¯Ü]…Þæ^] ¦™[¢¹KõõòêÙK™zy'Qâ-ׯ,³LxËÕ/þõ7‹ï—7ogóH…~Ìæ* ýÅ‹ŸfBqw}ó‚¦^ÜÝðòf1KcùãÛ›û™LR«r^D÷7×_òŠww‹ïn¯iðó›»›{žXÜ1ÏÅË™Èü7ßGK{ûêîöîÕì×å·W7ËAM×"”¨ãïW¿üz+°È·Wa óLyO0‘ç‘·»Š• T,¥ÅÔW÷W? Y³tÊ´JfÊ¢t¶Q4e[•‰Œ¤±mWm½b­;]¨®¦ñ‡¶ÑO۪ܸ.ªš ¾¥ïcQW«¢×̦hV¼¨ª™’¸öÇCÃöƒãTÊÿé%ZuqûÏs~ý–(ëJ7}€f]ç" D–§Fð·ºÛ·MgäËbWœ`é2EÜc¥ãùö@@ÑðŠvMô~Ô‡¢&$ \t°j•K¿jÊú¸ªš oXu Ìdäë?ö-Y1¹Ý¦jÌþ¼X»˜êˆ W*2êôlx³[œø~”ÿ›>`íàª5JDZߴ=¡vEogÉv¼¸§ïÛ·f²ª¹ Ù´kÓC§ téÿ¨"ZO**—¦A˜¦ñ§™Ñ˜18,9g6fKfA.”t#zp›µ—‡A* K&i¤IÃÞ¡¶û*‰Š0PæCCñf6O„¿„ÿ‘sià RJÇ*í½ß=„qžK"r`£ìhƒxv»‹¼-hä9JYÆs—³Q*qÓ”ˆÐ&qä%1ä©<£pÿ×Ö«´Î+!®g8™‰mã¬0wÐ¥® Þ„ˆ$'4ƒŸÂÊõÁø¨dï†ï±¡DHófBù趼aÑ´-\®1'Ï©pg%GA– +–Ë¢t&BÿØ™Qâ—mó> #”§ ÅSÕoiÖh‰(âd‘³¦GQ‘à G($NUM+«¶)êúDóµ^3ƒc3Ÿ +JÒJ¥”‰‹j«!á( ê÷0‹BÿD0Í«õ‰³"ÔÚǪ ŠÁ¸JÙê Üó³swPšŸá?Ic8Ïö°êP«/'³&Mš±W`í…°sŽ0ƒ÷¤15-}Mš„¯ÝÊ Ö3RtY—Ûª^Å( reFŽ[,!Âú¦P¾iâ1QŽ“'2ˆDq<–à†DsY…’Iö‡vfùj»™QÞÝÖQX$~5~Ç eoM–œGQŠ‹š³å‰%x”}!9ë}¯Yóy&8Œ]¿ùÆH÷„®ÑvÖ% ãviŽÁßž¾ 3”/ždYœé1VpTtÝq§¶”V%3rDG~-}ìúð±nÐW:=Ÿò©ª·ño]öÝ…¸ûdìËÔí¦³(úêá5ú_8 ¥³¥å 7zå.au +ë‹ï£(¶Å×DXbO?´¦u±þ +^!õ™l¹a°iY+×j£6χؙlN(…)¬^U%„+f˜0£Äh[‰F“ãmƒ{C6‰eä¿Uø=ª=Q{ "<'\ôõ-öÛåA +>!­W"Êš°‰=æ:à>Ø Mgs&Š„6gIiÌÀ˜ØÚCèÛ‹bŠCÇäŽþSnDh*.«jœ§Ðt'Òs+úgv Ø‘¨<ɽùx;ø¼.æ¼ñP"kt$<2N"÷.'9ô‚, —,8Þ0¼¼dšbW•|ÉÂ+Åå=aqì[ha-Í=T ìÇ6ƦD8Ú6T EÑ¢£B…a åàF€7 +BB'TÅÄû÷‡ZÓ¬ñ@À–Û¢Ù0® ÔÊʃTcavlr ׳¶ØåhkÂFSœ|(ÊßµZ„wÒôŸòÛ©Ëߊ +îpc4ô ú@0–O‚Z#yé+`À¦n/ ÛK膓<·‡>Î붫Q?ôæÜ?aw>¦§ggÜôù©@ŠŒÊæ5¸JIMUdõ„sòò³¬¸Ä“}0éVËŠgú§–€§âÔ}…9D€5/E<qôºÀqoﺒ¯IÈp«£žéëi~>_5™‡@[T˜i·×e…FÑ«ÍÇ^&Ã8ˆ³ø̹ðŠõT|BQI•õð¯&¸Íe&±æBs,¡¾ÆqæÄr‰TÿQìöµ|‘AÄŒ—Å)øX˜\ÜmN{^µ+º^&›UÊEó} {"êº-‹úùÔån]ÕÌñ ÎlÏ\ø‹ÉÍØîlóO2âÅóI­þû|²Lšž›íÖTuÉ·[¸n¿¾M.§±’þÏ4c–~ מ›w44ïgH@q€(ŠÄ q€§ŠÙ#‘fÌŠ&_"§ 2Ó…©¼F‹cwäg¬nº¥ÇBrä|(u¹ pÌÏ f€éQÀPÙ… .?> endobj -893 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 408.0972 539.579 417.0535] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.4.1.1) >> +1428 0 obj << +/D [1426 0 R /XYZ 85.0394 794.5015 null] >> endobj -894 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 396.0152 539.579 404.9715] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.4.1.2) >> +218 0 obj << +/D [1426 0 R /XYZ 85.0394 486.5796 null] >> endobj -895 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 383.9331 539.579 392.8894] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.4.1.3) >> +1432 0 obj << +/D [1426 0 R /XYZ 85.0394 454.3582 null] >> endobj -896 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 371.8511 539.579 380.8074] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.4.1.4) >> +222 0 obj << +/D [1426 0 R /XYZ 85.0394 412.0822 null] >> endobj -900 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 359.769 539.579 368.7253] -/Subtype /Link -/A << /S /GoTo /D (subsubsection.6.4.1.5) >> +1433 0 obj << +/D [1426 0 R /XYZ 85.0394 381.7503 null] >> endobj -901 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 337.1969 539.579 345.9291] -/Subtype /Link -/A << /S /GoTo /D (chapter.7) >> +226 0 obj << +/D [1426 0 R /XYZ 85.0394 150.1125 null] >> endobj -902 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 325.1348 539.579 334.091] -/Subtype /Link -/A << /S /GoTo /D (section.7.1) >> +1434 0 obj << +/D [1426 0 R /XYZ 85.0394 122.4306 null] >> endobj -903 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 313.0527 539.579 322.009] -/Subtype /Link -/A << /S /GoTo /D (section.7.2) >> +1425 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F62 1352 0 R /F65 1431 0 R /F21 930 0 R /F41 1208 0 R >> +/XObject << /Im2 1341 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -904 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 300.9707 539.579 309.9269] -/Subtype /Link -/A << /S /GoTo /D (subsection.7.2.1) >> +1437 0 obj << +/Length 3008 +/Filter /FlateDecode +>> +stream +xÚÝ]sÛ8î=¿Â/7µg׊HêƒÜ»Û7M³Ù¶iš8mÚÝ}-&ÖU–œHNšüúR–l¥íL÷á榓ŠAñEÈlàÃ?6#/R\ bx¡ÏÂÁ|¹ç®aîhYœ±C·±žO÷ö_Šx <ñh0½jÑ’ž/%LÓ?†§¼Pð‡/NÎÏ~y/O&oŽèåÓÛ“Ãs;19yaÓ“÷o&£8NîùñÑÉñÉÑHDq8<ømr:=<£™Àî3yñ~ÄJ‡–lMƒ—‡Díâìð|ô×ô÷½Ãi#f[Ì(ãÍÞùƒ4òûžï %ÃÁ=¼øSŠ–{A(¼0ÂAò½ó½w ÁÖ¬YÚ«Zæ{\D¼G·ké–ù0ËD4ˆCåE‚ £Ü_GãÈ÷‡ëUšÔšÆIšÒ@I–«\{…® Jxuø‘Æ<Œh èÓcr8™|*X¼ºxé¿ZÍN'|=ÆÑû“w~­_MÅáÃäèêùÕk©ßÉ$á㣰DÙrÿ|òîù—ã›7W¯ëãû›§éu½¨Ö"JÞM.å¿Qé ù˜1O…!ÿQ)â'¥H÷ã2½Ø‚’¿>ª²«Ùëúݲ~+Ó—/êéäÓåù%ÿéRèý‹“üFÿv#>ú´ú²>ð×É}¾ó9yõþË¥æy)êŸÒ7Ñ…^<Ü|þš•.RœÞÉyëüÆAìIîǃ1 Ñš‹,‰¹/†õÂœp|‹ oÖºª pŸå9Žøp^¢^b’/K‡“-—:Í€Fþ`ü‹ñÍe¡»ÔÄ°(íâ™rä†y¯²ëB§–âÎr+cÛF·R$ÀG*„ð"6"-’ +ˆÆ> RÔÙyˆÙ°. rŸäŸíœ‘V@J +»îZú–4×Æ<˜³…yvA„†¤àyižiDæt{ñ6"Á’ÚØÁØ +d…§°GûCÄIVú ¬¶a4ssijt +Ã<©jØðD•'vE½Hj7ÒÄ ½f•%E–U„ û_$Yá5f£Œ=¾™!j>”k0`³ZA2Bu•×4DÚ‚æ³¢ª5ÂË+žP¬o‘‰å:OiÞx8“b³@œŽNÎ&ohn[ëm®PÃ=n˜YµEjãKÍ _ÂcŽ¤± 8 Ñ7æ +&ÂŒ jŽž‹äNo-x{Ji ²—yŸe5aTÚ0dŸ +c驆¬#ò§ï‹äÚz¼p§]aéðPÙÖ(6'ÞV"ºJôÈ#;É¥76ýƒâYQY%>òê:·aþû›üÿDšbÿiêû¤ s"SÂwÖ}ø–ÆEF±Tþß•'×àkè.z… rAËaÜMrá5í ð&5¸•ÿIEy¯ï ¢‚[6Ûuvh…|ܤ,žYZÌî[öùƒy1ð|Îd;1 +? Äˆƒ„†Š¹¦±‰…𜭳<Ý'†—å›]ØMäún„Y°nè`JýC° Ðê6»3 +6«Vå­( 0Ò¶ÙÛbÍ Ö§ s”­\gÚ¥)¿|XÕ– Aé¤=W®0ËgeAð?ýЯ´EžéÏÑ®€²-K—.ñ-Õu’å¬b˜œXDU®p +‘«¾PŸ¥´ŠoØ-vz,ßbÕ›y]ñ§\üV~+{)*L¾Åª^$e¤}—–Ô&-©¦2Ê1Ô*z.’ÕJ#)”\±4E„™"—²xISYÀ˪¬ªl–ë¾P˜Øªã^ç¹×X|#º1yz,fª¹»0à +¶ÎMQ‰E˺.—Àïœ^mQn$ßu ÌZ$é4ÅT‡ÉXò¡.’™Q¨Ê0e顇+[z Ø–[îÊ¢¯ZÊ:"’§EUéy?pi $wÕl¹²ÊGâ%±Bg +€Œ}/5z"NdEONfï©X–² Þ¼,®ú˜P^ ÷B‹êõȪ#ùf ànêcômï“Ò +î)ÚË{[²66CÇkÌéz’V¿ôÉÈ¥Ìñ•£ûöî*âæÆþÜC‰y2 +cKðˆ:qjíÐrÙ¦¥*°(¸¨3_±-ÿ…!”h‹ur¼Œ³¨ÇB(¦óþDÁ ßZ¬¹) a×J“ÂçX¾³ØÆ(˜ø¬hf6ìÖåí!Qœ$¤Š@à7óÕùo¨ ùbü ~}[7»,I‹,ˆ¼X(¹]S’rüÀÀQâÌEßnºÁZÚ‘]g¯Û0uI6<® äÂwnã›h7voSÝäª1° Õ²#±¸ÛaHJO©(êp´ÓŒm°¾ÅˆžˆTÔå$¡ûM_K™+‰N¦¾¡‡¦ÏÞÆßÝ~‡jK•®±ö¤"˜€TÇÀãÚ[ì(¢Áú' Š<… ¼ÃŠÉ)XØljo¬z²&–¦<õ kã"¨iÂ.å%íE+z©ÚÅRS»¹…„º•Ý:HØC¹5·@¬È¨ÃØž7µ™q´XA¼÷ê&1ÓŠ‰MLÔ)–‘2°Ýçâ82}½8Ú4KÖוxªåÚQH ê7…~l32z3ÇB6Å ×q;uM5ôDØDâþ€‘%Ø!Øÿ¢ÿUËž˜ >äCÀï&0´Ç颬tÓ¦Ä%¶|4Œ)ûë)Ô¶CJÉ»§š´_Ö… uv™µ@‹k]Ù&këÞï9?Ù¾ ]TöPä7P.Ä£ï¿(@Û¾(m×É°ækL͵!l°L”45ƒk¼¦!\д¯×´6m#J[‡Äô2°¹Ü^úŒ)†ÃÙ¡ÀµÈÞ¹(Ýø,b[×¾>‹d"Þ®áÇ›–á¶åÈ÷>ÿ†9Â~ΉÒxUæÙü¡ßy¨\!ÕºX FIÍ<©†UV—‹äFqFãQ0¢YE#jÃÀó…!3mŠH¥®"Žšfô˜…ÈPn7:»m¸J²ï¾Fö}J½š1µiLŸ“Z}íÒLÜÐç0p}¸þØNrà:ÉA«ù6 +—s]U„NŸû‚|- K +›>RÛØ-N ƒÆAzKè‘ê«d״̆wI¾¶CÇj†"@ßõúz/(\Ä!ðþâ„w +æáp`Û 1ž`>)˜“» ÇAéæñOl (‹GŠJ%ÁÃ0g#ºS.@ÐèÛ@Ëym>x跰˧¸é‘÷~‘Í6¶s›¯B]æÂv› ^Ìþ]=š زmzƒœ‡î\¼Ó$¥ù_°Ùb?²p{ĵ›T P'; ͱÀ˜·¸ÅÝè(7Dú·ÍŠJjjf™UI½µÊ†RÜDë~5šÁõ¹lR9ÂÈVJ…+{µHëÒÌ]Àár‹O š+·¡‚"~b. v»¤^7™€ˆšÝ¤³ƒ+ûÁ”[½T®6ŸÚH–ž^«»éõwTŒR 8‡Êâ1E÷ëò´°¤–>š«=Aó ¯àtÅ*Ä1ü)DOµé7{ýð/.6t{BJÞ_¶Bô D,S(v8w?ÍØeý¿GËendstream +endobj +1436 0 obj << +/Type /Page +/Contents 1437 0 R +/Resources 1435 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1424 0 R +/Annots [ 1443 0 R 1444 0 R ] >> endobj -905 0 obj << +1443 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 288.8886 539.579 297.8449] +/Rect [411.5778 307.0154 489.9929 319.075] /Subtype /Link -/A << /S /GoTo /D (subsection.7.2.2) >> +/A << /S /GoTo /D (man.dnssec-keygen) >> >> endobj -906 0 obj << +1444 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 276.8066 539.579 285.7628] +/Rect [55.6967 295.0602 134.1116 307.1199] /Subtype /Link -/A << /S /GoTo /D (section.7.3) >> +/A << /S /GoTo /D (man.dnssec-settime) >> >> endobj -907 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 254.2345 539.579 262.9666] -/Subtype /Link -/A << /S /GoTo /D (chapter.8) >> +1438 0 obj << +/D [1436 0 R /XYZ 56.6929 794.5015 null] >> endobj -908 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 242.1723 539.579 251.1286] -/Subtype /Link -/A << /S /GoTo /D (section.8.1) >> +230 0 obj << +/D [1436 0 R /XYZ 56.6929 439.2963 null] >> endobj -909 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 230.0903 539.579 239.0465] -/Subtype /Link -/A << /S /GoTo /D (subsection.8.1.1) >> +1439 0 obj << +/D [1436 0 R /XYZ 56.6929 409.315 null] >> endobj -910 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 218.0082 539.579 226.9645] -/Subtype /Link -/A << /S /GoTo /D (section.8.2) >> +234 0 obj << +/D [1436 0 R /XYZ 56.6929 215.0565 null] >> endobj -911 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 205.9262 539.579 214.8824] -/Subtype /Link -/A << /S /GoTo /D (section.8.3) >> +1445 0 obj << +/D [1436 0 R /XYZ 56.6929 187.7252 null] >> endobj -912 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 183.3541 539.579 192.0862] -/Subtype /Link -/A << /S /GoTo /D (appendix.A) >> +1435 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F22 953 0 R /F21 930 0 R /F11 1442 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -913 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 171.2919 539.579 180.2482] -/Subtype /Link -/A << /S /GoTo /D (section.A.1) >> +1450 0 obj << +/Length 2621 +/Filter /FlateDecode +>> +stream +xÚ¥Y[—Û6~Ÿ_á·•÷Ä*EêÚ7wâ¤iš™ìŒÓžlÛMÛ:‘%Ç’çÒ_¿R–F¹ôìñ)A>ÒÁDÀ/˜¤‘/TN’,ô#D“ÕþBL¶0öú"`ž™ešsý´¼øá•J&™ŸÅ2ž,7g²R_¤i0Y®ÿð.ž¿_.n¦3 /ô§³(ÞüåoÓ ¼ùÕåâ% ½¼º¥Î«Å|š„ÞòÃÍâvªâ$‚YϦÛÅå žññjþîÍ%}ü÷újqËó+–9ÿ°œ©wýŽ$ZÞÛ7¯¯Þ\½žþµüåb±tÛ<7E îñóʼnÉ,òË…ðU–F“ø~er²¿#åG¡R–R^Ü^üÇ <5SÇL©ÔR™ŒØ6 Îl›Å~–…Ñ$‰2?VRÛ~ÒOÓY,„W¬¹­¨­tûP?ÑG}\ë#uÿ‘¨W­néSR“W<]Áx€fÝfAàgQ$ÍBG½¯ïó’¸6e¾~iúªÞJÝêoÌìü^Iy¶w–ÖR`ÉHÅFèuUÂîU(¼#:Y¯jÓ®$ [¨|»ÕkâÉjÿ”2´ê`Ÿ˜WyEÃwú\$lšæÞ}‘ÓÈú©Ê÷ÅŠ¨§Ã:o§§1>SéÍÛVï-¯ÕÖCa4«nwà;ŽÅ}ŽfÂ(mŸÜ{¶?$>eI½;fkŠRW-¿ŠmEôÚwk¥ˆ¡YëÍ•I=Ð…:`0ylZüH<ö +Ò‹†Ú¿µW[îH´;;fÛœfÓº>²ù` ÜÖÇ¢Ýíé³:íï0&IœWjvõ©\“ˆJß[†üpÐ9÷‹êl¡óÁÛÅÇшíÙÌÖLÉ·[¹uú¬H‹`u±W4IJÚåÕÖ~·ž ¸‚œ¤cQ1_N‚éÃ(‚dÄ-›¨ÁÀQ©·ì+cÜ_õæ뺎žµª%0 +0®±5*¾Ÿf¢7ówcaŠ¨@"8JçÇõ¥FϘ¸Ôeicи{õAó¶¨y94¶@ÝÔÇ=ÇiÞh–áøÆV»+ÚƧ4ÐKv—³Pú +ê‹Ù®xeë÷ËkÈ÷=“Ì“ +â¹¼YÌ—‹1³‰Çynï®ûdž«k4(§ªÀiÖå*Ô2õcɹ ++X4B³ä‚º,!-›‘¬‹ËDD‘1›Y +ç¾Ýa/ƒjôêD^œµõ¬û"Nˆ Ni°0ŠŒ<KÕ–X¨ž’8(&¼„ɆHºcIëºÒvM¢@y!ÂCþÔüÒÓÐ;5NnNƒ6WŽØÒ•{“B5WnˆEÖ¸gø"ñ³0ƒrj$ä'Øóºj`Û#Ö‹b?ˆ2fýÛèOqŠAê{.ĺŸ*(3±Çœ'Ñu±uÍý=ÀB; þ^·»zýmo.ñ(Ö”êÜ!ÁSÒ]uáaH\ƒ’ó”tTIà=Õ'›?5gÒ–—É×–`Û;]J$¾ˆ£MöÖ8-ò³$‰Á4~*Òüß#›ËüP…áäŒ 3F©YïM}ìVfíÜv™©©-ä”羇ì'ý0IÂ~ô˜¹•òÓ Ix3& eªŒZv0\A™=$½’ÞGãÑ3• +$Ó1‰(fHq§ú77 G!Å9Êœã(ds*Œý0RV÷û6ÅÀ*Šî‚Í„¾È9( ù©1z§v‰=Hª©½ã‘ƒÉÓ©M6½‰¼óÔ¸í'•÷;[ʱ¥FŠI8§hˆØáÀžÈö •`ô†°g$³?Add.3MmÓ‰­S®à”ycKAƒ™¸®U¶>YÌ3@P‘CP$ÓγíÆ汜š··o©cŽ§YA[m©,ª®R:-Œ!ªÖ–óµí0ÌkÓ2¯_íìÚ4óP7E ÐK³jõf°ù“”Ýfw8TѤÊìùêC^´Ô£Ó Qöùc±?íéc¹ü•† žéØ8MmËŽ8ôLáÔMÊ =®‰Â§¯”>QŒsp!V̸F™Ê„dôÈHÜÃd5Xð`nªkJEæ¾ áèLS6 òÕ΀ ˜Ã§€†U‹eÍ܉p€¶„=¼;çÌnÎ>vÀTÏ]*’ÊÌB»3X|K ~"€;²®­#é'Aö‚m±×#c)•Zv¼F#ÐŒà>»!µÇ‘:øDÄá9PçÀÂ!’~h}Ä+PVþì¡x™1Š§¾ÉXÐR•6× Ðmšù2Ž%KÚÃ/É#K† D¾°ëÅÈÞBa¡úö!“ DQïr¹ JÈ¢OD‚|pä.1is™Ì8jeÖ»`r1[Q™LøA%¸ñÁ^RPµgì³—©¤·ËêTuKz¡Ð÷E}jŒŽJAÒ£ô+j˜³ =ÊêÒ¤¦P]–ÆSX&Uì@Â`”ÄÚ¢!¹hHos"»°\»–Uòó©X}²Jå£OS@éá÷ŒŸëÍ&ã‘{Vˆ³‘±Ã̆Pe¾b¹ýX4­£º™õPx‰Îþ…c©ÌÝ=ÕXf¤ˆ™÷IiAÑÌÚHáA¨V\“ *›ðÂBñ‚ÊÈãÌaÖFÚ†¢kO‚ø±)¥dÊvÒ¡¡N´UàŸ®1²=¾\ð5 žñ|j®ŽÅ±» œÃ Ýçe±.Zžê¢^óÄÈ ¥ð~z¢µÞ䧲Eod±ñiÿâÍÛ– ¾ÍTÔ*Á‚ò§†¥P1»¨ìŠÕŽ~ûÅÜ|£û—‚ÆùzíìÛc<m2Hóëe4re4å2Ê/‡p~Î^»w ü$äƒ|ëÐÛ7Þ³Ì:YÕ˜‹+Rž=VmøH‹4Zfv×츻fC™r7Ón{u‡Yül‹4ólK]JˆÐᜌÔຳ±˜å;RŸœ z¶¤Ù'NîÓƒ*~P `w×ÎY$"oÞ™ßÛ¡w¨‹Š‰ôâÄüFõÿn¢N«Ú®8Po$^¿þ6ì¢ÏÚm4œûù; Mø|Òö:ÛÇ~cÿÕ©ÈÇ?ØFþY.¾ÿïÿñºÿ?¨4•î/º~Í1`‡,±J¡e2ÔÜýá÷\õÿ+¡äendstream +endobj +1449 0 obj << +/Type /Page +/Contents 1450 0 R +/Resources 1448 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1424 0 R >> endobj -914 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 159.2098 539.579 168.1661] -/Subtype /Link -/A << /S /GoTo /D (subsection.A.1.1) >> +1451 0 obj << +/D [1449 0 R /XYZ 85.0394 794.5015 null] >> endobj -915 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 147.1278 539.579 156.0841] -/Subtype /Link -/A << /S /GoTo /D (section.A.2) >> +238 0 obj << +/D [1449 0 R /XYZ 85.0394 544.6974 null] >> endobj -916 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 135.0457 539.579 144.002] -/Subtype /Link -/A << /S /GoTo /D (subsection.A.2.1) >> +1452 0 obj << +/D [1449 0 R /XYZ 85.0394 516.8643 null] >> endobj -917 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 122.9637 539.579 131.92] -/Subtype /Link -/A << /S /GoTo /D (section.A.3) >> +242 0 obj << +/D [1449 0 R /XYZ 85.0394 467.6389 null] >> endobj -918 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [527.6238 110.8816 539.579 119.8379] -/Subtype /Link -/A << /S /GoTo /D (subsection.A.3.1) >> +1453 0 obj << +/D [1449 0 R /XYZ 85.0394 439.6503 null] >> endobj -919 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [522.6425 98.7996 539.579 107.9053] -/Subtype /Link -/A << /S /GoTo /D (subsection.A.3.2) >> +246 0 obj << +/D [1449 0 R /XYZ 85.0394 266.4633 null] >> endobj -920 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [522.6425 86.7175 539.579 95.8233] -/Subtype /Link -/A << /S /GoTo /D (subsection.A.3.3) >> +1454 0 obj << +/D [1449 0 R /XYZ 85.0394 238.4748 null] >> endobj -921 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [522.6425 64.1455 539.579 73.0021] -/Subtype /Link -/A << /S /GoTo /D (appendix.B) >> +250 0 obj << +/D [1449 0 R /XYZ 85.0394 132.4384 null] >> endobj -863 0 obj << -/D [861 0 R /XYZ 85.0394 794.5015 null] +1455 0 obj << +/D [1449 0 R /XYZ 85.0394 107.4147 null] >> endobj -860 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F21 714 0 R /F39 899 0 R >> +1448 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F22 953 0 R /F21 930 0 R >> /ProcSet [ /PDF /Text ] >> endobj -924 0 obj << -/Length 885 +1458 0 obj << +/Length 2222 /Filter /FlateDecode >> stream -xÚíÙOOÛ0ð{>EŽí!ÆÏÿ}e‚I˜6zCX -‚¶e›¶O?§Í+už(œ"„ ÏïÅï§`'Pòð¥6ÌxáKëÓt9]¼œ‡¿}. =§Š'Uø¬ãIqt*mé™7”“›RiÍ„Þ æwÊÉìrôéËùää|r1¾šœ'“4*Î \6Cþ,.¯x9 œœIïtù'üÀx/ÊE¡´dZIóP\_Ӏ诛Ðì•gB‘¹!Ð¥X`FšPœöá@ÈÍ•3W^úÑìn¼±q¥9>6Êûƒ öŠòA–mHýØkîã¼Ü|CíNqÜo÷þøM¿ÃÚè'W¥LŸ´)ËŒµÐj[m·«õS˜;pûxn±!½¹¡@Šn8pÓÍ-SÅLŸ¸Iͬßr“íÍm¹^×Ój¶¾yƒ­÷õßq%4½šQœèÞŒP Å7¸ëf”)„bD¦OŒ„dÖ×2R;Œžèèáú{ý0®÷ƒvâìö¶ƒ);¸{À}·L!”2}²À€iíè—væõ2̯ÒÃÿµiŠóÝ[ -¤4á~ë§L!”&2}Ôd¼gNÕj2;šÖwóå¿Õ²n<ÉÒ!¥©î vZ ;!å -! Ñé$g™ç·}v iy½¨gÕô¶žÞOWË›qe´½ZPœãÞ‚P %÷Àv ÊB "Ó'AV3¯LÜʹ=Aí­H÷ × ŠsÜ[ -¤át/«s…P‚ÈôI‘Ì{wg -‹h¯‡ýÿûïÿSz C”0Üc¼[X¦J™> Ó‚q©ãÆ x˜Ô†Øú×ÙõSÝyŽÐq÷¢Itª+ó šÍI E¶YÊoÎÜÕ@óø¶gFê0vª·CH9Ä@ ·L!”C2}r†åé¡|¾ïU ¶Í3- r¸ÇUœöÞ¨P … -·$±V˲‡*½¬®´ãÌJ+rï«Ã70¯5¼ýíøóK|e™tNä/WXÏ綔š…±¶{Ÿ»ßOCÅÿx3B*endstream +xÚ¥YKsã6¾ûWèHUEX<ø<*¶&™lÙãÈò¦RI4 IÜ‘HE¤ìq~}ºÑ=ãTÊF£ÑøúE‹ ‡?1 B&2™D‰Ï.‚I¶¿â“ ¬ýp%,ÏÌ1Íú\߯®þóAE“„%¡ '«uOVÌx‹É*ÿÍó™àl +"¸wóëÝüöãõt&î­–+Îï®ü´¤ñíünþÃâvqk"’‘wýãü~µ°«¾•4¿ùßT;7´ts÷@ƒ‹ù4ò½Õãrñ0ýcõÓÕbÕÞ¤[Á^ãÏ«ßþà“.ýÓg*‰ƒÉ L8I"'û+?P,ð•r”ÝÕÃÕÏ­ÀÞªÙ:j=0€T¡1Ÿ!Xr`¿ a¡’ÊÚ ¶àœ{×Uù¬MQnèªëcµ§ÑÝÃÂÚµ©:ŠÂûÃ)²÷H|2“1‹’$2âWÓDzfKàåö·Ùõw8 ½×êD´ÿŸê†F¥Ö¹å³üin¾—–D0gߣäùr~K´ãTÄžÎ*ó›Ã;*x¿luéÎÔ4ÈÌ뢲 EíèûÃN7Ú*Öò››Ã5ñb­-ábÙ6-@„RÜ{)v;mÓgM£'­Íª°Ší«g¼.¥¥˜3pp~¤ ïóöA)ò—6Œç\¥›v,õ- [Й¢{¿îb¢1|c:GOš~7ºÔÇ´¡Bòš´ËÖj}¼ôÄ‘©¹—ëº!m_5èE Tò‹“P´ü] U—(ý M")üZ*žx§Z·Jv2ˆEQ‚,QÖ§C†9ÌÒ16V~ š§ÆÔ0¸wŸ¡&Æ—¢ÙÚ½ôÓagvl1à’0àŽ¢½¢° Á2pƒÜÿÔ›XèyÇ»‘ ¾‰„Zg§£B¡(-õ+p‡pÕ(\44Ié§.6¥¹¶H¼¿ªRµ±;Ne·³šÔÃw{-Ó}‘ÑÒÉw$!×vìÆÈ(l«[¾ÿ.~¥ñ% +àwMo¾ì³z„­ô ¿`l”V³K\p­üwàZ2Ha1¾@:›%•1RÚœHgãI¾ x:\°Yt É ƒ8… ’@MëºÊ +ÂY»ÁºÇ2ô-‘Ïmc œr † Ƀ„ôÔTû´)2xWS`>=n;)MúÙÊ9ìÒÌÓuÎ8tkÈÞ‘ž4e=Þ¦Ÿš¹W“œAB:w纅5lwÆåKF!”IPAÑåe 0#'˜5Õì+!DÌÂÈa :46]vÞälWë¦]0rü¸''L„¾“óªë‘³àž¾lñFQĈ:LÄQâ ™î!X€c®G¤AiEAÜ‚Òà@A¬†@.‡Fýh´Âò¢À "òåk$Ë7lK@ýiå#PfdX’µ7©»ÄЦ\0é ÷8pOÝ,öºlè\|i$CÖÉJåÜV§]NlOv÷Yya= ÀÊ#º×Üe&btqæ úêeì¡"–øAûNu£Së/¿ó€WîEsî ¤á 0ŠÑ0?³Â/ƒ½´Áþ^‹*7áe’¼.‚}%»›wŽB)¯40°·© +çö)`ô²-²­e:Õ±©iÖÆnœ#c¤òyDp´Û©>ƒÑÁjkˆ¡ô¬@„å|§îŸ;RŒQ'ýÐ++4¬ÙÊI=‘&r)­í/ñÚ qÚ5D®Öô[W{MmPÂMº£¢‡Šäír"튵nŠ½¶‡Ù§6ºYI9ÖóN©º¢Õ´ËH.¢Ô:ª›Ë!aW9@½‹²ÅÞ±§°³½©Ý“:4¦ŸU™éwWÊ‚°W˘…ƒO÷«O«÷:ƒ!áä­Êg¾Ï]yX•0þ€0ˬq¨ÚAJ©_hàR(r™Jã—­nAŽOb éÛÎælßEeDÓÞô7X?‘m?ì"ÅX{|ëÔ¼J¬ÐJ(-eæ&豫%!KDÜõc6ƒÊÙ¬³J~¼¿¡}ñ@0øEõ-OÏ6†ckî}c5RlÑT¯ý ®¢…¡± UЊ³H‰pˆó}ñ…j>0†’âmc®XÄ…ú–9|ÈÎy…·ÄcLÈ0òÉ@D5yPKô¸:qÒ‰x0j } çE™ÏE~JwDïZI¸zÄâ8Rëm‰IMH{28d¾¢E*ﺄ$1ßj¢â+âïSÇEé ùLÎ漓9€0¸ÛÀReyÍm8ÜY[ÀÒøñã=3*Ó‹'>ïhãI¸Ÿ¨ö{•&7mC€¹©3'WÎËlërêmZ¦*F³‚¢Òˆ‘ÿýÇ»P5äTBŒcö)mß2ƒXî@“µ©€sùáš(_*ŽzÉè »š†ØS«%®ì[-!…„*ñ©÷1»LkNÒ]2ëO°ø¨G\A“TÁ;ØQãÃÌU:®3[W'W¢P?ÒÿP­bHQ‘/'aÀ „'øŘ֎› –½OÌ-û¬ÇO_˜Þw.¯ó ³NõIh‚εñȈ¡5êI¿øÌÝ2}]‡ Ym8ö¡^ ¿®œÇ[ïù×ñ»ÿoøЇƱ×\F1ócb•BÅe|¡¹ûÚ©úßúQyrendstream endobj -923 0 obj << +1457 0 obj << /Type /Page -/Contents 924 0 R -/Resources 922 0 R +/Contents 1458 0 R +/Resources 1456 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 715 0 R -/Annots [ 926 0 R 927 0 R 928 0 R 929 0 R 930 0 R 931 0 R 932 0 R 933 0 R 934 0 R 935 0 R 936 0 R 940 0 R 941 0 R ] +/Parent 1424 0 R +/Annots [ 1467 0 R ] >> endobj -926 0 obj << +1467 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [494.296 758.4766 511.2325 767.5824] +/Rect [379.778 61.5153 440.978 73.5749] /Subtype /Link -/A << /S /GoTo /D (section.B.1) >> +/A << /S /GoTo /D (managed-keys) >> >> endobj -927 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [494.296 746.5215 511.2325 755.6272] -/Subtype /Link -/A << /S /GoTo /D (section.B.2) >> +1459 0 obj << +/D [1457 0 R /XYZ 56.6929 794.5015 null] >> endobj -928 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [494.296 734.5663 511.2325 743.672] -/Subtype /Link -/A << /S /GoTo /D (section.B.3) >> +254 0 obj << +/D [1457 0 R /XYZ 56.6929 769.5949 null] >> endobj -929 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [494.296 722.6111 511.2325 731.7169] -/Subtype /Link -/A << /S /GoTo /D (section.B.4) >> +1460 0 obj << +/D [1457 0 R /XYZ 56.6929 748.2119 null] >> endobj -930 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [494.296 710.7556 511.2325 719.7617] -/Subtype /Link -/A << /S /GoTo /D (section.B.5) >> +258 0 obj << +/D [1457 0 R /XYZ 56.6929 682.7685 null] >> endobj -931 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [494.296 698.7008 511.2325 707.8065] -/Subtype /Link -/A << /S /GoTo /D (section.B.6) >> +1461 0 obj << +/D [1457 0 R /XYZ 56.6929 651.6058 null] >> endobj -932 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [494.296 686.8453 511.2325 695.8514] -/Subtype /Link -/A << /S /GoTo /D (section.B.7) >> +262 0 obj << +/D [1457 0 R /XYZ 56.6929 598.1176 null] >> endobj -933 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [494.296 674.7905 511.2325 683.8962] -/Subtype /Link -/A << /S /GoTo /D (section.B.8) >> +1462 0 obj << +/D [1457 0 R /XYZ 56.6929 566.9549 null] >> endobj -934 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [494.296 662.8353 511.2325 671.941] -/Subtype /Link -/A << /S /GoTo /D (section.B.9) >> +266 0 obj << +/D [1457 0 R /XYZ 56.6929 448.4378 null] >> endobj -935 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [494.296 650.8801 511.2325 659.9859] -/Subtype /Link -/A << /S /GoTo /D (section.B.10) >> +1463 0 obj << +/D [1457 0 R /XYZ 56.6929 417.2751 null] >> endobj -936 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [494.296 639.0246 511.2325 648.0307] -/Subtype /Link -/A << /S /GoTo /D (section.B.11) >> +270 0 obj << +/D [1457 0 R /XYZ 56.6929 351.8318 null] >> endobj -940 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [494.296 626.9698 511.2325 636.0755] -/Subtype /Link -/A << /S /GoTo /D (section.B.12) >> +1464 0 obj << +/D [1457 0 R /XYZ 56.6929 323.6339 null] >> endobj -941 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [494.296 615.0146 511.2325 624.1204] -/Subtype /Link -/A << /S /GoTo /D (section.B.13) >> +274 0 obj << +/D [1457 0 R /XYZ 56.6929 230.1472 null] >> endobj -925 0 obj << -/D [923 0 R /XYZ 56.6929 794.5015 null] +1465 0 obj << +/D [1457 0 R /XYZ 56.6929 190.6255 null] >> endobj -922 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F41 939 0 R >> +278 0 obj << +/D [1457 0 R /XYZ 56.6929 125.8181 null] +>> endobj +1466 0 obj << +/D [1457 0 R /XYZ 56.6929 94.6554 null] +>> endobj +1456 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F48 1228 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -944 0 obj << -/Length 2175 +1471 0 obj << +/Length 3064 /Filter /FlateDecode >> stream -xÚÝYÝoã6÷_áGXëø%‘ìãî¶ÅÅî’¢½>(c kK®>’ºý 9C[ŠåÍö6ÀE€ˆ¤†äpæ7¿Ê|Éà/M–2iÕR[•fŒgËõ~Á–x÷ý‚“ŒÊdš))¡3óv•I“fFèåj¼ÈÛ»Å?¾|)Xšç"[Þ=œöʵI­TvyWþ’¼Û‡Þµ7+‘±„ßüz÷NS©6šûi ¶ÈRm™ >Ô}۔ú¯ššÄÅÒ¦6y”Ö0ÔõÒw[K›ÜOsmízì½oöEUcûc±'™Ûc×»=¶ÿÃ2öþã-<¸Ðɺ©»ªë;|Ý<à³ëwǺ/~§Á†Æn]=ŸIÖ°ß³U\ÝW}…£:©nxRcÓO‚3úSqžÚ,Ñt)Xâ"O -ìn+×í 7Éz[­‹Žî‹º3k•¼iPÿ¦½1É°ó›ûE†Î•8þдØ(ÝÎmŠ¾ª7´ÏÐo›¶êAÍ#Ž4ŽdÃáh‡¢¦•h+F -žœˆ‡UûÃÎíÁEðëJ€¢ý¶ðîÒYR¬û¡ØíŽ8¾/¶¢)A$؆F~öË2XÂuëRPÂȼŠ¢eÑ(Vuqå -4¨joßñË`wÖj†Ž‚÷f|SHÚê~èÃ"Ùœ?ü¨ßü¾ZEÌs•J• B±b©È%bž§BÎKn×ÍÁá -<ð|߬o¹ù`&͵KÞºö85ØÓNBƒÅp€ñs°o?||OñoOëP¢ÀG'HM‘Œε"~4à*ÎðRÃþÞÑ<.Xl5ga‚¢È$*x–[8_p$Œ—Ñ&¡w@¿=V¥£÷`ùjͪ…öv0PÜ7MĘ B]KÕ%6ÖèÛ ¨È)£™'ãÎù¦C7¾~iÚ¾öØ÷ÿpûŽ ÞüØSv¤K,>ºæ¡©Â’C±þTl¨ƒF÷r‘ã ]”ûªöp-ú¦E 5Ð3ð9B¦êf6Ø£cz"´×MKAwhê’¦‡øüÌ)ÒüËAP ü³ÝuõÇÉ#gÎ*yd|8QNE|ô'K;šl §e<‡E¦ à3{)éÓ -†A8Bs]ÜÖá®—0F4•Ò`„LC‹ÖîÐGî˜('˜NY.ÔœvâEí BÖÀ^Q1òc3 a2ZI-RÃa‹ šQö·¡ÂF¤- |Щ¦®1|¡O$ˆieòX´U3ÐkòiLaÕýeÕ¦¤jŠóGϾMM¥åO]¼ÞUõW–¡ŒŽsÏegè>Q¬ƒ¿Ÿ܈Aâ–l\À‡BÇzï8;Qýo¼V‹oïNßolu …gêF)üǛ߿üÊ–å‚-X°TZ“-Ÿ ÃÀšP)îJB“e&Žì·‹ý³¢£Báª8ÁZÔŒèž.µŠgZqNÌðÓ©)šàC*XFAŽ¶Š®<¡|¢ëJÌ~f“‡s³oñuZŸ–|Am ¥£‚ÊgªöÏ7‚%WáÒõÇÝå!2‘§*ϲW<„Pf1ŸôiîÿNB¦\ü'Îg\…“€¢ÝZyþÀ)fá$5P -²MáÓŽ‚Ëx¿õŸC ®•’p¹gbçN"ùéß?¾AÉmÓõ#IàµPÏ|>Ø‘¢wI>Ü‚éž_»'‚€k÷ÓWT¾^Gôè”_g¸¢Ÿ[Ì3‡è‘徫~÷›ý>Ue¿½ÞWÓ÷/ÞèèWäB¡Êò—ÀËeʤˆëÏiX¥9ï0|?£^Ÿ+¯Ì,~ÆÊôsPh¾mvåu(½šêk(Y2ËíKHbpMÓ°Åùˆ/K" ýç@4Úâµ0ô\ë+4ÖúB×€ójêþUp#àŽÍ4‡Ú #µPãßþ.~‚ýíÔ7ÆÌþPÿƒÛZêNœE„”‚©% …:üÂìñ'ÇóJq·ÿÚV[endstream +xÚ¥koÛÈñ»…€ÕD,—ä’Ëë'_ì\rn×òÝáp¹4I[D(R©(ê¯ï¼–™F-x‡³»³3³ó\E-<ø§F»^„‹8 ]í)½È¶Þâ æ~¸P²fe­Æ«¾¿¿øë» ^$nùÑâþqD˸ž1jqŸÿæ¼}y{}·\ùÚsBw¹Ò‘ç\^ý¼TJ9—ß^_ñÔÕÇ5ï®/—qèÜÿtw ˜8Ñ>lSJvÞÞ¼•uRŠÏžöÞÞ-ƒØùõö~©ŒóéæàdvýÓíí'š½_þ~ÿãÅõ}/×Xvå(Ô¿.~ûÝ[ä ‚/<7HŒ^áÃsU’ø‹íE¨W‡A`1ÕÅúâŸ=ÁÑ,mÓ¥Œ«Ï(ÓW 3ÑÚŸhS'nøiuýåJyhñÐmš}Ù¥]ùµi‹ý×b‚9t7Þbå×6ѹ_&¾Ó,WA;mÑ1pØñ˜Ö2Né#êßM-Ðc³gàîÝ[@ÅP·_çÐv–\¶±‹·iYwE ¨â `’Èy*êbŸvBµ; +Sx©ý&àZ ¾TÄ|)N(#JÕk ¤j˧º¬Ÿ`gpMËÒºYß´²0Ì<Ýö L,4¡³*“YcÅèXv†•8Íc¿zû7ÁÔºM)gÛ±'õÙ÷Ã4C"Ä8`Îe貪˜( ^µs27e¶áËÎë¦c %΢ã`ÎJY‰â3pvÛ¥u¾z81ˆE•¹öP_¹AhøÐËú+”v¾¦U™ƒ= ’ñ›i¶M…V˜¨ç&Qv³¦þìyþÓWçŒíÞph Al`õ0 zdËËÑ8ñ›Ì4»Õ6­Ó§žro~¼Ìo¢JMǵí'p_é—‚!Ð%A†®•æ62eõÅ_hP¼°¬Ï¢Î_µ CX»¹þ•á»;pµ7|¿@Šw·]Ó_ Ù2D6JÀ¡; KŒèü±à<ɳ“{æÆ;¿¢DõrÛ¹lSd_!2(k7€Úû²ÉË,­ªm’À³('}옲çyzji™rÊÇ3Êuqd :1d'0Óv=c°šy“Ãà»æEHgF\"„‰‡Ðz~–Kåì:´D<ÈRöI¦*B Z¼ƒÌ^6 ± çmløÑ=] *:vm-·2+zã'4jpÊ›³Vc×aä„•* B{7Ä®òÁÓ¶»ªAQm¾åVX—ÂEäRˆÌ(Ðð «X_›/BÀð%Ói–’„B<ì|;"ÑTU!ûP©:¤ÒÌÝ]¬À4ª“D+’–<š™ÞlpbKWžS¤mYÛƒƒÓc9΀W)ªçRÆŒZYs„Yòg@È*ñœh§9ry‰\V·é¾“8I€……Ej}YhA”ád­FÉ:0Ô¡IQÀ¼nÛ"[ƒ,grûª_?Q+ÞÝsÚ*qÃHESÒÈ(ÉùœxºQe¯Ç4*ç:u¤HE‘U]¤$;"*eÄîðPAèèʦf|N©§JÁ°òØ¥-FG?‹:tr€,"ûíɨžŒ×ç¤Ø2êPcIƒ–²ÂÊ.RSGâÜÏ HlaÄhß =£B£\Eá *$R«õŒ*Mìz -ï³éßÆcd¥¬³ê áËës"%bsÎÈí®³ ȇˆ@šœB墨\ 5©È¸ QtVjðm‚ÿ•Ýw,O¨¦5e¸„´üÏé¼3k%Ôê†G.ÉóÈ#Å"BÜòX7GA\öˆ×þ‰áâ[ŠñÍ­åzÏ"ä”áBˆÜú%VΈ>¯›Ç2Úºtˆ–üM&ö±ŠL9²æHÞƒ¤·/ø¦6`®:˜ZÖžÏxÎ[»A”X{¢$@ÎSP®DŽò¼È]N,÷›²í±-sÒóvwýó§êÄpÙ1Љ 6å®|_»:õTíìýÔˆyAúÔJ¯%v³šV¶Îo‡õ¹E)ÐuÇÖµnèXí&qŒ¦éÆa iâ/ã‰Þ•ÆàLQ~䆞¢½êó°è8øŸÞí1>ÍÝ’†fP)K áª*4òjwZmUoc\qKýCS}• È‘ÍõmZÅm¹èAæÐ?(¿N<° C#"£ª€g¸&OF%`Ï”wÊr7“í¹Ù±ûZ²¥ö†îì*r1•lÒ¹PYNTZK;tÍrÃP¡ºÔéÍ” +Ÿ¸z +(sáÀecàI ö„&rÓ*†Jü‚BÁ‘;/ÂPFQTù3XÊ:É[¸²”©t·+Ò=Î ¥Ý„I‰á3¯.¸¶ MzJ9±†|шJ)Àr”Э´­l) mÎKeK”NŒ“xqÖöÅ!•:tÞ7ÇB0ýLß/6ÂSÆ ];;.³‚ùÒp0Þý©mm8W¿¥ßœ8üĪ*ðÎ?@íÙ¶W\½ð‘uÔˆº4Ʀ;ˆÔ¨V#m!"9¿©½:·clënl–šÂ‡D¶éáò8«2°î2§›4`f鋢Š“â®(¶å¡*¶-š ôCÑf§aCÝ1óÈ›ÙZÌw#ðæ?؃E‰ ]U,«Eˆ(–·9†wN¬ +S™åš0¶TÌÏ%ôhÚЭfÛ‰-J!•™ïú¾2óo…·¶­ºü¶$U!, G y×ëoÔš,pM–ö —ʺ—²:JYËRã÷F¤·/»Žì@)éŸÕÐ6·éVÖå¥48]³—cYˆ™¬·iªÜ†câä(M÷6®¹?‘ûõqÀåkßIgãæ§*'Š!äÊbßB&kù‹ +¿ÿðñŠ¡„‡œjÊÝFœ,Ô¶j m,À¬1;Êóïõ7~öÊÊV6È<”räAb+€l¡î¯o¶‘ź_ÔΧVßDαèoË oò9Rü6=Ë_ËæÐò #*öœMÝ5N¯&êy5Qu¢áÑ3gÊtC€ßª®„È_cc( Ùjé7ç[fäÛ¦Ù¦¬‹ó„(A‘ª+~¥Æ±ø¶ƒ“¸°Ó}õ¥¹RÔ“WXü‰Îú °ö€PƒtÞH*ÏÅq[{Š=}¶„­zt|ºxÄý«¯0‡¯\¶ð×1¿lõûB°œVó?ú}ð¢R\=•u*þu¨çö3€1Üí#© +AÕ‘/=4TE‘1ýoXJ~Ázé×¼ýi×AÏ3üŠ×v»fÿrƒ%ÿ°%C_(€o銿oØe|‡y‚dC˜ÀYc=—Ú·¡"\ÀG^`ûV“)ÂgÊîJ;ˆ(Û–u^ì +øC—·à°>8/kêN +¹¹»²½ÎFX:N:!ÈG«'[;懪¯7@ä÷ë´ƒûv|!³A~ÒÍHÏR€~-³b¾œ”¨¹(áeSÓ—º9Öòô!9÷Øì¿0ƾÊ}ˆB6¿ÃWÅPr·>Ô¼jýö’1V_„:g“)ö,i3ÀÑ¥2MÑ¢gÏ$¨5Iʲ‚ò™ÊÜÄùf"ÜJׇó|k0w¹TÎõ-Ã`L;K .:u•vòXÁþð/=é“Ð`ÝÒže&DE°þªx(©]ìßËúðm¶ð¸†®Ï®û—¥ÆX’7Çvò 1Á¾çîK¿ŠCÅ?eÏü†íõ?Sÿß¿˜ÿµ ŒÝÀø1|ìä¹êË +î'çœ÷?­?gý?û”ƒendstream endobj -943 0 obj << +1470 0 obj << /Type /Page -/Contents 944 0 R -/Resources 942 0 R +/Contents 1471 0 R +/Resources 1469 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 954 0 R ->> endobj -6 0 obj << -/D [943 0 R /XYZ 85.0394 769.5949 null] ->> endobj -945 0 obj << -/D [943 0 R /XYZ 85.0394 582.8476 null] ->> endobj -10 0 obj << -/D [943 0 R /XYZ 85.0394 512.9824 null] ->> endobj -946 0 obj << -/D [943 0 R /XYZ 85.0394 474.7837 null] ->> endobj -14 0 obj << -/D [943 0 R /XYZ 85.0394 399.5462 null] +/Parent 1424 0 R >> endobj -947 0 obj << -/D [943 0 R /XYZ 85.0394 363.8828 null] +1472 0 obj << +/D [1470 0 R /XYZ 85.0394 794.5015 null] >> endobj -18 0 obj << -/D [943 0 R /XYZ 85.0394 223.0066 null] +282 0 obj << +/D [1470 0 R /XYZ 85.0394 769.5949 null] >> endobj -948 0 obj << -/D [943 0 R /XYZ 85.0394 190.9009 null] +1473 0 obj << +/D [1470 0 R /XYZ 85.0394 750.8067 null] >> endobj -949 0 obj << -/D [943 0 R /XYZ 85.0394 170.4169 null] +286 0 obj << +/D [1470 0 R /XYZ 85.0394 180.7476 null] >> endobj -950 0 obj << -/D [943 0 R /XYZ 85.0394 158.4617 null] +1474 0 obj << +/D [1470 0 R /XYZ 85.0394 140.0669 null] >> endobj -942 0 obj << -/Font << /F21 714 0 R /F22 737 0 R /F39 899 0 R /F41 939 0 R /F48 953 0 R >> +1469 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -957 0 obj << -/Length 3187 +1477 0 obj << +/Length 2492 /Filter /FlateDecode >> stream -xÚÍÛrã¶õÝ_¡Gyf…àBðÒ7g/3oºv'Ó&y EÈæ,E2"e­÷ë{ÎEJtvÛ¦ÓŒÀ¹ß`µð§6q¦³E’EÂJeëí…\<ÀÚ_/ìÐj õíÝÅ7ïL²ÈDëxq·• -™¦jqWü¼T"—p‚\Þ}÷ör¥­\¾yÿÃÕõ o®~àÙÛÜÞ½ýÆ¿H+ßÜÜÂG]®”Š¹|ýÝÕwo?кâ#¯oî>¼ó÷×w×ïo.½ûþâíÝ€õ˜2% ¢üÛÅÏ¿ÊE~!…ÉR»8À)T–éÅö"²FØȘ0S]Ü^üm8p´ê·ÎrJI¡M¬gX¥õ«l&b£gÕÝ£#ò6MU5‡²~ Ÿë¦~ru_6uGùîR¥KÞw® QYÓ·pÝzW¶£ ͆¾}¸áÛë›7Ãá¿H©ö»7þK]¹¿œ²4NE¬$`E"ü¿Š§:‰LNxúŸí -xÈ(…Ȭý hŸ„³xvLZšV‰Ñªè¨ÚÙH^I$²4Y$&]’1‰ëR)µlÆ<¿ž­TªYþt©åHD'üïúçþFY"2•á=.ÿuÈG¶ø?a˜–ÂZ8{VÃÇ4X_d#ϱîùÐxÝ-:¤ý›w‘mÑ:¡¥‡~W~BÍŽ¥\þTýãËÜ"D²?9»$Œ$8Ìße—Òpš$ð”ïÊü¾r(¯FXüyygà£Ôþ>¯$úZKaæ½wwyJM-T$Lñpób8UfÀ9N@Nôvˆ~ošmÄq“oyöö¹ëÝö<=ð¦1Qˆ@žÌ’lUS³l÷»¶éø‡ˆðí½>¤zY4ëýÂ,ÍÓ,¬7ôuŸÚŠ°ò›ø”²îú¼ªBä„™¼.è¸}ûѹöô2ÞÇáFHÊ·n÷ÑUî™f®ëÞíj×#eãH‡´0;²˜™D ’Îì²k6ýᨹтâæîÕåÊÈ„ñ‚é/ß»OŸé ÚýT:N=`‰0†Áf_9²'¯:‚öDA¹ÁØ#:!€Ìô%)RZÓ Qò™F„ð7ÄÏ显½̉d!ZÆ&’OÅúWÑæwcRæÕÇ -”'ŽŽÄÅ6Hfr`vJ,z‚oNë¥Û‘€Öå:¯^á4D²ë!qØ÷Þx‘÷ù}Þ9Hquèiºë)rºŽŽ+ëM³ÛÍøI+Û¼]Íñ¾%©bÚT ~©åcÓõ4_a =§ôGÊ‹‚¯ï© žÊµ#¨'·ërO˜4ÊŠfýÆfß÷p÷ÀæxVÂßÑAøwÆîYMFô µm ö鯶¥B«„|Îëªé{e³Ëªi>ÒhßÒwÊY?A_ÎÞlP%°œKµ|¦!H´âŒÝ‚Ƚ^MRHÞ=#ŽØÌͦžÍh¡1]Œb઄8´{ö ç+ºïJôH·u®.˜šßönWzY XjÍx{ ï–UiK”†ÐYf§œ®½ÊÙ¥<ƒ2ø÷¼:aìj<ó@6-݇<7‘8`&´ )²ZÅÚ’Éá"9Ie|õÄÇáÌ`<^V8åL†Êåô ØÇŒýeƒûÏ$LÌ7s’"ËÀM½¯Æ6a3oô6JÙÏLEyŽ”ª"2ó(ùê°ssü6 dKi@Ý…±!Š‚½UÅ Xãó­IªGŠu_Ö³ä+’HÏië„ÿƒr* ºêšÉŸÀü1y¥Ÿò[úu}ûšá=]¨tRH­Ó©Ò園¹6ß ! huÕäÅ׺Ü¿wà¡€®‹ù\ãë$9ìŒJŽž¹ <¿}õî!‘M¢Àr‹ì°<Ù¹-*È,ÍX£Šàõ ¨ÆJÄvZÿ˜÷4À‚°}Èëòs¸>gĘ¢žÀý|½æ¢Íû7OZC_š_±m*¤ÂDpl>þž|HÎ1ÚqªTlË VŸ81ºo08£ }Žd¶|›{/KuS¸Ò©€/a¦¼+öÑ/™á«Ñ)˜äÙÆžsvš&vdápxH çóÑÔÝUŒ6ª‰gŠ¦ÄQl¦šd©•fç¤Ó3D—H†)ëx ü„8W‡0k´Щªà -Â"×ñ=õÉz›÷45²SŒ8ˆø˜ÂKçœ8Å$Sc¯Ñ4ý oTIœžO¡Š ù”LvGizÄY|IäX Rþ„5}»²ïÿÀˆN£œ÷çôÁøá£6Œ=á[^á4œ<ö4ôLA`·ár0x>;/þé3øMÕÞòj.Wó([ª]¨Q›ºâ„ç>4–ê">%Ô2ìÊÊž]Ë–_÷Á{¢âÍfEï¼]BîS¾m+oLäprÐX³ÆBU± {ŠSIœè ‚T&ÖͶÍë97§#(QMÌñíäúëz-ærD¤± ®qÝì«‚®¹w3Í“ $á‚f¿C<Ó)³9UFØ$Rƒõ“vZ%¤ˆ‰v0g=&TÓF f}:0½ †2 Ž5\e)±ÊsP¯–f*÷„Zà Ø¥„ç((Ï`óïÒo…²° Ô±©ºWsÜEo*…|ể‘©J³*s½Ûßý0¸Í4Id¡` 3Ô)¡£A¸/ƒ}ŒA¯ŽIÀŒ¼"àUšLy5G ™dDͤÁ[‹³Þ»g>‘™[|X93DƒÉäI€Ä9nbtXÖ§l^&÷ᨃŸ‡>߈½èK >ÞûÌGðxxJÈ’CçLÌŒ¡Mª—ÏpÖ\¢µP&%ň¤ó1ÜãÖ#&>‹À»{þ²Ìc0•Äždßy¬ -9›ÂN<\k)ŸÒˆê8­À^ò 𘎆T¡GKG;&H®EaHôú¡§}7DAζ5fƒcéÇ&\A„‡ýslЛq9nGÎ¥/QèL;:*×63ªšŠÈLò ¡~DCèXÒù£ -V ëOÔ÷3—“ø¬1t`(j7}³nª9çnE¬‡"‚GPBeöÄVHIš0Ê»®Y—rá7ÆE±8’Q4K†h–p߉0pž!ûpg0 -ij+PÂé(;­öÔüá3h2ëb6‘O óCˆ­¥:l-¡âeÑò¶ H{÷ÂÈ£)biO\g·oÛf×ýšÁi˜ Ù>Kö¹usÏŽáÁ먰' r€¿‡òTP€ùg"ZÛ=,hðaÒF&ðÕþ¼÷vªï*ºõñíj&¡N‘Á”_)(ǧŸµ²¨/ q~ÚHQue§ÊôœS‡„fè½øJ«pÞo”UbÉ´ùä«/2ÁIA ¼/j®æ6óÕfÌ-•Ì, ´œeÇp„áÆíÆÕ^2¨Ø‰‡ˆ5?ëqšI½tþ9$ѳŠ¢2¨Z¡l]¨T -H•²/hÊ¿o8—Òù¹gºr5§+üe+5ÁçüÙ#@}‹óÓ]9í^xʲ8Õç] Ã]Œ¾w¹Ga3~óÀ/”šœmëvX=à Ž}?ÅhߨÂ9ÎŒœ´È |Åb‚|6;Ê-z’¼æéžï‚HOZg8`à (7ˆÁ†ck½æ›ï]pX !Ð\ ‹d Y¾6£œc.åP§&jÒw|á@_\ByÍVã_jûæɉy_qWèïCë¡ ï);«Ž½ÛŒò„4 -‘tôÚÄ„¶)Ã;Tèu®r£w¦³§( -®£fw"®höx׺©;°Çn|>”°ÃÓ¶PˇýjÎÖzýÁ”rþ!È£+Œ­$üE™ Bö‘Q™…­Ê"ôãÇœ/Áò±r=?5M[ô°ÌÏ[€Ì°u¸Âz ÆmÜo<)¶ó=P¿+{’‘OíRzwdîØPÖ6ôV`0ÐhõðlÓã>§¦|êv=£lÁá“xý1‡š[ÚÍ„C9ßšÞ4â¦Å7ɵkù ’ß ÿe¬ˆ¦¯¸Çÿ¤ùâãý×þ{Ôñ¿Ä T0iª_ð‡)¶ˆÌ€ -@Ÿ!þêó4Ï©Êendstream +xÚ¥]sÛ¸ñÝ¿B3×™P3Mð›™¾ø_ãK›¸±Ò™Îå ’ØP$CRV”_ß]삤dÚÍ4£.‹Å~c‰™?1 B;LÜd%¾8"˜¥» g¶¹¿]¦Y¢Å˜ê×åÅÕo^4Kì$tÃÙr=âÛN‹Ù2ûÃòm!ì9°p¬ûw7ó…8Ö/BðÙ œ›s/²þ}¿œ‹Øúðîp<ûðéþþƒž]ÎaïÀµnÞ^ß/o?Ò´Ï|¯ßük.„°®ßßܾ¡©7ïy§ßn¯ç‘o-?}¼}˜ÿ¹üýâvÙë5Ö]8*õõâ?Y&øý±½$f8¶Hw¶»ðÏ|Ï3˜ââáâŸ=ÃѬ^:iKáØ®ºÆtÅ l•{bÍ ±CÏõk‚u„ã€=Õ¨¯û¼Í;Õ¢rÀÂùÙ-ÜÐvƒˆ<ñ Ô|á‹Èê¶ ¼}øªÌªáØʪt¿Se'»¼*izMs‘•—îF3rUí;3×v²(òrs ˆ DÞå²È¿(³ƒ¯-3Ú±kÐóÕ~: Ôd’zU¨v[U´ =ª¥G¤·û±»±¯Wüz÷£ÀVBŸ} æÑЇZ•§ÖÊõ+mŽuWmYo:.X+T )Û®J¿LpÈ*ø¬:âuT¼f½/Š#/ß×uÕ0ž“ _tbxŽo½­“º«GÕ`ô‚<ž[>®I#„t! ÊM^*‚µZô¢â oé+e^H0*“éw4Ò¦í—V…l̲šèþ£Ò“0wÍl¥&ÖJ©’P»*Ë?;Ž«²S¥\r(XÅÀàᆀ®Â¯°Uó…0‡¼ÛžCäU¤KÐn@ñ30è…|Ì3E”¥:ÐÌZÉn¯gÑaˆi÷)3ÖòñýÝ{Bìd)7 +S€ Ì>_Ô‘HA… ňÿZÑ·LÕYtR/uøƉUË.Ý‚‰ô`+d +FYKÌ4ü‚óÝ +¦ëúB€¤:ŠÌÕ$'ù.”ÍmÎlÌWÒ§ÝJ3#¶E¾jdsä-WègL‚8Ï…Õ3§$z9e€¸€˜-0ªM¤{ŽËq +¨¼ìT³–©"¼v )î¡ bX¼ìÀb¢>¡OAt:,,;–r—§R§N•ÌP'œ\1nÈ@JæÐÌck_vùn䥑*KSd&ά±­ “V;]‚qB×*¸ÒRR#BG× 3«¶V©Î£”™UÏ153+eä)¹¦…Êž C²,¬ÃÊñ ;T`$ž|¬š„®ÖôeÛ„ÛPC©ƒÁÈPaÐ%z‡-o5$ ØQ—¼K©N·;lsÌYÜo·oyPyÂ}é¶j±i»v½QИ›}Ãç—¶œݽËÓª!k¤få¶ÊSžr=—'9ß×ÏõAäÛ^„/÷]c*Ý*tÎG„pÄ MðÙÑù¦ð±ûò¦†èé¦'ÍE,ì I‚ÓM?µlˆWt¦.dšª# $:xÌ;g(åDð›¾h2Ü<Ž•—ÃmDõB¸ªÿn/m:„Ûù¦Óá6Þ”Â-Š¬Wm¾)UY1¬¢Ð„U™°‡à†t¦p±6?LiWv½/S!ÀÖM¾ƒfH7t0©ÃЭJ÷«ˆ$€†±‚°™z„ò¡7ÕÝê3V!u‡ˆg"}Öº`yX°Ú¾*é-ˆÁhpË7[-6Àƒ¸—„èw?ÙŠzÙÛ'àÙ½‘¬d`-[8ȧ‚O›ØwO{jÀxhþ’æ8»\«=›MßÜ"$œ3AÕºS%Šêëƒù ²"è9¨Gæl¼ëˆŠrRïÅ}Y5¬ó EmYPµF´>fsÝòéU‘A>O) Lw,b©mã›Û„Þ±j¹z<Ée·«^<2÷Xx›«‡^oÛq[¯wgF¥²ãYŒEs—M¨ßÕ<Û©@üNÇm ” tcsÁ]IÌ&‰É$ 9â‘cãEÈP²J»Bã _ª÷tÁÄÖmmaÙæÌp¨wØö9‰>š'Üp}{OûNkÓ‹™îIrõWßä®.8´u+aê?‘ˆ:%°’8a8Ù·GãÛZ÷4Ë4YÈ 7^‹ÓbŸb]ºãÈ/2—U€;²É«…’`kò`b–†ÃR¼Š¤Õ‚¯4B€=¿u4Èrà†b#ñžþLP“- +‰×t‚Y¹gÏß%ɽ׆îO¿€4±g‡Qè?Ï‹Ö9À‹AZá±2¸&ڮ랜)£'–Ð…ÖE„3/ ì0ŒéPy?zI B_ ¡pìÀsArMña¾>I…®u{nàéDn4ó8±<_o=û:¶ã£4ÑÖº6Ј«»;{SF³‘R†ñbÌY+ŽÊ$¶ +ö@fdžàõô1C¾Ex¸Áàq7jÕ´úÈC„dªÎ,ÅV™ ·“)¾›ÔpÔê¾¥Á×±;.ôcÇ×~Àr¨ qX7Õ\ßâ=ÊdüîëLê6ÉsùöÌó-}¡€¹ÐPÒ`¤Ok©ÝÑU[¯mx›:ð l೘’´åþ ¶Ê9\ ö»•.B0ÎO9aú¡E¡U;Ð5:Â2h*P-¯lÇ3p¤ÆyUôMá…Öø<ÉJ?Ll¸ÀdzqÜÿ\*aÒ ô[‹áMóç}œ>ÔWߟîø ™çø6&©~Úã \x÷ya%L">!wIO_U“¾ï¾ä—‰Ž°:*5áŠ÷0]Б†Ú 8[j8Nöìèb8 +Ö‰Êùª i.˜Ã3@Éáîôüêk5pÞ>ÿ:°8Bø¡× ó„ÝÃäÛÁ‡U'äƒî0 DM*çÉS´çØQì‘ÿµÓcoðµ¡m×Õ¯¯®‡ƒ §Ù¶…]5›«¶Ú7©ºbÔ‚ I'{ó}úÁ›v¡ªwû­k¤¹Ä÷vÕ+è:^”2K øþmMÀÿ)Ïu]S'}ê@ÓŠ<ótÄQPTθ;øqSó>.jÁ@6¥á> Ï×¾‡Û^ä‰Ófñ¯D³ÊËl¡Û–+¯ê/i+Ä™³}ìOµ^`ãß%÷B§?§ú_™¡àø‘íű;]o ¶Ú~ LX(TÔsžHnþ¾y*úªÃãÝendstream endobj -956 0 obj << +1476 0 obj << /Type /Page -/Contents 957 0 R -/Resources 955 0 R +/Contents 1477 0 R +/Resources 1475 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 954 0 R -/Annots [ 963 0 R 964 0 R ] ->> endobj -963 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [272.8897 207.1951 329.1084 219.2548] -/Subtype /Link -/A << /S /GoTo /D (types_of_resource_records_and_when_to_use_them) >> ->> endobj -964 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [190.6691 179.6723 249.6573 189.0819] -/Subtype /Link -/A << /S /GoTo /D (rfcs) >> +/Parent 1480 0 R >> endobj -958 0 obj << -/D [956 0 R /XYZ 56.6929 756.8229 null] +1478 0 obj << +/D [1476 0 R /XYZ 56.6929 794.5015 null] >> endobj -959 0 obj << -/D [956 0 R /XYZ 56.6929 744.8677 null] +290 0 obj << +/D [1476 0 R /XYZ 56.6929 769.5949 null] >> endobj -22 0 obj << -/D [956 0 R /XYZ 56.6929 651.295 null] +1479 0 obj << +/D [1476 0 R /XYZ 56.6929 749.1192 null] >> endobj -960 0 obj << -/D [956 0 R /XYZ 56.6929 612.4036 null] +1475 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F14 956 0 R /F62 1352 0 R /F41 1208 0 R >> +/XObject << /Im2 1341 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -26 0 obj << -/D [956 0 R /XYZ 56.6929 555.4285 null] +1483 0 obj << +/Length 2317 +/Filter /FlateDecode +>> +stream +xÚ½koÛ8ò{~…; 21|è¹À~È&i/ÛÝ$׸·XlY–c¡²¤JrRÿû›á²ä(Û^‹;†Ãáp8oÒbÆáOÌ"Ÿq{³0ö˜Ï…?K·'|ösoN„¡q-‘;¤úiqröZ…³˜Å f‹õ€WÄx‰Ùbõ‡sñó»ÅÕ»¹+}îxlîúwÎ/ÿ5B8ç7W—4uysOÀë«óyè9‹÷ï®ƾ„eB˜•wo/ Ýß„ à÷ùÅ»¹ +ßïs9·o¯gfïßßÝÝêÙÅüÏÅÏ'W‹þ\ó ®ðPŸNþø“ÏV ‚ŸO8SqäÏž`À™ˆc9Ûžx¾b¾§”Å'÷'ÿìfõÒ)]ö4 S æWm+$‹cߛޖƒaBÁ_Öqàe@»bÌê`ê ÌW\ô¦–rVˆ}_¢­cÎB&}ì­oPÚ2f~à $ØH\SÜÎÝ@€%Ü@:WÇöžž@Ñ`ŸHI½õìÓL0îű"¢¬ÏzÐFœ]oå첂͇²ŒÝ!g}¨@üWÈñФÇ"8€Ýë¦ê²¹ëyÊé6I‡AÕI—nüÀ¹,2šß&sÅ=M”UGÀÒ,J«-¬Ë—sÉ»â)ï6vCöAJOóG€¨v]^äá[•ôMŠµ‰®@F"ƒTuÖÌw`§òâ!ŒœvßvÙ¶ ßRÀð÷¹ð¸Síh¾e–­ê*úæeÛáfzðææ=ZD¦ƒîȦ^ ~¦Àφþô}.ŠÁàÇA•—]Ö¬3ÍÍlM~†“F@B¹;ö!©Ï·l’&'¶ÜÉŠ6{Ú ¸q‡¤â䳇sI\Ï®«¢¨žŒŠ€áçd[Y :’\:O†*ÝTUk஢oïz4°hŒŒ³ªîÎêi+ÄÙ®mŦÎòÛ<–(7†§\»1@»Ö ºMÞtP¸&Õ&Ö¡L«cýag5ÈŸ®oL1‹™É„bà= ‹òÁ»P]ÔàNÁ9,ÞåÆsAo¬«ÆÊgv:¿º#àm¶Ç×°•ö—¼Ü}dâÁþXr‚(Öû/™’’˜ARì™!ß„>›üaS쉬ÍÒþØ8÷1ÛÐvU“·z7¶tF1Ô§p,MOPò˜ä8¥V¡4Ið”ˆÄ,J裤»Ôšx™—È›tT2¨ôzM3Z}¸¨O}0ÀvÚj2¥¢ãÀ;0î·—&N§ÂÀÄæã2K³¶¥ÓúTlf!¬úôç°~n"giVkï]ï{ïw·JšíÊ£xÒËMz­1³´“1ò´U¤®Ó#Ã}0 HŸv9­]GÃdÕNm5üí®íF1§¨KÙ_8íØgWô…ŒW¶mUÌ¢b*jÌvvQ•ë +_Fˆíé>deÖä)ꑤQ ¡T >åiæÐ@…JŒmîºõG!\ÐQ™l³¿)cŽGâfë“ß}Vüâ¢&[çŸ÷žJמ`˜Î׶´çp³SÂ5óÈÙ•ë~þy 8Ü<"?4×¥mò1›Øº›˜¾!¢«2…¶ï%î +dæž2×ëº <êù6žb*RÃm0ðˆRÁˇ:ÝòÿWÛÏN³†üÕÒyLI0[ýÙuËpsSÊgž/¿êv Wƒ(Š^¸ôÝ!Ëçw˜aœƒ#õdº)é E}Ä+¤y‘ðLkŽ§ZW»r…¢èª v~4vʽ¾™’ÝCÕ“`²Z¥œa*04Ëê1ûú¦T~KSzqN„·¤÷U—ˆö+›RÉ53×ðáý«·¯>XeÇý7µ‚÷÷ÝNpSä8no'ÛtlÓ¶Ð(“aðþ¢t 9dn¸t:–3Ú:H3o»PPÍÉdW è™a¾µE`´]Öë71ZLJ“ê¡I<ª ½Æý^»Iì%gi;D’Ö +ꂤ¯Ž +]n¯Ëã›QßYjR2¼{ËcЃÏQ0žµg<ÿõ20ú°÷Èÿ[)kIBèV@¼Ã'M¿¡lÙZxß\®¦Lô¿¬[˜Ÿ^[ŸùBÕ_–1q¡¾@Y&ukkš¼3Y¹û‡¢ã6ÊÖÏÑÛÔOÝ0éú9U594Ø}¥z©j†ûCaˆPÄ N1S~èKúÿ‹¥ËƒÜeÈ)‚ðQ‚AzÆg»-S}“)¡#°I +Üxx3‘m”Œ^lŸÉHÙ–!©ëöÌÄñÈʇ¼4‘ &N‚oŸ1>è«0®À$…_cfkÐúí !ÊÍ( Î͈jwu]5©²(ƒ,yTÕž0-+å™›&k(œº'lC%íŠþâžyµ +¸¿×úJ«ÚMµ+V„_f„«JK¸&DgW^  ¬~~R¾·QPܪŸªŒ4f©È®W–b5í²Õ/ýÌ€}RS? +ðþeý»‚8> endobj -961 0 obj << -/D [956 0 R /XYZ 56.6929 530.6703 null] +1484 0 obj << +/D [1482 0 R /XYZ 85.0394 794.5015 null] >> endobj -30 0 obj << -/D [956 0 R /XYZ 56.6929 416.0112 null] +294 0 obj << +/D [1482 0 R /XYZ 85.0394 629.0401 null] >> endobj -962 0 obj << -/D [956 0 R /XYZ 56.6929 391.253 null] +1485 0 obj << +/D [1482 0 R /XYZ 85.0394 603.8306 null] >> endobj -34 0 obj << -/D [956 0 R /XYZ 56.6929 164.815 null] +298 0 obj << +/D [1482 0 R /XYZ 85.0394 304.8197 null] >> endobj -965 0 obj << -/D [956 0 R /XYZ 56.6929 137.4068 null] +1486 0 obj << +/D [1482 0 R /XYZ 85.0394 279.6102 null] >> endobj -955 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F39 899 0 R /F41 939 0 R /F21 714 0 R >> +1481 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F62 1352 0 R /F21 930 0 R /F41 1208 0 R >> +/XObject << /Im2 1341 0 R >> /ProcSet [ /PDF /Text ] >> endobj -970 0 obj << -/Length 3415 +1489 0 obj << +/Length 1904 /Filter /FlateDecode >> stream -xÚ¥ZKsã6¾ûWè¹jÍàAäÑÉÌlf«ÆÉŽ•ÚJ%9Pm±L‰ŠHÙq~ýv£ %Á3›ÚÒ` øÉYa2¡Ë|æÊ<3BšÙj{%fÐ÷Ï+Écn ›é¨ïWß~ÐnVf¥Uv¶x˜ÌUd¢(äl±þuþý·?-Þ¾¾QFÌev}c¬˜¼[|þñÝÏß/>þxw}#¥uØ—sïâ‡÷4üÝŸn?ÞQûîöSï¹_¼ÿDíß„ïîîá!¯_üëêý"r=Ý™Yþãê×ßÅl üוÈtY˜Ù ¼ˆL–¥šm¯r£3“k(íÕýÕ¿ã„“^ÿiJRF™)”KˆJ©”¨L™Y­´Õ˦Ym®o´•óêp-‹y/b¾®Ûú±ê5õ =»aShÄ_Ý®îAz6×óÛ“šnG£÷]³¨«é‰´­OaÒå+OºãE»ê˜/œw9Ù„vE&-aëÈþÝ=}AãWÝaÝÓG';ÏËLçø›†¹ƒ­àØÙM®\–ëÜÎ@+²Òå‡íY¸{O¬x²8Žê:&wgÝ“Ó -¬f~oöTf¹Ð¹ßÓ”°R9È ªÝÊoH‹ùªÛõͺö&æÛ¹œQJ• *–býgµÝ·u¶ê¶ ‰[—•¥Pl›]Õ&Ó9œ¬°§‹ ʸXϤMÅ;Ûu‰å¬Í„ -FÙ—´·¤r™ ½úš©Àã§l¢b+åéykçÕWÛq‘´[S£æ9¡9ö[0ƒU½ˆNG ‰ÃÑvœÝ«t\ǼÛx]„ïIº]Û=òŠ4…QñR›¡y®G.Oìé•l°?>>’îƒqÒQ ùµ;‰®Zùó‡ï{jA¦½!åØ̉è%½†§ìˆòèÅ¢ ¸ð30ÇxItkÀç dãc ¬A›ß„P«c;¤ì‰Îã‡ãrhÙ‹ݾY%ýö‚½…bþÝÇ»wÔ¢õÀ{Wmë-\‚é7pžáŒñ­ZdåØb‘Ú› v¬k8]jî ÄiÇ)\‡'Á3íiÚôæBox‰mÕ^Ÿóc¥ý÷mõìGƒªÖ«¶:o¤…ãõì›qˆ¿. -¶ÜÙ¼Ãî!åUVDÄóhyÑ~_¯š‡WZÏoÂ+‰ õD"[+îÍ•óÿlêÑYã,„&ODé»-Ï`hŽ.%8r——Å™½¢5–FWÝÓûKÓ¶¤Z$tDôhï½á…N“È>|"°xHA-dðoC­6–·<Ä,–ÿyå{å®þ‰YŸ0™5žÙfÅœóCâ#ªòÌÊ\{TÐî%Óà—Uø—³(ÜÔµ\@®ã?ÇÌ^ -PÌÛ#„]‡f¨v0 'o†)¹¿„@`>ȤùÂÊ;\¥9¸À–?>¥è<ÖDóé <=VÁ³­«ž›ø]†¶uˆ~ªSnñ;6chñÁ'"NΫÔrr|ù%À—`*ƒ÷Cþ¢ à|‚s@^WCE-:'IÇdasøPÎq£ 7_\—jŽ~ÂÀ‚'”¯ã8I% ¥këCå" ûsjPi¤LqW/ÝቨUÓ9BO\(ÈûFzµ q¯y~¥—ŽO3LOeIߤjª,!q’áþ¡>Í™å> èŸë~xG ›?»Ýâ[q~ð8€W¦~Þ— -îˆçŸ¡£ë_ìy˜0âöÖW.|ÿÒÇK~~nPšVŒ3³œ=·Ôµ¯VOIQÕÂ¥Ñ%¸2çÏ¿ì–ˆ`¯LëˆÉçn @ê ¡-Ð×õ?¡ -txÕÁ(1Âùãqt0úØÇ‘C×µLm›§:ÂÄ$è’y¦ -sÔæ1eME&Á$£1â¼äc w,°¬’C¼WJˆãV[î<<ΨñyZ­ ão¦\Vk.çEîëÕ -4¤_gª1Rg:“ÙEyJj•A¤_Ìr“ãB.YOŠ£n¦Ã.9¼œe$³„¸ÁfÊg–’U þ%¢30Jø¼õŒŸ|•“ON|—)þpî8' ‚Ý/›:ú°€KHa ´WÝþ•º}¤ã\fè‰AÒQp‹}èQ\½ ˜Ðc„Æ]bŽÇ]DMÛ³¸>Å}'€»}K,à¿Kˆ´CâA;w¹ÏcJ*²©Ò½ÿ•à3ÍS©³ÂÊKçé’Êl,T`À„‰À5,õ -ñ,…¸Hs (5Û®ò¥.^ÚóÙz¡¼‡8àlD®}°EsÀÜD ‘’ëuCu0h/Y€ÒØ,Ïeyj.›ã¶ò£I(ðÜ“jlª=w<Ö;ðQ\YÓóm½ÚT»¸+ L؃7fg¤X›ShFN¡«ˆ>à32o45³™Qxê5½ã¼‚'Ó‚P)¼<`È$­ÍOËF¾Àí'K´Édî‚fuÉ S‚Θ0g0©/ΚËÌHm¢þð‘•€¼ÂœºÍˆoÒ1C -¾ªz - „Ùt/õDוdå’fd>‰²òôW"RZ*)Ööµ…pHãAQc€æ‹@!óòX:«¬>'NybÏúF†Ø=¤¥«òXÈ^¿B<جH¼Ç=ÀQJ¼à>LYÆCÛ×ì2“ í\VäNÎ' ­¤ï) ÿ[!3A³ŠVg"¼ã+¿¥³ÒÊLˆ<¤”^$@ Ä¢' È!/zq®ÍO»îeÇzªh$…ÉTéÆ™ÖiÌ5œN ßyM -¶|üßùò„R!èyìØ5Âiq^·f@ÔÚNGûºI©ž¸9=C@®ˆB -·o¾Àbº¦úž&\Õ=¯d‚Ó÷aŠKѨðÀæ@pðQ}ÿtNÎÅærtÆ–çÎB‡BÎÅNY/…@J9V_•=õ‰aaéspÓ ß±P­×„Û.„ºÎEç_1KŠœÍÆû˜™;>¹(†t}ß,=¶8®(£ÃÒ ¯†ñ±Ëë4>¤QwIpÎEÌ_ÂÍg%§*£•Æ„Ê_MqPÕ }Ýr& Y<7ú“9¦èí73™þ¸äu›ÂÎk‚ôR0#Rø¢¾d¶Ãæo"ÌÏ}(D˜1Ž‚7ÃGŒÔÑozu@f’fùþ%L"zª¢C‡¯OÁÓ'#Æ]^Ⴢ"›âä>1°‚קZ#<öuœ3qÞ——„ÊùK»¡Žgj)-\fT«ëãýl½d¼zñÙø4Ãäð@Ù“du2`ÜŸ¯+Žæ•ûJ>kGAûÁdMjù˜–º±!µÈœ«jrÃX5:yh“®£}XöÛö !¯u2T ‡nOƒ[ˆ+’e–% * ÜUµ¯ÿLß?˜MdoCh P[Éíü_[9®´¬ö¢"Ò(XÜø.1Ñ7Ü ›»¡}ùW_”繪‘´­Ê\nÌùµ ÝSOL_(”bP¦ ×ÔSðL° ásÔLL‚ÑÖp…°Yž¹ ûê¸ß¸`ñ¥§Q ¡Ï9u/gæ· ï{ŽÙb‘çâ¢>J˜êùÔðbNÖnÓ£ŒG€Cm}¹÷3 %0ŠÿzH8ج -–þvA•c«ÇøÀ†û,¤ÆAg€hCõoœ€}¼ew8ýš*çÐð‡#çô/œÿn1]/‚0Péú\í8 °ef´>+sŒBOD‡+^ .ùRéØ{.¿$=ÕõÞFñ«ˆ š‰?½Ž7]áVý:.½¯k¾Y;î©«ZQåoÀ:®Ä¢jè„Ëð+R7`Áór%Õ;ßÑÜDÔà3%<Í«çªi«eHùâ„ mÏ&Áªa7^d5UËuıJ/$ÚôúÕ”S¼|0DÊÞúëä˜ø§DaJÄÿÿý·ªñße¹ËtQ¨t…K‹/‚#Sxú¢þ~uÉùœ”'Cendstream +xÚÝX[sã¶~ׯФy fL^;³^­·Ùl²v×J;™Í>Pm±æEáÅ^å×÷€¦$:M“¶‡ÀpnøÎ@bÎáOÌý€±Œçaì1Ÿ ž–3>¿‡±¿Ì„™ãÚIîxÖëõlùV…ó˜Å æ뻑®ˆñ(óõö“ã1!ØTpçæýêváJŸ;‚?qŸ¯>.Tèüx³^ˆÈ¹~ÿdfôö‡››k=º^€m_:«o.oÖWiØ3z/ßüm!„p.?¬®ÞÐЛÆÒÛ«ËEè9ë>^Ý.>¯¿]­‡¸Æ± ®0¨ŸgŸ>óùRðíŒ3Gþü :œ‰8–óræùŠùžRVRÌngŽFõÒÉ\ +Τ +äD2=1J¦à0*T0½aHÙÄ|íÒVÊRÀmZ±¥ÓŠ¬ºÏ«ŒÚm¿ß×MG\ßæ÷õêª8h=˜å[)Gæ]°IÎ]Å™'Á_4Ýü™æ¹:9õ?áiÚö]Mý$M³"k’®nþ-—?d_º ÀB9Í"rú +Û ^JÏè‡âÃæÈ0€­ÂµÉ~ß.ë}VµmAˬ»Ø¦è¨ívÁî1ıц&±³Þå--|Ê £:麬ÜwÔÁ¨ñ›Wy—'Eþ‹±ÙíLÃÔRdk)èÛBÀŠLλ;£Ãè“àãÜQÀü8ô¡%Xìû„¬dSdT2Ú6|·æÛÚo[жw}Qt½]\ë÷‡P Õ`%g´—ºÊ¥T¸aÈüH„&?ŸÌF?&yAÞ`÷óDba]È£à(¯:4éûLÆPÊ$óLÍ`TàSî°Q÷ݾï°íaR´,­ò:E´¨ØЂ£/ E(ÉÂ0ôŒ#eò`,äUÛ%s×ý)ðïÙsZð´ËÓiê4jߌ–cïËz›ÿĹ̶Կ|ÞÞ~G¶Ï»ŒVÃ6ž§\*`(Øz²Øî–”9O*ø¾gAAÅC_öm3J Áû‘Ñņü + $íðˆÅ€™ç#A.\Áa_÷y±Íº)¯ß}0 [Pu;j!âëçŽpÜx*Iêÿ¾Ë`ÛD¬œÍ {¤[1"—›œ¢ ¨Ó¤Ëk³¬¾£¯öœ´o»ºtQ]GCCÒõê|Ó$Í:%Ì5ÖòvŸ¥ÃŽ¡à1OŒÞºBù}OÐcƒØ”©ƒÓä9uL˜ä­/gð®n¨ñ]^õ_þuúÖ‹X:¦ä‹¼z8Ý¢ ò8ßë@êÇ|›5xì^Ø%`²mI@IÂÖÆ(Ë*,ù­a”êÄÔYPzg©èùQ±¯õáYï„2ÞhØ'”RZ@ÚÙ—W74ô>;ì33ªydioø¡êŠ áéI-KY@¿FWÒš/­VÒÝhšÑ&¯Ð $P jGDÔ0ëÉ.&KfºÅ°uTžX%|´¢DàYAÑ®n5‘)©Õâ0%1v°fGË­“(ÒVI¼9˜Y[*%”!q¹¥’†À` é ;cpµ¢1`¨­–„ÖçÎÎB'…`éö9^ÚÜ´.ˤÚØ´ãVÌèüÿšŽ‘tK_Æ–°[x‰ñ©œšùl >Ýåà‘9‡V«W_ݧ)u0ö¯LÓ%èºr¸¾½EPY¾òŽãp],'×Ü,^iQí±†ÿÌZš~ºt Ç’°¶ž`wpÉ X ~D,ò÷Ëm]$ Ý.þ¯¨å¬W_’&ݽJÊmàý6|…Ò+þk𲘠+¼)Xݾ­'§€·& }.´¹6;Y—V +ѤR“¢éÊ$Fß÷ìà„þ5•ÈNÅ +Ë}‘äÈDŽádSã-G†ã;Um¤OuóðGåÊ9Ô=‰Ëä@ +vɣќÐGÉ¥å`-5nÕ,íFžÀ%!oˤKwlj ®|‡±Z«¡°VC¼ên­…>ºm €}¢ë E5}ŸÃ¸WÚsT²«û¬ßd'zÚ¤4-}ʇ`k‚½áppá i¦<Ü÷p¢¿;†Ò|vÏ3’Qï‹©óÿò®Ë ÞÒ1‡]Ø—‰yú/>÷W^4¾ÔŸÃ óÀ]ä/~]+Ì÷Ž +:Ö¬z9zŠy*ˆŽž º„ìá÷‚%X$xpfæWÞ#~,NŸRgyÀ"¼¬ÄÔM^™3c‚´×úšS×Åo8 «X±ŠÞE¿ÍZ&$,áE\&ÉÚ¬#)ÞØQÐiS¦i†öø£Af„Z ýæöû ‘sÁ:M'ÇìØ]#ös²Ã=<0Îã bÅÊÎ&û±s"Š"vªì‰ž] +ÒʽðäÙ&sàÐKrsëCÏ.”R ÔQL`Mø, ý.òI¨AP#¯Ñ„ž¬mÔ›»´$>½Ãøð\GšRCtÂ%HŽ±ÿfêÁ‹?Šäð+ß1„@](1N¡ÿJžyn3> endobj -973 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [519.8432 463.1122 539.579 475.1718] -/Subtype /Link -/A << /S /GoTo /D (diagnostic_tools) >> +1490 0 obj << +/D [1488 0 R /XYZ 56.6929 794.5015 null] >> endobj -974 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [84.0431 451.8246 133.308 463.2167] -/Subtype /Link -/A << /S /GoTo /D (diagnostic_tools) >> +302 0 obj << +/D [1488 0 R /XYZ 56.6929 596.0056 null] >> endobj -971 0 obj << -/D [969 0 R /XYZ 85.0394 794.5015 null] +1491 0 obj << +/D [1488 0 R /XYZ 56.6929 566.6651 null] >> endobj -38 0 obj << -/D [969 0 R /XYZ 85.0394 570.5252 null] +306 0 obj << +/D [1488 0 R /XYZ 56.6929 532.1171 null] >> endobj -972 0 obj << -/D [969 0 R /XYZ 85.0394 541.3751 null] +1492 0 obj << +/D [1488 0 R /XYZ 56.6929 506.5445 null] >> endobj -42 0 obj << -/D [969 0 R /XYZ 85.0394 434.1868 null] +310 0 obj << +/D [1488 0 R /XYZ 56.6929 353.6477 null] >> endobj -975 0 obj << -/D [969 0 R /XYZ 85.0394 406.5769 null] +1493 0 obj << +/D [1488 0 R /XYZ 56.6929 325.2657 null] >> endobj -46 0 obj << -/D [969 0 R /XYZ 85.0394 301.1559 null] +314 0 obj << +/D [1488 0 R /XYZ 56.6929 132.6175 null] >> endobj -976 0 obj << -/D [969 0 R /XYZ 85.0394 276.6843 null] +1494 0 obj << +/D [1488 0 R /XYZ 56.6929 107.4872 null] >> endobj -50 0 obj << -/D [969 0 R /XYZ 85.0394 200.1512 null] +1487 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F22 953 0 R /F21 930 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -977 0 obj << -/D [969 0 R /XYZ 85.0394 175.6796 null] +1497 0 obj << +/Length 2294 +/Filter /FlateDecode +>> +stream +xÚ¥Y_oÛ8ϧ0° ¬|ˆ‰Ôß÷6î5›^âKÜÝ+Úb![t¢‹,ù,9©{Øï¾3œ¡,Ûj›àà‡äpf8óãPö.ü¼A8®LüA”øNàzÁ`¶8rw0ö#çØf’ÝõjrtòFFƒÄIB&óŽ¬ØqãØL²Öë·gãÉèfh‹Àµ|gh¡kÿ6ô<Ï:»z=:§¡ó«["ތΆ‘oMÞߌ€%€ežÇ+Ç—¯yÞOžGÄ'7p_ß ed}O†^l]_^GoßÇ×zt2ü<ùõh4iíêÚî¹úïÑÇÏî üzä:2‰ƒÁt\ÇK1Xùt_JÃ)ŽnþÕ +ìŒê¥}¾ d챈zœ)DŸ3ƒÄ ¥Ú™%ÆÖû«‹Ÿ¼ËËõêO×y‘ÕÇЉ¤ÕÜ«Z¿©ª¢&2]¡kÔv~CdU¤+ŸçÕÅÕ9Q 59‹˜Uå'×wk•÷)oîy·{E’> j¶gÙˇY­O +øղɫÒÁsgØp¨ImâÕõdtŠ6øÖÅœZ#i+˜ZhkÕÑTíl£jlбg­RPjųîÓrw>) Ä2Õ6UÍ÷†8à€úÉì¿ÔöWy¢¡¯÷rq‰–l“ÿ{Ì}Ê‹bhKÐpª¸¥#!’ -‰5Ç­€BÍyÙºÌT©2ȚȕÖûZíI´ÔÒ‘0½"‰í$´ŒÞK?ö!½#M8‘ð’ç$Žp’8ŽûÓÆn%Ú]‘‡9áÇ‘ãF¡Øß\ÿvqƒ~¶}W@â„ñ®¿Uù˜“Ë…*‚†Çt•§ÓBQO´õRÍòù†™÷<ÊÒ™·Ú Gƒ(Ú{ƒV‹9Æ€Œé'„ŒÕü¡í¹® '”—w{‚ßÞþ“ÅtRDà$´”7ùªnŽiÁ/\¬k6‘RˆõrOøjC 4ù‚û½ª÷m½^ªòööuÒ2#¢”‹|º÷ªšº3z@LYPQ¥™ÊNÉ>ßÛµOºND䥟‡vþQ_–Õª!úÝùï.^ÝœÝ|øc|6yû÷∓u½:½OþßÞ¬?û]ÙÝêwJà³BrЉ@7eöÙhLÄ¥Ú,·¹$54@P)¬´Ð®N©fª®ÓÕ†º ³·Qz8!‡«YJù¨µ˜ï o‹tvŸ— +IÅL/ëñtŸÏîû§n*BmPPJaåå¼Z-x3d¤ÓJÃŽ”œÿÀc35=¯˜X×<:ÝPK§ õé#k¯€Cñ°Ñ·>^åA¨1~g;6:d+Û*Ý/¾9AD`1zÂ0`¸;^À@!£NÛÆ+RòÄì}$^9"„ò€äsªú‚×ngÿ(ˆ/GÆ£›ž@îÕïÇÁ;¡[_&Éa*·`WÓ‚˜ò* HŠz)5L•Ž]ãr\‘—Äà <Äü®‚ª˜KxÐÊÃíÂAÜj­q %…Žþ®|HZÇoA»ïxg*[›+@bÝ6­5ÜEA jÕ0ÐdùçÎ-Ñ/r¢F ½.4“kÈ B?bÌ ¯¹ùW#ŸxÕ"ošv//D¤a&±eˆÇ¼É‡ž¥mš¬ï´÷¯.O5ën¯³ï—â™å’碚=¨ù•Ê¥}½^ˆ½_ ö>jIí³êŸjóGU´ƒöëÖªÒM÷šš›ªÞ|dÛF¸ 8àŠîa¡*SvhUÚYŽ:v“ª}©·_Öv1§ßú;@~Ãïùxï¶_óþï¿ +¶ÿ©ø‘#ãXôñ”nèÄ"‰ŒRèV)÷5oÿS8Tý/Þn­™endstream +endobj +1496 0 obj << +/Type /Page +/Contents 1497 0 R +/Resources 1495 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1480 0 R >> endobj -968 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F39 899 0 R /F41 939 0 R /F21 714 0 R >> +1498 0 obj << +/D [1496 0 R /XYZ 85.0394 794.5015 null] +>> endobj +318 0 obj << +/D [1496 0 R /XYZ 85.0394 704.2027 null] +>> endobj +1499 0 obj << +/D [1496 0 R /XYZ 85.0394 675.9152 null] +>> endobj +1495 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -981 0 obj << -/Length 2457 +1503 0 obj << +/Length 2284 /Filter /FlateDecode >> stream -xڥ˒ã¶ñ>_¡[4Ušø¬œÖÞuv\ÞÙdG9¤¼>@$4b-²Ž¢|}ºÑ ’’8Ž«R:°Ñh~7$V!üÄ*N‚$—ù*Í£ E¼*š»põs»Lóà‰æT?lî¾ÿI¥«<È™¬6»Ù^Yf™XmÊ_×"ˆ‚{Ø!\o>~¸q¸~ÿùÓ»Ç'‚ŸÞ}bìó¿ž7>ü5ŒÃ÷OÏð÷B$i¸þñ㻿o>|¡yÁ[>>m¾|~ÿÏ7ŸŸîÛü|÷a3r=¿™²üûݯ¿…«.øó]¨<‹W'„Ès¹jî¢Xq¤”ÇÔwÏwÿ7œÍº¥‹’a U"D%å’¨âžiÐèÞ™ƒ{s|õpe{Sïîé«™Ì]Ûý¦ëvÖ0ÄÀÎ (™•Ž7t „ßø«”Ѿ*KX Šé€ƒ<Ž¥»*³D@žD×—ýª8Zn M=»ùKb€ãðv)!i2F¹1†D¨Id€E6[³5ûª- § …ЭOº®—n¤ÝŠØ©†ÕôÐêmÍ°YŒšnš¡­ -my¢¬hIaë3aN•SNìU@7ؾ*ypêŽu C`ab5r´CþT&£ÆàLa¾¤ ¸á { nx¯g§þž7››+ì%£ DäöÚ8V²ˆ-¢ïj2ÀÔÕö¨•éixpÝ+ð[f{¦oÓõ– î`PsŽögÐHãÖÇkÍ"t,©|Æ’L³@dÀeèXêí°½åié.qDR -^÷,ÊÕº1º9°{m=d˜]=êmg <(¥‚$ŒÔ¥)úÀºêvô…K‚A4tÈdŽ`Ñ”ƒ â0^a˜ š%Y˜žÍ~{7jÀ½_Í5^×ßÆÓ® §»+>ô`÷ݱz¸4n -âôóŠtiLAâ^¬=:)Hã±Å R¢$3áE–ú[¸ó`™»|5MÖ]¡k´d€€ã`é(7FîÍ|ÆÜ*Þh(Ìëe7•Ùòœ³Š - ®%~êŽ'},Q6ÿ³nøðJ&’PÌMfR…ˆÉ,§ë²sn‰óeÀ ·B•AER2Ë0`¡&X]jcyt%Ž S‰Œ™BæSF[ÐÆg¥@|º]ªJ°óI£)¾¢l–RHE„cñÒáÍqW4qüb‘I {ʇ=@ü>*¯p@• -B3¶œœî!k÷»3 vd’ mäbÝìÃ/î×ññ°–±¼%+ NI.5$BBš\ -¬9ÈÂßM%n×újv¡ƒ˜•Ãº;ÓŠ(„ÊÕ¥d£¤Y™Ž™È² RBúÈ“ùÈãc˜#p!-#ºÖ1é)º9=qáü’f»LRŠPdˆ¼ž/"2 F G; }Ôt(é µÂZÙÑ÷ô5ÿÞë¡·~Ïžn—ª7Ýö'§Ìˆ*Tú®Ú»è4gö× º‰e4¾ó¡ÂRèLsßq‚º+Ä»PeG²Â#Q¿§)2ê(ôÆœÏÊ<Ò2 _ªW¿y_ÙÅÜíÌ5‘˜r¡…(,.k]ÄP0T‰òÕƒô±—Pq!§éGܱ5<ÍlbM¥Ø¦;Z -S¦…€Äüœºã2±öŠ 41ÑÍ–,÷úBäí]¨u›«˜úDOâ‚ÙLë–3žatÙ±º÷5vxnïH‘šªmÝóìAߌå³ìž¢Çð²÷CdÔ“õ±0¤RsA„$ÏW¬DŒ‘ß!]ÆZ7]2}e1¼¨„ë1Üi$žo1ž-Û¯N›$†hj¿F&zÂRå§Þ*'MÍ{ˆá`æ[?ס'œUo›rj¸ÂúuquðÏ _ºÚüé®= ×?<>½'È·^³î' Y܈¬8H·† -8hÁ;ÑÍpÒEë”’ÒÙÛÀT©áßÿ?J1BŽ- LÖúÕ\-à´s³¢]¬£¦„ÁÝÚìYË¥‹œ?NóNolÆ.Ðúzö[£«öcw2Sæ‹$ôÉÜzä\ò«NÚÖž†ÎÝaž[oßeãi!ä¶*x@NKø®ß_÷Vo-ó§”k9ÖÝËß3\vÐG(%ñ"BRi‘qêHs_é#J—¯ºµú „0.¤Ø¿e`·7 A]{yÑz}àLãîe\¬Ísk³ð‚ÂyúRìlýSÃìÑÉÙhr-àù«C2I Ñh6Ë•](!•7ºØñÁ½ÐlÇAšå©¯òÜ%Ø á(v³d”"¹nO“›î&˪ÇÍ…)RA)³Ëx;5äT´)òKL¥·U]Ù3!É”ÐPñDSƒöCXG¹ËéAɸÖÈ|)ÅãVWö (çWt ŸçüùêhÒB:[ÐîuùžG3½åŠ2I>½+ŠÝ•ðN¯Kue ÍŒ€Îö¢~K¡@œ&¡ZR(œÁ­ -M­ - ZãŠÜƒ[æž.ÇñS!L%:P–ô˜¥Hé!”·i"®"!G­š¼ü…3Ãø(M¶æÒ?/ÕºðõwÕNïÉzê-çÕÃÿ­@úÂ?Dþ ÇD÷ÿï2ýý¥Ê2¹ü—ŠÌ OÕÈŠ%ºaÜÿ?sËùy;:»endstream +xÚ¥koãÆñ»…€×\¾i¤ŸÜ»8‘]K ÐÜJZYÄQ¤Â‡\å×wfgø’ØË…?h8;;¯Ýy­åÄ‚?9ñ|áGv4 "Wx–ô&ëý•5yµ\I¦1"³OõýòêúÞ &‘ˆ|ÛŸ,·=^¡°ÂPN–›†+¤S`aOw‹©i{–ñ) øhyÖÝóÔ Œ=-§24ÞŽW??==êÕåd{¶q÷îöi9{¦e—ùÞ¾ýe*¥4nçw³·´ôvÎ’îg·ÓÀ5–??ÏÓOË®fËÖ®¾íÒrШ߯>|²&pÁW–p¢Ð›¼Â‡%dÙ“ý•ë9Âs§Á¤W‹«¶ {«zë¨/¥%lÇ·GœéÊ1gºðƒ€œùשé[–±ÉÊR­ÍÏêô¢2B©ÇûCªD¦*4óúÞ¶{̬‰éX“ž£Ù,wI95'2:=?&5•#SU2Rê"©NøÕ.ÎO¿¡ñnñ!@}oàNdUWÌ ÉÖª¥e®ëfûJ1Uš¿&/˜¤Þ¯TQæ{¦¨rZ¯KFlìDËà~EžgkË:…íÈ7´q*.ó¬DŬÀH*ZÙÇL‚*Ø‘gìs"&¬ÚâÇG˲׉ÊxêÐq-Uqä½Ú ¸^( Bõ4 F Ɉ¸Ú1‚¼¬‰‰ãïu+ +™eò’%ÙËÐJºùAq•ä™@wÃíÖ<ýÐø#ÏT»Qcð`4 nûY :ù4Uúîy¾ú:¥íÙÚc$[¢8å51|Mʯi¡°|PYW 7íâžlµ©×æØ!¢e½ ÿ’´ç‹ +‰vs( oæx•”ô€,ÇÍà‚è<©†N””Šæy¥nèóý–H³¼" .É©°‹·[†ÉY&?t:ƒ(ûÑl¤ÛmQI`T5‰ØÀ…ð\¦Ãî`U^“4%hÅŠdj ×).N¬ Ö‚RhÉhèßx³¸\”gtÉְ髼ڑjƒÌ$-°®2ëö Ey" +äˆÀu<½ðm¡‡xš—Û¾p-ÉL1ô @ZÕÕ>ÓÐ>.+U4µ÷4~Ùv×™žÝ(t¹4Í”mÝÐ †ùr˜vÛSÓH¼# øüNÏ2­'R>½ŸßŒEõ/ªH¶'­%’ikèdñ¬n!„óק/9Èn_ÞŒ©1_ÌîœçÅíâÝ­c¿¶ÂZ—átª08F¿mdÞq_£~]<” Ê7ôûÐC±îë*9*^¶è§PÇü³Ú ‘egsu3 wM€ôÖ„cK¦ ¢ ·ØwÝ®Iñ¦¦´€ûâ ÖÍA ®Ê^’æâåÙEí÷ }¤ÉhPƒTÛ¡ßTa¬eÐÔ¨V=·wôGG¯ÑT°º„•@jj("zìÄðsU'iEà+Ä-Òíóm>¯KÝ<·°6„X“êàp_[€j£¶qBn×Áõ„øg>Ó 6 ´I$!Ðܵa8é†]8„AS‘‚Žš“4=•ÏÛDô* ëŒû €©KêûÕup´BE=¤¦ƒP\ëÎrõ]Š1ýlÝÒmq̸’¶¡×Å÷YWAÒÇ7=n# êylñ.¦0¿pÙˆY^²=ëìT¿kÁª›Pƒ®»¾j—×ç‡p™Ú~TŒU>Z7:0:äíÈé + Ïð¹Îºf‰ªG««_Wù&õy?V¨þÜòÅò‡!%#îÓx³jÌó XhVÌl†aßåÈrsúdMéä]“&ÑPÒWõD‡NtW–òï.îjø7¿ ?lÄ_û’ÖÔ…nJÚ—d06VdÀÄ ¡~ÒæâcSBÏÊú° ê §¹ÊxOÀ}]Víb=¯×œQ%'öf`€FÕP7¡‚P|ù¢A €UÇ +û>HuÀÕ‰~i¼æŠ@ÜGr +ˆh¦¸‹ìãxX¦bm/›wœÄ’óþ*^åG5Èp0—©ÃƸ즫¹†H¸¦È¸®Ëâd^÷e_^$lž˜ÚAÄãFÙt%\Þ ð†•foz¾|sÕu$%}§Ñß9·(Z‹fDuxžÃíGUÉf£ü‰~! sâwdÇûñi6Ç*vö¾åD0R=±]pŠ÷U\¶ˆ ŽÆŸ·Ì–¡Ù㨟®†±EÂõýV,ºéîq~Oʪì˜P5ËöT‡Á”c\$&Ϭ®- K”ÃËÔU¤óÑŽÒêYÂ}XèksqÇ*Œ¡m¼ç7˜–·TeþF?Í´Zc#ɇK*ø4:¿è¢Zøî7¨9ú‚ÄÚ‡QÂÿ.¥)=!„2°ãŒpLH/ô$|÷ôãíݬ‚ x7{žõÚæèp² +¦ã(N˼ôC"‚Ü9‡Ý(£º,š7(ˆ +O§¬e³™4"’E=y5iŽ놕+Hÿù­ÿE…¢ëay½Ì}o›„»7£²ºx>jûXæfØÓµ½4h¹oŸNÆ^ÒOàó÷È»·Õö ÿ÷+{÷ï¸"NÚãY.ܘ°RèfǽмyŽ¿Tý?,{Cendstream endobj -980 0 obj << +1502 0 obj << /Type /Page -/Contents 981 0 R -/Resources 979 0 R +/Contents 1503 0 R +/Resources 1501 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 954 0 R +/Parent 1480 0 R >> endobj -982 0 obj << -/D [980 0 R /XYZ 56.6929 794.5015 null] ->> endobj -54 0 obj << -/D [980 0 R /XYZ 56.6929 717.7272 null] ->> endobj -983 0 obj << -/D [980 0 R /XYZ 56.6929 690.4227 null] +1504 0 obj << +/D [1502 0 R /XYZ 56.6929 794.5015 null] >> endobj -58 0 obj << -/D [980 0 R /XYZ 56.6929 550.0786 null] +322 0 obj << +/D [1502 0 R /XYZ 56.6929 519.9229 null] >> endobj -984 0 obj << -/D [980 0 R /XYZ 56.6929 525.2967 null] +1505 0 obj << +/D [1502 0 R /XYZ 56.6929 488.8874 null] >> endobj -62 0 obj << -/D [980 0 R /XYZ 56.6929 393.0502 null] +326 0 obj << +/D [1502 0 R /XYZ 56.6929 326.6298 null] >> endobj -985 0 obj << -/D [980 0 R /XYZ 56.6929 363.1913 null] +1506 0 obj << +/D [1502 0 R /XYZ 56.6929 298.4037 null] >> endobj -979 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F21 714 0 R /F39 899 0 R >> +1501 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F22 953 0 R /F21 930 0 R /F11 1442 0 R >> /ProcSet [ /PDF /Text ] >> endobj -988 0 obj << -/Length 2097 +1509 0 obj << +/Length 2429 /Filter /FlateDecode >> stream -xÚ•XK“Û6¾ûWèÈ©qù~ÇÙõV­k+ž=Å9`DHD  -J–}ºÑ œ‘SÞÒÐhôóƒâ]¿xWåa”ÖÙ®¬³0â|wèßE»Ìýó]Ìk²< ó,MapgvŸ§U˜WI¹Û¯…üüôî¿&ñ.‰Â¢HòÝÓÑŸU”eXäeµ{j~Þ·âläô°Oò(Hþxú7m˲*cÜÁeem7üüñÓ/´ú7©Çy:H7úsV“ìå`´gaš ‹)P:6 ã‡}EQð/15W1±”é­”dW‡u‘,$Â<ÏS+å—OŸa[‘­˜â*@AøEaE-Bâ@Ód+.’6›I4ʨq]w#Ö³”Q°Û°¸~l¤6áÃ>ÍÊà×q¢½x“´EéGäå–ÓEN|¤i…ÁKá5â8¬ó<±×`Uàú|.Pg9h#ŽG¼Â‘G{Ÿ±§‘8åö7³¹µÈ<Ëé8N½“$š^Mâ¹ãuBÓ—L kzEë0‰jòÚS 2Ó(ÅÕŸ?¼'ú(…™Éš8 ¬ýR¨ UÓ§7"Îtƒ ‹3#}ŸyÌFGòýÿG„ šÄmiÇ«=Ê,S§qh2ZÙ'1¨oä ->ã;ÆïÅ‹5T´R\nDΚy㑾¦…È‘Ž»½2rì͸*Ýò–‘¾PA5”bEÐQ„žÜXß´‘½•’ÇqrÇù³ÄùÜ©Ýc/©| -hWü(½½Ylovœ;çå~îŒ2-©,Ù<²÷»n¼ªáÄqˆšêØ|>þA콃ÔzäʱºFä®m3‚XÖ –¤ IeÂïTŒ -Zš\2.6&¾SsîV‹ŒJn‹ëè^]Ð4c5G‚LŒTÍ{Äp’¼È§ŽTVûC'4‹èÅ¡Uƒ|-ÓÊhMË4`šÑßF¿é -®gCƒƒ•wz¼çab\rc:OJK§ rM’¨ Ô‘¸·q&Â&TC´´ò¬“a«ìonƒèQYdÏçFÉk„“âªÒZ¨xm¯öx/ù¼UllÑY6HÆYƒX½ ¾?g9)©}Ys 2¬ù±J9‚þ#ûqºýA”.%0©³ w"j*xÈ3n’Š(Ñ­-±5U9d<ó"_ -hZã|jY/ýE‰áÝN6“dy 8xp]7b~{é0h”~’e±½„3×rÓ,Ã,*r¸2Ư{ë³½ŸØøÎê±×꛼cµ¬Ë"-XÔx¦J’VP¶ØW¶Ö6DÙ6ßNõÊ0«åU¢癶¿À×¹`+åùöj«U -^–@Á³"ÊÍ—üŠÍVzÙtg¾ÀæÊT/šù@1[ÔÞ%t\Ôy§ðÈAvݬipûqA)µ15âë/túK=ð~jVÐ$Žclv ô<›Í0/ü<‰†dà¢ÍÊùC¿Dy„W{÷áÉcÇÐa…0)á–qU!r¤Éé´#â·5Ôtë÷ë 5×Þ+­÷Y|@åaµ5-k]–A8,¸z­mœ%ËE’ç܃Ã~Õ~½ì­Žo¥¡`¥˜ÔPÖ…¤%€%j˜eøÛÌ)ÔpË%qÄßfG™‡e—¯²OµÙÇÚ" ŠkäØšÎ$©&”Kv Ó#øúUrvXÓ'QFê­õŸ-„Y ¢ZyhAéÞÂÝ,øhhµ -Ìk±NãØóƒF¼´ùåA¨ÔjZàêæD¡›G>>V›£ÐfËÕ·;¡ËìþÏýqy»àðÃpQÓ8Ø÷(Ík=ËöÑ™–EPõâµ²Ú<‘JD…B¸t>I³Ø渻2®ËZÐudn±3ã…ƾtš'ÿ¨ÂõÍã<=í€xfQXrÂ{î%URŸ›¬cPwMß%2¨vŠÐ9ÎQ °ÄÂ~ûNbÌ‘œÁ*Î#²­œ.ø„›XbI"èÓ 5ÜÛå™I•ƒz -âþî^̲EÑÅk˜èPÄÍ w®@íÄÿýu¼J×b´ûWdÓ3Ò%©p °{ÙÈb6îׄZáÿ$áÖÑ\Ä`ÄI®ÿÔÁÿ»^l¤ÿsnŽ ¤Eþß…ûìq[ÙÚ«Çž¯çƒ/©K4à ÝTnX®¦Uà¿!„¯¤û#P(þ­zEº%ûeÍ[™Fu˜&‘„×Ëß`l÷÷ìÛÓþ sèêendstream +xÚ¥YKsã6¾ûW誥ª,/‚¤ošgœJ<^[“29Ð"d1C‘‘´âüúíFƒ%ÑÎV]e4€F£Ñ ZL8üŠI2®=‰ÍB.ÂÉrsÁ'0÷ñBxžYÇ4r½Y\üøAE“„%FšÉb53Çb²ÈþÞþ4¿]¼¿›ÎdÈͦ³Ðð`þî·©"˜ß¼}ÿŽ¦ÞÝÜñáý|é`ñùî=ŒW°NH¿ôúö7CŒ÷Ÿoo?ÝMU,hàú†Ú7×7^h2ýsñóÅûE”áqA0žãÛÅòI§þù‚3•ÄádÎD’ÈÉæB‡Š…Z©n¤¸¸¿øo/p0ë–Ž™¯ç™é˜I2þŸmáÄIêñm98E±˜ó²,ZÇA–'»Ç¢Þ5F2…Qï])'B°$ %º7á,àÕHIG±qîý-ì8-Ö„„wóéÌÈàÎý\÷´ >žzvÑh"Ç,Ë¡2“o`…Dh­Óv§?XÅ üx½Q“wœq28f'x6”ìŽiä ˆ…Œ´œDl½F@Ñ–d6ÁyÀNÃK'àUeÔdìß—?˜©ab’Éì€ß—ÝÇ)É£HRRL„fJ9D\#äfB®F°rŽ`ùÔe»ÝV»†:Înç@éӸ˰¼Œ!åÄzf³kVmQ<#i >œôš&Ò¢ ‚â&lÙ'xߢ“K›yÕnS“ 0äuªL7–(;(9ËH`í¥e6:sXrRTÕ×v[³±ô¸ö–ÙçNw Ò¢®ˆjkëï—ÞšƒÝlMCçÞ¤_=û·Öîònz¿¶Þè»i´eIYýʧåé.Ët›>^Zý\7vsP>b ¤»SþC)#¥BkîS§XFþÈ—Ø‹;ÂxBw¤vMUéüÔ~ˆ¢ƒ.+’ æ›).‚»oiZA2•Ù-Hòìic½¬ ;â.+¿‡Ýár,ïÉÑ& –Eá4«óÌÒ@ÝG6tVÎ@8ÙОȦÁ}ê‰tÙÍ€;ÜÑû%›êÉú-Wn¤Ú ÄôIã Úñ²ÚÛ'm¨ZÐÒФm³®vy“6ù“‹·Î1¹"îÂÔaú„Õ¾ÓP@YTiFÔ?Uéyé.ñ¼ MšûÀ‚>™7îL¾XÁñûì\bvb9†Ú+¶®÷vGL‡ †Y÷\ô ž“Ïa€/—vëóÌófÛ­ÜvУù”ïètП›.NÂó(A¢A‚`åA¹eºehhKSƒT1ªw2wþéÂÁ Å4 ƒöYÞäU™4óEJ]æ¶H‚]L2u Œ"Ö–ÀW%ðU1Q2Ö¾ˆÊ·†¥»m:Ó*Féù²jF"?ÀÅ¥LÈõ‰?ÜU)ƒ½u‘©~„NDUdƒpŽ1³‡i}®­Ð +Û0h›Ã½®¬Ä*Qª#m1‹¢(øä6uû£[À¦5©çàF½O€JhÂûÄt¨>Zþ!/ÓÝ3ñéƒ-œ;œYD…lËc€ù–ò˜oÂàkYíK" +Œ—ÚÔÍb;°B 9ø’Pá¡mhtL¡/·Â × $’¨šß`M;µ~ïeµÙ¶±Má)4…ÁÖ™ #$¢3ÚW›à×´tRdn·E®ô&†ŠÅÞÄFvaOÅš ʪ!¢-ÁKuãá¸3:‡ƒI28‘‡Ø‡}»¶ð“½FJ_{éMÞIw×ñȱˆ»iwX?ëÄÝØZB4Lwìæ+j…1Ì –žu›îš|Ùiè +3¡“w„ßnˆLƒTB !6R„ØDSáæÑdHp;±Ô¨!åß#÷Ý)ÜõæÚ™·~¥T*»§Üî}oåAwm{¼%÷¸%¨!ıFY6-Ùùxí UÐ¥_kíiÉ­¢˜Åx3£á€PÌÒäîÑ¿ÚîÏåž6\Ð=HÀw&-p×YÞÕTs&™8{bÆ +ÿCñçöŽë_´8—†Z0}bø€ž©'á RLnúz´¤Š}6¥Ôÿ…î$ê|®wg@ÝáÍúxõ®Y¢…v›,¨ + ;÷5øñU^xrÒ˜{T᳑¬îÒ$¯Ëmp%/¶ÙxåIŒJuå…‹3Oµe‘µGBôéeCªšWäÕ[»Ì1“l=†}¬CÙ˜z4H¾ +AËwuø± +ˆ­‚ÒÎþ"b_’C´8qHÂâ8JœZ?|º»þˆ ï—1ÀûÑçɺª!I# ¬ +øa/Íé{v»xÀ1`WÙC|u%^ŠŸ±øQJ»ÜVŠ8ËË™g6pY >yõàûl ì` 3Ïfcá¦ÈÜG;\¯¼jè8¸ÎÝyn¦¤–B§»!:‡!= ÌÁ/Þ Ã¿Ðýuð(Zì²{ò5ëw aàÝÞ—*WW+ø¹‚76&fÚãʉ}q7:ö‹ÒúngG©$Óa$FBŽ!D÷꼡çÃ+˜qãŠRÿ‰•Pÿ_Aãw÷hpsÕ1}ÿ‚N»¥6õ“G郹Ÿ(ýžH÷5’‘ÿ€5¶+¸ËÆ÷Ó.c±Sç%ÏD +øÌI5Á_­ +®á½"c}ˆ1¯Þyç¾×PR‹DÔÞlÄ`!„B,:ÆNgH ~Ò]„£ý™ýÛ¢ñÕ®–€TÑ‘‡dë¡äØb«ª(ª}ï‹}Õ~#‚Íê _ÆTèrÍ bÔqeqüòÁÜèc‡Þ@ã/1ÊÙ>aÎps$ƒüÚ­#oבɄ, +U÷Üa#âð]°öË8ÊÙñoÌX­p=ÉŽ\y‚ñ×~!ý…ÖÀ"öìP÷vqç)|F8áðbCg8ÎŽÀÞ©í^/ü§pÿu0R¢ð9¾û¿‡Ž:b*Žå 7,–IÔ)å^á©æ¡ŠYËhDõÿî" endstream endobj -987 0 obj << +1508 0 obj << /Type /Page -/Contents 988 0 R -/Resources 986 0 R +/Contents 1509 0 R +/Resources 1507 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 954 0 R -/Annots [ 994 0 R 995 0 R ] ->> endobj -994 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [519.8432 268.1131 539.579 280.1727] -/Subtype /Link -/A << /S /GoTo /D (acache) >> +/Parent 1480 0 R +/Annots [ 1512 0 R ] >> endobj -995 0 obj << +1500 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (/usr/local/share/db2latex/xsl/figures/warning.pdf) +/PTEX.PageNumber 1 +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 31.00000000 31.00000000] +/Resources << +/ProcSet [ /PDF ] +>> +/Length 557 +/Filter [/FlateDecode] +>> +stream +xÚm”In1 EOPw¨u€$ÅIg0²Êľÿ6¤¤êV5 oʯÅésÀóή¯ƒÖ×O²Î Ž¢‘ÿ¨#h8Çùø:„5?ùÆ [ÄIÚL’~”F Ø PÈùYÌÀ¹dˆÐzZ8å±Ýƒ²ÙËò‘–Œ€f¾Å(ÌÀE#@x˜oL Û¹[ƒ±ñðù +ä +6\>RgÈbÏWÖ¹j[†› +WŒÏ¢®{6;»²þFÃÇñ÷ø]š¨)Õ/Ô¬Mu;pk;Ì©Ëdh<åE–ñ¬AÏw³ð¬±±Nê¦ó¡Ä½t•‹ùD„™Â²]°Ä(‡;„ ·åŽ°Š­r²ÂÙÄLûˆ T¥Í¡誋ŠŽt’¹w_ =Î]ˆ‹=¦uSä÷—ä"ï±yl±‡µÃ-ËkHsŠöreOÚ³êvg›<7ºt,‡Ýe—;ãÒèЭ/I…B÷&ê(ýê³ö󻉨YÙ¹Ç,çkRÔšÚ'^ m" ^˜h±ÎW9AVªy­Â©/fýÆ"•œãûFy-Sng \Çdª¼˜©Æ¥†Í}B©•µŒÎ$âw1.¶&Øíþ²C¶O–ÃVç X×9g¹E{îÇ< •ãóP)!ÍZÜÅŸLÞª~ÑÔ'¯UâXLµüc“ÅXsЖõÚ¯½˜Ó’~òBL–§èªÆ¹O¦ºNZ_[Èü.øšŠû*]3QôçÇñ!Ö-žendstream +endobj +1512 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [84.0431 256.1579 143.5361 268.2175] +/Rect [377.8384 431.1147 436.8266 441.8991] /Subtype /Link -/A << /S /GoTo /D (acache) >> ->> endobj -989 0 obj << -/D [987 0 R /XYZ 85.0394 794.5015 null] ->> endobj -66 0 obj << -/D [987 0 R /XYZ 85.0394 769.5949 null] ->> endobj -990 0 obj << -/D [987 0 R /XYZ 85.0394 574.3444 null] ->> endobj -70 0 obj << -/D [987 0 R /XYZ 85.0394 574.3444 null] +/A << /S /GoTo /D (ipv6addresses) >> >> endobj -991 0 obj << -/D [987 0 R /XYZ 85.0394 540.5052 null] +1510 0 obj << +/D [1508 0 R /XYZ 85.0394 794.5015 null] >> endobj -74 0 obj << -/D [987 0 R /XYZ 85.0394 447.7637 null] +330 0 obj << +/D [1508 0 R /XYZ 85.0394 640.7425 null] >> endobj -992 0 obj << -/D [987 0 R /XYZ 85.0394 410.3389 null] +1511 0 obj << +/D [1508 0 R /XYZ 85.0394 609.2714 null] >> endobj -78 0 obj << -/D [987 0 R /XYZ 85.0394 348.7624 null] +334 0 obj << +/D [1508 0 R /XYZ 85.0394 416.9256 null] >> endobj -993 0 obj << -/D [987 0 R /XYZ 85.0394 311.223 null] +1513 0 obj << +/D [1508 0 R /XYZ 85.0394 388.3459 null] >> endobj -82 0 obj << -/D [987 0 R /XYZ 85.0394 189.9853 null] +338 0 obj << +/D [1508 0 R /XYZ 85.0394 261.2322 null] >> endobj -996 0 obj << -/D [987 0 R /XYZ 85.0394 156.0037 null] +1514 0 obj << +/D [1508 0 R /XYZ 85.0394 232.6525 null] >> endobj -986 0 obj << -/Font << /F21 714 0 R /F22 737 0 R >> +1507 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F62 1352 0 R /F21 930 0 R /F39 1151 0 R /F41 1208 0 R >> +/XObject << /Im3 1500 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1000 0 obj << -/Length 605 +1518 0 obj << +/Length 69 /Filter /FlateDecode >> stream -xÚ¥TÛr›0}ç+x3EÕô˜ I;ŽÁÓvÒ<8FI˜bD¹8ÉßW “Ä}ê0 Ú=»«³GZ°‹ôƒ]ÂPáF"€ aænwr5vé`ãAþ4ê4u¾^ÐÈP„$tÓ‡I-çØM³[@ ƒž®€@²^.¯W@Ÿ{>a\/ãÕ‰ -.+ù™¤ñ<ñ|* ξ,Óxe b Î6'×ëÕY> endobj -1001 0 obj << -/D [999 0 R /XYZ 56.6929 794.5015 null] ->> endobj -86 0 obj << -/D [999 0 R /XYZ 56.6929 769.5949 null] +/Parent 1520 0 R >> endobj -1002 0 obj << -/D [999 0 R /XYZ 56.6929 744.7247 null] +1519 0 obj << +/D [1517 0 R /XYZ 56.6929 794.5015 null] >> endobj -998 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R >> -/ProcSet [ /PDF /Text ] +1516 0 obj << +/ProcSet [ /PDF ] >> endobj -1005 0 obj << -/Length 1215 +1523 0 obj << +/Length 1913 /Filter /FlateDecode >> stream -xÚÍWÉŽã6½÷W}’ˆæ¢}êt$‡ @ Ì!“-Ó¶0²¨H”N0ÿž"‹”í¶fæ0‡>ˆK±êÕ«â“Å~lQ¤„Š2YäeBRÊÒEu| ‹=ìýøÀ¼M’ -’&BÀdf7NEAÒ‚ç‹øÚÉ·ë‡Õœ-8%YÆÓÅz7ÅÊr8 àÀzû{ôrQý2æ)ÄòõÏx,!y‘3{ŒBˆŒ°R8û_äQ¡ñoª?…ƒ/º}O)ß½4µn½¾(I™ñÌ{É¡yž87?µp0g‘9ÔƒѨš€ÀòYá³ë—¬ˆô©Þ*´ôÑo ã~¯£¶8­nx§²ÑíÞ»¬ÍGûÜ5u«¼ÑN÷ŒªýpYÆ"çÑ»eÉ£KÌØæf³aŒ”iÊ]6áð*9èVnOÔI6£‹•†X0¨TodÝâDwŽ57”1u»ÈT –‘dܳ˜0’Ñ’¹¸‚°eÌ(…bÈcâ½¼¥br ;G‚žù.G“«gïEVÀë¶yÅ•»ÒÏV™§¶¹—õˆ,…´›FŸk[ ;í’Eß}S;\´}aŸ²óMÐõµ4Áœ¶L:ïä¯]i^Ï·ªÈ¬€]„ã`ãí«¦V­æ -\·Ðš­lÀ0M#£í3q‘S ¿ï4B‡žÉx=7ÞòÏQõµ­½ì0#Îôh×ÖÖSív$6Np¼°[4¤ÑâzCm/5™ h 9XèÒ2[ ¯3K Rä™ð¶Ø‡®ó Ñ8'k„’)œã¦U–~;9ûÅs=pdü)G%§ÂÚÉ®×GrÛ6H–¬šK¼K„ðÁJNXV„ÐOžnóëÅOsM‰Õš|Z ^’¢ÈË[»mÝC 4ÔßY>®”©Vörl76€] ½ÓýW;¹œËíª¯®³ -©ÞBg‘Íç°üÚ{áwÜ㣇fé¿vm˜Àº{íªuðÛÖÝFV¼ƒí¶Wƒg‹qà~l.³¿uë=<:°­ÛØž'²ïäã 7¯Ý„ÞPýl–»º Q]Éæ C ½Ç§9L­6õÎÝê/s:£÷ tÜ×IïyÐ{ÿâyÍA÷pëìÝþJÙwâÍJ'ôNåáêÞ«< aáU¤ß3h¬á$å`cÒàjˆçjoHüý‘)Î{ΓáHhJroEDõ—K (bؼ!¼E¿§„夼ð~\4¼Ökô:×È“zóßà"¥ãf«Óß„O`fPYJE0·{pÏc+JøO(®±Íi(„Lá¯H¨×RöÿRؾñÕö´ps/ºo°«ßé`cîÔ\VÕ$ AìÑûÌÅý”ðÉöõ*v‘\ÅÆ aGá9‰ÔVíäؘ¹@@ÃØk3ñÙœºkÉôçOá%× ®Ô¬t°7rÌ)Mþ9~ø~=}Ü„O‘û4÷ùLâ‹ ~û\w¼ %æ&G6¯üm°éCê>Ú¿x>—Ãendstream +xÚXQÛ8~ï¯È£h\K²-û±½Ù[tqW,º³O×{Ple"Ô¶²‘=¹ù÷GŠ’gœn ¦)Š¢Hê#e¶ÉàÇ6U‘f¢Î7²ÎÓ"cŦéße›gûõ 2y!Ò"^VF·…¨Ò¢âr³½Vòéé݇r¶áYZ–¼Ø<íçµJY¥µÈëÍSûŸäuõéaË‹,)þûôMËSYI†Ó2X¢HeU~ÂÓA“ð§Ï_‰ªéñ/ó|Ïÿ‰ñU;Û½€ò¨•å©ÈK´–"•eFf){ز,Ë.úï« Ã»“:½Ý|S§uÉË šWi)kA?ÔYrR­T×½ÂBu™¨ã±3B¦#ÎA½h¤d²Óz ^g†ïº%úlÆ+b¸qÚuz`U2›GÉíèõΖY5^ÎKH"ŸêƒBªßK*ÂV{lÀM÷6ÚŒìF D¨ÎY¢Bž¼˜6ÈÜ&ò0§ ¤RP¦†³àwöÆ'çSʯ†m¿3ƒº(Ä@]wWس§åqç5¿w^‹2ÀUôþV¼UÒ諃Å«d:Ê )‰@ žyà ÕRœ|BèEéɸXú +q¿–D"­Y• ‘¹ÈjmËêÿ@CH®FlM‘e‡Hakâˆ4A~ŒJÐÞµ›Æ;2ûiœæ‚`¯Â|üš¾B{ÒYšãë«gøF )åV¼™ÃfË¢X¸3ó8²ð#Ö¬ÕÓX§U%ë &t;_>ÿ(Pß8wàn$3ö·¸ÅÓJ–Þbx°0¡‡À^oM¼?\: jº·3äŠÅ.…îÙ|˜ëãц›À¥Yé›Îe<èõÞd[°4ÏËòÇ-Š\Ô=䄨tº¢ ‘ÒDPż´î¡bnó‚%Ÿt£(wð0Ò„AëÖ%–ž±ðp¿ žV>€ÂLÀ–U³´Ú™çš¯înö×dbŠ î÷e•…â“%½Lí2/µÄc5l: äÏ¡ó@…âo«W†Ž:Gå6óÖ"\æ…ªÃþ0ÞAo3k[+±7ª¹‹vE u«K´¿ƒv%ÔÚR¬ ÝD«kH¨LUÐ û9\1`Wx‡c9A_9HQ#T£ŽÊ_;M}ÌÖÒí® +í,7 >ßš§’ß&µšF;Ønn 1ûpݵÃÚÈuc0žº½¹§T? žA³ÃòŸhv†ä hèì<¼"¼ÔÎ_ÙZ~Á(u3~ÆJY%Ò\ðˆb˜í½Ø•€¸ÕÜѼzÿƒÚ›Ä'&r:LéœËõÔaPÚ3™ó¿‡vvå«»¶A,¢¿vÁªŽâ +¯“Ä `ÄЖœè• +Hg‘…žEÎJŸ°ÕËûkŽ½.{²úöúâ-Tšz§mØÀ"'©3V‡+úJZ•ø?Õ“²Û¦t¾¦¿  ,çóýÃì(êTÊ¢ºîUÞýò4KŒ_E‘â÷Ƶ¯Qd{‘¡O‹“‘änGE¸˜·«Í.ß.÷`®lendstream endobj -1004 0 obj << +1522 0 obj << /Type /Page -/Contents 1005 0 R -/Resources 1003 0 R +/Contents 1523 0 R +/Resources 1521 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1011 0 R +/Parent 1520 0 R >> endobj -1006 0 obj << -/D [1004 0 R /XYZ 85.0394 794.5015 null] +1524 0 obj << +/D [1522 0 R /XYZ 85.0394 794.5015 null] >> endobj -90 0 obj << -/D [1004 0 R /XYZ 85.0394 769.5949 null] +342 0 obj << +/D [1522 0 R /XYZ 85.0394 769.5949 null] >> endobj -1007 0 obj << -/D [1004 0 R /XYZ 85.0394 575.896 null] +1525 0 obj << +/D [1522 0 R /XYZ 85.0394 576.7004 null] >> endobj -94 0 obj << -/D [1004 0 R /XYZ 85.0394 529.2011 null] +346 0 obj << +/D [1522 0 R /XYZ 85.0394 576.7004 null] >> endobj -1008 0 obj << -/D [1004 0 R /XYZ 85.0394 492.9468 null] +1526 0 obj << +/D [1522 0 R /XYZ 85.0394 544.8207 null] >> endobj -98 0 obj << -/D [1004 0 R /XYZ 85.0394 492.9468 null] +350 0 obj << +/D [1522 0 R /XYZ 85.0394 403.9445 null] >> endobj -1009 0 obj << -/D [1004 0 R /XYZ 85.0394 466.0581 null] +1527 0 obj << +/D [1522 0 R /XYZ 85.0394 368.2811 null] >> endobj -102 0 obj << -/D [1004 0 R /XYZ 85.0394 237.1121 null] +1521 0 obj << +/Font << /F21 930 0 R /F22 953 0 R /F41 1208 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1010 0 obj << -/D [1004 0 R /XYZ 85.0394 206.4074 null] +1530 0 obj << +/Length 69 +/Filter /FlateDecode +>> +stream +xÚ3T0BCS3=3K#KsK=SCS…ä\.…t œ;—!T‰©±ž©‰±1ƒEV.­knj©g`fA‚!ÂVŒendstream +endobj +1529 0 obj << +/Type /Page +/Contents 1530 0 R +/Resources 1528 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1520 0 R >> endobj -1003 0 obj << -/Font << /F21 714 0 R /F22 737 0 R /F41 939 0 R >> -/ProcSet [ /PDF /Text ] +1531 0 obj << +/D [1529 0 R /XYZ 56.6929 794.5015 null] >> endobj -1014 0 obj << -/Length 1863 +1528 0 obj << +/ProcSet [ /PDF ] +>> endobj +1534 0 obj << +/Length 3198 /Filter /FlateDecode >> stream -xÚÍXYoÛF~ׯ üDÑz/’ËæɉíÔA⸲R£Hó@‘+‹…¤¬ºEÿ{gR”LÙnk öšùvvÃGÏG~HC'9ò0ñœ8açÖÞˆ¥™´D“>Õ›ÙèøœNˆBŸúÎlÑã%‚8³ä‹ËCcà€ÝË“gã õ°{}6{žû34züéêlz2¸;»øty=ž8äîÛO®f-ÅÓ<Þ~º<¿x÷yËgüuö~t6ë´èkJ0S*|}ùŠ~?ˆ…Âs60Àˆ„!uò÷ò8cíL6ºýÔ1ì­ê­ƒÈŒ(óétœ Aç…Èg”iè~/ 9žø»G4@i1‰’¤BQµŠŽÌÚJQ‡†Hˆ®ˆzÕ šû•eGu#«×šï-Ò¬=%+ã([–uƒ*yw´Gm®³(›tqoè‹ÒLÿsð´ãc³÷ÆžU¶Ó,wD5ýZVwmQÚŽü-ÊW™Dq™IØC­Gùò`õ˜£d>ŒV«íÅ•ÕîNÖµ¬Í°\X5³èNö5¶ëQ–•™X€JÛVQQ/äS`y5‡Éî–G0 !EÄ^T¨%ðÇžqùϳ ò¸eD@Ú7‹â=Fß4v©ÿŽyhAUè[Ç.4ÿvôè{س]ûØWíÐ;ào¨êV=Ýôn™¾6Sî‹ôîëøœ‡pÄ8¸3pYpG%¡uót$ =_ct ?žpÁˆ;›}PøîÛ'×ê­ò€º³_® ýã„úîTÖåZãÛ÷2ílÅŒÕN·/ì4j¢ý àž=§'ì¿S_MBÈ/»ÛADY€ ëÃ9d)'ÐÁ\CºÙl s(wÁÍ+%̽¸„)NµOò1%Ý#>ŒNïàÿ1<ÔC<þ0<ăªî0rXØgÙ¢Â÷QÁ[_v•Þy/‹Ê‹>C¢Ëï)T Â♨°Ã¨ôÎ{)T¶Öá)&H1.0Ï -õ”|4€ÌJ@Y=? tض%õ€;e&ºYJ•©p¦£"46î–™NxÕÌ÷µ¬R†Õ@g ªQ§–ý-]Ü„ÈÌ|ß}sqyjÖmØk)Ë&jdÇ$·§«ÈÝ;U¶::Ú­<÷-g•>´« òƒNƒPçfªL“@«ª\QÄE£RH‹Ì ¹M¥J|…½°›µ8ªcs"Ër^ÞéôHÛЯ ª¥QRæÙ½¥NA{Ãw‡¶ÂUFV2˜çÐWö_ÆkÓvcÛ;o²¦þ‚m©Ò™`÷#Tèff« ¬NÐ[×6$u,Ä´jwíêÔŸkÖU!“=1’´Ž£>mÇÕGÓe©Òˆ^– -¶›ƒ¤%²‰ÒÌôK…#§[øtòFwÌ2N¥>‡©.?þf(¬…éªdû¨(ñÀ „ÑöVAV9)«ÄGû/#ÏÌÒÖëy­žBnLŽÐ×|ð(å ¦Üî.WM -ÂœÂ|0ÜJÔ¡•RY¯<ô£Š„ù:˜•êÖ1éЯ¹-õaWci”өηõß·>ú{²qÌãAO˜¯£yT†}NJ4TWN 2õ}"ÔÏ3ä‹€¶¿m}i’Dý ÐþÐJ¬dõ¯€tQÅT›ÌfÂïþIËn6&„¸e™Õ{uØçöÝŒYàšÂ¨oüÃrœF2³.xaäÙߢ³eª«, Vr›A"ë¸JçÚ½ckÀ8ÊÌZZÀK\É¢Žæº6Uäit[€7Hcå婪Ôò´HëFaqg‰Œ/‡–6ee+$p_FkMsRó*]Ê=ÕëûºQ‘B»‰í‰-r„PV5&Æd™yÚ;~EÎ×··Ý|ǽ耭{À&Xtè±ÀõrÆ ;O&UÏýå»}n<@Lˆ¡b€Ê¶R)ÅÑÛòÿ\c¯endstream +xÚÍË’ã¶ñ>_¡K*šªŒ7ÍiýØd}p{o¶«Â‘8#ÖJ¤,R;ž|}ºÑEI´ÉÈU)‚ÍFw£Ÿ$&~bâ ãÊëIá53\˜É|}Ç'Oðî¯w"Âh£˜ÑJÁCæíÌ(ÇŒ“Åd6FòõÇ»¯ÞK1‘œY+Íäãã0—-óJûÉÇÅÏÓo–妯¶÷3iøÔÞÿúñ{úL³Â?ã0…a…ç.|ðõ‡¾%hOÍ7mó çòi·-ûºmhðÇê±ÚVͼŠåÄ3o¥-PU9F¨l@Íü὘64^wÔ>lï…›¶åbõB]½®Wå–ú[3Bëþ­Óeû\}V =}ƒoÜ´_VWE€åÁ5Õ3ák¨3@•‘šö1GuóGV…`ÞDV»Ý| ÐÎLÃ×Ð~®«çŽÝÏ´°‰buØŒQ‚€1í¡C2†×ønUEDݲݭÔn·Ÿb¯î—L|àÌ+Xî@bü²n¨ÝOïQ<^#(`}ŠÖmO†±y»Þ¬ªßÐòcIà4Vì ˆ‡ŠZBˆ2¨Vq,«ù'êÖñÕ²z‰/ËfŒGìI £Õ#> óºjúUüªF×0æÚuuótÈÜÀL¤Å´æÐy¬Ê~Gstq¤Ý5 êÖQçG–Á´˜š<´9Õب$(XÓ±ñ¨ÑÂ,1 À,´ h1qÀAb0‰–‰h $n×eOPÄë!`·¬V«ØoëMO¶ªÅÈV•õÌ™ ­sÓo뇯šr]-fÉÙr Ƕíú1‚¦GÖ-3A€ƒÑ¢q6¸!¡™ÒV"ÌlšiΤU$TËçgüÐûz×ò;Zü.龜äU@ù¾]­Úç(/NnÚ’šUÝõÔ –m•0‡§]WE½è—ä¨À‚Ú]ŸÆªce™çè& þ¢ïp‚ðú-Ò÷ÝÇÁÿ{ B/ôD É,÷ÿow?ÿÊ' ˆßßq¦¼3“gxàLxXßiéYÁ •FVw?Ýýóü*ÑBTÌ ®ÎS@ßqÀ»é‹CT³ÄÓL9XïüÑ”¾dJ)3Ñ\3©y–¯œ¯Že$¤`Î*¿ü!IæsyfgÆÙe†D¤Î€8 m"g(° hQW÷z¨rJ€.6[-$sN»øu¹Xl«®;…²š T—[I"!¼"e &ì± À?Í—'$ú‚YínIcÂx…HÍ!/Q áD‹?]- Jê¹Oâîh…šnƒ>^hÁÐî“S­t•Kn/*îÑ4à+„G©¸ƒàvرø &!盌çuöˆ–¯8ˆ÷0q‹©¦³WL\9˜CquI·…†<µÐjüj3Ogc”25¬‘Uâ̬v Xt©aÆÛ™0^#ÒI&Ua‰<£ÝÖ2+ÀH5ßÝC àbìÃ:¢Ð6Uìl©g‰ÇóƒþJÇS.QoN <˜uâ†ë7`¼"Uˆÿ\œªYÎðƒFëÈÆ› §Ž¹}6sʧ†¢ÌnoÇç€ñ +ŸiÇð€ÏͶz¬Ïpª ¹!åTE€O ³êÀí(NoÇjÂxUßkqä9êE.îF¿šØœY¨÷Úm†]Ì¥ÑÖô¡3Τâ*ÐÌ­ƒŽ‘¯f|À8£Ë®E¸­çâM7hC-ñõ–ŸË'Hçé”í¥ë«õñ½²tãȧŠî¢¹éßÚçlÕ7º@§P˜5^ñƒÊœïÒácÝQÛ´Ôv}Ù,èêÜ‚FÖ 1$CÎ©Þ pÁ×Q˜¯;,rÄŒH€! ²r:ßm‰¢xÌ{Xuìú Ü>–‰úñdÁ®êæS„…y²K1¬^¼/7ÜBó šÝ7çªRÃÑ£t»5Uê +*3ëÛk=_>TýsU5Y–ÙaJ’Lè µañ@yÞ‡Òχ˜Ž—ÞÞDÆö³U;/WÅ(+8õy2xk\òy•ãàï²;­ ò€`T/U2uUØ$V*û¾œ/CŽíà~…2žØZfŒJ[}MÅsÀÓéL¼ºVFJ"þnñ?¬_¤ ëóÉ!ƒI®|”ßò3ÜÌpfïø ø¸Ú>•3Áy«à…hd݆ƒ ¬N‚vô0^*|-UEÅÊ,Mu¸½½z._â}4ŠwÏöB]±ª)ÓuƦ.°µÔ>¤‹hã(p>e¯L\þÈ홢€ B_ÛqŠ%!Îœah˜À^%„³Æ yÒX<Ÿ“w6 ‚~1œú¼Ë¥ïÂâÍðb8õЧ©»Âss3F„—…ÀÄ4^9üFv€²‡;‡µp&³UZ1ɵ¼›ÂËl*máó/ã2Ö ×Jô‘z¿rK &¥uhL«ü_fé¿x~UÈŸòsÈÚ%èYB”?a!ýŸa*M÷QO¢endstream endobj -1013 0 obj << +1533 0 obj << /Type /Page -/Contents 1014 0 R -/Resources 1012 0 R +/Contents 1534 0 R +/Resources 1532 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1011 0 R -/Annots [ 1019 0 R ] +/Parent 1520 0 R +/Annots [ 1540 0 R ] >> endobj -1019 0 obj << +1540 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [55.6967 190.8043 126.3509 202.8639] +/Rect [356.2946 363.7923 412.5133 376.6291] /Subtype /Link -/A << /S /GoTo /D (rrset_ordering) >> +/A << /S /GoTo /D (address_match_lists) >> >> endobj -1015 0 obj << -/D [1013 0 R /XYZ 56.6929 794.5015 null] +1535 0 obj << +/D [1533 0 R /XYZ 85.0394 794.5015 null] >> endobj -106 0 obj << -/D [1013 0 R /XYZ 56.6929 480.2651 null] +354 0 obj << +/D [1533 0 R /XYZ 85.0394 769.5949 null] >> endobj -1016 0 obj << -/D [1013 0 R /XYZ 56.6929 441.7923 null] +1536 0 obj << +/D [1533 0 R /XYZ 85.0394 576.7004 null] >> endobj -1017 0 obj << -/D [1013 0 R /XYZ 56.6929 373.7178 null] +358 0 obj << +/D [1533 0 R /XYZ 85.0394 479.565 null] >> endobj -1018 0 obj << -/D [1013 0 R /XYZ 56.6929 361.7627 null] +1537 0 obj << +/D [1533 0 R /XYZ 85.0394 441.8891 null] >> endobj -110 0 obj << -/D [1013 0 R /XYZ 56.6929 167.4388 null] +1538 0 obj << +/D [1533 0 R /XYZ 85.0394 424.9629 null] >> endobj -1020 0 obj << -/D [1013 0 R /XYZ 56.6929 126.8733 null] +1539 0 obj << +/D [1533 0 R /XYZ 85.0394 413.0077 null] >> endobj -114 0 obj << -/D [1013 0 R /XYZ 56.6929 126.8733 null] +1532 0 obj << +/Font << /F21 930 0 R /F22 953 0 R /F41 1208 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1021 0 obj << -/D [1013 0 R /XYZ 56.6929 98.4089 null] +1544 0 obj << +/Length 4062 +/Filter /FlateDecode +>> +stream +xÚÍ[[s#·±~ׯ`žB¹L,î—¤ò°q´>›c¯[©<8.Ÿ5’¦–äÈœáj•ÊO7nœ!ARŽ˜ªSªÝ1@hôåC£‡M(ü±‰ÒD;î&ÆI¢(S“ùò‚NîáÝ×,¶™¥F³a«?^_¼y'Ìħ¹ž\ß hYB­e“ëÛ§š0r èô«ï>¼{ÿõß¾{iäôúýw.g\Ñé»÷ß\…ÒÕ7Wß^}¸þ~Qá¦_ýÏÛ¿\_}ÞéHäï?ü)Ô¸ð8@õû«wWß_}øêêò§ë?_\]çÅ ̨À•ürñãOtr ëþó%ÂY5y‚”0çødy!• J +‘j?\ü5¼õ]K ”’Í•˜Ì¬&ÜhuxØ0…acQ9bŒ²;£Î´%šQÜj çÛ-‘l°%FgÍÄ-¸ð;Ò<îòÄ¢„sÛf/` +ÂÖ–Y2KgCŠû³s”(¾;½ÇvÝãß¼ã|Жq(C`«·+”;}ÿ|šA¯ÑÒ#¬ŽV›åM½.ŠX­Tl¢Æž^?ÔŠÄÆÊ“ qB¸Ø¬éÂdͲéëÛ0ã¾ •4þ|X_2;m7÷¡æ#Ô—H{2cRÌ#N)î©>5=6efú©Zlê.”oêEû„E;e”ËPÙ??6ój±x?ýHuׯ›y˜‹ÓêÍ%›vu(ßÄöajóºë`œOe} W«fu9TO«Ÿ* Ô¶=pTجUxݵË:4˜W@ñK(s:­V©s_¯›îchñªèÿ}ñ[x°ðzþP­+˜÷:þ„n£³sƒ(3Ýt¸@,ù9) ~>.ªyýÐ.n=!€Ï®^Ôó~Ôv]­nÛe(?4÷³¸ïÈÅÛ?PÉ®–IBÁˆûVc_g$è„K;™9E´dâWL=™Í8Qìû1»¢#Viy®äfg³+CŠ‡íÊhzëú®ùü2Ë"õ–Ep7]ÕýS»þ*»ÇzÞüƒRî¥ +Þz©^x÷m–X)“]Ùg0ŒX\çÙ8”)ž`‘€´è£G<ªnoKÖŒ \ð•a¨®àaïÚÅ¢cñäY,@káY8Ó-ªî!š/ï´«¨×ì7Q³%òr”$PèêU¨‚R(Dó¯Û»PwÓô](5«Ü16¯ûeÕ}»c¥^_: +JÜ,Ð@ÔõŸA—[ÜKÃ<5|Ve‡â„“w”[Jœƒ.Ú(â¤f¯ÞÑLq6$¹¿£ÜÂ.Y@6¹Ù±5DSvtY=‡·àŸÀ#Û´Ówí:Tן«åã¢þ2b;ÊÞÉFJŒ›7¶4ž&ÊP6ð‡H·Ö(5±Tì8¸¤yû£ +À hIó „â_ÉCQØ䈣ËTY@ +´5[ËÒs¥ŽÓN¤Qx ìqô?O”p"}ÃK,’ÒŒ C˜ç,ñHžq3V¢ ‘ãqKûↃ&öÐãìQ ]öä²4‚6ðÂØ ­‚A° +ø"Ìx¿ÿîÕ`r0³wÏOàï +<âíïçð¢Y}jŸÆí˜îO:ôèæí£G8øUÁŸ.T$ñÛ±¾´<(nbÅVA xkû‡ª%Ä3©.v& 5OÍb‘è÷ó‡Ø¬šœ•LÝwaOî‚‘Z†_Õê9ütƒ¡4Ø¢àä¯ ™<È!´¡,”ŒÇÑ•„³È–õóîšĘQÛv¯5½‰àlH±7À¸¡1ͯ¹-B àƒË·%Ì@‰4h­QU àé@Iz5Uxt€ù#Úö¿qócE¸qáìÕ7ÑØeØX­ÃIÀ+ú5,ôì;8K4í*êR=߬›>?¬SCi}ìê”8§NiIŒ>®R +À… ÒžR©Üîl*5¤xX¥Fó[4]ÿ¥*Cc_BYBMÛU+Öá¹lƒP´wšŠäå +ŒBƒóWî|œÉO°F ì—:æMÙÜDñ«ðçl¥@ÈáÝØ.#lÇêe3oíª õЀ Fxð‘6Õ«Ûèué6TI"©#*´ÎsiP +⼜dêqPƒ8œßœ9[SJÃRaG1éBŠè®]ÍVõ}Õ7ŸP65 +>ƒcMxÛ¬úúÞ‡'àž–RÜDkBdb{,Â7—kDPø‚†º´‰;˜&6Ü)$'5 5_l:˜žÆ0Ô*Üô=Áa¬ù¼~ì«›Αën +¯–ÍýCjï6k0äëPS— Ì6þ¥ÂqÑaoý¡0oa½Ÿûð£‰ùé¡™GájÒ«ˆ‡Ð °ÁÞ½Nþ«6šz!âÇ%Œûx† aŒªسÒpÊpÀãÜðÕV:œ )îÏQN¤…#Ðh†Ðc–Pf + íô—M ”1éˆÚ¤mÇꀖ±äczðŒ1=(ùè >Ãyƒ££P;3í6‰FÕlünüC÷fé£o–Ϥ¯»žlñ×îj4C­7ÃsMY;|.Kº2ù”†D?ã‡|j ;já–¹ƒ; +:A·|"­$Z‹×Gh3ÅÙäþ®J´0Ìl>¶©ñ@žÞþBለ‹+½S±'Å€U(u N†C-½'Š³!É‚$cxÕ›šÔÌ+rûTZ3H†Ìqº~Ó£ @ +s–Ö*hîžm­™â‰µ +°CŠÁ’FkÅ륓 þM*‘œ¤d|ÿpqÐÜ ²Ø" Ť¬D€S;†g9ÀT`$@#nÔFbdÀ +ŒÔ”ÏÏ“HgC’¥˜„€Éi¾ù¨ÐHE“Þ¹Býô1áý%ÊÙÖœ)žX³Ð°f£ÝxÍG…gp}£¼%ŽˆŸ–&Êð£z# #”S}¾¥gŠ'–.€-‘/Ùn ó‚Ç6;Fo¹Ao/%hE ˆ-¥ÓE4ùc— ¡ÝâÍcj,?&xië…C7y=*ÏgC’%áÀ+ ŽÔìÅ–/Ìàtéo~pù㛟‘k6Š­Ý®gFcÏpZŽy’4¥!±¡tS ¼p}(\ˆPß*ÏêXÜÄñWK£T +¬ð#ÂÒ Ó³÷³ £©X{Ž°Ü¹Êw.&&ÐAbÖŽ|‡mbþôÇT炈y2 •Z±2<àHÝÜž>£'@ +ào6ž8Œ¶¾Úì&Š³!É‚Ù0ØÇÜì$@'OKÃsȹn+0~¥¨þ54s—Cç%n ÁÇÑãEôa"nþY<.¥†ç;. (;.fXý%Ç%=ÂNFúü0ˆóbª·ƒáÑ.ž6« ÚŒ¶qvà°rÚ¿`(0”‘C¼D©ïªÍ¢$–`©¬Ì™d{­Œ[†·E/¬QùV{»"@g¼¸ãpXq9Ö³ãg ‰âlH²à¸Å‡•›Ùsn‰dl|qó˦î<ª„¥í¬t†’\!ü6ae¾Ûg‚®ÌÎ]ï²úÜ,7þèÆðSÕ,B|Ñÿ\¶›æŒåÊwdÖ`g½w)±Ó/-àò‰µ¥è´^ VÅÙd¬H Ø _nvŒí`SœÌ +’ríð"›pôŒ#f=ð{‘t£Š¥§ªR̓òÄ»ö>uõúS½ÞéÞõÕºqÖÝpnqk@y¾‹9œ‰yYÂæUŒZ·xñwÈâsƒ½¯o} ÜN»yµCl ¸]ÿ®`8@6°?É’ýo.jE¤æ;²Ú®K‘ A8¸ÉtCT æˆ¥Ùˆù;Gaåôc³hožûº+a*%\æ>ß šA× &¶|ñÄ–õ}'žß NÔ;Fœ«œÿúõfxÿâÞ79F¦ÙÎ6m§/D> €|( u(zÑ'‚Eßûâù·Yh©Íù¿’Dp +ÚŒ8‹Áµñ.pÃ\bŸ®šîN N!‚š æP³‡yãKΨ ©ÐCËxMU›U×ܯ°ÔùÒ¨0 D¬x/DyHvkͬ”ÚHI0×¥™¿bjïJÚMÿÖÅ º½8‹A¼¤_âÛ5±ŒêmšSØQ-1ØÅÇüͦé¦î²]K×Fm4PÕ]½H©0u?º‡ ŒŒyÏh)ÓánŤ ÷JìøßLŸÁc®ã‡âÃr F×Ѐӟƒs)Ýõçvg»ëR<|×?š_0ÃéÁBm!3Î5¿LñÄ},Øh‚«¶–) '%’¹ +ÇÉ} ((º™dàâ^좀Ë*§2¤Ô™üuC{2;-‹Öä>Aè®ä‹ÀÒ³œ»Ü¯7õ9Å—æ +›¬s짼h "”IŒ)%F*7îؚ͜¦þoIDgûendstream +endobj +1543 0 obj << +/Type /Page +/Contents 1544 0 R +/Resources 1542 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1520 0 R >> endobj -1012 0 obj << -/Font << /F37 802 0 R /F41 939 0 R /F21 714 0 R /F22 737 0 R >> +1545 0 obj << +/D [1543 0 R /XYZ 56.6929 794.5015 null] +>> endobj +362 0 obj << +/D [1543 0 R /XYZ 56.6929 165.9801 null] +>> endobj +1541 0 obj << +/D [1543 0 R /XYZ 56.6929 136.242 null] +>> endobj +366 0 obj << +/D [1543 0 R /XYZ 56.6929 136.242 null] +>> endobj +1546 0 obj << +/D [1543 0 R /XYZ 56.6929 106.2766 null] +>> endobj +1542 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F22 953 0 R /F21 930 0 R /F48 1228 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1025 0 obj << -/Length 2719 -/Filter /FlateDecode ->> -stream -xÚÕZÝsÛ¸÷_¡—NåéÅA°O—Ë%×ÜÌ%×ÄiÒÌ”– ‰w©);Îôï À$EJÎø©ãàrw¹Øf3 -l¦SBE.gY.IJY:[ì®èl Ï~ºbž& DI—ꇛ«¿¾Ù,'¹âjv³êðÒ„jÍf7ËOó—ñëÍ«÷× Oé\ë$UtþöÅ/¯påÛ]ÉTT -V¶W®þvžºWÇ,— -MRͳÓq6fº4'JpáLg¿™v0JéüDzXWuÓ– üÚ›kÆؼ®·ýRàÇ;üè,áŠä<˧›ñD]¡,'4eVWK³,×#Œ˜$¹ÚÓ|7ÂE­A l@Á1.9*ã‘KÂ%›Õr„‡ÝáZzÒªÙÖõïÇýO™‚õYæ ÷‡k¦çõúPì`/ô¼p+ÆNòy±Ýâê¢Þí¬`7Ù–•ÁQëìèHWõ×€îï=àì£9<”ÕgU±óœs¸3‡†X g ãXÂÎ3Fò4åÁü¸iËreµZ™ÎË -›öakpˆÚÁ >¶ûc‹cPjW´äħ)ì šÒ98WÎÆ£×%]ªiŒT§èÊÌá-øy™hDfÏ/(¸—’i_¨õÖ„Ól¾¬w…³Õ`)´AYWøp;¾w¦„ù¿iJÇœ\JÞ&¾ÁËCžeƒÂÛ ÑÎú·ÙMmܮƒí·¦õôõ*2hü’wh7vnyçjþÆ3Þ÷¥4§Bõ}©½¯¯A¨²4Íß®Éø¼)­P\/«ÖŠE[Þ™GB9×K -œ7àÏá5çß.¥@x -&ñ‹ì“Û¢]l†¬î7eX4_ÌâØšgE—ýÚ×à \Ú–A7 -üÙ–÷zg=¬]lq‚œ=ee¬ù£óÛÓçõÞºKã¹Ç|`'‹…išò6Ý -i‡3ÜnÂ6c$=ûÍ!]Åïä§ä²qËõ´ q£üé¢þ6¶LÕ^ܲÏ#ùrcN$…µ ðõX7 RÍ1d‹qÙļ2R(¨¨¦óó…"#RÈà½÷eH:mñ»ä[®FÄDž°á]Õ]ÌØ·¾÷h!Ô¿ÖÐ1;óŽS ñ_‡ûëswu7 öKjzLfââ®(·EL›>?6Cä‚y÷»½;¦95ˆ€Ü‘*ö-v™ÈqÙo¥4Õ@Q—jEª.Èí -µSR¥ÎKT#bù ¯ -‹ª{r§Q<“ü<ç hL§GÀ-eë€m:7»=@ŽòšÍ¿š—\Д‹HⳄšíB–œCÀ -Ä”-À4ÿà‰—fU·­Ý|ªÅÕE][· ¾ukÚ{c*|´ALËU{ð#áÈ¥(© - ìÅ8•ñÎY,—èÖMc‚ÓÝä\¶Þ;WÇjaݲðŸnÝ7øÑ­÷Pó¥5ÕÒx)÷e»u7…t]}¤”ª`'ŸQƒ»<¦qA¤ºˆ dÆ…CÖstêò˜Æ‘*º&V‡¤x¹ÜV‡ææþ.Œd1V†Ľ–¡8N•PžÃtX’·ÑGµ¬ÛI~ñL¶Nà†~á‹üþu™_¹3p |Bô,ß°„²¯‰Ê¹ì×ýƒi¥ižÎ{wQÝÕ¶X}>$½Ló!?Gj ßõŒõwæÁ‚dyä~à}â죞ƒe|îÿkq®:þþ´ê*yf;Uò|uíRMW×H5lùô*,×pÎøyÉ‘ê‚h…•iØÂIÙ§í&‡¡Ýdé ÏÇí ÇEšõàö!n ªºJ:OméÔ¾œuéñœíÞÜnëû kã¡ -°Lªœ0Áù EàTÊ,D„ªîÃ0ó-+ù€ó?ÎñHže> ÏœÛÂZq[»R -Ã;X.e}ôïYoòCÿÊCV¿Š|UTh€oÇ¥W|À‚ ‚È´×8Àâ@˜cø/Èþ³ùÛ¾Y‘Ðh]VÀnK9àIЖ~;6~䫽&³B1úÄC, Älnüê ØyèrÀþõ@<â±ÁÜCú“(Bdê {Šèò˜F‘ê"ŠŠ’”«gu<º<¦QD¤ê…¨¯˜ !PMŸ:KA¤êb䤭“U:Ðý“³&Œ†@ÿ/ÊI¼8 ÏãÕÒhªò^qèG¶ÎƒSÂÈ9%üKâ¼j‰ ÷‡Œs -ÙW°uµ>ÚórÓ]ò¬ÖÀ¾Â¡í‚¢ÿÂÄCqœxgÖ¡eí…áFçâ.]tÄqÑ]£Š*"c+˜òºu_a¤ÃÌ]ôÂtó°G)ªüŸäϾëji\°u™7ÎËK¼‘Ür¯ƒ"!‚sT]uŽ#)¦sTfü Üh0a&ç$2r»ŽŒNò‘àihžÂÈ*l1ÙÔŽÜG®¼0»äº¶ðûxê±³ž²ŽlÕãVn©Æß[ÿĆPmCÉÊ+G³np- üE3ÃàqËíÓζ¸¡öýx†1êZ20‹›9xË?Ý›Ei9›¡8¿«0òû Ñ4\ªÁÎI>µÆÜø ûèè~<×ó{Ïiéu¨jO‹ ±¶D5<~ïùÆ ¦LFˆxdRY8gù¾ûÇÆŒßâi ý†ž€†ÖK2Ú2¹=Ú*[Ĉ’Lv®G¹¿}±Ü•˜òPðÔ+R<Ž½n-Þˆ€ßšu¼•Ø‡¶›{€§¡Œz?M*ÃÚLf„jukw©¦±v¤ -°L³ø*ÿÑéTóÿQ”mFendstream +1549 0 obj << +/Length 3065 +/Filter /FlateDecode +>> +stream +xÚ¥ZÝsÛ6÷_¡>En,˜ø ^ŸR×iÝi“\âÎ=4”–`‹cŠTHÊŽ§wÿûíb’’(¹£‹Åb±X,~ ŠO"øñ‰‰Y$S5Ñ©bqÄãÉ|uMî ïûîyfi6äúöúäüµÔ“”¥‰H&×·Y†EÆðÉõâ×éůÞ]_¾?‰8š&ìt'ÑôÛ«7ß%¥ââí›×WßÿòþÕ©VÓë«·oˆüþòõåûË7—ÐÑ0ž{ ¼¾úé’j—?]þ|ùæúÃéo×?ž\^w‹.˜GWòùä×ߢÉÖýãIÄdjâÉ#4"ÆÓTLV'*–,VRJqòáäßÀA¯:fÀX¡G,¨øÀ‚<,Õ‚Otœ²D +éLxoŸNgIaåS¾ ú©Èæŧ2[Ù-â¾o±¨mÓ|Zeí|ù©È›–èÿ£âcs´Îùk1ÔaÆ5K%êª@iÎS§Zž3q:ã ýÎ~Œ"Qæm^•dî¬\På—&»³^¬ˆ&3‘0såä½ÝN¹™‚~0NË©S’ª¨©£ŠiFLD_×ù*«ó≚›Æ.¨ÖVT.lkëU^Z?x>ïÄÏ«²u²ª‚·UM•Ymü|­¬ï¨Ö¶Îp… øœÔéôz +õpÎÒ8n-%aÒ¢©¨¶9åS¯¢˜æ%•íÒŽØÜð¬\ÈÉÃõÛr¦Ý7£’,Jcí9ÑêûÒxÊb­¸çiªºu{¿/L*&¤ š6kíÊ–-­7Æõ’Ò¶ :µ—9íG«6mÞnÚ°x¿Êl{w…ß]´ÝŒÃ ä‘2Á†¼[39Ð<ó.ucƒk=Q¥º¥²]úžÛª(ªÇ¼¼ûסSž(ÎtªÓãamÈå%8io¥ªFd¡¾#®w'…UÁ ¥ÏÚqíO»µ9<‚ºJ¶§ ¶¹zçm³eèØêèê݃ò«ûCŽû¨™„`FjñŒ™\G̸ž7Ó±YfÚvÜLÃiwÍ´&#aÐúÒÛ)÷\¿Ÿ¿ JYµîÀ5U$™ÑÉ3å눩×ó¦:6ëÀT»ÓŽ›j8mFKwwŒ3ÙwgÞµ¼G-(Ö[ßožúC8z ö(ÅC칧€¹«G +1ÌÈÝ°sÈâ±åñØ·øë°Å;®g-~tÖÞâ{ÓŽZ|kÚ.|ѽ=ŒlÁo÷Žu¸¡ÚGÊyÌÛå±½BÁ¶«8Üóblob&¸0zo’˜bøñ½pÙ›ÀõüÞ›u°7»ÓŽïÍpZJ 7ðâ¯ì…-çEÕ„1!²ÜÔ@º÷Àúi”$x‚ùÂe³Jé¯>¨¸«O +Ðã.#E€è÷j…ÍpùQÃ~™Ù*óˆLâ•[ßSƺ߿zQ ϶L§1Íù¾jeÓyÑ`pF¬«¼)¡Æ$Ë] fÚäå|Ô4oê¼õàôvÐOy§ÖÞ©¸]u¸ý!+òEF RmÁvôùjÓRƒ¶üŽücGDFºux¾õX¹“€¢ÃYFhî`®áÓ7àÄ`Ç&=·µ˜\xô€§á™¸@í¢A<"/¼slºPÑ.)-ÙÜù…iQÍ7¸WεGýè?K‹æ5d(îrXÛC :„[ÊÁ™Çˆ]d=¹ç˜W«µ?Š ¢8[òÇ„  +"è1þ(¹q$1o*?¾Íî­¹. Púù˱`’­IÓê 䀭ÅP +>}‹±;¼æÚm¾²øB Äô‡êÑ>t®+eJgIŠh HCÃhŸ7yUPÖ2kCÍ“(4b  +Š"?GÊMVg0­Û_lnJØuªfcÞålæÏ߆Ÿq¡él'Ç}HÑÛ. ’>mgNx¸Ý*\ r%²Çáˆ$]ªÚ‚ ÙÚ»Fâ*t¹Uc~‡û”…]ÛrÑ=°?.­SÕÛ ßHyC”ë €$:Ht :’B<@â ÇÛ$¡€}ȳc룉5¤Úೆ¤¹9ÛN¢Â¥žL&U”ü‰”›³Xò€}w7¶3ØVl` ¸Ücæ³j)˜Ž#3 ’‡€{\{¬9·@Û~%B8Æý•Wþ¬‡%xG„°"1â;±*¬/îd¿°en»ñ³±ã‚B1nsÈTð®Ri¨NNYQÛÉ?£z§Ô€ÏMŠ¸BFi¸–#Ý6c0òñ(QEã’g8æ·c©Nœ@:¤u·Ýûâê8Þ’VãMÚä£nª9ƒ;+yN H&…“d˜QJl‡ØÑù€jêÈ| ž½5ßç­G­Ã)ü9af_Øø™Õ&6GÞ<›/Çž)dqœüm‰ãz¦†©4MÿšT¸GÊæ\{_^¢7æ/jI[¯ ÑšÇÛ§j³vðk<\©£îã«ËÖD$lñû1«}`Þv+|Ô½_ÁxÎ1.&XïÂý²*Æ´Uš¥i’öÚ` H§7Kˆ[€{ÂU÷èŒÐ'Óù*/²@ç<(wàÁÃ$L§òÏ<ÝΗŒãiÛ²}² È© BmîÑ>T}Ž–ôÓH¬¨ô8 cF_¤ + –^P‘p»#r•!ø°/ü€‚ŒðÚ Õ…Ÿ¢Uº¤QïçKý³î(ÚxK žÀöÀBà ‹ xÃx€ !é¸+s¼ç!™y³`啲êSA ­ô"KK•îú¤ ¨ \¯.~Úž*ä‚šlìf0GðѲÂÆq€°Ç> lyÀ”êQ¦«!7úWtë/2Ì°+ùƒŒ<ºJ˜HN½Hx`q¿bGqÈ5ÂTwå½V¦Ã#eK’.j£*õ(\á)“(Ä—‡™—~"²PƒB°?*‰§ßZïÃNµ[óDŠEQ”îfXÎúRMfÁä@º±Ëì!¯: ï¡ võ; ¿h)»w1/3£¢ÙÜ4Öó:wÃ.pe¨»Òò2HµTñ¨A¢V,¨™Ä¨ßß ¡¹ï,u ^e‹ð•ÉÏŠ¼i;Å-º<Ø\̇;€ˆŸeòP÷Y›Kw=*tÎùº +¬_²Õº°n–Ô§X;‘LjÉRÓaXΓçB}ƒY™š~E•qùÍX|ë$Œ¤Ï\tc©ÕƒZN‰11+,¥wØÿñ6à˜%„ Èy/5+îª ±¢¦ \tÁ y\üƒQEUÝoÖD¤€{z¹ÀÊÅ¡ `dêB ÃD7þÒŒg!=¾¨Ë=ÔC‰§Ç¥—P.ÕÀUZÍï °{Ãjò$8Îgá³bÆètÇÏÓE^6ª>¡Ù¾¦¾Ì„œ¶c<~°Îp¹]þ†_ÎU*ºÐáôEµê“¢øÂõåØWçxðêÄÿLê_©:qÐhH=,…œèÝ7cÏÝ ß ¾QØÌs€Ë=òâÖàJmm³¦÷éûiW€:ô ‰êCmŽ_«"q·©ÃÓobœ‹ø">½>Mñúqn‚‚F:­¡ôŽsWg°¦º!¢‹78 ðÜ÷9d÷gôÕ·]ºW +覷=èv/P>ÂQl­'æ^r) \œùòåË3ŠKU=ú”¸´Eq¾¶u÷”ú„ËÍïe‚€=éýƒqï!C§Pü°Sœ;bH›4†.¦•¤ÿ(|í:‚bƒŽkw_á(B™QAû‚µÎŸ\oà.©¼ ÁÒ¡ÈÁÁÝ9½2ú¹ÿˆ¥L†ÜSçç$÷ëõòå¡=2fø—‘.Qg¡üWšþ‹ yiÌO¾â©©J¡ ÔÞÛî?7ûªÿoã\)endstream endobj -1024 0 obj << +1548 0 obj << /Type /Page -/Contents 1025 0 R -/Resources 1023 0 R +/Contents 1549 0 R +/Resources 1547 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1011 0 R +/Parent 1520 0 R >> endobj -1026 0 obj << -/D [1024 0 R /XYZ 85.0394 794.5015 null] +1550 0 obj << +/D [1548 0 R /XYZ 85.0394 794.5015 null] >> endobj -118 0 obj << -/D [1024 0 R /XYZ 85.0394 769.5949 null] +370 0 obj << +/D [1548 0 R /XYZ 85.0394 730.0812 null] >> endobj -978 0 obj << -/D [1024 0 R /XYZ 85.0394 749.3395 null] +1551 0 obj << +/D [1548 0 R /XYZ 85.0394 700.9798 null] >> endobj -122 0 obj << -/D [1024 0 R /XYZ 85.0394 221.8894 null] +374 0 obj << +/D [1548 0 R /XYZ 85.0394 216.5924 null] >> endobj -1030 0 obj << -/D [1024 0 R /XYZ 85.0394 197.4323 null] +1552 0 obj << +/D [1548 0 R /XYZ 85.0394 187.7778 null] >> endobj -1023 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R /F53 1029 0 R >> +378 0 obj << +/D [1548 0 R /XYZ 85.0394 127.6814 null] +>> endobj +1553 0 obj << +/D [1548 0 R /XYZ 85.0394 101.3894 null] +>> endobj +1547 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F21 930 0 R /F22 953 0 R /F14 956 0 R /F39 1151 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1033 0 obj << -/Length 3426 +1556 0 obj << +/Length 2310 /Filter /FlateDecode >> stream -xÚå[Ý“Û¶¿¿BoáÍX>H‚lŸœÄN™Ú‰ïÒ´ãø'RwŒ)R©;Ë“?¾»øâ(y’δ“Î=€‹ÅbñÃîÇVþØ*ŠIœòt%ÓD”E«Íîá·o¯˜¡Y[¢õê«Û«/_ -¹JIóxu»ðJM¶ºÍß‚r hðúùß_\¯yDƒ›o¯£(ø|TýÍ÷/Þ>¿–apûêÍë›ëµ¤i|ý·çßßZŠË<¾~óúå«oìù\¿¿ýîêÅ­›Åp¦Œ -œÂ¯WïÞÓUþ&Ñê *”°4å«ÝU …BØ–êêæêÇpð«êêÓ\QEa´Z‹$0¾ŠÅ$qe r³„C!JI,¸pÊÙ@ù #QšF+G…ʯ³]‘¯7Åæç¦.®×1¥Á»uþ˯߼·µ jêË—‘pcÖ %B.›*k[M4’§$Idj¨¿ÆÃOD0ûÈ2lŽÝþØy8ŽÉÇî"Ǽ<›®9œ•hPÛ}•F {l³{ƒÈ»¢í+YkÑVmï¿Ì ‚ÔbÌ(¡œ% ²˜#± GNÿG%è‚HF1l—ß/ÒÅr„ä¨Ü² „ ƃpÖÚ7߶¼÷.1HPL]Çö¢ƒl ÏË‘óO9î/rÄ­äsöFn²ãwºÈïCá {¸¿Q¶ jÔç;&„³”}®z†‘ò¯ !ä½nE‚#!ÑÑ$MÒþÄö‚!‹<xŒ’ÎíLK³µ†…­þêSÖmβ¾ŸmOkÉQDñ,»`í=‘6öÄgì†HÙzQ5Y>óŽAa ¨wnPG4u Àwa‡£aßêaÕÔa¡7y´þ€ö){ÿ5¬ -èÁ¶dQAàæ°–ñ¼†TgTd©Æ:#Œ£·AD•,…Éï<\”)ûò*Éâþ[dcwÄcY<ùdoøYPÆáü¢`ßçué¨æÊŸsè]¤ ks¸ôÎüïËÇ¢îyqÔ@À »`Hµ¼ÆŽJ¯ñšß"âØs‹< ›—翼Ê!8 )ÀâYm:ª¹:'«  )ÁUéó"Ùühwð'|»¬ÄØ3S>¼‰¯-€¯ËS).Ø€êŒ-X*m àÔíÖžÁ£ˆ!Ä\ôOa0÷”Ãî<«PG5×èØ@A)&ÁF*}Û«ôìb›ÐänB»Ë 5¡à’MJDÄà 61 :c–J%ºEñÉ&Ëÿ”(á‰Ø°ô¼RÕ\«c»¯‚B>VëͱÝx¼ Ç}žuE«+˜W:-…ŸüTg»r£+ÖQÌ1`SMuÓÿ¤K¥a¤Zk“Š$ÓT„Îvaœš -´6•ƒ‰tèÏͳ5m.l…J«…/rÌL°nóP|0&Vœ{e¥/ ¼3u›a{T ƒ#?¯L7gEXÑÚÐ}³®+v{µ6ÜÅÙœNxnA?F¬§‡²òN¡UgÖû7°ö©¨ñ 6‰’89_CªeürTZ¬ìi½Æˆò‡Ùÿð²>êYöžìL¥~Ov¤Óuv§Œ0Nzìâqª-3]í×]7÷V?,q¬° ¯›þ'ÝRƈeÊDB„Nn%Ë–I‡eÒb™Ëu‡mrˆm˜£Ç¹)dk·È–8ŒÀ&E,mÂB76šP33®þØâ™óÐ!/ÛÏ|Ц ‚iÃr­EChâlp.A€@%Û*0C°M‹ƒ¥‡Ì0À;¢ªèÔT#Ïm7®Žø˜#hKÃ7“R²SÖ>°KÑmŒrxj™á[5€´Æ/º+l‚ÑáÍ"Vp¼’ñ_gHµŒŽJ‰ÞtåöôïžÕe3eúQb¤Í·E[ØÆë7·¯^þk”£m— ³±ÇÔ·XxšÓ¯ý€êÌÚ[*ûôùÌQF–5äôÂÈŽj>ô8'$B⛡ÑØ.3 b{k{²CÐèŽ(kO -}çŒAº!ŠÔÞ—ÆAÞªÆ4Œ  -êÅDzíÊú¾ç1µ57Ì<äc¨*t0“¦A‰Xž&8“nyÈ ݦ}+…­Ql±û´ú÷­õƒ   ¦Ö­™nØ?æyI.8 cwK3LY4/„¯îþééÁÊ r:øOÍÍ™®VúlP7 -ÐZwwZÀ3™úš81gËÇ(hmêìßhdM™·˯‹Âæ‡ DM­;ÕǃM®Î»Í oØ•;;à,Ç:Æ,åòþ¢à%¾[RÙ_–Jåö»¬kçéVg¹ŒÎë¨æãŽ7‹Á‚Gÿ„qó¡ìŒ.Ü‘e -~ÓŽµî7%ÐÚ[T>£‚]8˜†TËÊsT8‡_ÅáT5ËàtväœfCûÁi4öíuʃæþ^E:LjY°»š.Ð`<øaöƒî°ÁŒ­&à‚&%1çl™FÓ¹ø¸¯ÊMÙU'Ýž—zƒn:Ã2±qÔ -¦ÐÄîʼ SÜ»·k£ÙãúpwdöC|wÙDˆÔ]ƒ™Uä]½®^†˜g)“„%‘ÍXýyxJwÖ¢RÃXÒôÀ 46|kCð ó°Ž9fY«c¸âª¸ç1ÛS/ÕpÉIÂÛUYˆñÖ…TçÜä¸@SVêT´õÍ:1w¿mßÔ,j.Lc÷šÒ\ûy‚33ÓœL¯æ¢‡Ÿ£¹(¯'²J^†¼C“ñ…þê )S ¨àƒ^FuÐ;ˆ†´ò‡i“A÷gÆk°!”bdÚœûb$;9I@_¸(-ÛŸ%ÒG{³wWò3«`шT&gwD³ÑÇ'THÁ^S6þF /hbÓtÉàíƪ\»ì¾ÂQçMƒöh•†Ôêí Ì9£žéa} LLžR£ã÷ãýƒnècqš¸ì–›ƒAAÀPî_ýóå[´ÀA+¸à‡¶ÃJ´à;纭¥ÒÚ½tYCÛ©Ò/•ÿ‡¥Ë‘bÅÜ%ƒËÍ«Ÿéãˆà èmn_YL\ˆ/c1¸åGÖ“'”Ó÷ˆö–=ûôÁ4…PÒ½úÂp6/ö6EÛ.ý+XþÿǺ¨{~ñ‡ÿÍ¡ÿï|ç$KWƒsTÀÄ…SatþÔ5sèÿýk3endstream +xÚ½koã6ò{~…~8{3|èÙ~Êf“\ŠÛ´—õâîÐ8EæÆBeɵäMÓ_3R¢låÑf{ñ1ç=c1áð'&aÄ¢T¦“8 XÈE8É×G|r{—GÂÂÌÐ܇z»8:¹Pñ$ei$£ÉⓇ+aÉpJ)&D'mò– BgÞéŸ8—UÑx3ÊÅ ÃÁÇ&»ÓŸâ“K|gô¤†­³‹f³ÑÙÖ¡|¸_éíL$SM+í*kit¿*ZÝl²\? p´Ñ§W±¼®þ»Ý6ë_€+¥fËb–*™±ó¦}(á*¥¤Fƒ35mÚlÛÒÆ}Ñ®h±]YØö¾¦•|•m³¼ÕÛ†6NÞÐúO<äM™5«c˜‡„ÖA¦"˜¦Ç›Z1àš‰C‚ ÚV˜Lßê<Û5z¨ $V §x<Í£qoÜ”ºÕ¥Ý\ê²XÇ—4µTðÏ7îL÷D$CÂãgbڡϳŠ·²ØÚº»”´'uåîÎ賩·$+³ûÉí(xYTV+j«x~Aa¬°×»²-6¥…ÃÍžäã¡äå@òR |QU·´sk! 0‰!qjza®‡Uý[†ì<ÆYHÊ˟견ï‹êŽ¦…ÅÛ!ýœ•ÅÒá' €ÐRtæÑÓ7ÆP kj$;²&Ýkþ¶±–õæä²Þ`ÏøqbîYÇì°8PdÖŏ»ÙÛ8ôræzãªÈ„pˆrõ< }ÓÜC„M[”¥õi»Û8»G ˜õ%^—UÎKçõv«sç¼ÛV¯7Ý„¾¨5F {ºâKÂ(!ÆRé­õs¡)QA0|Ú!¡UMß²®îÀÙB xàj$Wôâ?@Í^(˜K3$6eÊ’$NÉÖ¾þº³¶ õ­ fVIph5F¤Á8@?ky~ç''ôõý¬Aç\$M)z™KÁ¦ªC[ïÝ£ªÕ`g³zhæc–WäY‰þ02^=²J@ Æ/¢ó"86®×,Kšf¹1òºihÞû.œáÅÃ;šoaäWam•}¶°uee}ןéý.LŒ‹1·‡yLcå«~Õ¹WçNÈkùÞƈ$D-LÐBo)¸õ–ˆ¼åK¼ÐÉcÔñ-s! íŒñ7{ÀZâØD–€j4z]äu‰ENÑ!ü÷Û¿‘bn¼Í LŽ<­íQ¬ `4µÈ3{Ÿ f‡Îì6ô}˜ICÛˆöÞãEõ®ÄÆ `i–Ñô÷™m4†Už¸„éA,È*qÇ{ž.ª%Ø ¾´Û:0*ÀÔE°`¯éë\ól[?Q™ÙêÑteÔ„‚(e2I“‰¯¥¯S|4±0@óûöÊëÌrhK +̽·%1SA$ýfŒ)‹Eœ¸n–ímœ5. +—ú\n³õ:Û>ZÅÖ:Áö$™í:À(¥Ïaó!R¸Ø šb¢ |˜\0l?€pô1$ˆ§öà´ƒ³!ZŒN¡ü“*‚‰á¡‹á ´‡}Ç'6¤‡¶pÇ‘.µm{7ˆÅáˆÀõj`Œ”Ö;úœ—uC•1ìÝBŽ Í[y:}oŠ\ö¸3B?Æùl¯t[Öù/Ã@Þìnç=¢ã®»ärÚÌï?eeã2½]Uf:"êÚ^å1z¤­°péƒßùPàû·7» 6Aôò›}ûLbÆy<*`\½,Ä©lI¯¶ôçNyQ‚²ûzà܉=c¶O‘˜™gÊ^ÄPL% +Œ[†,Šñ6ËËãgÛ¸¸¤þ¥q¤QjÜ%ć*[›š V®~ ¥l¹$4tµùÊÈ ·K°Yìv¥)Hrk‘å9AǦÑØRñVŽéh×4­Û•ÞvSsè€ãsqÏŽ×ñ%Š(î z9Jwâ‘AQ”<#2òqh›†M5µ«Ÿ‘[^Z›hºVnÇaZXAŽ ËfØù»Õw-ËoúLþ°û-RŽÅ‡Ë£¶Õ2!*”ÕŽ€vmQíÃL1}\‚w^Çî¿P‚ DC!¢§%˜@ôLÛ䇽[êgågáš«ôï£ó¨ùRûân +ós.ÔÓ‹c–Šš¿è‡g¹Õlt^ w Ã"nË ¯Àݬ»ü“÷Áê·D¶î„o¶ ‡’7ï²×î²›õhøß¿{éÏ®éBÔâÃÕåã²òøð:Æ`[‰â È*bI”¨±ßßøäYÕé¯}}öÄ ­Dú…˜gñq‚¨!.dU JN÷³ …òHÿ’ Q>endstream endobj -1032 0 obj << +1555 0 obj << /Type /Page -/Contents 1033 0 R -/Resources 1031 0 R +/Contents 1556 0 R +/Resources 1554 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1011 0 R +/Parent 1562 0 R >> endobj -1034 0 obj << -/D [1032 0 R /XYZ 56.6929 794.5015 null] +1557 0 obj << +/D [1555 0 R /XYZ 56.6929 794.5015 null] >> endobj -1031 0 obj << -/Font << /F37 802 0 R /F41 939 0 R /F53 1029 0 R /F14 740 0 R /F21 714 0 R /F22 737 0 R /F48 953 0 R /F55 1037 0 R >> -/ProcSet [ /PDF /Text ] +382 0 obj << +/D [1555 0 R /XYZ 56.6929 730.9277 null] +>> endobj +1558 0 obj << +/D [1555 0 R /XYZ 56.6929 704.9004 null] +>> endobj +386 0 obj << +/D [1555 0 R /XYZ 56.6929 236.9993 null] >> endobj -1040 0 obj << -/Length 3964 -/Filter /FlateDecode ->> -stream -xÚ­[ÝsÛ6÷_á·“g"Ÿ$x÷”¦IëÎ\ÚK|3mhŠ²x¡HW¤âúæþøÛÅIA’;½Éd‚ `±Øß.h~Íà¿6:a2W×Y®͸¾.·WìúÞ}wÅÍÒ-ÇTßÜ]½~/³ë<ÉS‘^ß­Gs™„ïïV?/Þ~ÿ槻wo–B³…Ln–:e‹oþúŽz>Á+­ÿðoüðþö»¿|s“©ÅÝín–ËŒ¼<öÇŸÞÆ}ºù|÷ÃÕ»»°‹ñN9“¸…_¯~þÌ®W°á®X"s£¯Ÿà%<ÏÅõöJi™h%¥ïi®>]ý-L8zk‡Æ$§¥I´YDtBŒDÇ%OL*Íu¦ó$•BZÙÕ«›¥LÕ¢îñW/v7Ü,ªa¿k«H#Õrq·ñ/‹¦éžzP´ÔWý6T»¶h¨÷ÑŽïʪwdCGd« -ȶu[Q÷Ó¦jQzÀ#ñ(™NxÆì ™k‹mµrdã­H•¤B¥ŽjS¸=”Ýö±uì륔y’åéõ’ó$×ZXâ~èëö!™Ÿg -æWÙuÆÓÄdŒG…¨–c2+leÆÂfÐ1Ú RÆ?/?1Ê$SJ^`ÀS30=íÔ$™Ð3>ÁîA‘…\ › -bÑW»¯ÕŽ:ë-È».†ªy¾áœ/@$ã‹UYµ‘”›¢}¨nø¢§çm±ªüŒtöû‡ u¬žáüê’–Ù?®`^zѹånÿõþ£;*à1åfzTé"ðÀõ¢íjôÅ×jEM«[\Ñ^°c[ôîÛ¿0&šªO’/î÷nøSÝ4Ôºwƒˆë¦ñ³®»Ý-½¢é×D±u‹úÅþÝíÞVsk rbÜ ó;£c2Ïrkx"3Îðú¡Ø Öòdž.nפüjl#`äF³Ì)ÿò1b\%™äŽ‚ÈýcUÖÈg0©ñ¬C&/Kò\zÃû“›ybô¸t*Ç{ N·FN‰¼SAÂâfÉ-µƒc±Âs‘(%fÖ<]ü3ªþŽÜ >žp7\ðDÈ‹ÞF&Ê(9ö68çÁÛØG4î³~%Õèâ³ô‚_“ö+ -YvEY­ ÞÏ€ ¼°®§:^w¦Q u¤>Yø¶-éh·äð6Nä¤ã½?Žûýȇ›êkÕPóþ™~»¶:#:žCü¿ ºÙÑyª‰è^¿×z|æÌzè̉ß9w™NÒ¢ýyî<Õ1wS–¤†™){Ÿª¡Ê ‹"û;+]o¬ñ·úí±©ËÚÕ×¢ÙŸ‘º6,ä%©ÉNK=PYKëâ* N(39¿°²§:^y*Q&YÆÔtéÿ—DÙ¹é N/ÊmDvFnž -™_7û~sÒÐϯ ýhݸ¡O~ W/\Y”›s*%Rhäæ’hFdgDã©‚hЃGŒA“Üüƒ9x5ÛôTÇ Ne˜ŠéŒÃ¸ ꯕ3N˘mÇ”·ÊÓ„§â’¼Çd§å¨Gþ?ZXßäœ_ØS/<³`ÞNVþ¶î›Ãž ÛîÖøë¡- ÐÄ C@†÷¡Ü«aS ¾åºÚýöÞ‚2˜‚¦‹ÿ@Xr³×mÙìWþ)ŒªÛJ™'3 --ˆ §w÷u»zýöûÀø›bSpƒ‹{÷½š©ÂªZ{È&ŽWœ”kæ#WòúöCdEŠÌ”>›ÚGïÃ’õ:¬èa¸ívzgáøéÈBúÛÍZv-"Ї=͹:£¹ù*v1äÉÎh®§ÂÝîªr¿ëÑ·ŸJÀί°£µã Ødño÷ÛÇÙQ6uïäÔ9™ÿº¯vuÕÇ+3InÀ¡üÄêÏ ¶Mbo‡æytNAˆ9!_Dc²3‡â©G€"5$ˆu׺¹kÿۭןÝSÄ©s¡-r¿É¯uõDÄI’¸¬i¼*Ø¢Ìg.GÉ·0y"2©Ïo1Poqj^£ ­òéßµÅ}‡aĦÀø»ªûCç·>}z÷–ÚXßÅÈwE4"‡ÄMz…Xµ}_•ËŠVŠy œ O“L»é¬i«j5K¥îCô‹cùb=Nqï랃öμŽ:¤[óù«5*ãº*‰˜%r¶¸&înÆm“œF–H#is2§hñ&2cÇã”Ln“ö¾@ñ㣭ro¿îkç¤^Ý,— 0‘²"ŠÂÖ`ä€Û}[—aRH5ëaC-ª•ÛØé)öðºp¨-<™9©Ðé¬ê‡zÀBƒÓê‡Bž«`ŸôÁ ÞR·µnèG–°· Ç~ã**+7Uå²·áv¤.ÌØ N­߶£×O6úBÇà:\þµ^¹ž#9Z„ÞtvnÏv«ŽAQˆqu|xBúŠ‹­P©Åu¦R‡¸hÇ5](¬ëPÃef†Ì%`·N9wíªŒi°H K=’Œð¥_Ô®ûHýÆd‰Ô¾®†ò5®–ÀlëÈ’FB^˜zÃzEº®Xr5+†Ø—PyˆÉEc±‰Å<Ð=‡EŽ-uûÕ‡ì wÐ -›lDX{>uYÆ+QJ1碌GçЬm¯“ÏÀgÞqª|> cÝíÛÕ«Èa¢ô!gùTB§NÂe&<“®Bȸs‹Øjºî µê6"‰L%:åéÑ‘~©žc' -¨–eÞeÿÂ4CÍÄÉŸÀl*tÇK¤€Ø¤òZÓ?÷¨.«z™?;µ/ÿ==M¾ªP–­õ6v-[¤„ù)h|sûá[Weå‘uŽöe‚G^Ê\¸ ˜¾Õ)¤VïZŒÉ´ÅýÎi øFÉÓ|~?úŒåT¼¹iv"ZAr‘3>q«}ü¢L†MÅ¥†0’ùd1n†rS–e/ÄèÝÈsO†X#†f•‡páRîØ\)šòGp†ÐrP¨]HþðŸÕáR _>LVÑ÷]‰7_t6/Í0¹˜ø?ŠT&‚“¡àzzcþi6*ƒC¯‹¨ØÚÔå†(€ô™:¼Áö*Z7½ŸôÞ/€zZž;ø”Ý[Y„„6¡Äc!á’9Î 9=bL‹# I YlôôtžêËZ™%B†SÌaž#ë\ópŸXUôX6ž¯ú?G]zFå!—\žÔÄ#;¯Ñüøl¾Q -2<ÈóGÞ€©Ú ‘ç°m?ëc·bÓª$3ʳÄ\œülεä"I³ù}êIy{OîáËP|±‰¤<ýl:[¡€–+QrAw¸H²Z¹\ı{w¢ØcÓ -hᣣwêÈ}ÁS,/ÊC -½È°uïèÀ1EIqm­ -¹ë"ž}éw71åe¬æÌLô-B9ä©Ç‰ÎŠÞ…ö(Ö~„°uõ: ÁÀ]kÍ5P=8wñ2 ÿÊŒ˜V~M*ÇÚ•(s‚Ç/Öµà³Û@=¸±ãcrI…U6i:«BÚ‘™ÃG|´X ~‹˜f‚Äeˆ'¢JžH•ù€˜°.Í í&K´~íCNãvA"ƒ†N]ý’KŽœ²Š÷HìBZÖÝtûÆI -”µFVU3íT¿Q1]õüZ›˜Õ[G×Êò¦ qÌjœ£Û¹)|6ÕC•@lO_»y<ûô´0Z:V1Tw"§—Tò[ F5ìé± ÒshP¨tž~!dØä@ ÂF¸UÚ¼àlsî'»ø¡†CåS#CçH‰²„‰`翯Ȃׇ<*_Ün³ý3¸½ß|®‚T³T£§ÔÜ“eË~œÂÝw2씄t”±”_:’Œ±È‘ØÕb)1Øaž…kˆß§qÓ9w90 =9X);Âù¥&?ïj +b"Üå{­;üî„>ú¡Ô{‹°(=#ã¯|NlÀ̬Våpœ0‹íÞFIá**Â~Í‚?¶”KÍU·-¬=MíÊeþ«©|a¯P€+±®Õ¹.yû¢±Õ½Ñ*›r`+ rƒgþª„ ›½M!¤ô|ôÃŽÔ7õ—*†BŪçIn¸œYÉüZI­ †B¬Lú’oÌjLüËÇe˜q9ž2r  £š²3j J)N´{– -zô¦è\½*îÏrôßýËø3X€à.ºó§ŽzÎ]˜*U -ÍC·³,ª2Èü‚Q̶¤é!&5U,¤Š„ûDiüsSû²œÿÈ ëÚä¹'*)륋Çb×[¤§Rï U”eõ8¸vûL ¶JQ>½Rém*—á/4•Ý~ eå“ùÜb‘ªôK,c³-Êåv¥ãçaDÈ9œêÙÏƼîµîN?û!YÐ:wý2Ê9GÈ p·(E_-Så/FÊnå?L òCâ>Vë„ïߺϨµ2.¼#,dâEÁÝà  ¹„&6¥Ž„d‡L¼'OUP7ExxãPèß»›Ky*¼Ù1²pOxÂDak¹–qŽ\Ö~àeò]dtþú]VXi@SÊ_˜—d©_ãJÁÇK¸À¿¸s©vPN€-[]F’Cª†ß¹ y¢,~d/…&;@Þ(€Å¬^cÃú5lœMàa±yt£†©óõ£¥ÁfYMÇÏœç#·–~B" °é!82 ‰0m6Jb톮í'™¯jBÃSæ -ž‡WÔÚžŽ:îݵØãŠø™ßD¢=Ø—ti§tØ#lÚ˜èçÈ@ø*ò½I$¿ËÀ¢BîvB¼€º$Ëó™<7O£›_ÒG7»VdëçY¢3Zi -â!@}ñæ|ÎQ~F×N.?1p”dmþÄ_}HàŸjDjçðßéãþ‹ÃÊ`„7FÄ‹ð’¥dÃŽ)Ü4çsÎߎ³þ?¡.ܯendstream -endobj -1039 0 obj << -/Type /Page -/Contents 1040 0 R -/Resources 1038 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 1011 0 R -/Annots [ 1042 0 R ] +1559 0 obj << +/D [1555 0 R /XYZ 56.6929 205.1553 null] >> endobj -1042 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [120.1376 318.9001 176.3563 328.1154] -/Subtype /Link -/A << /S /GoTo /D (controls_statement_definition_and_usage) >> +1560 0 obj << +/D [1555 0 R /XYZ 56.6929 146.386 null] >> endobj -1041 0 obj << -/D [1039 0 R /XYZ 85.0394 794.5015 null] +1561 0 obj << +/D [1555 0 R /XYZ 56.6929 134.4308 null] >> endobj -1038 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F21 714 0 R /F48 953 0 R /F41 939 0 R /F55 1037 0 R >> +1554 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F21 930 0 R /F22 953 0 R /F62 1352 0 R >> +/XObject << /Im3 1500 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1046 0 obj << -/Length 1675 +1565 0 obj << +/Length 2383 /Filter /FlateDecode >> stream -xÚÝXmoÛ6þî_!û`ÃQ$×Oi¦îдKœlmW Š¤ØBõâYr³`èßQ$eÙ–Û  ¶að‰Òñîx÷ÜsgÃx¾†K»~ýæôâx"‚ñlúúürâ ¬‚ñÉ‹ã73'ñu'¯ÏŸOÏ®6z&f/G§³îý“Ìô~½ÿ€½ür„S’{w°Àˆ(E½bp†xÀ˜{’.G?u -{oÛ­ƒ‘#QÒÐQÚ $ˆ+Å=Á -emèŽÍÉê¨X橹/²2+¢Ü,âªüc:_¯¢&«JóP?qÒYm®‘½ÞVy^ÝÕ?èÐ=HÏìùT!)ekùcz?ñCŒÇ«2‰ëVêž•ó AŠs“å(ŸW«¬YFðÉ¢ˆb¿Hø“§íì¤i+]§ñ*m¬hÌ.îo(/§g×ëv]F'ÏŠ6¿½|Ö¼ý9˜¿-¯ñôŒ,Þ]Íßê~zv:O¨Òï~´êým—Œ‘Ï;¦£ÕR‡ª>|³9Io£uÞøuºú”®Œ4¡aø‘Á3¹m°hЋݠ¤çã\*„jef —F“Úïmnoíµ¬›(ÏÓ¤Kõ~r ÆHaÀ… %Dh k- Ó¼Š’O}»Á*í¾¦—×õQ¦qcîa—E³\V++ 837p -»?Zשݽ°7eTØ;¾òÕ„Èqë«š$&KZç—v·¥Û7’W1ÔøÈ ªYi#~—sfµšÈñº,³rnßB5ö«¾{QiÚUnqjÒ"-›/2ƒ…c»½Ýº© @ I±Øöülv -Ç,-zÌööÒžwQÕÍS³þl.P;õ–ܦ¢Œ˜­¬Aó)-“i]D¹."‡p˦YaÉbǸ¦¸û!s!^ •ò§”ôá¼Ó”¨ £Jz”H²à!m‰"¥™d°)ùF¿¯²í8[ÎQ©#2ÜXvÄ¿6W\æÈòå(äDlõE‡A%Z@m}Ë\BTÀÞ&*¾æ¡yZ˜¢B:á¥î|ÆÂ]–ëÔ¨PãòSZf’üÞ¼‹My@¢ŒD4”"p†„aß™C¤óƒàÛ]›C:û­…ûj uÏ°²ÈÒFóº2ñb,D%b»$Y½Ì#í1¡–ƒÃ¬Œóõ²*Ïý0’¹õ§+Ë}Ç™„‘B9Á>r[“Qcl‚óæQ™¶Íµ´O¢dó` †Ä -sÍqÉÁ *$—’ÚøçMº*a†ù”Bî!ÐrLÈ ûÁveG5“¹*5Ü75µ@‡Öîó£4?Üå¹ .øÔ–úzib šˆB¥ú`.(eMÛÅRK<–ÊÊ,ª$»½°&Uå {H C'5]G]кCS 0AL€ŸqD»IžN|&`úÎæe4ˆ6M±R1„r’®š(kãMÆWçÓ_Ì]m÷Âv}žÛq‚¸N©E]§Ô¯+³£‰>º·Ë4Îtc³Žâv¾ûÞÈ™Á—ÀpVÇ«ìÆ IЕËk[-R«¿ÉS4Ô€g‹´¶™ê¡Å÷¶ë ëºk½Ã|H¥AWÈ5£ P°Dœá «övØB»í¸? @1Œkn~H/aí¿!¾ÓM¾m—ó¢7rôÀìàËÞº(ï´3w"ŸP—*P›ÿOý*Š„ÒcP‚0wñ6J—Ó³WovcDpPÈ™××ø÷œìTx¹Ä][nžhø×;ãôõ¸ã ÛÏ’!& È ß@Žp6³ëŽ+IõÕéÚ˜oQH¦X@ 7ÿ©ÿUÓÇD0V ý -‚°'Œ<Á³Ó‹W‡!ÜSùhÞssÂ}? á8OSvÔ0ý#kcìÑNúÿÆô %ÿ -Æ(E\Äalz>; ±žÆGƒØž—Ãë»ù@ìÑNú_„cABÉ`VÛß(÷¾UÂ?U$¯)ü×ÁB ~ÒÄÞWQûШ›ïÊЙ”(Hæ#FaªAZ—F¡{ŸwÝ—V+Õsý/• gÀendstream +xÚÍZ_sÛ6÷§ÐÛÉ7  }r'çNâö÷)Ídh‰–x¡HŸHÅõÝõ»ß.¤(‡’ìF7“ñ°Xì.v YŒ8ü‰‘3Œ+¯GÖkf¸0£éò„æ0öúDÄ9“vÒ¤?ëÇë“¿½Rvä™Od2º¾íñrŒ;'F׳÷ã?ûåúüêt" 'ìtb>þñâò%Q<}^ü|ùêâõ¯Wg§V¯/~¾$òÕù«ó«óËç§ጀõ2rرàÕÅ›sj½¾:{ûöìêôÃõO'ç×ÝYúç\áAþuòþÍàØ?p¦¼3£{èp&¼—£å‰6Š­TK)NÞü£cØ K‡ô§¥bRz5šδ»w¥8ì›°Ò£œÛ›N„0L…&ÑšqÏ7&‘¢g!³Ò›‘5ž%Jª`“¢šÏórŽºù²?Ÿ;&´Å}pb}—Móß8—Y ZUv|¿Hj5‹ n\g«ÏÙŠˆÀ¸þššÓrÖ.QáÆÙÖº0—,³S1®ëtN›¸qçƒx œ•yc$ ”• {lSÃ-s–‹Q__§_å%3"±£I;á˜&“0ÓqyÈdÊ@Cx2Ùý +ÔsÐ`ÓªDsÍפÂvEŸ¿GH”é2› ðUš%VÅIMu:Q‰§E- Ö6‘TÇ/Ñ‹|¾h&÷~h +RÁI2K³I°íÄi¦B\!SÀXV%Ýà߸áòKÃœ–>Šô2xμS&N^bßô r\¿ÑÇô›ÄCüK¼;ä7 M'DBÚLë&[=Ásf:N‰wPYCöÔÑ=¥å:E^74ã¶Z)/§ÅºÎÑzÔ¥ñºYßD–eäTéçÁÛýïªÌÈöÝfØ™éºÎêÝöë+æ¾÷‰•Ðò‡Buâ,ó\P¨®îPéÓn~îZU Ú¼Ï‹ê&-°í7A蛑6Á\8¡Ý'Ì Øí1¶75ϲÛt]4õÙ‚  ¡ªf‘ÅfݤM¶„h½Ïl=}Ël­\OgÙ®Øm¶’6×êÙÍsóTÐ÷áK +F'ÏVMšÇÐ÷¥‰P»‰°‰)}î(ÇN:;í&­ó}ÚïëëTõÿ½4*aÚëCÊ7pq¤Tð=ˆOù´žLiYfÅ“â„™6kÄLÀËåºÌ§ÑÔ² =L‹øg 5Òé4«Ã ÅÁÜ¥ãRªÉwÒÍÛ?ݹöXu£®oùJI¨#”;”É &’FY­!'Ì&Ÿ²‡ç¥3¼ Ý8¬§þËËwïÎ_PîQhOÔoùšpÎ@]s‹H˜°\ElPè~ªF1å£6mO{Ví¯Rn2êÊîj­ïh„fp@€MF 圈W¯^P +LçG« %´œ.Ú¼³„ÀÙd%²=†ìiè¾Æ9DÞ‡²¤ñ”m>çÙý³¯DÌa­—ãÝŠëKt¬Ðþc*Î&Ì +w¨ª26áÚmçŸT®Ý£´ž4ÇRÚæ…áГ®ñxm=Yü¹U­  ¦m9IZÆíöSÇOŠ'ÌIR(8!Ÿõì"¿x3R#£˜ÅQ¨¿^dÉSxjè +¿oÊ2(3Ûʱì /eºúv7Ȇl기-Zë@mwZ4V´­étÝ¢aGt6„ëX'YÙnÑ¥%ƒŠ\Z&§BŸ¾ , +αú.ˆß»V øæµJ—Ë4ÂNÝ?/GLÁ¼¤àÀ !ND!ÔûO´mÔÛ·³ÚõÇeÚLCùJøG“©„ÿ㇡ƒ <'‰( $è%ݼ|‚©4Ưø`4`±G'ÝíJµ®„»P~¢ücÓãëÔ²uÏסVÆOý°¼©Š|J=Ò*¶BÖÃieü‚* g†õÉ8è”ÆP± ªdîÆq«9•ÐÊÛƆ÷-•|Ë-AîV9xÁu r&K)ͤ“nÛ¬ÕmTë–LÁµI&Ã)ñB >>‹7¼Ùn*N"¼‰!¾Ýœ½xSwï.!}C]«¤ _V”õ„'E¥’  ¤l ƒQCaþɤ¤.×uäq)mÌžù>oCxÜ:(µ»@¿ÃpZÝÆ€› Ë]zÏÄò¸ñ´•ž$HPñ3¢@Áu¯ ?àˆ—U¼?œÅõ=#ÑÛiímä¥ÍEÝÓ*vŠ¢ºÏfƒú¾^ÄI·Î"Ô]4Ò«›u^4“¼üþq‚B3k­)Ž)È“Ò‘ZûÜt4´ª„DÄCM$`­õžÂD@BÒc¹ŸhÒòaÀk¼bJ˜6 ½EîŒVÄ ³¨êÁ÷”â_˜¯ÅŠ% Œ±v:¨£Oé €· 9x9 ¼ö(­¬ž¦³ž0ÇÒÙ˵Ng@õêÎ,€E<Ó´ÀÓ?CoVÅß[¬_üòY‰r(‘’HÚ„ÜvaH 0‰¼eÖÜW«OÔÁ‚ku›NÃo7qA9T§5mà© ü^î±\O%_[Ÿµ–¼á$·Ï`Ù®Øm9-ãz»†t+¸Ý˜®Ìšúé¦^‡À |žHƒhˆFȨadE_²)ŽuöBòm;~¿È1—â„`¤‘i†¬·Àßw¤P^„ÜØÑ ñ»*@˜ALjš6«ˆXV 5î)|wÉgqEJŸû€¢¡ÑÀ`\7Ë`›e^>ú™@ô\JêÈ4dú߉Rd%0™7‹šúÁ‰‘Ž ftzhm9}@]b|QÒX½ðG’”@˜¦uöÝà“že €É®,ÙmêI7wƒuÅòðº‹ÓÊÍ(û6`ËÂO®@ûg@AÙ> Á^‰Õ©tª/뎈¢9`è¤F{nmï:|ÝÛÜÚçÔ¹Çs»‘ÁK(û>¡ÌÖ@Á/E?.ôŠŸöÿ„rÌaºHÅ(ü~C¿Ý<·°ƒy| ÚpÙÔs- Ürº÷4nXC­ðk+Ñî>ï +ÿ ¡ 6k „ÌjE¥Õ_ã1í è§Õq—»jÕt¼7[غã˶§˜ÉùP J E.z—Œëñ„¸{P¢öe°t^¼_GŒ±þ²¡ÿ+’]ÓSÙc_ᣃØë©ÿs²ù‡ÐrnÇÛJçœQ(<“V_\eðHã¤ý|[moendstream endobj -1045 0 obj << +1564 0 obj << /Type /Page -/Contents 1046 0 R -/Resources 1044 0 R +/Contents 1565 0 R +/Resources 1563 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1011 0 R +/Parent 1562 0 R >> endobj -1047 0 obj << -/D [1045 0 R /XYZ 56.6929 794.5015 null] +1566 0 obj << +/D [1564 0 R /XYZ 85.0394 794.5015 null] >> endobj -126 0 obj << -/D [1045 0 R /XYZ 56.6929 424.8255 null] +390 0 obj << +/D [1564 0 R /XYZ 85.0394 513.3136 null] >> endobj -1048 0 obj << -/D [1045 0 R /XYZ 56.6929 397.5211 null] +1567 0 obj << +/D [1564 0 R /XYZ 85.0394 488.974 null] >> endobj -1049 0 obj << -/D [1045 0 R /XYZ 56.6929 368.0037 null] +394 0 obj << +/D [1564 0 R /XYZ 85.0394 420.2055 null] >> endobj -1050 0 obj << -/D [1045 0 R /XYZ 56.6929 356.0485 null] +1568 0 obj << +/D [1564 0 R /XYZ 85.0394 390.0916 null] >> endobj -1044 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F41 939 0 R /F48 953 0 R /F21 714 0 R >> +1569 0 obj << +/D [1564 0 R /XYZ 85.0394 312.7536 null] +>> endobj +1570 0 obj << +/D [1564 0 R /XYZ 85.0394 300.7984 null] +>> endobj +398 0 obj << +/D [1564 0 R /XYZ 85.0394 159.3 null] +>> endobj +1571 0 obj << +/D [1564 0 R /XYZ 85.0394 131.3824 null] +>> endobj +1563 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1054 0 obj << -/Length 2369 +1574 0 obj << +/Length 4330 /Filter /FlateDecode >> stream -xÚ¥XKsã6¾ûWè¶TÕÁ‹™œ²óHM“Ú±÷°•ä@“”Í E*"5ϯßn4’íIUÊUVF£»ñõCl8ü‰M–2®r½±¹f)é¦<ÜðÍÌýt#ü*–j¥àcev—ªŒ¥™´›ÝœÉ¿ïn¾{'ÅFrfŒL7wûx–±–¥ÒÈÍ]õkòú±8Žõi»“)Oôö÷»Ÿi›f6³·q8Â2‘ÃNÜðcõ¹èʺ¢o>Üñ®.Æó©"¡™Òxˆã`R&Lž:š‰íNpΓýØìŸü¹ÉYn¤ñ;gVgÆíp§(e’¿Ü½÷?¢›mRÐç¡.‹®ô9>£ŸoÛþËàƒ»,ÒC}ú\ŸüÄØÓâŽ$ò,ê&¬m‹ÏõÕ6›ô{Ä£ê ^^ ¯"ËÓ”ôýµïêÁB©Ò¤*Æ‚ÁZž&ï;:mE–ÔñFþQ³“š„4L ›Á!ÈÛkçZZ0£•õËöîþøºŸ ¤éŠ[«“W8¡&ü éÉ/MÛU>Ö姥°C¤wf@ªý­Q{Mïï -D%턱 -¸îBYt.xj(´:þÆ©ò|"¥u# Lüá£èªW~ãž~ÁÂa¤kƦ=Ÿâò¤ñTtÞôÀ¢)sðjA/á]ÞÁmrèIújº}:£“Šûþ<‰Ž¼bÆî,µý–Îa„–½"–NÕH8 QÕCyjŽ“ÎKýŠ5'‚—&D8½{îMâƒTщúÿ¦Ãå7oï&Ȳ‚ÁS"L¤&GH¢ÉÓƈ3 ‹ëwó „a G¾â‹²ÜÖå$Œa  æB¤“ó^Ó— XªMÎ$å¡àlà::õÎ šb+’h Ck,y—Ó:(uÅFpL¦µöÊ/Ú¡ß=k(ð&“«à&×Æă£&‚ð/'®ßÍ7\ëäšïÂ8xUo{%R†Ñb!Еiüšo qÁ Ep›%w«î‘¢þj57~Ù‘ tì˾¥›9\Ǻl~ã\B„tȦ ôYllǧï^ñÕ°KµD/!SÜ -Wþóæ×ßù¦ýü|Ùʳtó>8Fh¹9Üh!Yž§:Œ´7·7ÿ‰Â2ÅŒOÖyÑ>¼<v,Yí‚t;¥9ÜL-,/»ßäˆ/¼YSRÓ›ý0Óqj´Ë4g),ð:þe»3"¹ƒÿ2y{©à©ˆ¦ ¦&ܽÒÍŸÁ¸ÎsE‹f´»ë¤7ðÝûƒÜ¼éáF›Ù¥ãÝœ³»”‘ дŒ[ d€5)÷¹:A–¹X?-·ÒV¦df“¯[àÞ;,(‹Îo€MÔ}=ca§° C£_ÒrœVN÷+Ò«QsP3„/äœwRð6y®¦ð"sžÜ#ÿ':­ª÷[‘òÜŽ~v¨»jX9q'-ݪèõ¿®­æÉôÂÌEtÓi.üñ‡z -ŸRéÄëÂ-|ÔøAWv8qùššéW5#ý¶}Q9Í -¤B$·ø@÷OM÷°¦)y/—±Ðññ–mìú®E†O?¬Ü"WLg*õ \’D0 ,ä`ð,0Pç¡^“ÓŒÜ~Ë`še6 ÙŸs îѵOD¡uV˜§D´*"ÞK6ÉXÎU8!Z™GÏ:h~ OŸôÕøß™.3…ô¢@¾9ˆü3\BLsˆÜ;¿÷£æê‡kVé„un%¥õåŽôåΛ'°dSàÿ÷XaîùíÚ'n2yØähqà· ŸC=>ö˜Xžì‘p®ªÀÑñ±BKIê±-Jt~7ÖUu[q”–”ÕVþ±fÇóíëGß?‘àÖ"é*â ßà +ÕOº]Ð,ZúÀ왨~QdPÀ€.¸ èqK1ÆŒ?,†rÐ?cÐ9ÔKf˺b¿}•p©¥Pfµˆ–oHÎÞRÊç8VwÅ}‹|ñå&»²=“žp¸XKÿ “a«£þAE»;?ç@F1›Úª€×r~–‰ˆÄiwìÛ¦\K(a©´!¡,[ZNZTŽò¹ìõ)SË—æ^3—ødT€ýaDI25  Me¾t™z`ÍÕ3 † >Ø9~ªŸv`éc³+Ou»ÑÓ®å\aó$ì+t.õ–C 5ÙœwÕŠ¦[Óà™ÙBk.?äSðûŒÚ$Ó¿. -­a­ ƒE9×ܪ``M¾6ãÿP}@’ ±ŒÐ.ˆ`•\?ô³â.ëîðÐ(yâ><¨b,ó)@+Ã6õáÕ5«þ ±Ÿg1»þ¦?¦,µS%ºêà‚e&ÕóÁ@D1f3¯kXJZ¾qÀÔ2B‹5xy-C,´Éo<å_§Ðxüf× ¸}ûæMí{ߨÂBX¥8·ßo±ŠH>~¼}ÿÓ+šÿ[iáRD^øòîqnÅ™³XN€qËk Á"^ fŠóØcc£}>Ñu! b jŸÉ°øœÒ‹].õ eŠí¼ª¦azцB­‰ý­4«)1™"—Û͆Ñ÷¹*š¤ÈhB+ÎL½MX<»‹ñwÁ¨--\—̆=3?†>¶jܹ㠕”$Šw:¸÷$ Ñ:@y¬»‹i<üä ->H±”ôu€;ŠON«@bî„×yæ­ƒ˜åà`~Ƥ`ë'š‹7Ià‹iŒ»ŽöyzÞñX‡4 -†}Ó(OënˆÝ"½ì'BMmMˆ©ìn-àaï8E¡s“xFº QÃj6À2õ©'ÙB+Ÿ–'gÌ[ȵ.ò+²%5!mÎ-¿¨z°Þ©© b_¦{kïdñÞCÎæÓËû¦+NO/¤ŠÃcn«Ø^†µºjÆ€‡¢;;¹ã;_kר”iLiÖºXS%1-Zébq>€t‘*D¨g{š+'þ <—ÿendstream +xÚ­[_sÛ¸÷§Ð[åŽÅÃ_‚HžÒ\rõM›»&¾™vîn:´D[œH¤+Rçs;ýîÝÅ )A–;ÉøA$.‹Åîowa>cðÇg:Ïr+ìÌX•iÆõl¹½`³{èûî‚û1‹0h1õ§›‹oÞK3³™ÍE>»¹Ñ*2V|v³úyžg"» +lþö‡ﯿûéã›K£æ7×?|¸\Íæï¯ÿòŽž¾ûøæ¯}óñrÁ ÍçoÿüæÇ›w©+÷4þtýá[j±ôs‚èÇwïß}|÷áí»Ë_o¾¿xw×2^/gò¯‹Ÿe³,ûû –I[èÙ#¼°Œ[+fÛ ¥e¦•”¡esñéâo‘à¨×}š”g™¹HPñ‘Êr¡ÍÌh›åRH'ÀŸ/9có}SÿNOe¿öOÕnKOÍ~{[íè¹}lÂã¸ù~×î&Í šç™Õ8 8åçê©£‘ÿ¡høç¦îzzûïkúýÕQX$IqeÙÁg&³Rá3Ò ß¼!  b .ÆŠwDD}×b^wÔXÒëÍÛé½k—Ÿ«žžÑ&TMÝÜÓ˜Ò7“f@C÷P-k<ƒ°‰c¤r0†:°üph«¥²c…œÕÈ +åÖZÀ +‹"m«‘âbLÒâ©^iØekø03røÐîRB9ì½°üÌÁ0 +¡ûW“A¤xFRÎñC¤†a™.|=&ÅsL™i½&O ¾ò>GÆ ÀÁ}ÓÒû*8&ðhFi9uLoRz 3³¸.›™0Þ"3’ç鬊gUrŸU1”U1óŸ>\ÿ:Ví¶¬jR,fšbÉ}ŠÅ„ü‚™äÜJcW çÇætŽÃw.BB ÂÄü „W£JX:L:çRä!îË í#Æü€hpÉ;ÿUÊFðLä2ì™Kf'¡yÁb’è*AGgJÄô‹Ë}S‘$ û¬ŸU0\†1”-Oz|kbx58i3ÿÐö^:Îk:)m}ËæìÁ*o;BþOûæ‡OÔë9ÂL*ÜDúŸÚM ÖCrvœãî: aˆ%ôV§YñÿÈz˜n8Nøòð°©ÝsŸ?*@ûh¬KÁCǪöaCßîž<îÜ"œøÆ#¢¶ÁsÝwÕæÎ×à k=@#þ‚ÓL¥8!·ó‡]½-ðRîûu»«ÿÓÞv¾­ð ×Ý–2Ô‰>—TwpÕ¿Ä3/î|ø¡ ¨‰¬Ûˆý¾ 4ø!4Á\gB²¯€MÅŘdÂcŠªÓ‡½›`°`²€±&Î £¤ª*áSHLXHÌç*?*P + œEa ÀLfK¿ÜM‚‹1Åcp<ÀÅQ'Ñ„‹ƒ¡r6Ców%¹Ü£45fOë&p,fp¾Úz#Å3 F³mÀÔó+æ€2´ÊcMs$§¼(2P²g pTÑ~ÅŠg,—<âdÁ§à§c¦£%sâÌ&Š ¥ßê÷j¹wN^F•'x£x7È Ì²À/ÈÊxUúTU§ªÝÒr`‹¹²3õíîgôð1Uç'ˆD?ŽrßÕ–üŸóTÊ2rþm Í µ¾ðΕ,ýõ(@Ð:3%'¼UÖã¨3,Öd£ð Ïus4+wÍ©ÄâøsóÑu~x’ŽÌd€è8Hà™’êŒâ¨3|SyzGØšºA´Rì•·í¾§>ÐCDy÷{BoHk`õ\~äjê’ëd‘Æå¾ì™Ô,Ë”‘‰%Ž‘žM¤¹ÆTbº01QóLÅŒ „ü¸d¤Ýq†__é ã*Ó3:«hðÉ©¢!{=HàÁsí<’@Õ(W¾eí—1[|‚YåÜ´ûjtŸA¨á6‰€ðYaõ Üá¢ÐD‘"[^Œ/sd: †›¤\‘,xÈ"ð›ªOš–|œ™Åȉ¬­íø­JUR4*HÔ7ˆ¢Aåî0Ê9¦Ÿ X½÷èâÃÂd¼ªÓ…Y«†žü57l ·ûzÓ£¡ÎèÊN¨Zbß’ô³$÷Ë‚âMø¦útnBËç¥ ±‰ŒâÁ]» +¥ b¾b/ƺsÈãøås û_‹2U™ÆÄ4SÏX³ŒcúõÞ79î°Éq‡dòÜðd-Åd¹Rç+ ÌvÜ™<¶à®{"¾-?[¸o¯ øZ0ÚSq<´]WߺL—ô`[*Ácƒ»g"}ƒŸ$/ Ý~S ½ Ÿæ$ÍBƒµ§¾4îR*4ì”è=U,¥õ÷Ä ¦sÖ††=ªº9\¦Î€"ˆHD¼ÑöØî>û¥Ë ,ãªàS?Ö,W oe*kïbmö =5œ5fòñÔîŒ(Kâ€_/åµk¸X…x¢6—„QúôUH£¨!rl[xp.üÿ3.ŸŠUíò®waÕˆM »æ}¿Xd>Ci¹n2l6'²HŸêfYQ.µOš(¡¨VâE&ª..MLRw¨‰‰xí»{:Tw³·ôKËȉïÑßZÉm@¯Ý)ÁQ{w!–hßÑ/I¿,¨¤½ YY™Ì 9öñi±þ´àØ<ù°}jy¡Áã(Lž´GIJAϺ¾_ûÑÕ=}\Q3¹ÒŽO¬¯-Óý`>ŸÿÃ9̽JõÍ|W;í””·»÷Ó†ÃĦ‡ˆ@Öñ¾¦¦kj:lxè Ô÷]w“.…W#ü*w80·I#èn ŽX·ûÍŠÑäÑSʧƒò‚õ‹˜Öižˆô)#¶z¬]€fõÌ· =ÄÖwÎðÚS·&ã½X–ƒ9g&JÑ-¼íâ#wL|I€Œ'<9÷ÅЗœˆžøxIm‚H×ΟãJzÿ0M5ëmáÃÞy_F´ômtÈ&;ë/×'¶V€-ˆÀ_noÅ#ÆŒõyðG;/Mœ1QDd™Ño>ï5P7T‚ ¡ù¦(Cõï8ˆTö¡Òqï6†û+92캄ÓÖÕCF]Íï#8òEfX·_®sà˜Ú_pfÈ3!ç-¬Ý/ïc.«2¥ÿ€2dE`1á«0`‹ó÷ºTDø!ÁvE7„z‚Û0‰¿VfæMEº"Î?ÖÈO2nüi&¼¯O¦—u†ÿ•HL²Èüÿ£Õ†xB…8‘i5EAƒ Láj”:â<üGÖ1ëÿnI”endstream endobj -1053 0 obj << +1573 0 obj << /Type /Page -/Contents 1054 0 R -/Resources 1052 0 R +/Contents 1574 0 R +/Resources 1572 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1068 0 R -/Annots [ 1058 0 R 1059 0 R ] +/Parent 1562 0 R +/Annots [ 1576 0 R 1577 0 R ] >> endobj -1051 0 obj << -/Type /XObject -/Subtype /Form -/FormType 1 -/PTEX.FileName (/usr/local/share/db2latex/xsl/figures/note.pdf) -/PTEX.PageNumber 1 -/PTEX.InfoDict 1069 0 R -/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] -/BBox [0.00000000 0.00000000 27.00000000 27.00000000] -/Resources << -/ProcSet [ /PDF ] -/ExtGState << -/R4 1070 0 R ->>>> -/Length 1071 0 R -/Filter /FlateDecode ->> -stream -xœeU9²,GôûeË@@Q ‡!é¡%bd(dèúʤ—÷ÿ(žÑ¯ -’$¡T¬)ÿ®ïë¯ãïãÇ_¢ýþÏaíÏc‹®½Ú¿G—=ûÌöÓ1ÄF¬lÖ]töö×ãqu‰Ý¦‹÷5š”<8Ç—ý:\;âúãñ‰üéÆ&ÞЇ h—õ:ÀÀX=&02²oÒCó eD3PMtð1CrZûbœ7³}t€mA£d«·íä'ÐWŠ!è®»½KO(°ƒÔ¤‡tÙKb•^¦Ìì »å*’ÎÕBêFåmY¸™`Uõ´™Õ -¿nÜž í½³`*TûÞ£jg“¾=Ås–A½R?Ô =}³Ú§l -¤Ï’ÃigÙ¥—ÇáC6uéíÛ&”\Ê GTœ„Méêö–KòlÜ’Fyu|?é%åiÈ¥K”êNÊq{vˆ*êèJE¢]8hÍò¤p0R±ˆ$Á(+Á nÖN¬ -qª„Ñ«ò^ÿï>‹«>÷— .13×…Óƒ!¶3¢SËAÕ”ih¥Å¨Š^…(€<Îm䦽ªšÛÆlLÊâ³ò7ÙaÆ´Ëdô 6(WðÚºK -г2"ïE9~  -n*Œ1½÷¨¾x¥Æˆpîâ‹&XîÃœ§³±è\íD¤ßä0}#XŒûž˜‹¸À>#^V°¡|2Îi‰9ÊÎr)`˜¢Xh¡Ò& „hb—H°Œe"Ãêʱ„£~Ï“a³tŒºìZDß!#Z¶ÚÂk! e'jÝ=§ _tsÙ¬ûÍ&­Nå@‚i¬ˆ3t%kÐE„\H–YZxÿ/U¥Ç™åë—Φ@±¯iW H -þrÓGçX5¾ûû8‡´ÕªOª«t–Ô³$Ây°‰—BÒ›ÀÄ5©/¨vp÷o`kA“ôr ±ñœÓ4N.4Žæ&F°ÑTÆG%V½ Î'ÌØR5¬BÔ‹`qUžv-UÍ=ëÆåQv2ë_ ”¿­qq‚~èr¯Ú5ÌJ¼ð˜°h»P¡õ‹kÜàéÚýªå>Ò¸D °o»Îi¸CrT]¿MJ¥ ÆÖ¹’°;¿ö‹ûóZ¼¬ å[Ç-œÁ¤ŸBx¿ýpü|üÈÂendstream -endobj -1069 0 obj -<< -/Producer (AFPL Ghostscript 6.50) ->> -endobj -1070 0 obj -<< -/Type /ExtGState -/Name /R4 -/TR /Identity -/OPM 1 -/SM 0.02 -/SA true ->> -endobj -1071 0 obj -1049 -endobj -1058 0 obj << +1576 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [470.3398 477.3512 539.579 489.4108] +/Rect [55.6967 387.5149 256.3816 399.5745] /Subtype /Link -/A << /S /GoTo /D (boolean_options) >> +/A << /S /GoTo /D (rndc) >> >> endobj -1059 0 obj << +1577 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [316.7164 465.396 385.3363 477.4557] +/Rect [268.5158 387.5149 332.4306 399.5745] /Subtype /Link -/A << /S /GoTo /D (zone_transfers) >> ->> endobj -1055 0 obj << -/D [1053 0 R /XYZ 85.0394 794.5015 null] ->> endobj -130 0 obj << -/D [1053 0 R /XYZ 85.0394 769.5949 null] ->> endobj -1056 0 obj << -/D [1053 0 R /XYZ 85.0394 580.0302 null] ->> endobj -134 0 obj << -/D [1053 0 R /XYZ 85.0394 580.0302 null] +/A << /S /GoTo /D (admin_tools) >> >> endobj -1057 0 obj << -/D [1053 0 R /XYZ 85.0394 539.9341 null] +1575 0 obj << +/D [1573 0 R /XYZ 56.6929 794.5015 null] >> endobj -138 0 obj << -/D [1053 0 R /XYZ 85.0394 315.9171 null] +402 0 obj << +/D [1573 0 R /XYZ 56.6929 692.9565 null] >> endobj -1066 0 obj << -/D [1053 0 R /XYZ 85.0394 282.0038 null] +1329 0 obj << +/D [1573 0 R /XYZ 56.6929 660.5438 null] >> endobj -142 0 obj << -/D [1053 0 R /XYZ 85.0394 146.7217 null] +406 0 obj << +/D [1573 0 R /XYZ 56.6929 112.3379 null] >> endobj -1067 0 obj << -/D [1053 0 R /XYZ 85.0394 117.3479 null] +1578 0 obj << +/D [1573 0 R /XYZ 56.6929 85.6994 null] >> endobj -1052 0 obj << -/Font << /F21 714 0 R /F22 737 0 R /F62 1062 0 R /F63 1065 0 R /F41 939 0 R >> -/XObject << /Im2 1051 0 R >> +1572 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F21 930 0 R /F22 953 0 R /F48 1228 0 R /F14 956 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1076 0 obj << -/Length 3492 -/Filter /FlateDecode ->> -stream -xÚ¥Év¤Fò®¯ÐÍè½.H’„™“Ü’ÆígË=’fy^(n -Ê@©ºúë'¶d©Böa^È%2222ö,ÿÒƒŸ©#7J‚äÒ$¡«=__fÛ ïòæþqá ÌÊ­¦Pß>]¼¿Sæ2q“(ˆ.ŸÖ\±ëűù”ÿâ„®r¯ƒç|¼ÿðpûãíýÓ• ë®VöœŸº¿åÖÓÃõýãÝíÃ#wõ´÷ñ¿wðõ¯VÊ„óá»ëOO·< -Öë›_ù¾ï\߸½á©›{Áqw{{=ýëáöñê·§ï/nŸ†CMî{ -OôÇÅ/¿y—9œÿû ÏUI¬/Ðñ\?I‚ËíE¨•«C¥ìHuñxñÏád––.2Ò÷Ü@EÁ'ƒ`‰“:q#(âäÓ¦€cEÆéŠöµh¹}(«Š[iÕ5Üj²,íʦN«ê(PmÙËbäë¯Aæûí¿Ì_œé-þ¬Ùzu_Ô}'¸×'Àû]žöEίMMÃ±Ó -¥]HSpÀˆ•ï»‰ÖêWÏ ª.3TŽX"x8ö[7=7rFSÛm‘—°).ñtÝ;`®H³Àët[fÜa"ßyó\dé¾dý&• ;Êá³lntUs¨MQs+]:M•¶W~ì¼ ‚ ±ü€¾#» ³&àâ=ðƒbì2ë®/Ò(T(Ìb/mŽ//ªôhñ=í&ü¥K€¯¯ù»-ë}_t„UÀÀ©Êú…çÒ2ÒÅÖ ÇF—9=„Ï"÷ÍRá#)‰!DµDJäBž -•sÜAÂp«:Ä fçáz–Àº§î»co£~*ÏsnsvrXxÎ }çaY<¸ˆÄDs téaáBãêØ3q ‘ëƒ^±›´ÁIÕ¤ù Á,ÿù)õlw‡…«¢Ds˜Ðõ<ÏCD'¾Öíõ…Àm ÐCæ»>0ßæ©W+ðAìµ3g÷ó`xžH×æo–¨žóÁCóé°N&þ+^r«ñ`âbp«<>O†qDºo²F֒Ƀ•)wÙBCcÝ’®ûãIÈ% ØÚx'[Š­‡Öx5 üLß-e%g,È-f¬g‹á®ÈJzvº‘„Úy¸ûÀ»kÂ9EqZ# Ù½Ž@Ê•ëéÈ`†Î“íË%7&)ý¿š.8OéÏñ"×~ùÄÙ»¶Á‹]í‘3™ˆõ#$9»ò¼ûí”hß ÝÐSv‘~«Œ3@­¦`礞c›ø:P~ã{ñRL¯ÂÐI³žnœÚ|ù#öË„è¬T;ß~¼¿á©„?Ý~Ñu/Ëø¶±E"Œ k°)16!Á±’Ã@Ò¨ Ì2)›R¡9æ)p} >®¬×b.ŒN $ÉR>¤+¯)©ÏdL5$ºOœ…HUû\:ÖNcÛR Ë·ãaœ‡r‰S[âwô©d ?NíÆ(.Î3¾õ;HÀP”rëR:©å³Ý‡¹Làƒ]nÞqêäA…ôFšÏè‚ØVQ -ÙX-¨×56ð„Ž¾U*tvE‹ÀvCq–Ãë=…**´F¦&¦ÆÑH^‹‘”‰ Å—ˆKDÄè@0,VÖ‚“Œ NíHÎÝ¥ -c×x¡0Ê/œ=­Öm³]å€:@T û‚CHP´ ËNÔ*ŒÜ0ð‚9OºbÈ%‰g±+D:LÇÅÝ|ã&`Cçñ*äòq¨ƒEÆÊ–Õa¬­u2ƺV`nfYÔF†•Ð -¡û¾ØîzîPhˆE8Ò€ÅÆ¡7Ù¡ìy¶”~ñeW•Y‰…1êç–æ ±î‰$Ç·ÍÛyÇL—°és³ï¹ÉøXÌÄڼ㙮(¸Á²€°E—µånÄCN *°õ^œØ›i±Â×õ+’”ó+ÒÚÕ:±W”U’_þå.ÚÀåy6º”*Ê9zå¹¾¯­´v=Ø 9c"p> /Q˜œÆF¡ÄFp'ýXeÿ“p'f·Uô"K`%0]Ãï¨#tq˜×âðkY¨Âr%‡Çºò¹„=‡,G _”]¨Alt;ª()Úà,XÁ‰­²– -ƒŠâKå;ÃŒ±5‘¦âȈ–Êwß±M\0^G‘’Ú¹PÂ]å°ý ¹VüþN%NEèÀ&3–±¼ÌØ0tcÄÃm÷ûõO£û£½ÆŽ88 —´B¡5í°(ÊäÕ<Áô’ÖåW«+0j âxHë~~2¶L0ÀµæP -ý0#ä#›|7ótR °©ùŸ–y~"oÖ%·D™ÒÏsìl`¢³R†£D¡¨»ü„@Gð][*Œ’0Ùˆƒ0Šh0BÈ…|%±B„mž¼êÄÆÀÌPL[zí€õXšq)ÉOUò vËš›,ߟpIJ»ŠŒžÞ8Ζ²²k¶2’ÏF±àFÌ°¡rp¿¡ø7“/•¬š93Å -Þ@"ìmOì.… GE‹´¨d¤Oâ)¨ŠôsÇM2Æ Äß-•I±#@è×_Ë”;„$²ÃÒ PU´ ‰âKŠ¥ly7„VyDN%5luéëëñ­ûç•fŸ³\N¨ - ¹VEè´­@c~Bž92|Mµ?ã*5á?Ìo ˆ`ðV•q¾k¨­6@ŽK2Ù£‚€•Àª4ÏÅZu§Ñ ƒG¬&¶{“¬/´%9¶òȽA©c«¥°R°Åœ*«‹ôÚÆ€Óq©,Ç!g_ÐÔŽ‹’@ŸÞ­dŽ˜³ ZHÆѾ€&bËeü%Ëe0L=r#Û4Isá»·)¬å…¦èô»“ãpíÕ®Á×’ºƒ Á÷ž È{ Mkþ‚E,ªõáÏ Û4ŒM[-?\×":¨–QEsËslU4±ŒJ³e´u4\‰²<It‹[îÚ¨™È‡>=òÐD´ ¶ +ˆƒ‰láVƒ3‚áçbSÖù›À=û݉U*ÅRêŽÖÉOüXl8z}°÷ÔÒ«™ÌO@ŒXñUKðçM¶ÇÈÂ.îcÿx0ZÎI„Àlãà‰Á^8ÞÄ|cUñ$ˆ¢+ÐìÍÄ>®í;ûjb«Ùö4ehÕÒÎL¢žÁžÍß],¦¡?¹NíÙëœÄˆö4á©ÈõTÚØÐõ%:¼eÓ+ô…SRØòFÔ¨! -5\$û¡è¿¡,2¥ðßpÂÿMe7}È‹|!ºòPl[ÓÊP” -Ÿ»@Eº:«µÚ[(ü*WùÆöâjÜŒý):í­ôˆÏg’7©=› ΰ3yYD ®äÒzbµ‰W’ä%dÿ¸ -›è$ŒNÓžá2Í ›Ü‘§r3<±ŠÊàˆS6±Ÿæ%6ÃŽøã'©Amu›l©Á߉S1˜?m1ˆOÛò«ÝL²xÚ›æ´ýé(íâ_kªZÞ ›ÿ÷?xÆÿ9…ÆUq,—Ç»a H„(丞QnÿêsNúÿåå²endstream +1582 0 obj << +/Length 2372 +/Filter /FlateDecode +>> +stream +xÚµËrã6òî¯ÐQ® +<,Ÿ&ÛëìÆÙxœÓdjŠ&a‹>‘²W»É¿§)R¤,ﺶt`h4ºýB‹-(üØBKBE.TI™\¤å]<ÁÚõó8A‡ ±¾»?ûöJ¨ELâˆG‹ûÇ-M¨ÖlqŸ}^~üÛ‡Þ_Þ\ÒeDÎÑåw7·ßãLŒŸ?Ý^Ý\ÿr÷á\…Ëû›ŸnqúîòêòîòöãåyÀ´d°Ÿ{ +G6\Ýüã¡ë»?þøáîüËýg—÷½,CyVßÏ>¡‹ ÄþáŒk¹x%,Žù¢< ¥ 2¢›)Î>ýܬº­sú“B©¹šQ g ÆH,%iPÆ$\8 Z¡#P¥t™Wi±Í Šø©MZSšªÅá÷æWJy•·y]áLReüÒ$Oƪ䃣 X&Bp¼«ûU‡ÄH,&”Ó-NÇÁ”˜ˆH†^3`NHØÖ˜MÛà ]šµIs˵±ŒŠhiáÂ/&íöºÎ;r/+³9gzip[;Ë85‰ÀïãÜ3mª´ÞV­?7#–Î"!#\3½úk|M‘R¼…E˜ŒÔ ;Z-“4/r;gùÒ‘W¬$Y™WyÓno°X?âZZWVµOÛá"*»AŒ‡~×fSæm›WOäQî$ëWê ª@‚öt,:  )½lr¤!(r!(\w]œiW°ØàìöÅɪnq¦†C7 xz¨Ôò +Îq³æ_I¹.Ì70âùrD÷ú±Dà’Š Wzg±óëMþ ˆ8øÍìÎÙ²éxIüÞÄÛ”‹Žo´“>y(¼÷ÕU±CèÁQUTIé!0úg°ˆQ¤7ˆ¿Ã!`{àØ{OWÞÓ-‹s^~½IÊ2Ù µwfG BJ_ó áÿ8Ù¸ ± ~£KŠ§.mU"&Ø\ÑÅœ.“nL;E è"öŸG$•…½äú„äÿ¯øÆ)x?½»ÙÓ§„G*1! æ/3dÌz’&øiVÞœ2?­¹±ßåÄ´À£3p¶A஡ûO7×ýJ%mŒ9Ìg!U$âÀ¤ä Î0v 7O dž0 žÒµ‚2)jßr™l”òt<âf’{¬SÈq;æÐ4$“j*A4„”SÝáà 3®4¡ûF‡– ZmH~êÐÖ).&ÔöaÒ²PnŸA|UÒ%,Ÿ=“ö ~AÀ¡ –8åÇ¢‚ö'¢)€sxE‘ ñ‘ŽÂ·¼Ã8‰µÖó¯° § I:eYƒz Œ¡êèÑ\-žÍy‘wS”âkÒ <£©âjù[U¿T& ~QvÍ•0€1¶t®É—7-N£kðÐѳ®U:Ø!c|}^sT¸D!iWùBvÆK)¡ŒÏ=lÑ&}hÀdlºÇ`3AÇ‚ÜÎøSq¶F-Ø—?õ &Ü›û Õ©È©‹…QˆË2ä¥ñøeÒ¦+\@ôÈfÒal)rdžBŽ­—ÀÜŽŸC¦‚gG]úW’>ÖWɳÁµc*œë…Ø £]%i'Кp,ö”½¨ZõV«}ß}94SÂc1Júå“nm e%:·Þ¿;à )³%$¿o{‚ÁâŒkG‚ÐX >îÚPùHÖ¿ÄA°ÇªÛ~ðIƒ0Þj.æZðhtÝŠçº J—¼Ý}›lÁAÁcS_8¢šÀU¡ªZÞÂ]e~ßv½®mSdú– âÜŠ²ñ­­Ê$ ÊLÎH)Í©êƒÕ”¤$Jöuƒ£/6CJ +¢b-N‘Ò¤8gˆE·8½™/.££ÄäKLèYÎ kF}Yêýä€P…ò€ždü(½.ú‡#Ù]ÉTˆƒVÑÐb¶6îÏc +q„Ìc–!l4+׬‘¢oT¸oFˆ'|7búz EF ˜öÉ],m“¨Ü–ˆTmË`aÁUÔr¢óþùêÈæ.~Áúçƒq\Á ™, c߉WÙaìÛÖ Ø½!OdFÙ1ÔÇLðC 4ѶbD‰®6´"ÈÍG¢Vy,ê3ö.B–`‰ `ΠryoÈêCŠÓ%lK0fz0fQ€f+b%µ„-«Y¼Ù˜: n¡ö7á×}?¸¿•Óvr Ú.æmµï·¸£m¡èÛbm_Jú…ÄœIc‚(Äm f"ÊøÖ¦Xì[CEýôä-úiŒaïhìûaLA½jÛóCa?#Fß0 ¾bÁ6 à÷<í$E¤Ç¼ðèë¤]áî£}8.Ô „„G{ZÇZøül«"/sw—!ôe.õ{úMþo3 Ç w³rùS›]ªÂ_}oz7º]mf6›9¾þèä+Š½C>ؼ Æ–aín¯¨ÔöžÓ¤) N­Çj{I6UoÝé5ì4Ý”=Ûš‘,yõX¶eæaë y®|§u9BÝÁõçéPÄ¡ÆÇÇ]ƒÇ´Íà«^ÜñÒÉVÕ§ï)÷fJlJ©Í;w8EeÞ¢þ|Ïc¹»Ñ)OdæßùbtYG× !ïäÞRÀ­ãýñ¹ÿ' +­ù|ƒAЊËXuLYÎÃIï·ÿ“sÊú_—0‰Äendstream endobj -1075 0 obj << +1581 0 obj << /Type /Page -/Contents 1076 0 R -/Resources 1074 0 R +/Contents 1582 0 R +/Resources 1580 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1068 0 R -/Annots [ 1079 0 R 1080 0 R ] +/Parent 1562 0 R +/Annots [ 1587 0 R 1588 0 R 1589 0 R ] >> endobj -1079 0 obj << +1587 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [464.1993 469.2511 511.2325 481.3107] +/Rect [406.6264 524.1437 456.8481 536.2033] /Subtype /Link -/A << /S /GoTo /D (proposed_standards) >> +/A << /S /GoTo /D (tsig) >> >> endobj -1080 0 obj << +1588 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [55.6967 458.3121 105.4 469.3555] +/Rect [140.5805 512.856 196.7992 524.2481] /Subtype /Link -/A << /S /GoTo /D (proposed_standards) >> +/A << /S /GoTo /D (controls_statement_definition_and_usage) >> >> endobj -1077 0 obj << -/D [1075 0 R /XYZ 56.6929 794.5015 null] +1589 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [103.6195 470.0794 159.8382 482.1391] +/Subtype /Link +/A << /S /GoTo /D (controls_statement_definition_and_usage) >> >> endobj -146 0 obj << -/D [1075 0 R /XYZ 56.6929 535.4755 null] +1583 0 obj << +/D [1581 0 R /XYZ 85.0394 794.5015 null] >> endobj -1078 0 obj << -/D [1075 0 R /XYZ 56.6929 501.7295 null] +410 0 obj << +/D [1581 0 R /XYZ 85.0394 769.5949 null] >> endobj -150 0 obj << -/D [1075 0 R /XYZ 56.6929 345.0948 null] +1584 0 obj << +/D [1581 0 R /XYZ 85.0394 749.3189 null] >> endobj -1081 0 obj << -/D [1075 0 R /XYZ 56.6929 309.1395 null] +414 0 obj << +/D [1581 0 R /XYZ 85.0394 679.8163 null] >> endobj -154 0 obj << -/D [1075 0 R /XYZ 56.6929 120.0167 null] +1585 0 obj << +/D [1581 0 R /XYZ 85.0394 652.1211 null] >> endobj -1082 0 obj << -/D [1075 0 R /XYZ 56.6929 92.4013 null] +418 0 obj << +/D [1581 0 R /XYZ 85.0394 573.4726 null] >> endobj -1074 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F41 939 0 R /F21 714 0 R /F55 1037 0 R /F48 953 0 R /F39 899 0 R >> +1586 0 obj << +/D [1581 0 R /XYZ 85.0394 542.9681 null] +>> endobj +422 0 obj << +/D [1581 0 R /XYZ 85.0394 335.1831 null] +>> endobj +1590 0 obj << +/D [1581 0 R /XYZ 85.0394 307.4879 null] +>> endobj +1580 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R /F53 1303 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1086 0 obj << -/Length 3046 +1593 0 obj << +/Length 3489 /Filter /FlateDecode >> stream -xÚå]“Û¶ñý~…Þ¢ËD>LžÜøÒ8»I|m3M2SJ¢-Ö:Ry'_;ýïÝÅ HQÒ]3}êxÎÅb±ß»”˜qø'fF3®òd–å Ó\èÙêîŠÏÞÃÚ¯„ƒYx E õ‡Û«Ï¿VÙ,gy*ÓÙí»—aÜ1»]ÿ<ÿê›ßßÞüx½šÏv½Ð)Ÿ¿xù—k!ÄüÅ›¯n^ÒÒË7oiðõÍ‹ë,™ßþùǘ&Ñöùo¿ÿîÕm¿ã×Ûo¯nn¥ñmWHæoW?ÿÊgk¸Ô·Wœ©ÜèÙ^8y.gwW‰VL'Jù™íÕÛ«ÂhÕnâŽV†i#³ öH9ųTIeÙÓìé2¿H™4÷][­KÒd[®ºª©é¥yGÏ‚uÙšý‡Ïè­ÛªÖ=Õ¶XnKÐx@7±»_n«C‚óˆN>[ˆŒåY"-…7‹»Ý¶„ƒTbæ¯j¿gp·T°4K4ìÅ-‡¢î€ %óyE3¯ê®Ü×Å–¦WÛª 0H>—%ÕñÊþZ˜yÙ6ÛR~Œ±mš¶«‹»Òá+êu¼¡W›¢~ïÞcð -³…§z!˵¦ûªn€i6ß•ÍÎRc”>-ÿì Ô2MåüÖO¯š»]Q?ÒK±myŽÀ° -ƒž#ð]qï:·yS<8ìÅjU¶vÕ„ÕU¹ïŠª¶7âëøM½}$±ÿ³©Ëv¬3î«é&5(o·N!‰Cí úÕß.ÒV¨´ -Fâ²Vp4 b]‚E(î„Ópgàé¶j7n~Sµ¨ŒR;aÀ\ÏuØp¨BœnËŽ¦îwnïÁ!…•–¦pœAýñ»ö(lbòùŸêr„Ìá‡ÑÒ-5îHϤŸL`¼dùü®yUÓ1Nˆ5½úžVÚ]±*a W«æ¸¶60Ú;X¤‰ZœZz¨šV–Eë¼ L¢ ![¥eÝT«;#h†!µ³ÍÇGë¥&.klU8'ÖÛC‡´lÐܬ·&µCmª<ª¡·«ê‘²½|ý·‘j1d–z`kðæ$Œ/Æ‹¦—xÕÔ¿p.ßßÓå×4kõžïšýز&…ßÿÛ}¹¯J«œ&A§SîºÁJ@@ô¿÷ `ÊL¥©w¡mÕ•‚²=®Q,5©tàŸM`\$Z0®10‘€DÀ,按L¨¥%E –8Rpð´Âäç"ÉH‘KÃ@Ùb>È'a!Gq%2%IÀY¡ã,jP´šöŽE21z¨Ö I-€Š<öløÐâ éŽÈgãÈz¯²+=xç`QÇ (Ä]A¦ˆÓúËaÒßÃõc¬˜¯(9ÉkÇ ÈZt³!7Nœ–áöìq¹)Î3‘ÂÏ´Ò$L©sž¡âîªR$,•`%CrË9š>OçÎùu–Ñ„sø#bRHWÓ4{ò5S–©;MßOÀPè'_ÏbôÜX7ñÔ3¹™iìá͇¿4rŽðrwߺ«.KÇ%1£¹:•c—)]þ…ÏuÕ‚“lôF  ‚W °ÊÒ‡†f·áôòŽxçp`°ÇAŸJ—Ú(¦Üoµ½_Wõ{‡ßÆ -8 {~ÙÐ1J5çŽÍ†C¤´I«”øbxvI8_<•Eq ÑGšÊÚóGÈm\¶é<•8‡DâÚW#N(/¸_a‚3µÊ;¡aJ²4É%M3.žåÈÁrà -n‹ÍU1 ãPnlac$ðç~»¦ˆKµƒiï)ó¢í/k—ù4Eü]¹´ÓítÎw†…'Ð¥GzNl&E -†‚/˜ÊM¹•’{K<8ãYi~‰¯BçÞ;ëvpCª<<æÖB—@ñ¶"²£¾R’JØK½þÉeœŠOpìôÍ…Ö,ƒÒÙ_…Ý}t~6‘à}µN†Zyþ)$I".ñÒ+à¼ÀlÍÒ$(1^“yÙ+8Nš¡G°uŠ•Z¯+4f´`ÌÐWÔS„qÅôlJ1n¤<{GÉOŸkRrelRtvC†„¤» -gwåª"gÇ篢É#¹ã¤Íî)$@­•Q㡶u©U5psëUÈšÑ=£ÚüýÓO¼r%SÊ•Ìw „)òá°‡bDâ}yùrXu¾¢•öîÀÃT—åÚÆ%ÜV®Š{e Š °äM! æ=ð ÂETÌE¤/•¥ãŽ(0ÁÀ×b0<~Ζ5j¾mšt)˜ÄÚÔâ°ñþ.·ÕƒÇá芖;¸¯;4®µeÏ‘Îÿz­õ¼¢ -KùzIÅ1"F²ølTnyb|Âkë8·æ©öiÀTï©›¦ÊÓà ÏAŸ)ÝhPxQuèªÅzxΰõp:ÄãÈüÄ·ÌgQ“m·‘"k2|yöÅ„ñâñ9ËD–Úã?µ43̱U)X–¨„Í›ëEÊ 3>§§×ÔAÞ?Õ[x¤ƒë¾ASJ»ºœFå#°³´s³$^ÙŒÅ̦ؾssî šnC.½UuÀè'BÚo}ý®tÚõi¼¸Î]Vd7–ë)´ùÏçj{+ž“ý„Æ7½ýऻSXÎùoH‰IÉÑc[gØÂÔ t †¸¨¥ƒ#W"ìÊýöZÌm—ÛfÞIß­·ú|‰ç§:HGÓŽÍÏòiØXq -<‘šGPÖÁž0ÓQ ÏVÔ–ö‰Y娮w4OZÞ!ó7Êa07fTÜÔÅEßÇR®…®¶=DŽWé’½!Æ>w—¹oŸÁt_†¸üÏÎFaÁ³˜’Œ§pÒFËó}Y¬>„öé ¾NÝÔ—¼h{²½*!DÚŒ¯tQ¡]9&R§ÖvÔÐÓu*a´»¶Y@•°˜£rÍ–RÅlØÐÛ·(ˆ)B{ Ð[6á†c PÚŠçqâ3$L™PÛ÷Dþ“3“*ŸïDTüRFÊ1ßḴhŸ¤ðN5]êa-*Û4oGfYbÛï»òªñPþ¸-~øypÈ›-ë2† M˜î®»¬Õůnà¶U˜¢õùK=ct -½ór>æ¿Ðƒ -Ögµýg"Äpâ3Ô~ødÔÇÝ¡ŸéÕgèà(=êÛúâÔ‡@Ë2ìÙÏš1”ýnEAT&ÀШU "Š¹vž&ÙùSÔñ±£ÌÆI:<ö;ÈéÒ”6rŸpò¿õÈ'J¥™N¹º\æ«Ìè'”]É3k¸]:,óOHPæ’%ôY ÆP§% .Jð쩽Ž”ààØÿ¥/ô!ñ4Ϩ ŸÒf”ù°ÍxZT¢2M.2‚:#HuYçN9>vZñ±Oä‘¿~eyZv§y¥SfÐQžçUu†Wê2¯Îñj|ì4¯âcoú¶Ò¨|ôÿúÏ€Ãh@Yšæq>†Ê~š÷{ Œ§é0íù¦Ï’OòÿTÞö¤Ð"%‡c!$ž—QuFF게ÎÉh|ì´ŒâcÿC —,—yvA‚Ô z¨Ë;ªü—R„œ NÌyžOwrð‡ µü²„ú9Yõsà%XѸ¯®8Oi}曋6;k 0<¸©ØÏa8Z—íj_-é'pÔ²yÀßAA2Ót¥GUt~ä‰òO÷“œ˜¢É3ШŸŠ¿#ƒ¯È±ÓÛø¼Ù—™£j‹&›û}ÿ¡¨î(}ó¯-˱J'Â0“(3™bœÓïíhqÿ~Fƒ#åð‹xñrãEF¼ §˜8¢&¿“‰9²/t‰‚1®è3±2œimÒq•‡§Q?dü‰Ö`"˜1 %‰ÅjK-? [zý—kf`œ)ƒÿùç2ùÒMæ8i˜ˆ'ÿý¥×)ß ÷AuˆÞ5Õ®]¼o›r_ž@G™P³Cð€ãT)¦þrB*ðçþwÿ^³wÛ T§ÆœHR‡äݦ# -o!ô˜òðÃÎcÒÿ’qendstream +xÚ­Z_“㶠ßO±“'ïÌYÿJê=]’½tÓæ’^6Óé$™ŒlË»êYÒÖ’ooÛéw/@€”ä¥ïÜöÆ"A +@ø²¸Lá'.Ml!‹Ë¬Ð‰I…¹\7éåŒ}{!xÎÒOZNg}u{ñåk•]Ia¥½¼ÝNxåIšçâòvóËÂ&2¹éâëÞ¼¾ùöç·¯®2½¸½ùáÍÕRštñúæÏ×Ôúöí«ï¿õöj)r#_ÿñÕ·×oiÈ2¯nÞ|C”‚'˜¾½~}ýöúÍ××W¿Ý~wq}t™ê+R…Šüãâ—ßÒË ¨ýÝEš¨"7—ÐIQò²¹ÐF%F+å)»‹Ÿ.þNFÝ«Qû‰4‘Êʈ¥¸")Œ‘3 š"±Jª`A‘‚UÒ4]캻»º½#-Ê¡jªv î7Õ¯i*Ûz¨»–(e»¡ÆÏ}yW¡-`E9Ù²ô†“ãò°Ôí½Ÿ$&“dš¤*30çx ž3S9hYž×Â)•-Ö]‹ÒÝöW"_T=RóEIƒõ¦¢Öûr_WÃuº-Í +J;âê×SgÛí©1ÜW4·-fÕWû÷Õý'“‹›¡h§ÀÖ*‹½¾/Û¶ÚEÔ[j‘%&ËÕå2l¼ðp¿/{XR*°wßwëôî±/Ýax8 4ÖTÃ}·é_`O£àMÉ#A#|…¶ ¨}Ò×h +ìí ·ã)õ•…y>“ÚØX¬ËÖ“*n­*:ôÕUD eè´>ÖŽ¯qïÄŒU$©QÞT è]·ŠØJ§‰Í½Iƒ…mGϾÚUköÛûùÝ¡§ÎzÖ¬¸ƒž€Ï¦êÑ“™Z’/Q¤Ú$N+8gI¦Aµ~¢€¹å󆧥Ðó1l†z}Ø•{êSÞ¢ö¶\×;ÄŽBˆÅÑëtvð…ùiƒå¦§ÍM ‡)fáFôMݯ™‹‹}áÍ@ Ñ!"¹’ŽD2na;v= +‡H¿nêˆ$'ÐØÎD¢âœP±ŸN°7÷8h+~©\¯«‡ÁA2_=-0îPMMFNÀ‘ºÂÆ<)„)øDÔí¶‹Åš<ÉEbMjÄ ro­³$SFÌ]ÃÁ?%²Ñß°ã-<ƒ'c§Œ!7a’\ûœ†•Á&v’Ó¤(” !²j+õ¯<Ô ¯nÒ¸äb<G´ƒ=®¹PœvóeÇòŽ[…=Þ*lzÓ×6ÉUnç QŸãCÛ ó7žiWë>¡a“àpc¼ˆ—µkìÔïb³ˆ•¤H2ëóÈ<^vŒšä@å +Ð]’Fâ$F˜ü]¡PÐ^"…<­˜Æ1¤vDtþ ýÙƒ «dê6q(/@¡‹€Îy y˜€£ŽæXq‚á¶! GóÓ¬Èjª²<±µÎ7´L-l¼ßaˆè!Òؘ­Uf‚­U†!¡ÖCOƒä˜8Ë‹ŽÓ܉É\ÄĘñ ¬,) VîÕ²¥Ññ€ÕE¤Ò_9aÕa‰Œó¼dX¿:[H4Zê¹­wd@À¬`#CÃc)l;‡'øM÷èâÎì蹪Ö]ã’€Õ\•Šfhpf…·ž·z.ÏžZc¤ãNϾ|ï®Êõ=¿ë¢”'ÅŽFw%›˜{`mªtA‰^;цêâ:·6Ñ©òŽÔ‹\7ˆÄZ;)Þ‰k€«ÖáùÈ4]ˆ<_¯Ôh•üTàԉΔdI\\r(”6þ"Gh‹°µ*×ï4>nŽtÛÑnx<'€vÉ4; +’˜ÈT&ya—~&[a‹Ë7há¶Àtú,[¼vQÈÕïc€©ÀF*í4Ö÷]G§Nòq’‹wUõàסµyB·ÛPc¢’·A*l¨Y˜áöôøè4À(Áý|¾ ¦H²,@QÜXñM—’ùâïùakUm»P®B¿fº+´àIþ«"`§m–†+ úçò@P™÷AÏ<ìK¬@ºÈJŠ†,²ŽŒ­I‰ ösf (Ôœ™Ïð.Ø~~^q¡4æçš 8…ÒâH¡ô´BPNÈ3-7×̤\œ{Îê!‹b§Ÿv¨s#>³ô駤Gü )åoW¸ýÖ¤¼ ¨#bµ£‚°S€óÎ}Ì!ËZ—‡¢ñ*$­ <² ° © ýqðЬ\m—'àéDà$Ý09 +0sÈèi.AëÆò9¤}kÂé e5ð¬=Lò×å’oŸG\d¹Ø-ÆRˆoÍÒĤG †o¹= +ˆÒ†–/º°µáúØpˆD ;&9^UÌÅúHáÈÕ‡uUmú£ëvS¯Y!˜„–Á{Y™-Þt4ÃglO3ÚqÁ®wP¾ðÕ(WÑ _ìË÷%ê~׬á¦`ÔgDÓ} qŸ_+@³Mu‰àóã´víø¶rJcòš4M;ð•Õ‹HÍa“ ¿é|*’ŠBûIGde2uÖ!‡86wº>úÁMdvAç35C…Ÿ±Êöw. ~ŸÑùKœJ +ü“Ål7·5Ú'}Á¯"´ú‚HcÀÀž¢í¶dÚ¼Œ~?Ú×í°¤jç=U}ô#Í›ª s—QqÏùw2Eš<\{ðõl$a@Z)ĉ+&9¹b’ók$0L’Óë#Ép2 +kî²Úc¯0¹¿C8_Pø;v! ¹(Éï3S|µŒ@x"BÉ_– IJ,Ç÷xc$†âÖ•Æ'Ëý н.ô' &O¾ÐjJæù‹ÛÔ.þÔvLå›p÷ûåôÈ|»4N* wվߦÇÕ×üÎ"‘"ü™vn»é‚£j3y.—¦¬wñ  ƒ¸'™xÿÛ”¨c9\"ós…)ùO s¶J'7Wæ 8Qv.ŸÝCÔ¾*ù¨BK%@¤3‹bñÂBV¤É$Bhï·‡Ãú!ÆE&6×ù§¸xаÞG7 <§æ\Qp¯ ä½ízÈCŸËi;<œ²s*Îe²ëÖå.VBKpA›ÊÿŠøßù˜)ù™äQŸ‰þLz™Ï$ñÁo²á¾ê$Ñ6ÜÝ:VÙ"-¥Ux·]ñ¿$bÿÝT&Á?\Fþi™†¯úÿ÷ÿ:Ç?½ê,Qy.Ç¿lÎäÏòDçÀ„…B-´}&¹ÿèsÑÿ’Ý@ endstream endobj -1085 0 obj << +1592 0 obj << /Type /Page -/Contents 1086 0 R -/Resources 1084 0 R +/Contents 1593 0 R +/Resources 1591 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1068 0 R -/Annots [ 1088 0 R ] +/Parent 1562 0 R >> endobj -1088 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [417.8476 169.1947 466.5943 181.2543] -/Subtype /Link -/A << /S /GoTo /D (sample_configuration) >> +1594 0 obj << +/D [1592 0 R /XYZ 56.6929 794.5015 null] >> endobj -1087 0 obj << -/D [1085 0 R /XYZ 85.0394 794.5015 null] +426 0 obj << +/D [1592 0 R /XYZ 56.6929 769.5949 null] >> endobj -1084 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F39 899 0 R /F41 939 0 R /F14 740 0 R >> +1595 0 obj << +/D [1592 0 R /XYZ 56.6929 749.2381 null] +>> endobj +430 0 obj << +/D [1592 0 R /XYZ 56.6929 540.3599 null] +>> endobj +1596 0 obj << +/D [1592 0 R /XYZ 56.6929 517.4049 null] +>> endobj +1591 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R /F39 1151 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1091 0 obj << -/Length 826 +1599 0 obj << +/Length 3318 /Filter /FlateDecode >> stream -xÚÕW[OÛ0~ϯˆxjâø–Ûxê lCb4Û ð¥*¥I‰ÃmÓþûì¸IêJ'¤©Rë8Çß9þÎwÜcdCñA¶ç?‘Dxyv:· }-Þ}²ÐÒÆiŒÝêcl¹G$°#ùØ·ã+ +0 ‘OÏP0p09ýú%:؃ƒÃ“ÉÐA!õÂÁÁçÑi<>SóéèðÇ!4Œµ%rp4 :ˆ¿Ÿ'ÃËøØÇm¤ún$2Ì[ëüÚS±©c …žý  @Q„í¹E=u|ÏrEßïRõ€ˆ¯ÅS2^•³´RO`’¦Œó~ß%KïJ.xÜè_ú Â^+Å/l™-Ú—­&™rö— RyÜ㳊!Àë<€´˜ï­¤FpO¦æB2M†j,é£qÛñ_=-:kÌ2Ÿ5À{sw= ý ¤—F«°PÏè´hdXΛš.ʤšÝ«Àq@Ei‡Q×–¡"»«ÚÌJE®0«N¶òtžc¢]eÚ+^Ñ{©ÿ•9y·”¸Gk]špED³GEg+mÆmW${OyŠ/5qSðª>¾»=ªêžÔ8-ò ñõå¬Ó>s–¤™‘…µD@ÓåEg'&C€ôI³ØZøöHéÀ;:#­áŠ…4ç„ŠÞÐânÑb÷–Ðt{ -¿¡×‡íw¾Y¬.U4$ q{ièÈ! ¡Y%)BþZäÍd=ô¿mu”Œendstream +xÚ¥ZYoãF~÷¯ò220êôÁ£9ó4™µ“ 6“]Çû”-Q‰THÊŠv±ÿ}«ºªyÈm{‚…a°/v×ùUUSj&áOÍl,¤É¢YšE"–*ž-÷Wr¶¹o¯¯YøE‹ñªo¾5é,Y¢“Ùýz´—ÒZ5»_ý<ÿø݇ÜßÜ]/t,牸^ĉœóéóßh$£ÇÇ?ß~úö_w®Óh~ÿéÇÏ4|ws{swóùãÍõBÙXÁûšwxæ…ÛO¿¡Ö·w~øáÃÝõ¯÷ß_ÝÜ÷¼ŒùUÒ #\ýü«œ­€íﯤ0™g'èH¡²LÏöWQlDãGvW?]ý³ßp4ë^ É/6VÄV§j`œ‰ÄhãXÕp”©y¾ÛQc/Ë]Ù•EË͵²ó‚:íñp¨›®XQ·®&/Ëy}(š¼+« /?·]±oAªÀÃü»ú„²Ôˆ,Æ"†0ƒÁ+»zÃëÆä%+ý²SééÝæÕjÇä틶Í7žò¶¨˜¹®æç¶lqëÙÂÈTè4«SJdq¬Ý®Ìû•læ%îGóUÑ.›òÁ1Ã=»m`G©X¨46vIJ®Öž@»©V)¯Ýç¼óx™-çŸÖDù>ÒÜ6,h(§’1µOÛr¹¥Ùcëă¼î±hÎ4UïVýP[Ö|h½p³P‰6K§bzIG:ÕóÓmóŽÜ¥®vgjy²ä¼;ÕÔ Û÷ .?ÇSψ8‘B›Ô›Ø\äü"c ÿ*@Vž­¯’õ±ZvÀöÛþŒÊ·J>¹ËPjû±¶ÜžrSÕä+A2ã D¥Mæ»sA&ö6R€"Ðê×VŠ× TÅóSÝüÎæ¹+‘Zq½æVÚŠÔö&ø¦¥íÑ::4eÝ8 ÀÞ[š(þ\‡ŽÚ^¿ÊðLcK²a°Î][ÓГ ´¯h®\Óu4Âd ­6$U•D"K­¹0À®ÉËÍO×Y <ÑÐœÿ"¥v€CFÛ¢áe[G´Ž-ï©–È +eÓô¯É =UšùöÀÞ‘¬ž9 ŽðGù¹+ò–›õšÖ Õ»Þ0xåc±£æ¦|,˜„$ª4 +³ÒÔàÁbØžÛbW, Á¡·®›ÁÕÈöALU±{O½¢¢¯é¹á߯'zŽH^Í=:;_¢õx—‘SWA¨‹TFV^pØ9^ ‡Õ–nÝÿšÖÀž£D±÷ãa¬‹°Éà©/£y,LÚG¨Á}h’†ã˹F¼­Š®höeÅ<žœCa ¤XuG«gêò“€Ôk¢(žºD·uÒª›-dbÕüUk )þÌ÷‡]ËÎD©\Œ6© ¸ˆÕN!b,-Tí†Û€¼ŒTùX/„U^ì!À  [‚ðÿ|¦g=;ݪhšÍfBE:í¡¢%±‰Àë£Ì)›¯J&×%›IO]6@ v(͆ٶh1æÞð›mÞAQjE‹:d¼áw::+ßc’`,0Iéd6ïŸUWT+²

    Ãs?'¤s^¶Ê¤H"ˆ¯ +ÛǺ,ìëB¥w&ìDd²¶Wy°f˜˜ +[Š,…È3áâÝ X…Á¦zª6G›NÀ÷PãËQ¾aLò˜'_Û&h˜Œ×=C%n×*—"¨+x09(âé“ÊqX°¦Ôi•†"Jµ™fÓþ\ߨöCõ^íJJïOnª ¼)p@q:vÕ œÉl¹’!Ùo7› +Û +9ë×Dzè‰Aì‘åÅ#uçE8dAPQ,†UÅ‹ÔœŠcˆrL' gËçsË®%”tŽv~™ÅÔg.mÏíò^"ˆZiš1Ó·õ.2ÔÐ.UÓ—f‹9¡ [¡¨Úí©¸zâ£ôƒ«î}Ût<¹Ø–\éŠ..’±CìÓù7egQRÚl›4ÙІˆAí0Yð+yH˜CÙz ·‘…£øpEÁ·ag³£!›3§ºÞôã‚GèNÀœiŽb±Û=¶‡~UûÙ>æ¢QÊáþ]GQæ1 “É(ñ‡*ßaP„œ7ÝsÉл;AƒÛ¶/Ý&y?£` DI%(y,JXóC†™7ïÐÀÉ(V˜Ú•X—WÝŽ¢ê°³ÓIב;n^O™.õF½ˆØ¸n)Q÷§}€!azwûÑuéCCýÎÕÿ±± (ãŒBˆoÈ*5žåùª£à–7­mÙ˜ú>8ÿˆ/“Þ§æTïQ€(¨½Wüþ=Ôaù¹(÷ýÉÒ»»®ìyÎ9¸Á¥ØpùåFרWjð!Ö碖•^—uû H;‘ëcOìVOLg¸#{jÒ!“v‹m]´°‡†ByÓ×/K)eÀÍÛÞ«â&0”¹}Uëüx3e"”w°ãOòTº¬¯äŽõ`†‹Ó¢ï8ßsåjÃßÇl´êsGGÓdhˆÇõ+WÛ±kseØ’dÚÜЦ¬Ë‡Üu—3×ìÃ)‹4sIõ‘õîzV!m'2Çû§Oëo¼îóŠQXo¥ÏÕɕ À»Ïé Ç–~MâOªIwà"É´3P™8¤ç1¾Éi|›WÉÕöÐîV—üŽ c‘Äʰ㡾àiX‹D"óMM;GFC.™ùîK=äð;8üÆúûXÙ¾¶•qbÌâx d+$c-¡¶2ËÙ'v»s°18¼Ä¤_t°Jdø +FhìQŒ¶…*ˆˆIé“\f0“§‹ü$ éü$¤j¬Œ€ MЉÿt­×¼Ïg•óCÃo3íú©jÝøܳycÏÜôœ¤ +…‰#õ¢P¤ÂÈB*q–ˆ/QüKwõéX±["èîhc%ŽÚ1»Äßü Eö®’ñ­É‹mðe9ãg©Q+™(!Óñr\Ÿñˆ/F +’|#SIèÞÎbLM­3Šva@pk½µû„C#Î:þ¥;îö¬” ÅM‹doi ‡· À÷U1¾¹ôR6s[‰ÐFFá²-kLl‡­péÒš[nÞ[|­¹7zÙHÈì³ØL™ðêÍ^’DÄa¬^õ"RÄI¨_õ"Xó$ŽŠ ½á®1u- çáÙ·]W­‡žeËg^B :;µîã~ïR•ºÚU'F>è­>¹÷ÉÛaîYïúÅuæ¥Ay§±„æKË?¯X²]õçœ\S%B¥ÓA"t¨“tbÔåtÊKB(ÚÌ°•‹¬Š¢/|惘ì3öâ?¿H7“ŒDSÆD°iÂd³Œfò¢Ÿ¤HÚqÇÉɯK .¿\Í>™ûYiª²ÿµÔ:'ù¹L\ü+^Šº*æèdBÃ9ÍÏBC>~Or&Q#3t™& &?ôÓ^œdJÏe]O!´[í\‡ØIë¢pÀYÖË@“ë¼LŠÌÈ“©Í›Pô‘ +~lŸñÿ¦Ä–ÉIlóIûŠ3˜i~¶Þ_;Å”mÐCâhïx\y ¿pµ-U‡š3GÀq +¦µ36odr5—·œ?G%£RÇe‘QAGýJs¦Á&vE¨¡'füý­pdµé‹¢,m ì–ùa§ã ö@—MÍ÷1ù™‘ŸxpÇnö ¨Òÿ +g¦ÏO_ýÇ>ã‹&$X*Ë¢ù†8Yg@„™Â+ÈÂó>ÿUÐ9ëÿ ù«_endstream endobj -1273 0 obj << +1796 0 obj << /Type /Page -/Contents 1274 0 R -/Resources 1272 0 R +/Contents 1797 0 R +/Resources 1795 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1245 0 R +/Parent 1787 0 R >> endobj -1275 0 obj << -/D [1273 0 R /XYZ 56.6929 794.5015 null] +1798 0 obj << +/D [1796 0 R /XYZ 56.6929 794.5015 null] >> endobj -350 0 obj << -/D [1273 0 R /XYZ 56.6929 418.3076 null] +534 0 obj << +/D [1796 0 R /XYZ 56.6929 349.7668 null] >> endobj -1276 0 obj << -/D [1273 0 R /XYZ 56.6929 386.0953 null] +1271 0 obj << +/D [1796 0 R /XYZ 56.6929 323.7864 null] >> endobj -1272 0 obj << -/Font << /F37 802 0 R /F41 939 0 R /F21 714 0 R /F22 737 0 R /F39 899 0 R /F48 953 0 R >> +1795 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F41 1208 0 R /F62 1352 0 R /F21 930 0 R >> +/XObject << /Im2 1341 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1279 0 obj << -/Length 3843 +1801 0 obj << +/Length 3598 /Filter /FlateDecode >> stream -xÚµZ_sÛ6÷§ðÛÉsC Î=¥±“º×:½X»›¶´H[œJ¤"RN|Ÿþv± ¤(¹sK&!¸XbÅþù- qÃ_qit«<¹Ìò$ұЗËÍE|ù}.óÌÓ<äúvqñæ½Ê.ó(Oez¹x Æ2QlŒ¸\”¿ÌÞ}÷ö§Åͧ«¹Ôñ,®æ:gßÞÞ]%§Ç»wïo?üüéíU–Ì·ïˆüéæýͧ›»w7Wsa´€ï%pâƒ÷·?ÜPëç·?þøöÓÕo‹ï/n~-ázE¬p!Ÿ/~ù-¾,aÙß_đʾü/q$ò\^n.­"(å(ë‹û‹øƒ^ûé”þm"-“ôrÌJ‰|ZËqkÐÚ³Y±^¡[»+afîcX³>UMµ+zêÈf_ê~…+)II Û§°:;ÿßü›¹ÂåÈ,2Ë™)"ÿ\Un øÉå\™,Êâ$-‰(×ZZî庮šì2Og4ÕÏûªë;¤hút4§LD‰ŽÍ+SÊ£8KSõu¹*š§ê°é8Õ,oS¼P£Ý‘8OhZfé¶Õ²~|¡n«r¤–UW{½Z~Øây¤±Ò3èüJz‘¹˜Ý>yKt°úoHA"ŽÁ¼³Ô)ˆŸö9ÏX¶ì6ÃÓw ¶9·ÛL_jk Ðz¨HKI¨J‘êH$¹`5¹½Hã˜^ãˆøº-vý„šè91:ãþ:!Z¹r #ÿ³É´Jv”A¬ú«Ü}©»Šµ¤2ˆFŒÌˆT¡ÜN(ÅZRé¡k %` -Ak Z'´céœ`W4°R˪úJ²~ªÁh'4'ÐÎõY käÿ›†tšÏnšü¦ízZÙ²èªîòl\þ±ÍUG‰€¡j$ÁV‡Âe”jáVÒ­Úý4)MŽjƒ'Ç$$tÕî¹G€¤ò—ŽH.¨! -@_ÌsëzH*bkÝvÓkÓ6óêkÝõÖ0‘±Û?†Êgëú÷Š ÃMoà=¿J™Er¡ÁÏ€!5¢çÈ^2Ê1Ó¹kîGœ‡CNÄ} L¨ü Ùm9Gˆcã°MF:ë8»?:²L»˜‡+ÇP,br0—¿´{j°Ð˾«›'Nö÷÷óÅýí‡oèµ_Õµž‹]]<¬ù‹Í [L)«_ãX6UÎÆ©Ž£<Ó¯¤ìëtÊö\‡Y¡Çû¬²(N“ó¢Ó„èaÆ–Q e(Ûfl Ñõº~D¢ªùwÕz½±öìB1²ì;Œ;Hz`Jï¾vÞ‚˜Þ‘æò3QÃÐ…½”ÇeΉÛòPôîœ4ÚÔܸ.K€X<ôø37ÂIiPb$=Ž "[Nó 9Ä+˜´ãúu£4²) R03¶7hY@Ϻ-J¦¸!¶û‡u½äš’‰»ú™TTV´­ -!tS¶U:Js˜Û0^€Ö[½1ÖØÌ¿´»ß½³” –}»óÞºFñ[.ƒ‰Q²ÂM§òœãh -¤•Ç8éu:O£4ɲó^rö:Ïe¡B±\UsÒÖ‘ßÁ¦§ƒ/&ÏqMˆx˜m*ãl(áC“{ZàeÕðÑoRÛ¬{sݲÖÚÞE¿3ÚK¡PzE{×í9.Æ÷›íIåå‘I_‘í˜&dU—D&‘#á ‡‡¶E¿rp)=†K<¿xUHÄUt£Ê¢/ŠÎ}Ö2À¢ZZuÓõ»+3Û/©ô˜J~v-‰:Q’Ì!­™{×í& Š ÇAúØÕ½Í-ІÅaÚ°í}W<ñw‡ó8- kè X¸ÓMb*$‘„¦k3â?i}ßÿœ=Ç †<Í9â]™ªuŒívÂ`¿‰Q¯LÈuÚ`<JÜÖå)3à-XüYÙžkBø°êU‘éPøÂ…È0¬ò‘ŒÊôVÍTXͼ• Ö”4(a—eÕ1áöš9¬3iÍ;l$³cv^¥ñAœßy|™Üù$ƪԟ ¼! K$ÖX¹šovûæµú?‚­˜*†l'& ê×êWÒ4~²‹Êž„DÌïH#üŒ-ÄÏØÃ:yÚæéWEO}_ -¬-­%JW5ü}W?5źóÝ yjLJ/Òè™ÍYMC¸Â$3´Û:Àfè—"™ÝÓ‘²N fˆD™†:"[¬ ÊÝÉÊ[ÔF—u‡Ø¸£OxŠ *ˆ(˜ððÌÒ­Vñý (Áê0s"{é@©\;H™FJd£GSí+[éH†ß¶ñBG]¶pç:ªˆ¦¢ž3Ô‡'éMûŒ䎥Ӷ…Š8Az@¢­ƒÄ’QÀƒt§È€k$}`œ‚<:…¢¥<¶a…í ªU³\·TeFÙî}‰ýy -èN‡PÌËÑó!4à:B—ÅQÕr¿ÃÚñT Mt9&=?Ï51…A<€bZ©Ñ(Ýj¦[ÍV ÏþJ̇·Yíü@ëCÆ…6CÔAÿç=¨ïêÊw=µ‚c==ÐkÓ¯_ˆÄõ)ˆHÙRlÄcI3´‡ÚµÙ·u›Íx“Ÿ'Юˆ¡€NR—‚0×oÔô)¡ÎÂSÂÿÒ5hpnNUêÏO6¤©ÈdòùN¶ç²8èU$‰'<1lÜÙ)x®‰9 Ï‹R€ì©N‚2]œ„Þ,FˆÙD‘àó´=Ñcà,¶[Hgw˜Ñ~ÑÒ“«.`W]SÉO[uë¾›N\s<'KâQÀ#{T)Mb -& ¤® ßk®ø !üvˆTlЯ¨ë€TRuÂAÓ"CK<5À÷*Ë|>hHKSãƒì ÂÏhêØ—µpçl¶ p”+!%l -v©öqäp‡@vÈeÕ-wõC%F+5 ‹JJ0¶”®C©s÷tIOízþyøÁ±í‹ó¿‡×mã. “ŠÑ£ÚV@Çb0£#ò\¯Ìãx´ó¡#N#€mœ×™Ðá¸,Hkéîk-°2Ò&=/ÕsMˆ•£³T£ ÐÈåhaf?_ÿôfñî'z±³ ýýæ‚«$ qˆaG¬öp Il»UýlS’,n£O›ÒS¯ïîéSFÙ}»l×,kWø3ã%â5@ŒÎøøb:²ü ›dlÝf¦æ%%ýI^6k·ÎÀÌÌÑðºƒÒ/–:=߃cŸ÷§çx)Ngƒ·TX7bð—™ë%}bŸ½z""`‚ÆÍÓ®+_‚°a:u§¶‡k—ê—íf³oê%I»\? Oëö¡à!Aõ'\j ¥çk×(!×i#÷\‡[ÍyY=×ËãÜ»%„JÏ‹÷\ò‡¨ÏDqžäà ,è¾ÑޚܒßÛGzB&Sܾõ‹Ïf¤ -ÑR‡3,Ò$nƃÕ=·»zSìê5“›ª*ݨ|µo7èþæÃ>øÌŒn£Û-ÞÝ€1ÛKX!gÝ~¹BçóèèiïKl Ü©é -\;ºe„€7x½/ûmi-Û„¨”­˜ù?PuèŽ:g§²œ[X¹Kýù”AÛì‹\Â¥CÉ×l`б "ÂÁ z÷+öí˪¶‹…,ÈE¼¼Á·p#9j>Ï"ñ5OÄ= 7‹Uq âPÄç}½£6’3X²}8ƒ-jnd’™»a -Î"°½ÂÝÃÞ,!kõuUì»ÞÖ®*ヹ̅†ìig®ÞClÌð–u½gI“PG%Y”àÙ0ÊÀþ¼á_#L@%‰C^¼{d±BGy’ŒªäƒÎh_e’;m$ùðÇ*–BÕ~’Såm[þêõç.'Œ w‰¹nôkŠ ‘Å‘Ö®”ñ¤õÅﶂƒfeÓÑ#z/÷d–Í£²O´Òt\¡Õ}íï²mp—žödYDäKGŒìýð:ζûb×ï·ÍkwGÚ Àøi{¸ÁÕ| ‹ì:üÉSà -=]ý‹Š j:›B®ÓIÀsY¤³««Ý®*çOh‰GY F\hÎË÷\f£Äpt¨-Ç.“û+_5[ã¯Aø¦·ÙòE0Zø[b Ÿ”ÈÙ[øÃÆ Tw¦å.˜Õ¬ÚàéUéˆÁ™ Â`ºžÈ+H?:‘‡¹eÉñÂn”«ñš‘³®.Ю(ÜqOe/¼t[ˆl—î‹Suù8¼ÁÎúèl”Îã´eë ß}¼»Aõœ635{’¿ff×3s\ÖçÛ¶_WOÖÏæö’vll™‰t–™ó³ð\Ó›QFr1œÇâ -Që@¾bQÂ9Äö†aYm¨ðºÍ¹7a8qK¬yÅ×±£ŠûvKäuõ\­ùsûžŽ³§áX_P²r·9?BìÉæø1ˆ,œMmCs«¾.×û’÷}&òI2C*éöïúžÊ4Àºâ†/ÕWpÅ£cƒîÝe5ìaðr`tó¥:üð{^øìÁk’ÏAHÐòX&S³{ÆN‡INà’*‡îƒË‘"XŽD´EX„V„½uô -j«8ËXö–ÈÇ›.ãðR†@‡‡‰RuH›b wxá|û0B&wÿºþøãÛÛ»ã€Ð…Þ>×¥K'GÞݽýñæDx(ënÙ>Wƒ,äRš¯C‚@4ýÃW ë¬=á“ð÷åOÿ&üðƒy>ʘÎE³‘yæ&…*LÔxæZA¨02›˜ú&IÑ7endstream +xÚ­Z[wÛ6~÷¯ÐÙ—ÊçD@€ Øì席Óu7I»Ž»ûÐö)›ŠTEʲ»gÿûÎ` +”(;mb?àB\ƒ¹|3˜pø3.S5IRÅb.âÉbuÆ'·ðíÛ3áÆÌü Y8ê«›³—¯e2IYª#=¹YkÆ“›ü§é׿øáæòú|Å|ªÙù,Ö|úÕÕ»o¨'¥âëïß½¾úöÇë‹óDMo®¾GÝ×—¯/¯/ß}}y>&0?r+œ˜ðúêÍ%Õ¾½¾xûöâúü—›ïÎ.oú³„ç\âA~=ûé>ÉáØßq&SOvÐàL¤i4Y©X²XIé{ª³÷gÿì ¾Ú©cü‹¥a±‰’FbŒqÊ´Œ¤eàfÓݬÙäÅS¢`Š2L(c`‹Ìáéôæ®8ŸI¡§Åò\˜é²XtØN¦Í’ú»»²¥žö®ÙV9õÎݬUY7äë hK9½kvÅ}ö´e½(h¬¦I××@&UËš>užŒ,ÏË®lꬢv AÓz\Ïð`“™?ËL–ÆqdT.²ªz„¡ȯ}mÑÔ]VÖ-µ2*Ú ¥j½]Íbšµ¤(¤ÊÏ<æYSà å*«ýÚY[¸‘e÷q—õmUø]`yñb¸øî®\ÜÙCòáép/’WË,¬ëáÎà¶aQêɤkuÓQe•užÏÖ·‹;Ö/nXÂc¿ñK.›ªjvýz¥[-£¢Ý®VÙæÑí¾tåoÈ ´UÖ¹#¶q¢Jo$ÆX’Ål‘-€€c‘Rf’d/²‡ÊÁxh£™ŒÅ¸ArcfÁ Óêäí©šu6¯ŠÃ­Aú˜NxüäÞý ãÍÃS +° :f°ûÕr„o):ÖŽpÕÇ,Š¥Jz–½p×h•½G¯UØÀc]8:g¨x|/y±Ì¶•“¬û¬Úý´‘[Ö‚¡RGKÝŒ‘+ÔÔ³7ÇLƒ¾?}ÃûAOÜ°Üð¢*²80+kÐ8ÕÑe§1¨ŠÔO’Ñ:¦c ÒœÃG`JHñ7Jáb6÷VY¡¾+ÑDa”jÕÜûQ]†6$’ty®·¨»MY´xå`wç`.rú`/ÊÌ•o®¤ÉÁ˜¬ºm6ew·zA6å,‘&š 4í£Í Wñ@›Ç¹ztû3‘ð3Á›l»¢¡‹Rçš"ð{¡`:5§öpÎÕ’¾ZƒŸÁüØŽl‰ +¡m¯Áh6y¹ QžV:») +¥?;飻 ´w‹ÅÖz¸ÓÒÊBégÄ5õ„¼úQ–AÙÃ̱·-;6J1 ©$~†€~ÔƒËÑ(Õ$`ài)WÛ5²U³­;ª“… ±›Gª“w©|ìÈaJ{3Xn[·à²Ù¸/~ ¯ Àë/Ü,:=ܶÒéôßwE½ŸbïL©\ åÖSÅÊy-5ͳ.£ZYSéܪòîÈÖIõ°ÝúQ¥«Uåªì¬÷s{†ºEòEÕ9m¿Õí-5Û¶¼/ªG·Hã÷ʺ=mL@BiIÀÂîÈû}1-E‘;®¦W5ugTì錀ÎîŽzW fåÚÚhÝ—ÅΚã(Â-³õº*‰/¸à:Û€Û§3D¤xÐßOÜs5ÂKA8ÈfçY`çó4š>é~¼ÏQb`Q“‘ˆœEúí˜ÙIX*£¬8Ð>Pýšƒ`ÖOíP *„lAçZÄ+jGÏë²êŠï'#ÉÉÚSHƒ€6¥bme ¹/s«Pwx`㼬ÊîÑá߆ʟ9* êpl³uý›wï©âDj ¨¬pà}I[¬hJñ³Ææ‘P¸¾Zd€sÅÛc¸ÜŠA¢I½’Ä«WBK„ÀvgE/éá=Þ³I§ï×Å¢ÄÇ»´ÆH‹®qü"s«Ñÿcûhž{E¢ˆÜ/Mn³ øCÄM3høÂah7«\ ßiàlLÿÅ9a'M¯~¸WT³;R¦Z@Ÿet0·òνvAå¬@="Öà²ÀGJájxÒû/˜RB¤™¤i&éÇĬK F…cë¬_q.i}Å€>©4‹#‘îw&wÕQ,3 2ìÏý‰ô+>G$|MSph"«²íÆB˜¥‘ôÈÄŠµ»¨Qü>ÒÛœ¼¨gNÈáÆgî²FÑ:08aʈd¨PR¡—#s…"n¸“}–´²Âð¡@ûëwo/©jEÊoö]ÇVâ*¡ò3À¤¬*³+ÔUg«‚¶F­*YÁ¬Z&ûIÁÆvnHƒ8ö^tÊv;o»²ÛR¬¨ùô×maƒKÝo©Å4·1†æäQ´;‘ÓcÍIȬNi +˜uR‘t X5õ‘'nsBbΔ"·Áˆ$,‰Óô” GF¯?U é~>»!!4O÷é 26(˜,ˆÍtwWx!¥¶WfÙ@W†]+-UÉ—@ÅÝ V‰½Rž¶©€;É›Ufñš$sn˺;’=†Œˆ¹‘wÕ_IPÖ8N& +L‹6‘údõïWœ…K«¿R€¼ÀØ~ØS꟰(N½úU±?ßÚŒ¢±QFÀÐb1ˆbGµØ>CF¥pñF”¦*ñtP*¢w”ENÂËeFLõÂŽˆpÝÍ–€#;)É^mönÄdØÍî‹Ù…ô‹½N¤ Ök$6’QÄhG¬Í½Áô¹ã_Á1cqnf ¤×9Rn3"¥"G¯"ÒLå¢ìØ£#lA$؇F„ÁÍôMù¡Ø•mñ‚攇s½ñ‚ª³@P³ÐFenŽŠì÷÷>†õ¡G#Èá7Ð($B«&EEàxûÄÈï3)QŸ2 xFÑ$ÚG š0üã+¬'€á×â![Aàè+Ð’ÚÁ–]ðÍŒsñ@ÁÍÊù +í˜c"Špõ1  Ú çŒ†Wÿ;Î šrÛ‹í±®Íü—ñ$·¿Ûí˜;'äCóÞaõááa8`Õ‡ITºõn»©}òsîR¥™KµõŒpÍ&ä|8ƃLÃÜ…=^R·tØ©ø„E;ftŸ<E3©ÔD‚YJ¤Ÿl’ý‚³pÅc‹Œ™‰X?ì$jÆ ÅŒ?#~ÅçˆL †D‰<å60«4„Ws”Žå@‚p³:éqƒƒ‘Òôþp,p!&I”õõ¦X–#G(÷f-shÐ!âyâZQs¹­^y“3&‰b€S½|(ô,1LèTZ(—˜èÓ£³~ÅY¸äˆžÁÀ DûíæãoJÅþŽíe[V€Ö*g|ËÛÚåÜœÆqMuà,ª36C†E˜D¡žècvëŠõÃ0³X̸€+6]ãÂ[ñÞ. +´Uõè>½eéOí•—íÂá¿?JAc^¡ ÿv€,÷Au>xÔ{y}ÇӽƜöÅÕ÷D ¦9锎½¥ü‚÷ÉEU¹N<8ÚCéS¨ƒ>’ÀÜT;fBI¹2Ä$›N”2XÚƒÄyé²2ø=ëºlñ¡}áb#Ü ¦’žZí¼¬ï°MÚ>‡ž$˜<ÆrŒtºÄvJoÀpy>À‚.‡š¹Oùá¨`•#Ãv`&Ž.£Ât¬ŒdÀü–fgn½«\;̇áÚÔL›í†jÍÎÓQt»fóÁõzzë1èê1rì1?&ÀýòØKËc¯]ÞfÛí‘„G c~ryïgsê›Ó9w­Ï¡7n¥v±)×.¾ ß!¸¼{$Þ©ÓSG¨+žnë^”F.Ê%_öùFÐËlÿ +ÎýË÷âa[VÞ¡¼µM\YœfÃ’à£%‚++Í”rÅÞºÉÝ’”Yê™=U³è‡ù[±+Òkw ¨¿è¨îV²I]‹ÆŽYÓo#DÊ™¨XØjàtŒ‰ì˜ƒ¢ öÔXYgk<²zŸ••}§fGå]×­¿|ùrÝlº¬bÙbÅÈâÞ¾\”]fsY‹åêoeþ!E ˆÙ25dÜ…8Õ´ýùÐCšOðC˜ êGo\ôõÃÄ×þqüîå'ΙÖ ö?Z©øë( +ƒ€¹÷¥Ko)Ã|±è€cþWskª6Ò™'ï™t¥bè˜^Û¥eÆe–.©$‡*¤mŠ ;´û(U’É©! `.QÞ1ЊnÇ@je`$pô–ÙÒ½+ËÔç¿á›3ÒhÚÆ„Q“{Œ¿Œ”óJt +ä_y{ç˜dcÈåãÇ~¢²97ÓmU´_ŽÀ§`ì_Ûhï¿T„„½¢®ÿQ&O +Xù'?åÕØ¡»»xöãV:;%gZ˶X]¬©Ü¿í†z‹…­ªèZ×O…5¼X^ì(Ýr$ v2Ù%¬ö‚@ý«m×CRH lO莬ÕqTÛlsàtÙAxübô½i¨<Á1vZ0pT{Ÿ— úwì©Êý/®Ê§å‹Õ“3’X¸Ê—x>›`µŠÂŠ7“ƒw3mÌô½û]8š`¢}…“î]Ž¾[xÕ¿ ùÔõaz¿_nÏ=Ê»Ë$ ²|á¶ÃÌ$tüSàŸØÇîä‡Âû±Ÿpʘáï.G~ Á'ž˜Oþyçþ·¯*aÒ˜hüg’kÑMâ‰B&qHyÿ;ÐcÒÿbTü,endstream endobj -1278 0 obj << +1800 0 obj << /Type /Page -/Contents 1279 0 R -/Resources 1277 0 R +/Contents 1801 0 R +/Resources 1799 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1282 0 R -/Annots [ 1281 0 R ] +/Parent 1787 0 R +/Annots [ 1804 0 R ] >> endobj -1281 0 obj << +1804 0 obj << /Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [250.9056 335.8063 314.5963 345.2159] -/Subtype /Link -/A << /S /GoTo /D (statsfile) >> +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [91.7919 217.2504 93.7844 226.8901] +/Subtype/Link/A<> >> endobj -1280 0 obj << -/D [1278 0 R /XYZ 85.0394 794.5015 null] +1802 0 obj << +/D [1800 0 R /XYZ 85.0394 794.5015 null] >> endobj -1277 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R >> +538 0 obj << +/D [1800 0 R /XYZ 85.0394 548.0867 null] +>> endobj +1803 0 obj << +/D [1800 0 R /XYZ 85.0394 519.5161 null] +>> endobj +1799 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R /F11 1442 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1286 0 obj << -/Length 3459 +1807 0 obj << +/Length 3771 /Filter /FlateDecode >> stream -xÚ¥]sÛ6òÝ¿Âs/•g" Aœ>¹±“K¯qîlçz¶´YœP¤*Rv|7÷ßo»€@‰R’¹ñŒ ,‹Åb±_<ð'ÏÓ,ÊŠ¸8Ï ¥B¦ç³Õ™8„±·g’q¦ibýxöý›$?/¢"‹³óûE@KGBky~?ÿm’EqtÄäõ‡›7ïÞ~¼½¼ÈÕäþ݇›‹iœŠÉ›w?_Sëííåû÷—·S©S9yý×Ë¿ß_ßÒPÆ4~|wsE‚>GˆÞ^¿¹¾½¾y}}ñÇýOg×÷~/á~¥Hp#žýö‡8ŸÃ¶:QRèôü:"’EŸ¯ÎTšD©J©ÏîÎþá £vê¨ü¤ˆâ$‹GǵŒÒ¢HÏ󴈲$N¬ß-.¦ l½ÄœÌMm˾j·MýB­·¡Vg6OfCøeݵ´ ˆ‰ÉlYÕsÂÛÍ®zþv4Ò´ (ëçò… ¬Û®«jžÒ·Ž¹ÞlVP±ÃÞ§RFEšÆv#ÏKÓ/‘­8· ÄY1)›îÙfí -ÙCðbs!õ¤]ÑÌ¢F¸wD£½ãqoa›px+BN‹É݇K¾¹c†Fºº¹ûÛõ¯c°L™Yk¿sd5É&%A±“OʵùL`f `ã³ìj8ƒú«²>›GêÑ”nÝ6î—eOc³¶é˪éÜJ6¾Ž•à]ÝQ¿ró»ìÍ|¸Sº´%¢¥9 1íàLRâX¸ÐtÂMâÉííÝ»·=ä -'{™aÇ*(¶Ìçu‡éõ í #V Xš—:]õèç>X=äräDYé©M"*;lBi=¹GBP¹í—í¦ê_³33¾}бwqè–d· „÷­›ÄÄp°7˜阧jnš™qHxê–Î’AîÂXZÝØžvç”ÄOŒµ¿êã“JU:¹´ä:‡k—d/XûKÍÓížéÇíÈè—ÓNÈ%³‚œµ X«> ?¢‘7ÿºúðþò›÷ð‚tIæ -úUo¡¬kh¨Â_™}ê RÅ‘ÊDzš5ÂDJظRR¹¸".0fQ.¶I&ÝÚ̪߅ˆ­ãƒ^î®_Ó`À°³~­¢ƒ©Ûç/QÄûŒúùûmÝWS:,´‚up:ëÚ– ¤*³H*ˆ›Å qîÂ:÷í¦t=Ä)+Óô|ÃËÐtƒ¥oŸÑBZ—øÁo,VmÇÁïmÆ–Å[úGl½®+6·cJ¦ò<‚ìFŸV²븒y,+•¦ƒ¸bZ·í§²ƒà@Åå¢Ð§9ðX#, T,ü¢rÈÃ/dhU N§5r* -g.Ž²¼Œ"RqîŽqMþ#œŽÖ¡3‚ÆSYWó²·Ñ*tŸA/¨U2Ge 1HS’Í–“d휉´;¬œR+XXMáœf§‰‹ðm{$>M覤îV o×Ô ¿ŸO|Ì '½ÝX¸ -ù&¾‚HfC_ww³æíª¬˜Ðð.ÂtkGœ¦ÏtæƬMלä¨Bùûô'—C/³‚' ÇÊÕ.Eò+6ífUÖÔö¦ø<}¢¶´  ÔfÑÈÓød8‡Û6•è ¸+3ç‰N4‘è§äÞÎZ6³¥àEη:¨³²µAÖ±MyîꌖG:ÆwÈ%¡\‘ï&ØPaŽ-‰²5<º]‡Kgœ ˆœsœnøb6âÃY˜f„q -o ]‘T&0ç_â:ót»`³¹W[lcXÓQ&’Êö^òˆ›w\NóÖt66<ªÅ©î€DLÑ0¼%_Žœ)EÜ™ïþµà‰ÎaÍ/«Ù’šÈ.µ¬ ákMŽ”L‚ÂßÃnÍyàØi 'ß1_l8›S k/²Ž£"×ãÕ¥ØT›+ XŠ 3%HØuç‘ÒV1› ƒ£KS͸x×ç#“$ʵ”ŒÅñvE6l•³™Y£@r—‹w4`«Z¸ê„Ô¼„†÷ÂÜÑMÇ"‰À—9.Û±M³à7mõY‹EÖÖ"cBÈ2*’1Ädû’s›Œ#!ë§SŠ±(%…¡¹é ’»* ¢—ˆÊØ1“M´$­è(T\_AøÐÍïa4 ³mæ»fևǡ´?ú5 S4œ‡rM±0ëåÚnÆYé,Ußÿ¤î'Mà­„áæ,ÈÌKMe^@œAúƒ:)eê‹éN_L¥ú±mkSrvü³·#†/Ö2Šã$;møB¬ã†ÏcY±oûå´ù̇¶oðâ #1yzy5²þ0n•‘` 1y¢Š¯0zw“’XòMBýäØã0†tÛYˆËË1º:J3oDœw¯œŸuUt¦´§Å¨ž˜e®å23hžL3 Øë]ÙŸV£ÀI¤r½—F“M×jàn÷ ÷¸Ò –¢$ÍœBüÎ7Uc€¹(!ÄŽæöÄ.Á¾ç:;ނýà¤m¼¦R¨e†>³eÙ<Z2(AÿAK[F3aÿ¥Ý2 oœ ³íÈ„¡'¬‘| -H™”ØóH­«Í]ÙçÌÛEÿÌä^ˆVÁ ³äœ³1û‘É.|éýÀˆÔðUHëäÔõh€Ž5´øÂ=°NÜs‡eíA70>m›©ù\õ‡I*šÛBæÁc01¬ƒØz‰rÁ50,Á®Ù[a&OÎØ@ÅC»CM(¨Ý-5MÃ5WöeWòqx¶fÕR­QBòR~r‹3uƒ-=HZˆj#ü„Œ‡*Åï•'µ|­÷êá~(„JwOn¶m6ÀÖj•µêƒÔ`± —:­!Öq}ðXÖ™fª®¯f‡%10‚™*ŠÓË{¬‘õª'Q–€D ü‚O¾*ù)òƒ'k ºo¶ïŽ›Kž‚A‡=ÿBíE!0øð2F -é"s1À@S&7ÄÏ+wum°Wˆò7¥ØÈxgd«Q# !A¥q¬‡áÛ¸±U‘R>îÝ6µéX¾›®ÂÇ—©}·÷"2¬Aì4§íjåõµ®ü[†»šœl féžbª]Rw¸=pQnþbÿãÚ¯  Ù¬aˆuBû•1Ëû½eu ™ÈO/ëF– wXÈl‡.;ëÀ%ÂÖ·¥Jô¨‡$ WŒ»_X {#îh̾©áV½¬#Í~„Ë~²s½ž·Ö²ºÉŒ»taaÓ;aFÞ½s¤ Œ‚F‡37VË(} ¢Cf/t"Ó$MQ ?a¼¤c§¥G0hØ*M -)­¸}\ö4àæãû1~Å¢pÑç@|ôX5pçqCˆ<£á 런Ţ7Ž]Ùr›W–ü‚#›~,¯1Œ3ëí#±ÂDŠ/+1 [–/¿µ"Ä>ŒYt[Î’)>´Î` ×|¤{–ÌÃ(¾ÇHÐèZ‡KÑŠêUHØV½ ±´6¦iŸü`µrl/Ä—öîÇ\fié+ê¶vAl¤_XÕõJ¼4å¦õœ:Jc–7‰tªÜÝ`3O–íÚ,¶÷Bw¾Ý°çw5iË7f°Oëã!ÀdÞÝoä¤Û®×ìÏ;ãbîBCÌ'CýäwÆàñØ›PŸ´>'Aå­@ùÁãÞÑعcv5Î “Ìõׇæ\²‰ó’©$> Þ¦G²‡® ÿÖãŒä~%Ž´*\bì#ŸBs,æ€D\Ðï ð»ç¡5¹¶^#¬¤âÇÄ-òT™çNâ4’B§‚ŒnJ'>:·4BBøLäOV¯ø·Ì«s‡À>»CÜHOßö‰ Wib|?É0RõhÃï'¡=Öíƒ×ÿAý(ä*ÿŠóH2=<èØOç’4Âß»¸6áèÿþYÝî7‡*­ãq' ©m¤4a¦}¥£þýÝ!ëÿ¤Ë^_endstream +xÚ¥]sÛ6òÝ¿ÂôMÄ’øÕN”Äî¹s±]Ç»i{”DKS¤*RVœ_û”é¦3ÏàX,ö …çü…çQìÇ™ÊΓÌøQFçËíYp¾†±ŸÎB™3³“fî¬÷gß]éä<ó³XÅç®ÔÒ4<Xýîžò/Cà}¸½¹ºþé×ûùEb¼‡ëÛ›‹™Šïêú_—Üûé~þéÓüþb¦Qè}øçüîáòž‡bÁñþúæ#C2nÞ@zyuyyóáòâ¿?Ÿ]>ôgqÏòçÙïÿ ÎWpìŸÏ_git~„À³LoÏL¤ýÈhm!ÕÙç³_z„Î(-ä_øJÇj‚JM10ÊüX+M ¼­áH*ñºMÁz{ìÆÞ&¯Wï «•W>žL[ì/ÂÔkŽ­\5ÍSËc‡·97U±.»r›w²´¬»b_ç¯; ¦gF–x(eŽÇãE¦<¿ø’owUá×E‡`A]¯‚@À‰YúY):ÖcSUͱ¬×,0"¶hwMÝ )[w¤;ìëbÅ®‘v#S_i…P +Û~weB‡ÃHDê›$Έ8K=(YÞœ›0S>ÈÍWŒg$©ÞÊ~qòaH€€URãDøè£î„Ž· %{QfÓ>è1o3kN‘Í{2÷ìÈ&{Wå`È0¡¡cA‡)ŽÄ§†ÚUË@8XéA¿Ì +/'D➟¸ÔÒ²í|š<–>¡¢'ù),ÔÆÏtªû‹bÿpÿ ý¾ÝîÀõÂýßšZ Qp÷4¡ÜûŠã¢œn2g‡Œ81AJûñ¥’d¼4h‘º^V‡jñ°Ørí'V嶤”Ç·Ånae»åOJã`ζÿÂ0N² ã^rZžGf2Œ-û¶Dw3€þ<m7™©´@†&p¯F|räýU “-gí.ßò'+LYTà”ª°¢*EÚ›W²âäc¶"|‡u_ï­ BFDú»b8YulÞº‘ÀÍ!úÉ^všÉ&¯E6ëWŒÁàgßØß(oå ‚u–ÛÆ&ôý¬uÕ,¬¿e|ö*òøöõÚºy}aííüÄQR=qGâ” œâþ"õ$ ¤&(êeC?(éâØÁ“]¡á€%G¿’±èScÁ¡^ˆÚZ«ÝC½–»öé&íxt_ö@Ê°{û4}ï'…\…oj… ‘D,ø¨Ð‚ d,.Á +±ß¢±/XÅ®ëéðûþ¾-:*qV.{/-ŸfÅòçÿ('éKÅ +­É$xQP’IA +Òö×"Û´2Ì«-g»}¹´#›†ÍO ¼Å ›ÜÃØao©ðY•O“æ4¦h *gˆQL-4n ó-s'ЯNa O¨Ñ?L hžFi$³Öo¡±ûü0UŠ€0Ðûˆf?yŸ&£cqiÂ(ã'IÝÅ[GV™ÄAúGNÀ6-ûl¢NÛ(_›P}ëØæ/Ž­|“¶Ãîa–Æ€6~å$z32Ç&¼ä–öW­–tŸ‡M‰:¼eaèn + &½_næŸ.Ç#{ #à™ÕÔŨ ëø–˜#©W“7ÓFìÔ^¼¬áÒY ý $~dHs`ÛTÏDa(4(ñÄØ‘ Î’ (n¾tt½ãèW¸>ÜS s]ã”·ÀAÕsºÂeþ û·Rv[Õ󺵲É(ù\~ew¥„mÎR¹Ï½‡Íháˆ]J˜£,ic9%ÐñÂŽsÃù»©´}ÿÞr»+–¥¾$ËVfpv6Û”û3•Ü$Àv/;qIÓÖþËdTÅŠ™ŠŒ£ËøåÜ ]ٗ뵘ՊA‹™wz}‘$Ú96Z®}ø ÿìV#&‹ 8Í‚aKÑ·pa˜‹Ú†1÷ S6ÆI™-Å»e°^ž8Œå2‰JöÚ_`à˸ öN%Ч‹rãBÆEw,èî >à Z ¾­¸»ðÄÄM)Sûxñdq–RUxÌŸ9"œžW¥öù:ˆ{O§JSv}Ýr.OœI­»j:«KSÉêÐABð0L·|LS.ÉsLvQ¶˜A0á‹Díø¶•¦¯Š‘l;KLH%ÔŪž•Ð=X¤Fz®œÂ/áà¦2‰ìÈúì±Zž"p 6þ²ë5vÅ RÈßA:È™6üa8"%1a²Iµ•:Û)¼/¸œÝò IÚýîë¬ÜñyhJ9Gfþ#žš‡éPø=b8 ,ªfù$g<ò\ìùTJ*Ç°ŒNíõÍl~‡™ûÜç.ãý÷ü7u46­Í‰¨ÒÛ ~„ÜÐy°£Õ àýßX¤¢ˆ;|chí0·×wÏF £zB£ôŸãWc=‚)OÃ*:\M‚¼¦lªŠ›þMWŸ¿÷?áá¢ó)–ÛûŸý¯_¥Ã3¥ÜzG'´Ú‚ÐV¨A÷;`Ÿg2÷`>P )¾Œ^£¬êƒɇ;^îÞ]Ez7<}ÿ½¼Ü½z×ÜÁ]ܾkŠ«”5x@[¶¢ð·rð èf¶Eë¬{û îóGÎ9ðIÀ1rz‰ê¨l“h›·ÑÛEÍ-'ö$R¸=8œäI +Û\^>„U5>´ÂÍe&ï*NEÖ E#²¹‚Ù”À¬ˆ8…#Þ‚¨[û6pÛÉ—&’9NP¢R®íRdÈü¤Ç¸ÀŒÒ䞙صNM*0¢˜éiYp`C=öúk`ëDÒjy¨ FU~XB ?Û™´8²F`¾éˆ3# Xf8Ë"yr^ ð…ÛA§23ºG-a2s¥ héf†o®Ô#?ô'Û /MÈÌ8(dÌœ‹BŸrPÀ•ÝT‰|~€‹6ä¸xpqÀ­’g¬mkHp°öЈ‰ âÜ|_öåb-†‚Æ(Wy—'°¦`yØ[cè·oe_9L—6$“e¹ Zæ‡é"y ì…·òøõUÇCÅÑ9¥‘h1öÄÅDV¨>OÿÜ0´ckʼnƒË‹½ü9/«œ4aL^‰ wÜpæÒ&³óÃ"|Y yÖëÅCÑФ'?µpt6+jÜmÆ6YÀë«tà{²ø¤†0B‹µ‘8²ò¬+ºhM VÊŒ²Õ‹QÝÐƃޙ Y N­åeipÛà´·½K¯ÊZ< È6õƒ0ÑcOsÅ÷úXJ{\m‹mõ*–êUŒó3|¸×™áD %NüpøÅÇÍ>Þ~š_ßL:Ž€"˨¾´H»ó+*ösnz4ôuR™Œ%Šé(ã[.<³W~˜ñÔc¼d›c³©LršŒ½$wEóù殥òa˜8ø´Y/ömQr¹ »C½¿‰J-¿0Á[N#ÃýO- µKŸ —ÅŸ õµÖ¶>tsûqŽYÎå“Suï~Áȶ¥2a#¡ÁŸ½ás†Qȧ8¿ùpûëÍáøFbãZÒyÅéâ;¥Æ€+ñzM<âJ&Œ–âiO³ÿ¬·^èåÜ|°á ÆN—͆¯˜ÚØ_üiAµZÚ ]³›UXUüÙsÞ¤Äùëgq¾¡ðJ…¾Jz‹¿¹ÝÞM°^'~Ÿ*;íX•üáÃÏZ(îI?Ñy“ŠÎó1ßø5¢Ž|ü áÄoƒs˸ÿû—ŠÃÏ8Mâë4UÓ?BT 8žQȈT½¢Üþ¤ñ5éÿö%îendstream endobj -1285 0 obj << +1806 0 obj << /Type /Page -/Contents 1286 0 R -/Resources 1284 0 R +/Contents 1807 0 R +/Resources 1805 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1282 0 R +/Parent 1787 0 R >> endobj -1287 0 obj << -/D [1285 0 R /XYZ 56.6929 794.5015 null] +1808 0 obj << +/D [1806 0 R /XYZ 56.6929 794.5015 null] >> endobj -354 0 obj << -/D [1285 0 R /XYZ 56.6929 333.8409 null] +542 0 obj << +/D [1806 0 R /XYZ 56.6929 511.0366 null] >> endobj -1072 0 obj << -/D [1285 0 R /XYZ 56.6929 308.7186 null] +1809 0 obj << +/D [1806 0 R /XYZ 56.6929 485.4552 null] >> endobj -1284 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F41 939 0 R /F21 714 0 R /F48 953 0 R >> +1805 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F41 1208 0 R /F21 930 0 R /F14 956 0 R /F48 1228 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1290 0 obj << -/Length 3312 -/Filter /FlateDecode ->> -stream -xÚÍ]sã¶ñÝ¿Bo•fŽ ñE—‹}u¦çkg:i’Z¢,6©ˆ”}î¯ï.° A‰’®éÍôÆãá -\»‹ýØ$?6Ñ*N„‘“ÌÈX%LM曫dòïÞ_1‰¼½ŸýöðýÕõCÇKÈ/K2òÇÕ/¿%“°ýýU £Õä~$13†O6WR‰XI!üÈúêÇ«º ƒ·öÓ1ù)¡c¥y6"@β`™N2eâTpax»œEB«i»*ðïº"¨lÜ3wMÞ´Å®Gz3‹$3øau0ESìž=æK¹^ûÑjá zßf¾ûøp{ó³ƒw3¦§Åû¢!œ¶&\?O¿Ì:.ÜCÄXl”â–©_•,Še¾_·2ØÔT&Ó‡•åH™i³ª÷k$¶ºÝ•OO–Züa瀤0SækWûÍ£G¯Šùïnº²:øÚRæ@$ek™ªŸËEY=¹á²%Ìýv[ïÚQ.œX§s úÅ΀¿ìbÐbv¬vO~¹|Xšϱ„Ð˪\³Ìëª*æmYWî7ŠÊ. -cÏHP0” _³hP/ýnyÓ‘1`Ç™*¬:_9¿ááB 4ç<'{ÚZ'ÂõºXлW\4œ…nX,²„ÃÒ¸bU·(‡Z‚[KSEh9èåØ\±P™ô8릎NÎ'MÌ•Ì7¶ÜGÜÀ*RkBÁugo<å$xh[²’€gŽÖí+ŒÔ;÷lÚýcÿÕà`No€;´‚®9ójšƒÜðÓ~ÓW¿r.{Êö[¯Ýs‘·b.¨¸› Sã%­¹"MN³)˜÷®,÷ÅoºZ¿:h[ì–õnã~‘½§vldË8㱄´«"ßµEÞFežë¬øxë´Œ“ÄkBñi[µn’ÖË‹’lW¯Ý=Ú#mwŠ¾—•>ÔôÀµ5q'©@7nÊÊznB•§4 -Ð(„@Ã\•Å3šƒ}uÏ}C}s#u¨ÍYóT^¶ : _&¡ÉâÄnsB®vŽà hUþT4oFW‡ð¥!ô„«;eOžÆ™éPnÛ¼iÀïŒÙšŠ¹Pì€B™ttIÖÓÞ.÷Æ*›ÅŒÁ¿tþ^V |ÖçàCê”Ø!ñ -ßÄJi¯R;ø?;fäˆsrÄÌ18æICøˆ4¤`3‡ol¬À1˵ÑÉèäÇaâgn››˜wõߘ[Ô}4`:0¼7w¼SW©XkchÅ3J"c!D6Tœö_û†¢Ì¢lòÇuAÑÇ‹µ·Ó@288k|˜ø1Ü$‚MRðA@Åg¥~"3±fÊ S¿?÷•'$º')pß%0~+†SESQš0p“?‘Xró æIÈ?pÞli“  ½M½°I›Tç%-&œ"E¨I'°X&²#¬Þ¥…û9|ÈÁÿ&”¿dtü ¦'*3“³22x’71õóúCÞÎ!}~EÝ×°Îi¡M5*¿€°¯Y|æ“êKòÓIœj!­t^] q @¨¤²>¥ë$Ô >V@Æ—•Öµj•*ˆö &¤•ê8ãZœÏ†Q®³ (ùšÕ ªq¦SuI` -{&Ø…ࢊ3Ç€’¯Y` qÁÄ%A¼Ö,3¢ú }–û -ùš-’C%™¥ý¿à±N©j lúÏ‹í¬a})¹õ­¬ÿG‚ÄL†ŠpÒ€ôÔŽzk‚ÿàú"iÀ j¦Ï·Ö$.-õoê¶ë²ôYJŸý„µáaÖvF`ƒ)'^"Ò²˜·g» J$(ƒý†Sv¬°µ:Ëtصô2A‘±Á„à,Öf¡‚ìŠ I 3¸,í<3Â/9 –36­ÀE‘&µ¶çŒã›íºØѶßô¥3h„0zË„Ž,ŠŸó©ª;?°Èëáç µž>Ì ¨¦Ó= U<ô| {®ïÞ7F-€-ÏjQP›µè5÷߈²q”K—¦lΊA®“A…=¢bö8Áω M§Ͷ˜ÛóÀÉíKí›ÂÛ|—·4ìöeÔ:$v_™×ß|ß®¢êÓ¢Þäå˜E@pe`ˆŒ“Í“XòÎîÎÈùXº[Î9hV„éTH¬NµÈ¤T¾—\B|+òÅI£äPp§R\pü!Öi£ì°ì¾×M5-äiM[ÎR‚éTž' Ã¡`h”°i– I°bAt´©°b>È¥¿ /Š-¹]FGÀlð`‘–öÔ?}vÉ/€Èì°$bý4†šÊçDÛÄ|NGä‘äqÂYvpfR¶+òöw¾X¸ ;På§w›%q†ÝùÝ°Îì¶ÇBJÑVZøÊO®¡=æÍqŽ ¦nRyž tLd†¡G!«:|j%û `7&ú*f$£Õ±ÊÓÅ°Hp6½mÝ÷Ö#@y.NIS{©C™åÖpw$DeØßMéB·Ä”bç~äîÑîòª¿Ý‘º®éÜ•)Ž‰°”Hªjóh€œ>p[Í]<@í°)+ þÓ%xMd†§c°âÈȤåâ -1¨Æ=üVÒB¹{xZ¡0€„Z“iÊ6á׶†J,Šf¿]Ž]™x­÷>MõZì¯xÐñÝÂØ·Ouß78âoµÄ›?iÛ7£g驉Á¡øîÀv‡×W -§¶#çr7…ç»'“v)ùÁ2˘䂟 ±N[^‡e-¯¬ÊM¾ŽvTq{Ú („ |ž„k„†a Ncùà€ˆÛåˆð äœ:ýŒ°®ƒ°®2ñC)_§ô:¶ó •j¬Æ¡¿U—õ×´ð º…cPÕ9à¸r<§ˆÁtùžNô„°ßŸð:UnW5$å83¤ú®lX8 -î GÁ|áظqbPØhá'qd¹a·¢ì+Bán¦ñ“µ1ô4ëâÉöC¬ê f…¿mµ+øPVîÞØÙ¢t“¿v¡†nxÞª¢‹,y5/†÷¥úÛ[nÈÏ\,WŠÃÁD¢ä¨9Ô‹þ<áŒÙXgÌÎcY³JˆÄÑÜVÇ‘ŽÅÂpuž€k„‚³i‹Lè! ´c&èçì"„I}¬‚¡’^‘«H;«ëF¹xºe¿‹ò£:|ßIQæ»»·®±@•$9VS¡ŽŽ:ΧÏeíºznØj÷w¹`À59Þ;Ëik]ŠoÁëÐÕK>X(_¿ä¯ŸcWº2 ßÕ²¦žRs°jÏRrÈ‹žî»Ìñ±nWÃtÌ_+E -nÞ¡vM›Å+H¶œS´Úâå³&>uóV¨¯ËŽhQ2¹xÀõ¹·rû+ËP" -­OÜ‹ Än2OŠCª£³}÷˜ôÿ‘Cÿ·endstream +1812 0 obj << +/Length 2026 +/Filter /FlateDecode +>> +stream +xÚµY[oÛ¸~÷¯0çÁ9X±"© Õ¾¬7MÚ,Ú¤ëø' +Ù¦m¡²¤•ä$Înÿû9¤,9jšlpàñ23œùæ‘L‡.üèPøÄå‘7 #ø.õ‡óÍÀ®`ïÝ€Ç9mª_§ƒW§<F$ +X0œ.[²q… Ãéâjtü~üiz29r˜ïŽräø;úõìü-®Dø8¾8?={÷ŸÉø(ôFÓ³‹s\žœœžLNÎOŽ*| +üÌHøÃéÙ‡½›Œ?~OŽ®§¿ N¦-m{©Ë•! ®®ÝáÌþmà x —Ð(bÃÍÀó9ñ=ÎíJ:¸üÞlíjÖ>ü|.ˆ/XØ c}ú 8ãÀm%`R꟟óŠü«ÄÙ:Oe¥–`*ÜQ’ár‘§É<‘Ζy‰ƒ4.¨­¤™Ÿ½àh–æó¯ +±ÔVØ}žYIY¼±ú¤q-ëµTˆƒ]´e”.ÄŠ«-*eUäY%­ãÎ0´p‡Rù>ÓŒyQ'yÀ©;š®%zúü¹ø„C#P“ +Ÿò®Ð&Ë +„¥™!‰Mð?š¨¹Mêug¯¶xÕ8ŸƒâIU'Ù +çùÒÐYmnâ2‰g©™qY?$ƒŠ®i·™Æ’3ðÏjŒªí\©Ãù(®pS9ZÞÅ›"•džoˆq<ì ‹)Î7VÁJy$F[­¬çå^e‚Pâ²°‘Å­,6Š3\8û„s#I¹Àõ´ zÛ£K#ãmD·ÇÇ ëEãBÁÑ…‚Ù€BY¤ †­ub2”QBÕu×Ñr/:ç¥ Àê1…Œ‹œ@ƒðy]þ±js¦¸€ƒ¾f¯_#¹sH¦å_;ÇEîý=8œ‘7LQÁÖ‘ï‰ùpA{ÐŽ ØçmÕªî]Cy[&س›Ü1ƒ¬º•¥!Ò=¯Ž0¾8”wsYÔÍr ߃ðÄmÚè¤0Žy$r zÚa èP<âç—o÷A®‹®vÁè‹ûªíÁ²¸w²jEŸŠ§D?\î÷÷ðZ®âÉð+KtD>`Öwes¼®%Àqʨ×{ƒŠ³J–7ÒÜ—M…Åwû2Þl Ãé-NÌ'aÀ1ú¬ AR|‰‹òêUQÊer—ÊìÚÞ :G ¨t®b–¯¶&Jv²ú’—_²§þë>d sQæ7Ð:Éݲ|†ŒŽ¥„J_Õ/’!Ù?¶Añ:ÛEáTɽ¹“²íff¡}Âé›øîeê²uÙdë¹i·Y¾‰ëýí‚#(Dœÿe•ÎvN§H蛦sèc:•»ªÓTuÙT!#àêû;„k£ßž“SåÛr.÷–&…§ÀZ¨o‰0"œ©BªK³wX²ýak}oûU‘—u“UjrÝ£Ÿúd]68âQ žÎMÐV5x¨jh[Ÿv‰>[U¯fÐ'G½Â;V²Ü= Ðý5Ú hð2@Cõ>òc æÞ3ÿ5# +ïà,ìõ»nY;Xš ¥£~[í¦¦)Ûmí[½Ña(XdzcÁªçEÄãQЋãÞÂŽ +ûe ô8~èõhmîEðú0ì"͡׫J©Æ£Ï‹GêC·÷lMûÁ¢/ëéþjƒÕ÷ŸûD}yïùäî6’_üÿ-ëÿvÏÝ€…V)ÝòCÍ›ªþ7öNl¤endstream endobj -1289 0 obj << +1811 0 obj << /Type /Page -/Contents 1290 0 R -/Resources 1288 0 R +/Contents 1812 0 R +/Resources 1810 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1282 0 R +/Parent 1787 0 R >> endobj -1291 0 obj << -/D [1289 0 R /XYZ 85.0394 794.5015 null] +1813 0 obj << +/D [1811 0 R /XYZ 85.0394 794.5015 null] >> endobj -1292 0 obj << -/D [1289 0 R /XYZ 85.0394 625.316 null] +546 0 obj << +/D [1811 0 R /XYZ 85.0394 314.8075 null] >> endobj -1293 0 obj << -/D [1289 0 R /XYZ 85.0394 613.3608 null] +1814 0 obj << +/D [1811 0 R /XYZ 85.0394 286.8362 null] >> endobj -1288 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F21 714 0 R /F48 953 0 R /F39 899 0 R >> +1810 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1296 0 obj << -/Length 3798 -/Filter /FlateDecode ->> -stream -xÚ­]sÛ6òÝ¿Bo•g"Ÿ8÷”&N΋sg»3½iû@S´Í‰,*"×÷ëo Pü’äN;™1A`¹»Xì71ãðOÌLÂ’T¦3›jf¸0³üéŒÏ`íÓ™0‹´èBýx{öö£²³”¥‰Lf·÷\ŽqçÄìvùëÿåêã姟¯ß[=¿½üru¾†Ï?^þë‚FŸ®ß}þüîú|!œó÷ÿ|÷ïÛ‹kZJŽ/¯>ÐLJH¯/>^\_\½¿8ÿýö§³‹Ûv/Ýý -®p#ßÎ~ýÏ–°íŸÎ8S©3³gxáL¤©œ=i£˜ÑJÅ™ÕÙÍÙZ„Uÿé”ü´qÌHÌJ3ô§¥,˜€¬IY¢¤j¥,Å””#Jy]5åýËp³N3•87ë"‘@de‡¬K™‚£ï“½¼G’o?jלIcSÀŽ /EM0=lR0#Œ 0¿qÛÇâ|¡àˆ—Å}¶[50'ÞÀŒ³óW700éüêËíåÇÿØSQ×Ù ÷+Ùö\¸yÀPë†FÏÅ:ÐÄÿªu"z°RÛïÅ–&ˈn×äFrIJÛE>ÒŒêclÈX¬NÜüÖËØè—ƒ¥p`0j*ZnÛ%<š^VeÝK‚(ÃîZH<Úv¯00GDòÊ?—5¤œ¥Z¹þQ¢äÅ9Q:à…ÁSD·4nuÆå¸.ã\z–pf=øôæË;|¾z÷ù‚†þƒÕ2ª·1ól¾÷›‡g¶~é’«é¥Ýü€W×Cð¸3:ˆlUW‹½ƒzmL°ÄjƒzÃHPqi!Àö-›|Êœµ6à -ªõjŠ^b˜5JXJ½ûò‚Á½Ê®vH1÷ˆütИ#éöt`5 Æ@!õÏ„Nß×'âÅ›U™—Í— ÈNrû'¸Œ¼É–_J¾CXô™}…kãUd¿Ä÷xØ8ÞÕåúa★â JEyü˜u -NYG‡ËÐOñBÒpê«x,Èâ6Zé ›ž{)á{+%|A)í’ÆÍã:}Í¢­£ø]zX\‰e­î´,¢Ó–Éü²¡Ÿ«ÝjICÒjéœÇ\äèÒ·/ôŠÞ —›Ýv>¹Ç“¿Ëeà(ž —aµ ólW{½‡µz•}/ê¹WbºçÞòmV?²Qž’©LÏ}<áêη"Ð^Mµ¨«lêÁ‚‡TáíhL¼oi)³ÎØõI³u ˜TOº8ã<‰‰ÙÏ‹;Ü òÇ"ÿŠÃ”"˜_Ì l·Ž -&PyñÙB`¨Åçõu]4ôuö•ëºú`ˆ YøºÚ>e+ - Š³øIÈÜ$xÕ˜ûá8¤ôâÕ -ž´6JHIÙÎ0 `21ð·ó_®/?]^ap¦÷, /›>±z·ÙT¤©ˆ¿"zy”Å<óB’*Zí> ÓŽP¨ ´ÿ$•Câ[>-ÒtnPÙ Ãæf~S=àM é±z.¾D˜ÉèKo;4ô,êU ¬…¨¯~g{ÒI ¢lðÛ5?–KÈvú{`PÖáöÑ“>ì¶Yt@ÖRzƒË™EÈZ"·‡s/ÕŽÏpINß2”6ª‘íI¦»äý)DÝ”«M*LA}&NcŸ—b€jBË< -ê×z¦0ˆÑ~o]hoXˆ¢YôNFÙ --Ž»§.ÔaÿÔBᦶE¾ÛÖèf”S¶\Úã”#ÐåžsâšI§û”ä‡ÆqsÔ9K•tŒ «|©ôj -ªñýÛ®ðq†”^ÀDÝÔ²~À›¶ X<Q*Ûd?y&•AJ DB,pÚkL.Ó´"’çjû5dËØ°ƒª"2WÒwÃ)Ñ—PždëúÙsÀuô“:lMF/SŸÊú…Þ¶·mXÚGZ®ƒÐbi„3íNa¼¬¼ªÃrpüðÁŠPgËZùº®ž\Vƒ£jNióИ‚¥ ܆dÞ³îô=$7Y°Þ€Ã(Ö-ùk{ôRÖ“)½eÊXñ -ݲä6yU5JpH\GÑ4ÓɶŒó¥m礛N’ …m b—1ÞÂ`C;ÿŽáŠÊ¨å…4j߬J€ðÎÔÌïý7Õ½=vá%™/³&› -žÓ´ZgøCMßäý„T¬!°èÁ¨Ã` ¿.ž»+?†p/ <«§”%óÑÅ€:xí-ò¦MØ9Í}ÛA\(¶¥/ðOæï=ÑHŸàã ú~Ä’ÃÑ,Å:&‚f‡"RX@€Y{e…·jSPp á¶ÞA -?µµ#Ú¬CÊrt=ªúºÛÔ¡»)Šzêj²ô€ìÈɨ‚÷E“?.V»©D;¦Eô¥ÙCÆžHG Ðá¼ÜçRq·h^6…'È–q‘¨£´[ 1ñžiKzj“õ›hŠÛPxøQ5á@(w“± F.’'‡}µ©¤—m‹ˆú'¥!8¢Æ”5¦ü§ÙªŠL?—Íc± Í$ë{Z Ú¦íIŸ»ÔÊ$ó¾<êÝmLYöÎÖðÎÖ@5"Ú*㽑Ú5ijfšKÈõÓô5 xåü}‚›nÀƒåY¨üy’ÆEßqÀ†ô… ZDîJ ¦°¥ÙQºV² ,ƒ¤RΔó1~¯Wiß.ó½p£Z›ýrÕÞüþÊùèfÂy[P2¥ dKÆß$Ì¾Í î€˜uÆ~¯{ø‰·—Orö¡‚ͺ› -ˆ]Ì~SIß’K`Ï3e$KdêhSUHÀ_Î%Ÿá¥|Ú¬|¿ äöá~Féèèu’Bºx»Âýkç¥à ’”ƒ“Øß¾ü5m‚Œ‹9‡†$ 0)’㎊2`LÉãž±…B‰‚ËX”ËŦªV#ÇÈ!gàÖ̺hÇž1B©«´g‰p ¸Ñù[êÀ‰·}2wš»««UÑLÅ›6É ƒ8ºËVÏÙKÝÖPU¥Zx9; /?„¹Nö€ÐEs0^IKEÇÑcé>•y ì‚AMWæõè` ¸DØ£Ô[ 1ù¾æÀ̺äM ØäŸ-šbEŸšNcÚGC•¾ZQæƒ qË>Á‰Ø¥˜Ò3Ô<†Úë„{&»õŠ2D»¨¹oæø9Lý½{@\¡>ñ± -lÙ:— z–á:'£¤YøÅ"Ü×ÁÌ]V—áèî%Ü !Õû—ÝqP­ÙéÔvØ#˜ `œ1Æu¯™&:ÓŽAš.Ntƒ5XŸvZ±Çä¯ÈRŒÀu¼îpˆ‰-uËÁ‹ki½Oߊ5vžåØŠ¥fDrðÂÀ;èXì—9}D§´K+¦S©»m~»Öø]Ð) ¸Ü=mhäôF­…–ˆõ7_«‚&÷½z'‡zÜ’C¬å"íÈ´ø&*/x‰éz*Õ¦×I›^Oe%RùÄÙœ¸œmÓ„.üÄ•ùkïj–~Ö _Ï -¼L­íñ3ö7êcl“™Yë`Aೌã¶uÄÅF¨6ðýØ’hDî8á4&Ü‹yi‚7/¢O˜Bž²û«·s‡C^*™Ý—¤Ö·c”ãÔ²DëÂßYºÁ粬³;Tu|¹üåãu9£Ç&Û‚ïVÙ–‚óP<À«¿á´ñ÷ ØñÕBøŸ²Ð[†t ÄpÝ÷§åú[ë{U«:Ê ×` ' -ûÜl«ïårVC벶Ìàš-4A‡¿3€šUƒÓ‚Ê}êG|Ñ…Ÿø½Áë„]I&Üp~,I„é±3Ò´êcl¼hTÌ÷øH lhþj±´ð§8á F35JË…÷ OH¥…:ÁÃÛQg>sRŸh?t¡;›jJ‰ûýH ØõQê-Ôù~Á Ú˜@1Ø£ß*@³/¯ë|[vÌ¥ºŸ0Äü–ÔÊ“}ª24?ˆ@ Mo£Çì/ŸØòïk-P &l÷¬&-0B`cŒí¸®)É ‡ü縮u ŽèZ„¢n°¿}˜Ö5õ$@§ÞBMïëšfÖ[W—þߣkÃ] u ¼°yX׬'z=¦kþÄ–Çx_«k -ÃcNœ{ u‚1¶ãºÆA5]bNèZꈮE(¤Øl‹¬YäTeõ¢Þdùødž2…4(ÇÙh¡&øè)ÒÌHnúŒ„>‚ûÆÏY˜ ?ãÐájfB«FŽ¾@€çSöµ3^5ßW®8.§zÍ³í¶¤Ë-ú·LðŽ…éoRjR`¡{ñ‚çíψ& B³¬0ÚÃÔOŒ˜³&b@:á—È×c¶ÍòE¸Éjïº9¶Éþ2»¦_ÀÔ³¿Á «º6§W:_?ôÍ\Xi²»p{ãI6ûk9~òk÷Y^®ð¬áãU•-ÃÕŒ¥ ˜¤êGTKÒþ0‘zü|uùK`÷ª¶§©ûŽp…¦a#Eû{/x{(ÖxaBºz -0…çÕ-=ýÖàùáË žüíݺùe*”ÌÓ7ô¼«°OŽ£À%Œ¿°Ô~|åù¯§~3Y²•óÛYÆý¼ [0‡Ø°†)Û–³¯ÕÂþNºZø7íë­Æ°6ÖÅóª\Oþœ¯×íËñdzÅòM¼dX‚ÒT¿±|XWájœú©¾2,4‹‡.Œ·=ù¿ü3þýÿqЖ)çäáh¤R‘)”NÆQ€3‰½§1ëÿ¢þäendstream +1817 0 obj << +/Length 3838 +/Filter /FlateDecode +>> +stream +xÚ¥:Ûr㸱ïþ +?ÒU#‚jŸ&»3§’Ùœo.µÙJÑ%3#‘ŠHÙãTO7ºÁ›é±')=hF£ï ¼ð“—&Os¯ü¥õYj„4—ëÃ…¸ÜÁØ’ç¬â¤ÕxÖoo.~ó^ÛKŸú\å—7Û.— +çäåÍæ—$OUzDòýOÞ_ÿøóÇ·W6Kn®úpµRF$ï¯ÿðŽZ?~|ûÇ?¾ýxµ’ÎÈäûß½ýÓÍ»4”3Žß^ø žþžAúñÝûwß}øþÝÕ¯7¿¿xwÓŸe|^)4ä_¿ü*.7pìß_ˆT{g. #R齺<\dF§&Ó:BöŸ.þ¯G8 Kù'Eªt®˜ÉHs¨¬ñi®• üåj• ‘œÛrõ¯syz<6§nulš=ÁËöÍéuóõÅö+)SoŒ㘮_a«¥‘ú|¸-Oߎâ|Ü]YÕ]yº/öÏâZ)z)²ˆ’Dãÿ¿ÃÁß¼Wò²ßi‹û‘z¯³^~¤™€­…mÊ]ñ§v>”uGÝÊ¿ ¡êª«šš E½¡ÆÏm±+y+5b7ì¤@òœNxsWöô “¤Ks'r˜Œs˜€§¸ܘáài#Ú„L6D[ÙRw}WœŠ5°¬j»jÍÀ®¡ÿÛ’þ‹¶mÖ ÙPÿ¡êîx„þNWÒ%å¡é•ÔÅ—2‘  5Êëäz;Yy¤¥HÓZ»/¯dRï`‡p[™Kµñn*ªû±\W¸¶Ü¼AˆIº»Y®UئœŠzWR³Ùòª@SKÓ"ªuƒt"- T‹,ù©Þ?Ò ¥Æ¡i»ÙÎkBÓK¢Ú !Ô.ŽÇ}Uò„W„ÿ;l™ l"å$’´+ÈLCó£°U5ÝùD]Aó½µ|åÈþMºnêí‚t€>[kOM‰ËRêÔ…lö`‹rÿ5)ôh]²—¤P£²rA +­NÖEMf½>Ÿ¨Yð$¦kŽÙ—÷åžço'“SSã5ìΧ‚Õ €Ùó„†ÑWu[ms±p,-M*öLð}U>,éV–ºžyý¡Pb¬'Ù~ýJ;Ÿ:a³©$?¿`tŸ2ÏXÚvŠ,›%åä`–py!£YBØD•ÌÎ §r”Ià\Vjå|§ÆêM«µ®5ÞL¹F6HÙ|*Ç&Ù’¶x¤ÙDC„°©`›Ù9˜f˜7XTÔL—³fæ,­ae÷fÌ‹Ò +£Ív aÁ2fªwZ/_›ËÍiì›o9!$òú™<(F‘‚C]1È0Âz†N”atð ¢à(Héë¥õú¯ï±ê£³™5 k#£t2ãø‡7¡ïOè9æ‡ñÑ:Šè±µ‰Û7ÝwÐÊ¢ù†¡þzµEe¸z)Ë4D,Þ›¯:ÊU?k‹ö®9ï‘JB‹ýCñØRû¡9}FÍÉsŽv<ŸŽ”õäž$÷Ï™s§ÒLkójsžYƒDäÚ¢¡4Y¯D/kœõ~b'ù\ÿ‡›÷çp ¢îpJöèý<Š I™9FH +šêâíA£·Êäòz™‡VI†ÌiŽ·pÖmŠJc£Ú$;ÐÖ—fÂIªoÖðh/yЩÈÿÊdÛ0–òKqÀÐ1ÒX1Ed€îIäkœ«Ê å#ƒr{Þígå½õ©hïbŠ­Ôº9®\r>v<€µøøÐbæÌ Ö·¹P—Éh‹ËMÝ>SWÈzyìƒúP^\'æ°CD/ÇÂ=ÀúDÚ§cêÛAzzìxYCÿ¼‰MÞýðᯠ8[b5ãp8×`ô‚ã%?ANeôô¸èˆ©[t/hÄ´Øø|N·˜~ÉܦBÉìÂì˜9 2ä¾*S½Jâ%­Î›ãª­þ½T’<°hæ1µ 1fÈ™bšb{ÞèçþijmhqÚŽ¾¶%H±VuU  û¸D.Ü„ÎûzW¨+.e·(U}@ÆW 8Cž³¼>†#’£¡Óvz¿“ÜJúéeüùÊC\³¯64¢”–2¡ +F*‚’øù"¯œ ·É·Oþ.Œ£hÎÕq°»«Ìåc²#šHbµ‡ýc bóÏ3® `–éRýᆰfb¸Jí“%Ùž÷c”Ë0`)ªöŽñ21Ü`Kð‚À0nÀŒ-{~ª‹@ðæâ:ìE|ÐÞ‘GhÁÄ‘te}$’´`#{rÆ¡ðFBÿ†`Ûhƒ=Þ—oæFpˆW&–%VuiøÂ"ê^² Ulqh6¶à%R¸½=IÑn‚(Tï¿Í +[ã£9_¾ªßü7Óoá£~KË袿T‡ó:Ñ +Vv/Ûð¶Dë‡ §·JefìËú,†'–û@U +­ÎM•QDeäš#9§æ)b±J‘Š*Å/M E«(Ç*ŠC½Šâ I.‚ã 9–VütAE:UQ8“d¥ ècF¢øUþ£Râ8‹)@Ÿhé÷çºy˜‹Ú·Kô/¦¬d1y\¸~HCµéKÎÏ^xò̧^N‹<Õ™]x!‚¼r¨¬è!Cv=4æ’›Óã’†{h4P²•.Á7-„rKçÃ÷…LÀ»„‹ås£Rc• +H™ õŒ–véi"… +äD=‚Α+É`àu*­\rYmsuˆ•ã+ßš_í&ú÷¯ –CÁåÓ[Žú‘µˆä.Íú¬2Ö¶™-lw ×•ž˜¯“8[<Žü±œA9½Ø"nâÏÒ@4ðq–[½|È0†ÊxHû7,è)Hk±^[+ÐftdÄø’€“i‘ŠÏRAM¬ ¨Ï¸Èýs½:º¦Ù0ü‘àü5@<ã .ýÂ0 +ôaú±èÖw±(ÆG˜Ì¨QÌ/ðŸpb "ÉÔ€Ìç>Kþ†Æ48zO£ØOÌÛGêpêªäA_¨ü¸64‚‹ÅFÁH¢^"®—»çÊ9ü„§|½–ïW€÷vi!¡îWM_ì‚1egq½˜®cO|ÛfV¥ÂõÏ¢!tž*,è…¦Ÿh•=sPç1¿øvmD$ Eoýt?«A³³lâç_‰lª}ÏÿÑ«/n|—ðDåvöÌq[ÎÒƳðe(9>¥#›©•ë¤í h–½6@öÕ!” lŒ¿lüâ†æQõàz}> ñ(ªú¶9m‚N¬„Êi%TL*¡£M&üÇeÓÌ‚)•ä£LXµüö ¦KõŸ5¼À­…›×ŸG{ö]Ê8><Ï.P¬£Iî½}|¦\,ùäPáéi^Yœ¥Ìf©ÊzÅ‹ŠÊ¡›L…ÏůIe¥Q‘_ŸËÇgê Fäj^oÈ íÙ€(Z‚,}5átš ´Â&óo蔀{õ  Òåæ5_Ñ©Ô;ç–¿¡[õWc”á¹ÙùÁ„»<vʲPI•ºášâX:v0ÙsDp-N›æLh›ž˜ 4ü(öaÆóGÐ"_[£ààËGH?2 ôA_ñۉ} ¦~Óc€~óéúÇ7ó[q.Í!³AC«´ _6ÒÐiwI£OãìÕh:ñ{|Ê9N$àS‰v<ª™Ó!užÚ®f„ùÉ‘ý¤¯ïÿs@Ò»<éŠ=Ä€p ÿSXk§e—O-—U"ù #²Á…÷+ø…Ió«-­»¯ï‚¯åƒÆODáN\©…0š¦Ádãg{L(wuÑû:‹é‹~†E þwe]žè3Aìž[bƒ‰uX„L'.C¢„½h…ÆñYgœÔá‰&(ý®rm“·K™Ùô‘.”f«]U]ogGŽæƉù¦3¼ôWåO-øm_ØÕqìö1î‘!°b’>÷±°6ø¢°$È¢ÿrõþxøÊ:ƒÄ9µ¬Ê:|¶Õ‘(dµËžP¿8~Jú¬$ú¢endstream endobj -1295 0 obj << +1816 0 obj << /Type /Page -/Contents 1296 0 R -/Resources 1294 0 R +/Contents 1817 0 R +/Resources 1815 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1282 0 R -/Annots [ 1298 0 R 1299 0 R 1300 0 R 1301 0 R 1302 0 R 1303 0 R ] +/Parent 1820 0 R +/Annots [ 1819 0 R ] >> endobj -1298 0 obj << +1819 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [154.2681 743.8714 203.5396 755.9311] +/Rect [87.6538 85.4256 137.7628 97.4853] /Subtype /Link -/A << /S /GoTo /D (notify) >> +/A << /S /GoTo /D (tsig) >> >> endobj -1299 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [80.6033 237.2629 144.294 246.4782] -/Subtype /Link -/A << /S /GoTo /D (statsfile) >> +1818 0 obj << +/D [1816 0 R /XYZ 56.6929 794.5015 null] >> endobj -1300 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [265.4578 191.3384 326.6578 203.3981] -/Subtype /Link -/A << /S /GoTo /D (server_statement_definition_and_usage) >> +550 0 obj << +/D [1816 0 R /XYZ 56.6929 693.8729 null] >> endobj -1301 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [367.5441 191.3384 416.2908 203.3981] -/Subtype /Link -/A << /S /GoTo /D (incremental_zone_transfers) >> +1690 0 obj << +/D [1816 0 R /XYZ 56.6929 662.0342 null] >> endobj -1302 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [280.9692 160.0192 342.1692 172.0789] -/Subtype /Link -/A << /S /GoTo /D (server_statement_definition_and_usage) >> +1815 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F21 930 0 R /F22 953 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1303 0 obj << +1823 0 obj << +/Length 2987 +/Filter /FlateDecode +>> +stream +xÚÅÉrÛFö®¯àm¨©°§÷%>9Žœ(•8™99®DB*$@ ÍLþ}^÷ëÐ2NÕ”ìõõÛ7ˆÍ(ü±™U„ +'gÆI¢(S³ÕöŒÎnaï»3Ï,Ò¡E÷Ô7˳¼fæˆÓ\Ï–7X–PkÙl¹~?õýË·Ë‹«óWt®ÉùBi:ÿæòÍ·¸âðçÕÏo^_~÷ËÕËs#çËËŸßàòÕÅë‹«‹7¯.ÎÌ*÷y„0qáõå8úîêåO?½¼:ÿ°üáìbÙÒÒ¥—Qá ùxöþ­ìÎ(ΪÙg˜PÂœã³í™T‚()DZÙœ½;ûg °³®ŽñO K”åf„œ1P9¢/7Í]u¸½;_HJçÍ]ŽƒÛ}¶Ýf{œT7Ç] À²X&1Zi@Æü=¿¯ã©îãgZÄC«Mv¨ãSÙfS}®q|SÅ'·‡MSì6ñˆ‡ù …Wå9›oîý:›g¸]åmç(vyUçûOi\Ôf ¦%1–91â”âˆÕa¿?gvž—Á˹>ìvÕ¾É×$\¤³§„jƒÌ[Ž3ÄÆx$µÙge}“À‹º:ìWù{ È—;ïdåz®`LOÃ]|Ò# -¨¢6¶Çy`7—j^ïòUqãI•eïW/ß~’¸äñHK:^—ü“«<Y¯‘gu„ÙT¸q¡ÁkëÈtljLö™D.¨œÿ«*s?RGÒÂú碹‹ëw9.á‹Ûª‰¢ˆÁVAKìE”€¼¦ø”ƒ0cs°miÄü5>¨€:„†ôú•>\9„[•k(¦¥•ÕÏù¢½ÕWBç‘ð„ô+¥Ü+! ÅçïŠm±Éö‘,@ †|ôçñ¾I2ƒ•.Yb—,w‚,®$àÅÕ³5Ng3ž@ÏkDÝÌ·¢Šú"À¯9N/ò=þ:o²bãÝA°Ï<Çj/ Öy½Ú»¦¨J\ï5æ´ÀÝzý\#5J>j¤ÊˆÿÁH9 tQžp^„[ˆ‡Ú1b¤ ¡7÷·3\ubB{~ѽ0Œ C¸þýwÞnÿ|Tdš˜JZÁ{( ‚S{ê1DÐ<"$j‚àÂ>Ùû²$€²jÀÁM‹Tsˆ]†?îw©ƒ8.L£‰¦Š?ßãªäqõ¤ÇUOô¸aä}º^cˆ¥Rõ] ’GÁ+n\vЄY !Ð$‡•ž '¼ fhܤ¿°‡Ö  ‚#€«‘ÚI É1ÁÝ)ká@ÆS…,ˆ§ýèO › BÒž\G7râ¥ñº*&,~Ek‰rƒQ8EOˆóŽiÂëB>|SÏÓ7ÅLÏáüQRОÀž©`ü)ö'„¦É3}<äû‡ÍÉQª4'¨¤s#'©3¢­­5 CÖ$´‹Ù¡)žŠÖä÷P*áJǚ‘®50n\ÇüÅÌÕXþ"t ¤˜  È/x¢„ýüh@BM',JGòWBÂ"t"žš5°€ ˜l½äãRUºÐýc×1NKÉ4µ®§ÿĽÿ5êé¦@®š=Õ~Âs­ +øDŽ7•Ðžn˜'ÄM(@õEH“5EÝ«z±ºËÊ2ßÔülä[t·¾®ŒuWxFv©ò¥¾ÂÓðпƒL˜L›Û¾¦¾ÇE™78ú•*×v¿C“ÿ •§> @ü=n¡˜;ŠáíøŠ¯šZØÇɇhJP*îÄ(‚¡ LÔÀQŠV +úÛ6kVw¿m€ò¸ñgû¢ žö5q@7!äEÀ.ÓÇæÏcÂØsª\+dNŸ)äos¯Meq̱0ìÃà„GT´/ýÉÌÇX‘Ìt ™‘¼‘¦s'â ÑRið¶Ñ3áʪÚne±Êu(GçGJýàíà7xOøÅ\ÄŸ»¾Ç•ú¾†7pœ­·E Hî³EUÄ*{¢MµŒ ÙüÞæ‘•Ùj…yPgóH9΋œÌ6ëUýš¡Ì¶3Qð(Ó]VùiQ6y¹Ž{fÐÀ¤-ò?ŠëMÞÝש¹€“cÇÃÏNí—vAUS­ªM^!ðâÍ¡Áð–{ÉA‡wV¸¾èò·×ô0 +ýj}¿\¾ÅQËhñ·ÓñÅìü2äŒ)Ô}<­îøÓÍ]Öà(öç`äð'0 +~ê]± Ù+Ì°ð÷£MqýÇvÃÁh¹µm(ɨ/ ÔPýc”Jû=ßð€iHA¸älhÜjd…8ß› .y횀¼ÅÓy`à²er’ÒBîÇ¡ÿËxÐB|„ÒBŠÀëó d)ã<ÉTCSKÌ?ß«»”¡2´4'¶TJp?ÖÍÓ<¨°’S\Ñ8êÔ ¾ŸÈÕ„9h ž·} !c¹R„iäQA¤4ü‹ÛB\tAË•…lÕ¸ãË1V@A'“ŦVZ/1–jÈ€‡yâiª‘Rã~ÒH3°à}QÿŽ ¤ç0úGBêƒ^Ý*°¿>Æ€p*ÉÊzŸ·^aº²Žò<Êê*DBPqÚr­Àí„ŽW¨+UtŸ VªãÜE¸¼pX¸ÁßXƒª˜åü­Æs©"í5or¯@ÚÊùòÜñy…ûèÑð¾ÒšªXÕ§u$¢wž‰µRøÜýüP]µ#Ö˜iWè¿—8ù:7Ž@¥c¿X[[ˆ‹.È¡¶2 ¹9¸¨ãËk«âm#dJ[¹4éÈ×_E©ÈHÚmA2Ï;!ú¡ð2f’eL=c:§(jq¿xüêôŒ¥ý³±q×­Šcx‡QÊTb1½L¹k2 œýʹ¡Z@1'5uÑH夑*â TúS"bTM¿6î£ô\Q—.:GÒ9î;™Ó)che 0T R†Û¿Ãð !w<Ä: Σ-ÇÝ,Z¶q/Tb~ÐÍ6°ÕQ”ᣠl¢Â o Ôà¾}³ÉŠø X¾ì§S!oØa3ô3&‹yltÄXSœD£»âö.ýk"ë y¹N^<õPºþæ¤YÒûÕé¦ô˜Ö‚øx(ñõl{»}ÕtÛå©1;u¬Á ¾L>¯Ïú­Zåªûý¸ÄGôËqbÚ"cJ½Z+SÞëð@H|̇€”‰Ý'Îõ›=½h?ÖpæB¥-6œ9‹½Èf€Ä`½ÿŽó%æ> c‹ÙWþú‰³ß‡ð敇íu¾xÜ=ÿbL›ßÏ=.ö¥ !b¿÷wÖé÷Žý7—壟·i+–/þO¯ã¿ÁIC„µ|ü;¹ šXp† )¹Uƒ´*ýKØõÿb€endstream +endobj +1822 0 obj << +/Type /Page +/Contents 1823 0 R +/Resources 1821 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1820 0 R +/Annots [ 1825 0 R ] +>> endobj +1825 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [277.6219 128.7 338.8219 140.7596] +/Rect [399.2874 687.9386 467.9594 699.9982] /Subtype /Link -/A << /S /GoTo /D (server_statement_definition_and_usage) >> +/A << /S /GoTo /D (zone_transfers) >> >> endobj -1297 0 obj << -/D [1295 0 R /XYZ 56.6929 794.5015 null] +1824 0 obj << +/D [1822 0 R /XYZ 85.0394 794.5015 null] >> endobj -1294 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F48 953 0 R /F62 1062 0 R /F39 899 0 R /F14 740 0 R >> -/XObject << /Im2 1051 0 R >> -/ProcSet [ /PDF /Text ] +554 0 obj << +/D [1822 0 R /XYZ 85.0394 580.7887 null] >> endobj -1307 0 obj << -/Length 3849 -/Filter /FlateDecode ->> -stream -xÚ¥Ërã6òî¯ðm媈!>ÎÄ“xk3™q*[•ä@QÅŠTDÒŠóõÛ/€¤L;•Zû@ Ñ~Cê:„uÅAhòè:Í£ U|]®ÂëGûîJ ÎÚ!­§Xß<\}ýÞ¤×y':¹~ØMÖÊ‚0ËÔõÃö—Õ»ïo?>Ü}ºYë8\%ÁÍ:NÂÕ7÷¾eHΟw?~xÿÝOŸnoÒhõpÿãº{÷éîû»›µÊbóµ¬ðÊ„÷÷ÿºãÖwŸnøáöÓÍoÿ¼º{ðg™žW…òûÕ/¿…×[8ö?¯ÂÀäY|}†N¨<×ׇ«(6Aã õÕç«û'£4u‰Qœ±Ž’ë5 gi¤—¹a \[§Q$:5žËZ-qÙa!—‹í¶ê«¶)êõîÔÖÅÐï¿bF\•E¹·—lÑY„:Ô×Ó½_Pè±HÔu®ƒ0TɜƇ½íìÍh_µG¤¨ãNÙ6ýéFe«¶F€Yõ{AÛØ}ñTµ'™´ãoÑÈÎØžª¾è«':Ð5 lÇÀh¥‚<Ž5mÜÙÓ“…E"®Î{Û`KÁ2ÝÙžªæ‘~ c;‡U•{nV&xFòȶè àq”˜U{±z¸ÚµuÝžýêï>Üþpçöݱ¡#’õä[ÆÀ+÷EÕtÇÊ™1!ýLë¥W›¶ßs‹Øß^Ø«Ô„½/ˆ·–;í»Åå¿~e“{Sihâ}ãnÏÀBš_®BùËç×0ù¾`Ñ­ÝCÝLÉÞpVn0aÈäg†TBÞÆ“o„¨•i;–‹ƒŒk¹æ\:_òTÖ:Êéz˜ŸHcÁÀ?ÛÆ -“Ûæ×0ÔƒßÇ«Cãt(±ôà™¾º™ -ÈŽ4§Äã!ç€w<ÖÏ ?Wµ,°±K’dÖ5Q˜#…øÍVCG|Cì À‘_A±Ç¹®Ð(²¢“ÑFŸÎÏ„`“ÉÃÅñê¾aX×d´«ú¡ãiU'´vóóðM ÍÖvÕ©ØÔ8jB³êÔ6°«‚fQ$„ÐX€q€—Öx}¥= NûÄç4Žd?ñ´²‡cʪt¼¦`áÁ„ˆV–¨dQ¾÷‘¡bá@]M6B'#S“lu(ž¶‘1ºÄÄ1`‡v[áýZéoža@“ˆ—Ü»à*Q +‹Sæ -.Å$Éê¶îZ”Nð…ÅS[mY4w… J$Ûb4ôwpÜY“»Ëô\¸3å„ FD^Ö-‘ÀáÈ_gkq¸=Ú“ \²ç/Ƕë*Û?Ž¶édˆ®êÚ›é…kpšËÕµõ“èÛyO;c«ê­h% -Ö¹ê¬W=úYž*¾+€TÍTíg•û¢ìKöú= - p¶âp$y×!èÅ¡ZE«ˆÍ¢ûÒqk×Þ¨•ÌF‡ßþÃ_‘ìÖ ®µs[íÛ®Û> ´1Ašå©Øí]ÛBTP‚¿´óY$‰É_('ÁÅ]ˆ¸ïKZöÁበXm•âù•ýªu´@k䙊dg¬Ž×"º¨"`ø^0@ȦÂ÷lëÙ1 - ‚¾4í¹˜}"“ PpÃ#Ú EõY–ñf:MÛs£òsdd*T@“°gølûMÚä‹S£=1,®Ì"áT&ÓFXÑ´K’:‚|…Q¶U‡^§ã ÄÖÁêcœ‰p1ÎnêˈkæíRØ 'èÔºjVF˜Ù -+š›!6d DÈ l`Û2Æ+•˜0’:î8=·=Q>‹·™„ÐBƒdô¶!QÁÑ¡óãøÛ`˜ìšCâ(ÑÆìFÊÍ<òð³ÌꩲçIŒ;9ümßÛñÇ#꘭ºN8r%ÀÞüÐK¡Pa¤Æ¼-˜…ys®Pàeõ<©lx´eµ{y]ؚΚžl9œ:Žø`‘ÅM!LáâçŠ ÈeAÌÆ-ùÚæ¥l€ê±i½ -2D‘2d^zꋹÂFÝ> -Dbqj8X€ÎÌ_ñh…éó[܈² S‰K –Nuõ+·¡Ò@%ÊÙÇ¢„p²æàXOU6rj fY¤%¸žŒÌvë©q˱bF¢˜ Ȭ›œU$q§šÈ -kd]ûe8¢Å§¡¼ ”å[²â brR` ŒÈIRâË`“ƒžR.C•¬>tÂú‰5ûì‰Óã„ã^I©–Ôƒ‘4Š“ÆP{𼌥]V3ÃBÆog™PÌGb týnX–0ÎmÉÓ°ëiŠƒøO¤’€­â'6\êM¼”ý(]}® »Àt*§E¤5ó#Á$cÊ LyÁ;¬ NŠ‰ñæò"áñ` јÄ`› µqæÄDŠB-”º`‹¸ßIðÅ€9ÅÑœb‘áxiTÒA–CûM«j^³ªk?v{{Šã Aêf„'¡˜NÌñ!ï,¶&J"Ì×)\þÑ[v+™¤^¹KäâËi<³ß3§»÷?}¾û6`8[>š¸w™Y&zçâ—ŒYó<ËÖàbg:(lÎx?&†ž÷d–¦O6vˆ¿£¹¥`«=]˜<ŸicµGH*ÁP/ŠÏRáy â̤o—§X¯—=ç}¹_ŠãÑnטÔœ,ÏŠ½a$˜Ý7éðX „Ì’Elf”Üïê‹&ÄaôfubÜèiÖÉ¡¹†ŒÝ|ï?>ErNäHešË!ÀåH9³Ç-ô̰褺âT¤OkÈ(/ÓW°vNÈCçP0Ž’}(i¹ð¾ªàèx%šwºÂ‘hV!ÀÊÕзCÉ›{­<·§/ŒÎâÎÙ9ŽüùbO­âVŒ-¥ÆØ—úhk‹U‰¢—ÀØ3˜ŠƒáX ª»X¥á£E~x÷ÑÙì¦á -%¹;B¦¿cdN„ÈOœÀkî$áÈÅóQ'3ÊÒ©l†ÐvæBŒÈ ¶º¶ü‚™LÏ]©§ÊûH®– ÏxIT{‹²Ø…oaƇÞr{&V&ô²‡c(V2cºÇ†'å«ÐCÎ9ÌŸB6®øÝUÍcBk -ß·gûÄqåWKÞ$Oƒ$2.ÈF¼]ôo^Š xÍ+VÕ¼À»ànb†]ͬ‘¢8G)…®Q!&¤b™]Õm "ÝR£p±#äe;œ 5Ù¾jR5ïižæo›Ô)Öë&ÕcáÑ«?8Ž`¯»­vØñ³àg^XV;E:Lß&Çc-Ð3³…@Pê9=?ûhafZuŽÎÞüÕËM”Ÿ¦ÑÛLœJتïÃÖmA!KLUJ„4öÌ} éŽJqÞˆt(ÀÈ¢²ñôYáU/ ‚˜×$È"­/ªƒøða9$á²Bâ -s¶"1Ä‘‚˜<èä”ÈsH±«ÔãÈtñÍ3à S #x«y -.a\N(αºÉ±xHF@‡XÔ…Å˵v˹žOIµ7ùˆÆZf!ã:rä=!eQ—C]ôÎP~õƒ>³#_bÌA{IÖ,NcÖÑWPdͱ|”³g^0”uûøÈojR"Œ\‰0Š‰ÿèø_Pl®ŽAÇÝ ¶%”ŒbçUÆ"|!m­,Q²ÁFÖ§Ë9T}ï( Gß-¤+ûI[d‰Ž'Ýr´éŒÚ…HÌ tS‘Xôàß`IJè_†±÷rU/hz"ht[þnd˜Nq¾Û(ÀÛg°ñUÉhô,…Á”ñÏs¨SÎÖ¢f`ö¤i½Äˆsµ¥ 54ô”ƒ_NhøÇÊK}hƳâÍêÝÇŸd…F {h)3„6DÝp²ö‰œáêI”äô‰ô †²ïuR¥Xç^z(b?¤Yñ°á;ì”4GÚß°D9汶=Wb3ª -½ØÀ¶Øhzœ<©ÆzÜz®Ì´-Õ -fH\óô$™e¥D2: 6fã·Ý,àëª?-‡{l£8“ÆŒBCŽ›ªq!¥›8®(ˆøë TºèRØ;¾º{ '™¥Çô»å¨|áLZÞE\FæßêíáØžŠSåªZ¨b%YA®k²„M§ì[÷8Æî^]ÔqÉkW1냅kþð÷—QÃ…kγ2y—I:O%˜íö‹ã Öqâ•H-^.lL`ò$™øü…b6Ä:u9ûÈ…è! tèžÈ$ç©{JO©ž?û5A:)AC§†è´–¶ü¼›c¢pAÔ,5ôæ—ÿ·›Yª…hwùî±×6(ø—é}ÁbwæAªü ½Îoä:qºçÀ9»U%qôW쎧ÏîwcÑáˆU='ö}?œ[fœZT@~¥ój( 'ÕF™·#é Òë´C"ŽÁ–ÕzäÛ,lŽLdYöæÖéåÞó¿,HÒPÍ6—äLŽ/4%Z~˜¡ÄÌBC~u­çv`œ½ü´CñŽµëÑAºÙsŸ"ó -±wÞˆjžB2È×¥µ•Wa|0ŠÔÅ{Ä…UBÊSŒ»Ë=Xiú=äÄ‹ÕüUfœü½òË‚Ý Œò¯X¯¥‘ø[ƒX_¼u™\aKSy‡JSÇòÔY’_úNUá& ‡ ñÚíqL6°M÷‹ s‡Ðä%d­ÀV†ñø²Ã®‘~òò|:cèöÞ8`”Eî€åpr×á<оè.³^Ñ;¯¡ ¿¿BfôæÛ¥£¯ý¾Õ@êh)ôKüß¿}¥É2½¬’&„쌽# - ÒKÊc÷üÐéÿÝÁ’endstream -endobj -1306 0 obj << -/Type /Page -/Contents 1307 0 R -/Resources 1305 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 1282 0 R +1826 0 obj << +/D [1822 0 R /XYZ 85.0394 553.3134 null] >> endobj -1308 0 obj << -/D [1306 0 R /XYZ 85.0394 794.5015 null] +558 0 obj << +/D [1822 0 R /XYZ 85.0394 453.4945 null] >> endobj -1305 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F48 953 0 R /F41 939 0 R >> -/ProcSet [ /PDF /Text ] +1827 0 obj << +/D [1822 0 R /XYZ 85.0394 420.245 null] >> endobj -1311 0 obj << -/Length 3367 -/Filter /FlateDecode ->> -stream -xÚÅZÝsÛ6÷_áGy&B‰/|t§çN㤶{×™¶ŒDٜȤ*RqÜ¿þv± Š” )¹væâ™\,°‹ÅûRž'ð'Ïm*Ò\åçYn„M¤=Ÿ=%çÐ÷Ùdži`š¹¾¿?ûî­ÎÎs‘§*=¿_ ær"qNžßÏ›¤B‰ ˜!™¼~óöú‡_n//23¹¿~s1U6™¼½þéŠZ?Ü^¾{wy{1•ÎÊÉë]~¸¿º¥®”çøþúæ Qrú90éíÕÛ«Û«›×WÜÿxvu߯e¸^™h\ÈŸg¿ý‘œÏaÙ?ž%BçΞ?ÃC"dž«ó§3cµ°Fë@YžÝýÜO8èõCcö3Ö «L -–ÔB¥RÇ­,E&%0eF -eÕ[Yɘ•Zy^·m9›–uñqYî®YªD¸L†ÄÄ÷\ùj _*+œÕj¬ÀIž*§&onîî®^S»Ý¬Vͺ£‡ªFÕvÖ#•&»&~¢ºx*çÌ6«‘ç7â8˜$üR/˶eI%KénÜ`xj…µ¹æá/e!3‘kD¼Šèj…ÎòSŠjáe˜ëcùX|.YÅ‚«ÿ²Æó&pÔM‡SžOµR@5•RäÖÒQÚÚNFôpÿXRc^.ŠÍ’Yª6biÀÜ.M¿Â®7öî!b¤¦pÐs´ÈQ8¹ùçÀùs±¬æEW5õ¤u*rŽè¨ -=WD‡ÑrÉyë) ­uÖCÛ­üsÕ :ý -°ì¢ÚfrrÓtedJ–ʲ¬½¿3sš ÛO\,Û†”­ËrÞR³cÒG^£?@ܱ@¤™sʘTGð®Ä(TEAˆÇ Òrq!ÝdQκês kÖòÛ¬r/æ0¢O[{À®#\ƒÝ)f³rÕMË/«jMû?1ŒP™sÇÕè¹"zŒ–œ‚;N9VäÒk€û*'^ 4=¨„dÒVuÑmˆÖÓócYSïçr]-^ªú:¶G@î DØBÀö[ˆ½ýâCt !‘iš¤c,ÕMl'™¡?!ˆ–»²ë¼b’î±j©Õ¬èTz*ƒîw¥ `ˆ°,½CŽY°[–$ú´7ήϛe]®9ö Ä’iVËâ…ž‹®+fŸÚÃH”ü½V'8à:‚ÄÀ… -þ¹)×/ËæaWpž‰Ôºü¸àÀ<Ú£D‰3‘ä»U9ÁúM‚°êË5<èœt":hö@; ôö±Ù,çÔáÒºbÝ•ó~–˜³U\cžÈÓ;§]‡Ÿ±«!‘¸^Ä®&Mô††Ü™ÄkÛ{FPc9- 1å°À·:Ùq¢ÕïI¢Êù«€ç²î[Ô³Cƒ‘d§Ù•ë§ªövBOû²3ÁŠjYϘÒ,vXFÏŠ®|h@fÄ*J9Ý;wT­Šú`0w†yâ l3%¸ãÈrF~Ï…gåìÓÁÐîy^ ™œQ'„÷\éãŒrØè±ø{ï–´É{·¤yǶi½fÞ¡n]Í:îñºfź˜ux|NèE=§FûRwÅêÅõƒÊuWT,vÞ}ÏÂaÊ!©U,Ú8Å“ .kQTËXð³Âärj˜;®º‚Ó–gµ]B‹%fò¢Ôýƒš?ë:&<²Qͽ¢nŸËuËàK¡:ÎíŽOƒ}Ò<#¿ÅàáhŸØ$Zc*(ÿ\ÈÆ׌Ә+÷e|pZ0ÜÍOG°ÔÜúGÈ”šut+r•y6tç0iÎ5ÁÂÏ"Š= ÊNØÄM6þªTOÞš@^–Å’hMÛñùÆï þ„øò$ò< -îGNƆ‡±ïöík"Ã6ñÈš¹KOœ’,”'jæÕt|*[£Ý8RÑ4Р±j22ÉŽoß­} vÆ› .~V«%¹ŽÌ·Í4û 4ϵwr@ Ž© ú½|E]—ð(äsôîW"0PÙ!aB‘:9¹îˆ‹+/¸UC³Æ«á7>¨<2TðÚ*³A9lŸY;¹}C×_øß%‘|x‡ß›»WÔ¸{É­w¿rƒöûn/¬ü›ö×£õëñcüzT–âz.ä„–„Ï>ó=­UÄK¸Ç[>³'šˆÏ˜62JM˜¼qØDÛP«ªçæ.óÀ\tÜ~yÖb(*–'X6ͧ͊%,F¼álÑzš]"Pg~,zë9'kgw×7ÓË7onÅå퇋\y¨yò‡t—ä:w]ßÜ£W:˜Ne ÷s4rN§z®í‘{ú²WHäÂYÈyŽ -LÁãB€û]F’_£d´€”VŸLGÇø!À´,Ö-h†Œ‹~"&ôsýçsÎjü)y¸¥ÐÃ( 9 ×ý½É8]¶‰È·×›_.AÚ{¿TŠ‘P‰i·›¡­š¶­úÒós±Ü”Œ±àØ#ÑR -ÓßžÊ;2A00¡ŸˆÄTˆ_6ÓÿC˜‹ÁVgNäRGí€é0hÓ³ÏÕr>+Öû÷/*ªÆc²Ͼ쑽´„íQz$œ -¥Íö^ÚF€ÒŒ> ÌæФꩧTÚù^ÌÖ9'†aI“²Äűñ\Œš\dÊÖ¦ú¹]1¶Ʊ'p؆H¶|.^À÷·üXè‡ xöª„nã·éºâåÃ閭Šr”T8ÝЮ˜(OE7{¤ZÕ«•jÕ=>‘t̘MDL´!牯dB…–àÅ,‡‹4x,ú J\ZžoK!èôIs?CI [’P¥3‘fêø½¥¹Ñù8ý„)ƒ¢ÞXyÞcš+Ø·³×Ð5ÂJH0•H¥ÝI4Èè>¡m7ìN -úA‡¦>|p%L˜»¯´†\GŽnàڞݪîÊØÝ—ýà ÅybËLùãã›åR=VàC¹ÛzT%èj=ž!ãiŠ9Ñ ÔÚjéY¼ê-uùs¿BØ „»Æ^8¶£dH\€êcüò¹}²FG؉ԥ.Z:mÓ(¼‡„<­_þËaŒ#‚÷’šTãKŸüqdtvÊŠuP[ËMI#ödD§(¿T-%Hk,I°¶éè6o÷4÷¬C•¥KÉ\.csa›Ûu?ÁŽ¦^¾PwUOyO<,¥pÂÞgAŸß*ï¿¡-¶ò›M7mý4Ù`šHz¸ic!¢o"¥ÞfN½D?ë¾Ópþí•8 |-˜¶J"'xI£’ÈÞa'¯ºÃrø±\6ÏDíš3.ˆÀ‹ƒÖÖ(‰z¶FÁ£xØâk6©óý\9¤/Áˆü$첞qÅØh²£¡Ø¿gÈÓo§ÆWHR'¿ÂÉŸ|9ÑïŠOdòC®ÃžµçfòÓ™/Oö^­*arXÂQù=WD±kÍ„Ér3Ö zÝž «’(F¼ÿÎÌhh›.ÝáüñW6Ü¢ 3ŽWt |öMç”Ï«Ï[û“mÙ¤qOÁ^ÙÙQá¸öòë›ËwWw|—ƒ¯€uzŒòƒP -¯"Ò"K•þ¶ -â¨d®„RîD¢=ä: ªžk»aíúóQT—˜"ò#˜Òc`J÷-‚]”CH¥Ž!•æR@ -Êt€é:Î!ö:÷qDÆUßM¸B‰ ‘÷peånÞþÿƹ²Ù \ ¸Žà*p pe.&ü{ïqœ è{T|Ï‘?~£Eâ ^ŒøíºI'+J©ð0Ù(ë3œ´¯¨ïÉ RuÓû †õx29 ûˆ2ÃP\u»£À ::…RNºo©-ï$öàWO|1ä:²“Ëçk庙ÖÍ´mŠi×-÷z%¬±ú¸=WDƒñ^fNÒl¬ï¥ )h·âJ?¿@-6Ý#Ö’~™‚$|½ðÐ?ÉÝ·\Hòg¿IxI„ðFÔSÉy Û#OxÿQ|:%ë à ”Õ[€_&eõï pá>½Ú}u–ÄYS‹_Ýì~#ñÝ°6ßží(H±”uÿî²L¨,=˜LG¾Œd¦観bö¸œl"2 IÊ1z¦}%Ưì¬È ä1C-w2”ï¾Ìý•Ò¶ç!Ĉ · {˜Ý éüUÒ<Ì°á÷;=Ì<…G6YåüµÒÃ&{äÁvJ#å¸ÐŠî|.RÙç°‡¾Ü–>¸ï¡è·?Ÿ˜<é?þùÛ_én?a6x‘ê|È¢2Ù;LÂJ¡âÆí#6J§*¢ú8.endstream -endobj -1310 0 obj << -/Type /Page -/Contents 1311 0 R -/Resources 1309 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 1282 0 R +562 0 obj << +/D [1822 0 R /XYZ 85.0394 160.4691 null] >> endobj -1312 0 obj << -/D [1310 0 R /XYZ 56.6929 794.5015 null] +1828 0 obj << +/D [1822 0 R /XYZ 85.0394 130.029 null] >> endobj -1309 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F48 953 0 R >> +1821 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1315 0 obj << -/Length 3178 +1831 0 obj << +/Length 3468 /Filter /FlateDecode >> stream -xÚ¥ZÝsÛ8Ï_á·Ufj­ø¥Çn›ö²½íöœtnvv÷A¶e[YÊZrr¹¿þ¤%YNæî¦Ó’AºbÁ1KM©LÏ’L‡&f¶Ú_E³-Œ}¾Ì3wLó>×O÷W?~RÉ, ³XƳûMo­4ŒÒTÌî׿þöþÛýÍâz.MÄáõÜÄQðÓí×Dɨùðë×O·Ÿ¿/Þ_':¸¿ýõ+‘7Ÿn7_?Ü\ÏEjÌ—¼Â… Ÿnÿ~C½Ï‹÷¿üò~qýçýÏW7÷þ,ýóŠHáAþºúýÏh¶†cÿ|…*KÍì>¢Pd™œí¯´Q¡ÑJ9Juuwõ¿`oÔNÒŸ6ih¤Žgs£Ã8‰ä´–£02 µy¢²0UBy-K1¥eÇ…Z>>®ó®˜¯vÅêaþÐ>Œ-b¦"³þÚgx® dO‘Da’%#þ¹+jн̂õHƒb[ÔÅ!ïÊz TÝ® áÅâîösKÄMSUÍ3ñÀPNÔïß>ÒÅÞôüëX´¯Õ øÛbu$"ÿ»©‹w8¤«TÇlG!˜±afŒ´R“T™ ¾Ü}ÁŽþˆ"•o‰ØÔÔz®_ï¾ÜüFŒ‹6Ô®‹®8ì˺ árãæ–-õŠjwͱZqÉ+ÛbM£n=V`1Áª/´GŠÜYÈ×îi'eNgPqàhå¶nHIkØЬì•Ÿùé#ê¦#ª?8 ^rÙt;ê=—Ô‹ƒ¼^ŸHͱc*Ñ@É!õîw¼ÃºØäÇŠwYá\#‹×pFFö”/…cؤ3­Ræ Ïüž+NÁïc½î}®Ë蹬^æÝêq~(6‡¢Ý9 |P—¯ -à¹&$Ö˜P $¸¿Î¢à¦)цÀ Ý冋Q÷ØA?!¾ck}‰÷¾QíǾd8à¡íÛM^Vp—±Á'°+K#\Ç9)VÍþ `YVe÷r-„À-U[¬Sj8Iœ }òd°Ò´I¨P‹8þo-b´Ê™ùjU´-õ­ 2eïÂmG-:Ô¤Žƒå±#†çÒ:šŸ’UÓq]€ÂmA¾äu†Ü;Ï»rµ£.ã®Ë{ m)@'?š‡²Ï~b~B}ƒª.ÆìVÙÃåóº}öË×Üv<ÑÚðE7* `ËëÞçºŒàž õDN»>Cn)B“ˆìõ=×ÄÎP’qh ¤‹ƒ­)p«LÍcWZÇÍDàitÁ@Ùy 6°9V4b:s€„ð­*1kê/Hn„bÿØy[K þ¾'úS^yÅfC¸§ûúS1ž6chÝ”Øá%$‡©ç/Ñèø#¨-'¡“·’·P­"æ3bÇ›fLa[4ì—ßXHCL;Ø$?¤L¨GÖSÈ£ErfB{®è›m›–Â¥½›v>äJÍIêT@TQ;Ê™¡G£ä—©9ÍõÛÂ(xIQmິÐÁíÔåHaÂDz½[뙸œ8Lt¬™Éº8JùX¬JTR±Æ+ÈÔ[ ÛĨðúðr’Ý^³Ô2Ô‰VCœÞÍE_×1,”~Ý×û\—}Ýsõ|íbìîJC• _ßÚ1Ml=pv[³ö¾ó:¶e³$ðµÛoDÈ×kNØZÏÓ U ÂW ‚Í%£¤-ÊŸ{·ö)§b ìL@`iØû#2QÍûn¨t˜ó¥ZÏÝios˜)BwÿaA¦60'"ÎqD“ÒP&€Ê°gÏŠCMêÚOÕ‹äÒLÚô›GªaæëfŸ—<´ÌÛ²}G%bÞ«3 +M:ƒÎ¶j–˜µðè™|Ì-Ïj¦|ÝÊ+›ÊõÚº6 ˜è95O9Ä`«mk6D„˜¹¦Î¿]#ì‰Njƶèˆò˜ºruÄ4Ð~Ó[â"²x.œ<¾òZ±~Œ–v||´2 2좴o,¶ûíI-(±óQž ©;¯µÙÊúrZ¬"(‰S™¼*û\—C¥ç²™¿Æy{ºúáãb!>3¯Ëà¹&„>.BÂGéPŠAÐTÚ°f°îrÅm=í(€"—µ b=òz¶Âq_éi®À±¢khÔð¥Ù¥­9Á ½5zW”¡:%~ÈÚÐÖã,Æ\m®’Ô–ãP£ü\Ñfæ@E7ÀDY¸œÆ\â…ãû£=5Pm™ ”Œ™(Vê$óžQ=¹óºý2ûÜî°¥/.0 wfçbxLî ìàv—ãát”ØÃ!…³EéÔÌü-µhJØSµ'Î1#ŸK·ÿÈ.ÁþÃL¥.(L[ä8Ž€Y€6šÂ%hŠµµ±ŸåXWxÿöBÁãC‘¢©öoÔYˆuІC öôc ^f[Eí‚f‹7µ¾àç«f¿÷%tEŠƒf`E¸o™føSBÂÄ«åés=¡-Â$U‚¹}~v  {*"hŽï{ŠøÐÔÝ¡©ÞŽ~’–¤=íÒO øÚú”ñÀè’Ùž»C¹êì™uéRËÓb6‹Öƒ,š,FŸ8EÿgÊóP”—¶+ö˜ŠYßç :Õ¡V™šÉ( -M¬å‰ƒçŸ÷'LDí³u‡©ˆFŠ±Èõ}ÂÖ›ÛØQ—a¼í.~ì -¬7žéû\—£™ç²NŒeÀrG”pÇÀItš¼±»çšØ~øü §£ý‡ÅŸþñMJ˜zú èVf*{¸„–`ø&éßF8[ÆçDâh+@&Y7îñG!ë©·N *ž$ÞXim 1”z0â¤.À@‡O€Þ5WÙî%KÃÌ¿NŒïc¤Ä8 -•P†™÷ù ­Î¯Å)‡Ah{D°‰Ëv.ƒP2Œ´v? X¹'ÞHL¨g‚ˆÈõŽ}É’~¾Aì®–X_€—I&’a)mð–®B´Y|vŠ'Å„T(‰3w|_‚âœ7JqœŒEÇ\$1ôüžHN;ü #ô/Œ ¿.Øý¨±†D]Tš[oC$¬ÉìññâLţǽÑëR?Žò Ê#¥í§¨ãc æÛ¢=U—œ|Ó¤ý P£Ì?´.£FE_¹Ccå¥Ë= -õ˜.ƒc:Ù<=YžA|*ô«;{¦ó­‡„?­æ÷÷âÏÉz!ðøƒæñè'üI)Ë´Äö{(Ééí/ߊiȽŒNÂ€Ì C‹}R7RÊè,& ¥ˆe¤Ãò7XY$ÄÄ‹ \ð`AÚitH%¬¥³7ÀA4y냃L#¿So¢ h÷ŽÚüþ„—å`k‰ÔzŒ8ãu½Ž…ç(À:ShÂrê·›ÑûÊÿêµü[ÝùïNCÇ´/É\êN$®$(V“îùÆÿïÿËsúN:K/$I*‚€.³Ä …ZÓÙÅÄì\ôÿ¢dgendstream +xÚµZÝsã¶÷_¡·Ò3CüBòä\ì«ÓäÒÚNg:—{ DØâE*"eÓéÿÞ]ì‚_¢c7mG\€Àb±Xüöƒ‹~bÅ~¬¥^$:ô£@D‹õö,X<»÷g‚Ç,Ý åpÔ·÷g_]«d¡}Ëxqÿ0à•úAšŠÅ}þÑ‹}韇À{÷Ó‡ë›÷?ß^ž'¡wóÓ‡ó¥Œïúæ‡+¢Þß^þøãåíùR¤‘ðÞýùò¯÷W·ô*fßÞ|øŽz4=^`z{u}u{õáÝÕù§ûïϮ ÷+…ùõìã§`‘ö¿? |¥Óhq„Fà ­åb{FÊB¥\Oyvwö·Žáà­:«?øRÅrFR,„ðuÉ‘#íÇJªNƒR‚V‚ ðÚý¡iM¾ülžÚê]›µfkª–šß™_‚@VE[ÔõdUNÄÏMöhP!°¬œ[°XÊØO`]\î~ãƈÁ¡ý0NR‹cFRœ2é¥]Ðàf `x9 hj~÷áîîêÑYöEûL­ý¹H½ºn8û0£‘Eã˜5ë}±29wWÓó†“ñÓ0U‹DI_Êž8½Ü?.ˆ¸U7~9œ@G5Üâ)_ÜêY³ÞA˜ÐOO¤I,£‘4'æÒzM†n(ƒÕVà]:•.Q`*C_:^,;{ƒÁ¾•èôM-«axºãB «À;nLE/Z°K쫲X AÄC½'"£GUWËìÐnjX/k‹'žû[]bìÖû\ÕÇêéÈ[X˜uVUN°OµÆ‚"›òÙn1p[#à©WmVX¹•ˆAZÚÞáqC`MD™¶²'zeÖÙ¡1Ô(Z|FV4âaº¹Dô*Ãm©zžóÙe$wu2Ï­t¨šâd÷Ç£3û©Zãp¼Ùø`¥c{“5Ô³2xJص®+<¿GVUÎy\FÍvžzöFS +!YSvÏ„‹ŒÓ,YýÖž3¶Ïþœ ò6à¥ÀSÑç¼RqƶÍ*¸z¿“±½ßgÛ-ÈxjJ.1K5[ëS ¼ÿiw"Úôĉ6˜ˆŠ8¬Àt0+—öæbGuØ®0Xú=zÈà›9Tùx:î°}|ô}ÿÓ'ç G»# ÿ뛎!¾ÀL»;†ð­ÇðLœ£¨Ã›3púq„S‰7 ňæóÜqâC’"Þè‘c?T‰sßÌx˜‘'º—µI:ÊÈ•N8a9DþðêÁp,²64¡`–öŠ¾”pxE‡cÃz]K*‚ û¶jìS>›ÝÄ¥8‡ÂAžì¡…` -Ö5]ªãî~}h;WdöŽôñ@ØNœÝiRï 8>ô$$ÄX,Ø#ouwØí ‚¼Àœ=¢xVÁó%Û‚çãn!ìÏèaFáa`ƒMÐÓóE{‹¸ƒˆcÆCÖõ–ƒ˜m@ÇŒ)h×z8Ζ‚,Ü°4”Æá°zh÷Oõgœ‰ðm¹ÁA:ê eÃ]X¥k +pz¬FwÜé!IB ™ÔeÞs³¢¶•`ÆÖTúIFo®`¥Q8¹Z©êƒ[zeèpUŒ‰ŒŸRe+Œ_–KjzöÑ¿íÝؤº«„ •UÏD”uõhöß î%åÔÐéwÐ/GÛeô¸»º="ïï×h…—7? gafÙð‚ë:Ǥ:ŠB¸ÑNZg.˜„p½¨.}€Fùöë`[ö(é‚rÀM?=6©þµVoN84 ÚLÂÁw{"ieC„AŃïªÔ%z|Yo%¤ô6õÑàÞ@­ÜCEä +Z@Mv@«KG±žTÑsÎLE, zTñ›F„s…V» ,™å½„¼ìŒ¬|Ù‘\“}Yùò| (hEBò—¤b’*IÂÊU¾\=#=Éܨ^ö™+ùiÏ%cYþ”Ëðg“tå $Ã`zF`$ +s8ÅWY7mÝ2º´0õœÀ½°Î „‚ý>ô»bç`"$}E••ýDRMûQyÅèþ[ø•q8€ÈübÎ… _ê4~}“±ŒâÉ&»õ|ð$°AÊ*=†£Þg³ÿ‚þf Þ{c‹Ý(F$è:ÄáŸÁgy7-uÖÌʦîm]ƒÿùÍð²ìîKÂ= +åØbºD—\&.ã塇+˜]ê̺Ðû\{m²†Yò~0•ÝeŸHSÑ +;àk³å.iÃ\·¼n‹ß˜M—Ž'6l9ü›BaŸ òÞ‘£dÌîra0RÏ—ç.ð•êj.¯AÄ›aW©z®8p¥–†Z=J[ÈCÊV"bÞ ,Û®šž+~ÃR îÒ¬¡¶j‹Ê"UTÏl]¡×[aheí" ü¿±:V1\t™t¹F>Ý5†nk¸ ><9íûËi‡œ0ÂÝÛ‚%ö[[EN… a•«é ¹¹Ê¼Ýˆ sz±+¹¹) †qûÖäs™¥-í¢ƒ”4hþŽ‰=ÚOü€Šºø¢hfò@ðF¹88L²fÎ?ò“H¹?¥‘sëÀk²Še™w¸Id¾Ùÿh%3Æü·kW°hWáÃîÌõíž;P D~ Ót,d48*öEc”‡z¾>´‡¾šåÀ©Dœh¨‡kPˆ`¥µ7bÄo)U`ËŠ¦–…/ìlð˜ôÍÈr´¶aëð”€"UÖvRÚïÅ°ù×CAêÍ·v0ƒ +ï0Xûõ@ç¾Ì„Él‘„¾TòÍ`!d:w~j·3Ù¾¡FC•÷!œ¦óŒJ!î*lÿi>Š»ê³Icªgá“A9õúRêÚ…à°°J§æCÎM Ìhkë? AÁ”ÄÀ~ØJiÍ~JŠæq¤0"Ÿ«÷éÄ—ˆeðv* \h.Æþ¢a~•5“m1RCGš–ÄÊT: KlÜ¥åüñûÐJ½9KR=. -é&ÁÓÞ$-Fß±ß%ZR5’$êî®véà¶~¢)¢Ï¾OCSŒ3ÞPs¡“$J&À¬’ È@Oâ©8œ0žÔ*º¸>âxžsz #ò«·Ãj†z.ÑTS';¬Ø}¾=ž;ø¯®•Å£î;`ÍWf²¨€íié}M׌iLŸxqUrôv—ÜS°\möÙp–YÔ«†Q\»S£ŸCüž|„Áï +áªq ý4캽æ¼Q Ä$è¯>­©2ªJá'3²£µiš¿|A‡ìƒl`Ð0s°`NQ«×bwüƒF÷%ÌžºaäK“°÷Ñ>: 6?Kœ~ÈÖ^ç)~Gì6È ´GŠÜL»Þ–³uZá•–¦oŒt?dè ¡&_rvokŠ•âtXC‹]Z§…1úóå‚Â.:sès{CMksqê¢þ#:w šY♉½ŸñK’è »¿8½~E#¥NJµŠ@NtãBð q,&øÛY­ÓääkmÑ þ¬P²ÓB.:»çŠd1™ÓÆȚɫäF=¸RL6©ƒ ®gàõ¥rwý—þN§"?œÿ7SÐèÿë¿ÚõÿC tõrþoQp†>¸Uå„B•§ñ‰äî?y§¢ÿ‚Çqendstream endobj -1314 0 obj << +1830 0 obj << /Type /Page -/Contents 1315 0 R -/Resources 1313 0 R +/Contents 1831 0 R +/Resources 1829 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1322 0 R -/Annots [ 1318 0 R 1321 0 R ] ->> endobj -1318 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [367.5469 410.6007 428.747 422.5009] -/Subtype /Link -/A << /S /GoTo /D (zone_statement_grammar) >> +/Parent 1820 0 R +/Annots [ 1834 0 R ] >> endobj -1321 0 obj << +1834 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [483.4431 196.7586 539.579 208.8182] +/Rect [432.8521 729.0977 481.8988 741.1573] /Subtype /Link -/A << /S /GoTo /D (address_match_lists) >> +/A << /S /GoTo /D (DNSSEC) >> >> endobj -1316 0 obj << -/D [1314 0 R /XYZ 85.0394 794.5015 null] +1832 0 obj << +/D [1830 0 R /XYZ 56.6929 794.5015 null] >> endobj -358 0 obj << -/D [1314 0 R /XYZ 85.0394 649.9934 null] +566 0 obj << +/D [1830 0 R /XYZ 56.6929 769.5949 null] >> endobj -1317 0 obj << -/D [1314 0 R /XYZ 85.0394 622.3077 null] +1833 0 obj << +/D [1830 0 R /XYZ 56.6929 748.873 null] >> endobj -362 0 obj << -/D [1314 0 R /XYZ 85.0394 392.0307 null] +570 0 obj << +/D [1830 0 R /XYZ 56.6929 537.7045 null] >> endobj -1319 0 obj << -/D [1314 0 R /XYZ 85.0394 366.8157 null] +1835 0 obj << +/D [1830 0 R /XYZ 56.6929 505.9624 null] >> endobj -366 0 obj << -/D [1314 0 R /XYZ 85.0394 245.2415 null] +574 0 obj << +/D [1830 0 R /XYZ 56.6929 424.1332 null] >> endobj -1320 0 obj << -/D [1314 0 R /XYZ 85.0394 220.1859 null] +1468 0 obj << +/D [1830 0 R /XYZ 56.6929 392.2318 null] >> endobj -1313 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R >> +1829 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R /F39 1151 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1326 0 obj << -/Length 2907 +1838 0 obj << +/Length 3726 /Filter /FlateDecode >> stream -xÚÍËnãFòî¯Ð-20êôûœ&OÖÁÆÉ:ÞS’-Ñ#b$Ò©qœÅþûVu5)’¢d“2FÅêêêêêz6)fþÄÌXfƒ 343\˜Ùr{Ág`ìÛ ‘h-Ñ¢OõõÝÅ—ï•›¬´³»‡/ϸ÷bv·úyn™d—ÀÏ¿ùáæýõ·ÿ¾}{éôüîú‡›Ë…4|þþúŸW}{ûöûïßÞ^.„7bþÍ?ÞþxwuKC6ñøúúæaýœ`z{õþêöê曫Ë_ï¾»¸ºëöÒ߯à -7òÛÅÏ¿òÙ -¶ýÝg*x3{‚ÎDr¶½ÐF1£•j1›‹Ÿ.þÕ1ìÆ©SúÓÒ3«¬È3)€Ç+–U>jÑO/Ëá0³ÚêÓ¼h^ lg Y-¼`&3[X§ANºã•r& ÆH<_ï˜tØ(Å8¢àxoPÁ‘00cµ@:Á™QRs¤øáraÅüþ—ó£ãð–8Š™…ÍáqáÙo3Á¸AMŽ;=h "¾¼ÞÊÙ» -ö3ëo)ñ]ôÇYÕ3X!ìW«™ † "£ÀÙfS] -3Zü¶Ïw`|þ¼XfËKÖ9í×ÊÐdÚoQƒ :?/‰ =ìë|EPSÑoý˜/‹‡gzȖ˼®‡ ¬X@àÅÆÚÓ60郟õîólAÁ!ÛŽ±8ØóçYêB潃è!AÈàÜtˆÌ aáÀ4hSw°A1b:ªöÀè°žU9V’h ]ŸóÑúÕ„ý³ -üÁr1”à'<Ì_8—9¢òó§u±\¸©–ÙA7ÏV«Ý¥ðs8ë–p™•  <6W‘jU”Ùî™0ïn~"°Ëº)ª²†€¨¸ß­‹Äi›}l™‰ÏcU/P ^87ËA½;ƒÔuq¿Éß°æBi˜[ÖMV.[ߢ¥¿ß7¬ŠºÇŒ};d˜ÿÞ·¸>”¼]C}UæõŸŠf]áøPæèSÙ®Ø<âcY=u³È»ˆ–ñ„â¤æ©Ú}ü¢¦ÇÁ±êúöˆryæ$—',qd>N2-\ŠÛ %¦ÕA÷9ýÖA­Q ™å>CHðfåDbüèdbqˆv iKÇÜäÛ¼lPyR¤tgº.³:É- -~«OùnW¬¢¡Áã iœeÆ@•@ UÑ`Éä]%kÏS¼ZoÎY;Óv4…ŠD×éH«d=¾Á*Èö›DW¤Ã€ÌÁÎôÉðºñSÖ2Hu)Ë •TÓ@ƒ2pò…À(΂Rê¯,4sý_^ô9Ÿ)tPÌsåþÊ2àÿœùûÇõwÏüþ|æ×Ú1-y8Ÿù;ªqÜ e“¿æLêÞ¬ÉÜŸˆ&$¤~m˜T  ƒÔ¯”hã'‚ëªn6£ÈPl4 ¥(Ì òCޤѲ~ÊwiÞCœWmé)Zq³Ø…î8CmÀž2?RT -Ä`APŒ‰abí”8Nži®}϶•‘Z¨ó€€å„4ÖaÛèÂìòå~WÓá^ƒá„0ZŽ\ ¡â¡[7Ö) !Xy÷TÔ“ùb‘2Îëbbiã™7\½fiÔ|_nЃ—…2†3εæºÃ¾À€¿šÂjð«.UG)€–Ö ˆ“mgk€Š¹úXˆÀ™oõXBY0µ¸)§àÚ_ ·ŒÊµ¡§Ü8BVËwi±¿p甯öªå«a¨²ê¯`VPôŒ~2%/ehÏ 4©HÅ„¢ LØ0 -~0Û(£<(ä…@t 9†ÍdšjBŒ)ý¹õ;š#QÈB¬uc{ Û¶ýàÇíŒRûcŠO9¡ºðƒèCøÁ!JL€nà –ê,¤: uÕgž§íÐþtñE±éLV>Õao&,RB !ß-rµdÞuþ“•«)\öö<Å J&m[§>m¢Êc:2/iꌙ¶T'âî°Q†dî´9/@G5!Á°QÆK"3a˜-m×(#ØfKÙºli©FÂ_ìv "Ò¸§O uèPqÆšlxÿaÝ"Š4Tç;ègðælÙZ3JQçÚ@Å8ˆ2¯JbÜk7¨Er—bNåLŒmb"ŸÊÑPãJÄh½¶þ¤Ì…JšÒ¹óI -¡¸|mÒäÚœ]šŠ¨=çb ’@èʇDsº?;•ht& Î:›h¢XVM?M)ÒCû`Õ I¥OuÚ_;ª ›J+œLx}^†ŽjBˆaëXÁ ¥º¬ì’‹’]rAì(¹àhL.q,Ým!rì®ÒµîŠå¬æ1Ÿ !—r”ObÝ‘®fà³P–òQ ûÚ|2’äsûûÎ44«ØŸ7‡Õsh©æ°\eÍqŸ#”šPîŸ]½£šX^Ž®“‚wn¸þ¨Ê8\rBÎO±±]ìŽmìF¢x€¬÷÷Ûx¡ð»ç2ÛK" [NÀÒ&Û¯&»Íê&O0^qÕ©¹kÍ,DyÊ ’¥Ð”ÌžWy,sXн²Çµè¸KF5ñMÕä„mÖYÓ¶WŒ€?p„¡ûŒ‚¡¥Î(Ã:1 …Å›]Ü*¤£/Ò¬ë§n?{v84ò¢¬ÑžãX -{u~l+Þ0‡©E‚9(°Ñhp÷!]©Üö­¦¥_ô'LXÍßh5ù²)ZWrL¥‘J2í¥Hsd¹Õ 2H¥¡«EÏéË@óH“›Ó¾+ ‡BwoÏûnŸê´ïvTcß]€8OÙn…†2>'0?ªó‚tT’ÈÑ=¬óým»±Uغ1€7ƇÎá|GÜàƒãCtcz>Õ›¶É>% Ððx9 -ßѳñ¸Òèµã­8<“â⻑( ^8T‰thR šN £Céå…¶…üò½ö}ë‘¥nkùÿ@QÈyj›#øß©ÚG1 nšó†Ø·:Er訒°)Y&±S4£ôÚ'ÝÏH˜Ò •ÓnŸ‚Œ†d\Äà¤=) 0ù8m±`Y(æw—AÎ+¢ÉËì~“躥µë+8¿!âöžrBO:(#‡µá¤qã`¤UÃ’/©Z¶V³_½¨ÚxÝ%È~žé “âóOÙfOwo©~L×j묜¯#8D©?wÄo9ÛíÂ1Mð•P1uÅþñö¦¸‚b Êî_»(,5÷ ÏgzXV{|=õHéhµ_¶—w4£ôè}^u VHœ¬(—x¶¡õ °”3«².î‹MÑ<EG è,ݽ4ÀKßЦÂÕëj¿Yœ7Ä_ÂVî7Nìz®$*5D¡{µ5Îv1^PÈ¿n£Œo-ɳTkâéõ£k¯ª|·7„‡ÖžpyÖì»®t? 1¢¨1iŽ¯ðⲿ?VuÞ"i»âzjc´Úæ¹÷&ó8ê€qJˆ¶¬À±öÄðª¤*{ÇÕ/›&[~¬OÊq ;3ü "XõBiÐR/zäÇyhÌó5e†üm¬rü]MKt~}-9ãƆ]M°­úš~©B°†)ÈXç?aèhÎ|À@4‡ðùÉ.êç쵦Ô4lóÀl¸tçVïhŽ–¶x–yè{˧/œI/j ~Ê"Òâûñ.úP;o’îœißT™y½­ªèöˆÜAÂ+ZVvPL›ù[ø—誄±ô‹×kà '¾ÝR†éé‡w¯*?û»®ÃGoÐÇ®bºàt -S`’„BÒõÄÐz8“ - õXôÿ@««hendstream +xÚ­Zmܶþ~¿â¾uðªâ«(ä““Ø©ƒÆIí +4 ݮ֧X+m—Ú»\Šþ÷Îp†”´ÖùÜ68–¢È!9óÌ+%.sø—Îd¹*õeQêÌäÂ\nöùå{x÷Í…à1ë8h=õåõÅŸ_ªâ²ÌJ+íåõnBËe¹sâòzûÓê«¿<ÿáúÅ›«µ4ùÊfWkcóÕ—¯^M=%ý|õýë—¯¾ùñÍó«B¯®_}ÿšºß¼xùâÍ‹×_½¸Z gÌ—Lá‘ /_ýõµ¾yóü»ïž¿¹úåúÛ‹×é,ÓóŠ\áAþyñÓ/ùåŽýíEž©Ò™Ë{xÈ3Q–òr¡ÊŒV*ö´o/þ–NÞ†©Kü3ÊeÆÉbR.1Д™UR¾<^ ·ê÷Wk%óÕp[ Ô:ôMÇ;{ åV÷·uWßÕG<5ÐÚB™ÚÀŽjWíë-›nA[œ’<êxåV§Î3õ†—óuíãnê…¥ +•Ik +¦±¯ºê}½]¨ü‚¶Ìr#ã‚~¨†z_w/¹¹­7âb=ýî«5oäxöp¹VBgJ{¹"+‘â›—_Á`­VÀv-¹‚P×¾Ö]Õmj긭< ©Z¢\myèM]wôªéš¡©Úæwà_xµëÔ@n„!þPošŸó\Æ!Û—Â3Y»ªº-SÚÑ[ßó›À`ìhö‡ö!œ*ŸŸfßßÞ BUÐe¹ºËB óõ¡£éèwY^ÂæJ¥?S`.+]nypûéú' ò‚ß;`ÖÄJOUçïë£ÿOªéÄ"2^$>ã!N‡:aM╲̴ӑd]`1\þæ~ƒ°Ø ”wxjù¡'ùò\äÏl.óà|£º©|%Ù8€œ*Ã^‚ø«®þm ÖÐì—nQAœzJ;WE¢[í†úÈM^ˆP+°RZM¬ daƒiK‘ SŒt‘ˆ«Å=€Å•i»dŠÂáÁ¤óL短ü­¡]P~iK–œdÓi›  nÄé†?ôݶéÞÜ­~ﻚZ÷MÛRë†{¦g†Žrz0xMëBcD<0 + Q€Ût†ôûƒ©Á™žD+©¹+¶6Ø66Sru×ÚÚ¾{_3vo˜¤^ØÚEX“Kð f&[ÊT?aýGÙõ]‹ö$/hóð:š;„özàu[SWâ¾ Nawäj»² ÇÎ×ÿ<„²b…vOJÀuÛ|X“23¢ŒŽ'?<Ž&c3­Š’?[ g2[ò ›„)»¬¢˜‹â‘•$ø|)FGC86—¯Y4QDÉ ý¥ »åù;ZKϬ³ÈÂ驱Ȁ‘»%”YQ—ˆËŒûf¸†®¢Ÿ»¦¾¿*å*c‹&ÇAt2Ë+œÞ‰ÕÄxbuìê@wUïÜÐS MGd‘3FE‚V$hEx0îg´pÜ_EZ~`Ç*°¯x¬ïÐBÇ×Æ­Vm‘®ÏbêW'v*»iº%å¹È¬p_à}-@øï·ÁaEÑ*ˆRÉOÜ=W ¿›Û +ôz‹Ø/lœ•óÆbu: ÛÜòBÏy:Š‘ZU÷@{ r$¦MÎ`¼}Ü4TJzF>–¶â©Ÿì$¶njî96ÃŽ`zjUôók:vO!¦?[à´4E&EBåGœÎ~íÚ%nK:VÊ‘ÛÚ*ô±¼ ýàXÚï£kp2+´9“.“tE²‘W²Œx +:Ø üú¾ïhdì9ôÞ77iúâ{ÚÎ -(Þ’e\âXB´úÝlý©é„ 9ó1JãèÆ/ŃìÛÄþX ‡~:JͤõÐV9ýú ÈÖ#O¥Y½ÅðS–ŧ²©HÃ>±8«Å$4¤‘S†fuÀE ˆD|$ïèÜ4{Á÷žãz°Zåbéá¾'K2óäR7U7uõåªþ bá!ú𡽨+ð¦(G§ß?¤(bÛÌ6`“ÈeÓT‰FÆä/ƒ.X: +g ¾çmTûžH•¤¤žc^­L«-Èv¾6¹“ÛþÔnç.¦jï«ŸÆ>TÜ* ”#ㅠߤ[ñ”Hó¬,Uôt[°TÀEäéG_áÈWº+Ć Òy©£+Ûv€¸nûþCå›m½°º×'ŠзÐáðKWìÙö¸i|i³ÜFƒà[öå%Vtæd©ŸÆ> Šé5ë%ì+Ažµ÷ž2HB?£“TìC¤ŠaÞÈRòÒF5GKp ÖÆZwÛÞeßdýñýR4n²Â¤40£˜²SÆtªLñ¦#!@O JKR0|3=¢‰Ú5RqóÜß(ßÔž©Fê7XœšvàÞ.Iq)P‹„ÓÏCó3ŽüŒÀD1ç'Eõ讫n®\6Ív[sJ” ¯ÇLÝú½5û™ à•I"ˆ$ÓÎv¨o ''æAÆbiLš+rŽëÂæÞÆœŠ«bÇj¿¯ŽËzÜ\Ðñ‰‚eZïBz‰ÜRL¼1s[üÓ¦­¼ÿ…Æÿk±nQ ›Ûõ¦m`'>Ž ?Õv{‘¿ #ÞµÁ.cÿ¿¿xœÎ¶öCÓ…Hó#&&ÄŽ5øJßÜÕk +ßqüCíßõÇw˜ˆáãâV~š°‡,ÓÔ“eÙ/Ÿ˜€Šú.¥ºçsÖ‹ ¦ýŸ#èk°½:·#ìSøºFð¡zö1ˆHÿуýYå4®—‹He&eÝIX~ÁÖjÈ/œ;Ï÷qyŽÿ ÅùðsèïëãîR£bµ«Á耈Qöa(…#c5ÙR5Ù& e!¹æT¹N³}}¼£ìÚrQj6ðë×o©ù*¹_ÈWš.¿›Õ¥4ú¢œËšR\ +!êC=©KÄÈàþ–ã—†« +•Ç@ „jõj˜¿ß¤A©Ü&Å'6©%„<Ûdð@  ¶YQˆˆü~7J'4ÀòKå«2+l>fÒè¾bRfÆ„hü#Œùåh8wîûòS@ÝNGXÃÆÄÛR‚- ‚ ;Øðá°ÁFI+? +6•©BÉKŒuµ1æS\OI. b*;YøX³™Óœüa{LŸØ#ØÃÌ¡ôf›| k¦ib‚µ(œÐxk‰Bàj?k³˜l±4)ÊTÅ$ÀáU.Dô˜3*¯Ôìú +ËF¯n y^¼ÓOˆÙ&½Õ™°eŒþ«Tä›áDãÌœâG+qJrQÛzWZ>I(6)Etbša;˜‰XœºÛ*dŒÀ‰ZÕž³°Pƒ¥w)r‹ÙVI·¤ì«Kòçt–Ž +þ·p)ó}’{€5•ËOr€©ÿ ÷N‘ÉUñ ­çà ÕâÕ„I€lT° +؃«1©òpÛl°†juÌ:ï°þ€÷J+ܾØ×Xmüžé’×ÆK^¼”bŽí gxéë¶Þľ8p,²¯­„¡¥ ¡¸$Y…«;¦7»ÈÅ!K‚\ÇÓ-¤JgÙÍz!mpÓ+ƒÂFþÈBªpéXˆUéžú¸BEKL» jöOœÞ®‰Q©”â«xSǃ&˽á­Î´fÂ\•®V(³¢+„mêñqG¿Ëu©ÒeN*ódî¢S)*¢žè6üë›÷]u ®Ÿ¥,°¥©ÎcÆÈÚfQG,*7¤!¾oé¶ëÆÛ¾èΙŽJ7<^žŸéGºÂM“Çgw¾*YþOdr²ˆ,¯ ›!^ ‡P€/–À™8+ļVø>Dî2×)Çæj¬YçÈ´3“K…z:ÙÖê…dÈ2ŸsÁœ“Ö…%7X„¢ +?Žf6׬æ:9W «¹~¬ì YzauñÄve&”Ü.IÈ ¾| 5˜A£ ãg´g5+4"Þ$ٜܽ 4|HñUÇ-A—všÏa/î2|øãÜYÞËVo\G„Û +"ÂÆŒÓ'èx†»ÈJŠerÉ„5Ë`pŠ(õoæ¸|· º¥±Œˆ÷PØ>+h`èÅÙëQŒ“/?øB4¦ËX(¡@NéòY^Kþ.ÜÀI£¸¡¢z)®U{z``³éÆ ÀÖ6FÛYÁÛ/—áÔÇ_Mmv¢*9QŵK•*µÃqK[1Z—.Ë?aL +Àfp@ØÆ‚§íb샗ôò¸‡CP²Œê­ûp³Š­Ñ’߀.¬Ê4Á|àÈp%J×FA+¡oâ´)øš_„¯+xÀ:9Ø wVí©¦fÃăðžM + çãº%œ>ö¥UVè¤ãŸo‘É%ÃUjÞ–Ž’,5Ý—ä^JP<·–«ç-}]¾‘oÈaÈÎ’ÃlÜVwõŒ=„£òØY<vÃs—»6 +ò[.¸ì§<Ê´@ÊßMøzüha.8¼j§-³V‡˜1´¡ÔÛšo¨€©ö‘êô°Ÿ(1›Óò³3… Ùcß¡*H”Zúj4O¥ÞÿûÕñ^]d`Ðåòç§*·xÓUÄMá \q¾óô1ëÇ[ÿÎ};endstream endobj -1325 0 obj << +1837 0 obj << /Type /Page -/Contents 1326 0 R -/Resources 1324 0 R +/Contents 1838 0 R +/Resources 1836 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1322 0 R -/Annots [ 1328 0 R 1329 0 R ] +/Parent 1820 0 R >> endobj -1328 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [184.7318 214.5925 233.4785 225.3769] -/Subtype /Link -/A << /S /GoTo /D (dynamic_update_security) >> +1839 0 obj << +/D [1837 0 R /XYZ 85.0394 794.5015 null] >> endobj -1329 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [369.8158 92.1907 418.5625 104.2503] -/Subtype /Link -/A << /S /GoTo /D (dynamic_update_security) >> +578 0 obj << +/D [1837 0 R /XYZ 85.0394 500.2755 null] >> endobj -1327 0 obj << -/D [1325 0 R /XYZ 56.6929 794.5015 null] +1789 0 obj << +/D [1837 0 R /XYZ 85.0394 475.2167 null] >> endobj -1324 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F63 1065 0 R /F62 1062 0 R /F21 714 0 R /F48 953 0 R >> -/XObject << /Im2 1051 0 R >> +582 0 obj << +/D [1837 0 R /XYZ 85.0394 345.3976 null] +>> endobj +1840 0 obj << +/D [1837 0 R /XYZ 85.0394 314.7239 null] +>> endobj +1836 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F39 1151 0 R /F41 1208 0 R /F48 1228 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1333 0 obj << -/Length 2684 +1843 0 obj << +/Length 1604 /Filter /FlateDecode >> stream -xÚ­]sÛ6òÝ¿B÷&ÏDñAHžÜœºsIS×{hú@I´¥‰D:"m×wsÿ½»ØER”ã›fô@p±Xì.ö”œ$ð“—ŠD{3±Þˆ4‘éd±=I&·0÷þD2Î,"ͺX?\Ÿ¼¾Ðvâ…ÏT6¹¾éÐr"qNN®—¿Oßýxöéúüêt¦Òdš‰ÓYš%Ó.?þ“ žï~þxqùþ·«³Sk¦×—?$ðÕùÅùÕùÇwç§3éR ëS8²àâò_ç4zuöáÃÙÕé×?œ_·²t啉FA¾žüþG2Y‚Ø?$B{—Ná%Ò{5Ùž˜T‹Ôh!›“_O~i vfÃÒ1ý¥Ú‰Ô);¢@¥: -” ŒM6±©™V:(ð³R¦\Ï盳Ùt“Ï‹MPzo*|Úé|]滧.¨J;?ý±z,Š*êL;=­×å‚©Í«fE£³Œžy¹äQ*-¤ÑŠ îHÞJÉHu½-Ê}ÑÈv>.òù1`Ø A*PÔn½Ä#{†ë„J]ÔyXEí¨/®­´Q}òêó‰5C¢WÞDod÷ì(ñA‘“[ßä÷›7UôþMtèŽ 0h õ¨ïf>½ÔÙó¾ÛÅ:î»-Š>ßä‹/«jS¸­B‹üÆÎidçžÛj#œQƒ­{n«•šæôجë†FÕ O,—äšuq›UÞÄQAv¾0~\£^qÎ0Y,Š;½/vëHjïËaO¦p_²:œ˜ƒjóPDvƒí)Íg¦ï¹¸ÁÓ©”rÊ&õKÜÏz¿#›RÍÆ4”â~´ÖçŒÍ¨wU¹ŒY¢©x¿ëcö|MÇÀŒM,;CyÜ屺 ¤±ð™Šg3 gÂkKÉ ™‰ê$ß*›bw“/ŠzdÈ­ -kØIeTxó1@¹[”9wsšM€e¾ePˆZ$€ñ©$œ*@n*Fi)\~¢™¾‘áÒˆõ±¿£M2# ‹ „äåš´ØÄX>Të6_¬Ö%Ÿòšû¼²`ËÝEÇÈY6k{ÔL÷%爡*0?oþo; “Ç*†N,s¬nŠ¯Ý³éW”–/v<¨‰mÏñ0¸ÈŒÝm#º˜Å²*Ø0(hŽ¾SF³‰KîòdWn­2/Œ’iß;êjñ%„]íا!ˆçtÓà‚/ШõhzíÇ{Í–ª-ßH´,ˆEÄ »á WL®º+€QrAx­Ÿ@][¯r¦S”Õý-óuöé’1ïïB,I1œ}Â%ÓÏIš´>¶€PûD|6„·¨JX½­ ÔЫ Pñ;kãu7]†éwÑ©Q°“ĪŃØ%“‡dáX?€DQÓRJ–>¦ê.Ëñ– ª‰–})eëõ|a?Oɯ%$Zm°*ƒÌ%½¢Ð¡šjt Q·ÚÓ&˲\Ûýžób•?€ºÖa™ã â’½ˆ5Õ3Êëñ«à˜úobÙ‡4™Ï°>lï:¤¤»€€ý7ëÅý&ßÑ;é1†· 0¹- èÞ±° FH?ékeCÍ‚3|-GëÃ-‡”|‹";·(Ì]8ñÀ`Ü*âu<59â¡]U°‹ö둃âU÷jã–­hÓ6—I«8ÞÜÅÕëÞ¥9F§c9ÚÍá}§Fâhä´²EÞ_iÂîá8»š—wÞ -mô±Nùé–ÿ„ÿ|#Ñ.|®—PI"ß,çîÍ›×Z½ßá%í„NҶР7¤vA­4˜%ÀøÚ XŸ"$X€ °/ÁÜЗ`#-}d Ä+2Ò‹k4ì'ºÀéÆ„¸Q(ñý>«Oz,!ÄŽ¼!Eœ\3$dÑ(éÔ„3ü• ýëOšê öÂâ’Ö—ÃIÅû%"”ÜG¡ *–cvC;ªeÌ®O½šVñ®àKñLGÒvNc I8ÕXý‹#x‹ûÍú÷¨ƒàUè‹ì7Û÷pFíál’¾¯“ž½™ÚýåÙ|¸ š-¥Þy^Këõ&¬…äNÂ4UÆ2C½~³wzÛTµô"Ïê0ÉDZƒR8k 1u›$«Qú7ÏøK«$‹8Šy–îPª7rj&³®bZB)Dù¶HR`´ˆù:lÒzo¬"7>ñ¼ë¶…ÏaÂH‡8Tå~XháMH"í%ѵˆi}BAnêgšÙĵ¹§ªÃšo9x‚jÑSªâc4‘Ùk 1E`‚ÆúA1´)5„rnÖцKa¶Ãõ(Mx&w$j±©sØDÔ]‹ŒáûĶ!K2]P„H€ë106@·i@UÄÔlNP8Év¨¨iæX ++‘oV±ß×€%4wunP¨\hÑk…¼À•”ßðçòõ`í nJ]©@¤Qî/wWI, #F(óˆ· kºäóÍÉÇg–5JÂñ¬7-ð~¿0½sfEš}2«í\¤Ç ûÄ(/D •KË#f`‰ºo“–Æ …EÑ’LÌ÷†{nN¡¸p¬<…LÛ¦‰¼*2©€ßi%µÆmèä6ð† =ÂæéIcö‰ 0ã ‚eÙ@D‡ÒàF¡ãRjý mbzû€aÙÛDgŠ¢¦D1iëCgÑ2‰íôÇíA*v*Ãb ÄtTÃj7½ã}…Šlzü.Ü©ê k¹(Ûè®d—’%Ãy3ÿ$çxÝR¯Ð"\l tækMœ î¶ãý\˜à^{P+p­Âv†m{ …÷Z9/³0}ãÿZ¬,‡ø®ã [×ÑnY¶ÜRµÉ›4F¹m•(æ"ŸBPºq”ñú6/¿ôŽ^õ¶¯ØY+åJû€[@û;òqâû±R±â:Ò÷îc™ßˆ"j%‡Úªà¼–þòò&‰ä@Ptà¤Æ+¥tà—8Jµ1Hk¢Š};^=ÝÓPÊE©ÔrrŸ&Q|­Ó¹$K“À 9ÞrS†¥M,ÊíÅqÉ«ŠWCýÃŒmòª¾Ÿ.ºç<PÏ“ÇjHvö]ÁU½T`êXçü:Iï)7”_$¾zq,鬫ÑïúEÖ_¼—Žøݹ0Ä÷|_õímî X²¼îñƒK²\íöé|${EÉo’¼©öÕ MÆÃÜãäÒØC ¾nªgpF5XëÛ=Ndù£~è(eZ—IT+ì~†ôRÈ{uÇ +¼%·Ð7WpþªQE@–äJÕ¥Žì©Ä`ñ}8žC ú1T&zÄÐê1Ú³¨›^ ã6¨ +\·ûKÊ<¸É™„â(ûÔ» ‰£e¸Ý­âð()w õm÷PBZeáV/Ú›ðå1I×ç#vÑq3¿5¾6¼Ü ù]pÕ2h•&Uݱ¥}^êR|¨ÓPåýÛÔÖe˜Uk^þŠZ M‡êpù ¾¢:£È*Ø4T[ø6°ƒ{W¸wU6ª’/!—Ï§Ê hªÉz˜É¤X‰H¤Î"/ën^ ¤¬ß"®ï2-NOÕÓ>Àuå±&ãžApD_ Qõ²c6ó6,³oë0I¿%×Y^r˜£ƒ!ƒ·w?¯Žªƒ?7q–qw£YååJ4ñ'º#Îíë2©w÷<9ª8 SqÞË+üŸv¨A÷Á +Úøʤù¼dv­î—?fí¿ôÙ±|Ÿé¿S1.÷>(‘N‰(}ÿÀsõÕëÐõÿ82Z[endstream endobj -1332 0 obj << +1842 0 obj << /Type /Page -/Contents 1333 0 R -/Resources 1331 0 R +/Contents 1843 0 R +/Resources 1841 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1322 0 R +/Parent 1820 0 R >> endobj -1334 0 obj << -/D [1332 0 R /XYZ 85.0394 794.5015 null] +1844 0 obj << +/D [1842 0 R /XYZ 56.6929 794.5015 null] >> endobj -370 0 obj << -/D [1332 0 R /XYZ 85.0394 625.1831 null] +586 0 obj << +/D [1842 0 R /XYZ 56.6929 267.6943 null] >> endobj -1335 0 obj << -/D [1332 0 R /XYZ 85.0394 599.8772 null] +1713 0 obj << +/D [1842 0 R /XYZ 56.6929 239.3021 null] >> endobj -1331 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F21 714 0 R /F48 953 0 R /F41 939 0 R >> +1841 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1338 0 obj << -/Length 2990 +1847 0 obj << +/Length 1107 /Filter /FlateDecode >> stream -xÚµZßsã¶~÷_¡·È‹ß${ONâKiœÄufÚIò@IÍ9‰TDÊεÓÿ½»ØEÊ”ÎwiǤ `±Øýöh9ð''Ö%.Wù$ÍMb…´“ÅæBL í› É:³¨4ëk}yñçw:äIܯzce‰È29¹_þ“2É­U¡W³õ‹ò!”o`BçxUÎN ðݥ̦è¿ÐRTKzÙÖ»–tögÙªÞÑK³_ÑAÊ™i½)ÛÖ/ßà¯à.l„ [.ŠàÏ%©Ýü@-ƒ­FÎ2bªÜÆåÜÜ^}ýõÝ1~Àz!•!¼RІ$L_ƒ *ɳ,ÇY7â¬?äKp0™I”2ò03Zyuûϧ*@bÜÁ«•`. @¤À݃,¡|ED™{zb䇤 H"!‰H2¶ÇÎd)OÒgÄ"™¤mgB@Rä.?+:OeŒbŒŠ<£¨Èó^Th -wÖõ†¶—€B˜Ûø£ÚoæžGX…ðˆjÜsK13[ÔÈÞ~/I Æ}ðÃù·åâ=5gÓý–ǪXÀ.ÑÜóVdI®­î!N°‰–—N}ˆƒ"S ‹ƒÔ…²3½d¶¼¬”ìÂøn8}:S€›¢%Éy¶²Š*cp£>tæbb€‘³'3Û/·3œx 2‘mt/«Wq»ÿL´- z9¡³‰H­îÏçfì6%’,wC¶X[:zHIÖÐè!õñ…ùÒc9GlE yA*ÐÁà=›zÃ’Èhà<@׉(ô¿›-3ôBI#ŽÛO·7ÿÀWŒ‘ ý`VoUÝÒ äsý<Êy3X{wÎ<“²J¸t°öŠ(L˜¯}¬÷q&z#âôÛ]ù8b sÅDZ°Ë -¼®é².œ¥‹ŠÞ„ -"ã FÆG<‚Ú¡¨•=ıVÀü*<ÜVX>µ›˜Röø\oB‘£K¤«-ý2^íô-5អ Þz+¦©x¥`ôaüxÔ­ha·ÌáŽ*"ß®#éÞú†nx<(‰4´–Ì"¸©^ï)bO†Ä†$‘¿,ýºè‘EH‹Ã±bwió@¢Ê .µ¨X;à/<ñ·O¸Röξb’Ññ¸ZrÑxXÕð®²)V>‚ÑXÊêRþ1Þôñ"4WO%EkÔ¨žÿÁmÆ«n}2xÕêî4ºKŸWúúkLà_kŒ,ƒ˜û8ͱ¯¯þ*¯òîëŸÈ§pðOrÜiæ˜Ëý‚˜É©­Àû 麯X•CΡE`V½¿Y‡÷ä6ž£&Sšý–ï_AX, !8àIgSl뮤AáAýHÝ åg­6ÇHÐçÎAߌP>Û…Æ9dºüšç~Q¼Bíò¾!Ä‘‚Z>È¡(B0¼–<k¹¸(5´QeÉœuFé΀Ǣ0¨p.T¸“t2l¼HG8ã(:°â~øìq°'‡Cõ@Hײ9°CT [‡ªô+îWÐc[ì€ùî‘…μ·ÐBG#OD—ÆÛ«^}mé¤sç.¢fÆ×Ì¿µ{Ýýå[FEQ@ëŽ_@+<•6G˜I¡Óƒ8Š]8µ2Œ²sð›nøžB„mð½]&©„LäÀ¯\é‰ïã¤4ëkþ<ÞiÎâ¾ Àl°Ÿ±4Pvºì6MŸh&#lTË+)Ðô¿Wò%qˆ;¡³;äãèÓ9Gç*d˜ê‡ŒÀ…¦:†:Ð5‘kDóiܪoTýÔÍ}œ ~>·}#„¡gyÆ$i`Ð dLâ듳_O¿NFã!°\óăCàzæÉÇË«_JJXg_®Î//þŸ}çdrùåª$Gç£ñèêl4(p‘ZoU/,8¿ümTÎ.ƧŸ?ŸŽ‡ÓɧÁh²‘¥)/2m-È·ÁõÔ4b%ö§ í0pGõbB†–18® ]ǶkJ:øcðû°ñµXÚ¦?× X~‹ÔP 2:¡oøn=Û² ^gš' MI9’Ó출(‡©–Sm‚¡ëZÍ…s,$áz9HŸcY’ÿ2]S’¥\sü¨æ¨3ÞßlÁ3œvåíò²Õz èS-šÍDN¢»+1·2°,]­Ê…ì%E…C¸(ßÿ)‡ê+Íg8ŽyEË—º~™îl!¬÷+†;(‚.n°8ìH‹Õ gsÓ$!œd©äX1c|–±®0ržƒ>¶õì£*%ÙjÿŠQ÷9£žÑ ÷g4DÐ*RO‹:ŸXF€XR!i$u]AoÁNiLå +¨x@øCšg}]¾L;Û¢ÆUO¦,d,®#\O÷k¢èË(¹ÊÉA%Æøç*Ôr’(tp<ís"ùêX>Ž‚PÁF¥@N"Éxvr,ïfž“Bà… +tq&T”¬iÊ×uV[Gœ`IÖ,I:ðòD8Svª'2}Û›€eÃP¡;hªz¨ö¨?kªvÕ­ÓòU^¥Xˆi]Ä襭°[{)~ ^ÓŠVh¦­ª8Ò¡‹1S5dt7KUÔxµà±öA¿-ÿ_0Už<¶Eþ:ù¿3·‹\€¢×åçÆ÷ß¿BŽîHtîÅ}§ì½š +OСýJAl‹>E@£iu)A³r~h‚)BD”×A«¿`8¬Í »–ù9°¡xV{!ý~íxmŸòlµó‹mQ¡ì(['˜¦k•š'oµA»GNqºÈ›óË%­½©K#õûRtD_jý0})ú¾}©õ#ô¥èè¾Ô:²/m»%²]¨¯vZîtÔSízô ÒözÍQ-KX›Ë!Ëj\Ù¦+ôk¦´´AøœóÍUÓ>ëÿ7ò>×endstream endobj -1337 0 obj << +1846 0 obj << /Type /Page -/Contents 1338 0 R -/Resources 1336 0 R +/Contents 1847 0 R +/Resources 1845 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1322 0 R +/Parent 1820 0 R >> endobj -1339 0 obj << -/D [1337 0 R /XYZ 56.6929 794.5015 null] +1848 0 obj << +/D [1846 0 R /XYZ 85.0394 794.5015 null] >> endobj -374 0 obj << -/D [1337 0 R /XYZ 56.6929 769.5949 null] +1845 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F22 953 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1340 0 obj << -/D [1337 0 R /XYZ 56.6929 748.5275 null] +1851 0 obj << +/Length 1084 +/Filter /FlateDecode +>> +stream +xÚíX[Sã6~ϯðcÒ ],Ëš}biزÓeÛ4}J™ŒIЬcg%e!þ{å ‰ ˜$Û}h‡a"ëòéÓ§sŽt„=äþ°Ç"<.|ÈfÞdÞAÞ•kûÐÁeðØ T{½vŽN)÷ ¼á¬‚B†ØNGÝØs¨{òùüôì߃ã÷»Ã³Ïç=@êžžýÚ/JÇŸ>z‡ wO~9þmØMA‰ñþìüç¢F?[@ýÓþ ~Òï] ?vúÃõZªëňf ùÚ] oê–ý±ƒ !ónÜ‚XâÍ;>£ù”>ÖÄ?:¿¯+­ùÐFý0‚„¤A@W  ƒâLÀ€š 8ê¡î<2VjS|Œ©¶EQ-ÆÙÇEñõwñób¨6l+S¸_‹¦SéãaÆ ¹ã‡1Œ‘bâ†I²ÞèI·/rUôr…‹õü¸(½+ C˶‡²ªOçÆõEßu;Ó N¯€Qw²¨N–óK©k4SÛ X%f&5PÓX•(]Ú¶Hx+’UóÃPÊÞ@©†”¤VÍÊ\I3Nõ8Ik&#o±š¨ºÒ$^µ^}1˜Ê8*9I“©y#Y`S`Òè çÃË˵ÕVeÚV6V«äªõúÖbÒ¥žÈOª…_x]©`î|\@J8sHû”å@?åM +ίR¿q¬­!à‰{… R7¨Q†'<Á· J5xNUpH\„ú>T ¢.JrÑH5Š-x“¬´Œ“¿…«¿+W‰ ]ÛßÀõUi Ás´—6çÁ9ä( ^ÜM¦á èS4ê½4lÕüWkòõVžpH9ñ·iÀöóN!õ…x)ž´õƒS}—’ðF¢wi"±‘u繚˜ÆpÝbW¦‘.##Û†·ú™£ åLKs9;\»€àçL¬^íËc?ˆel(Â]7äNê$ùq¬_‡„BóX\aä.WåÍYmf4ó'ÑãBG“82f}wÌQ¬]-Ê×*±ïš´˜©¸Ñš^°AË+gÈiR¹=´R®¦þäZN¾€lMfãµ7‘Nîg‘ŠïÕU’jùìBZ®ùè¨ø=OKÇ<›/b9—‰•Sø#u6vyù’xQ§7àëRêUí柅*iÌxÙÉuåÖÿÐBÉ +¦Û‘ƒÁîºA/XŽŠâå¢Z§‹ÌZÍlo›Ñ·¸ÿgÁ"f©vªn”±òÖÞëèæ5EêDRínP²UÝÏ”6vœu¢Ynÿ¨ž3¶:Í\ÆWsµ‡Ö²ü“Üç§û$•ÿ§GÿRz´ÿž0Ȉ mó7åLÏïê9ù!9SÓc uÞIiÓÓû/¹îýP¸yEõ]š†dýHHå ðú¡)IeÜzÆüñEñ9õ9ˆŸ:endstream +endobj +1850 0 obj << +/Type /Page +/Contents 1851 0 R +/Resources 1849 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1853 0 R >> endobj -1336 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R >> +1852 0 obj << +/D [1850 0 R /XYZ 56.6929 794.5015 null] +>> endobj +1849 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F22 953 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1343 0 obj << -/Length 2667 +1856 0 obj << +/Length 2052 /Filter /FlateDecode >> stream -xÚÝZÝsÛ¸÷_¡·£f">Iâ1—8©ozvêè¦ÓÞÝ-Q'©ˆ”}¾¿¾»X€"eJN›tzÓÉL¸»‹Åo?@YL8ü“Ô0®¬ž$V3Ã…™,6|rïÞ_Ï3 L³>×ó‹ïß©db™e<™¯z²RÆÓTLæË_¢7yýa~y;Iã˜Mg&æÑW×oiÆÒãÍÍõ»«÷?ß¾ž&:š_Ý\Óôíå»ËÛËë7—Ó™H€õÒK8±àÝÕ_/‰zûú§Ÿ^ßN›ÿxq9ïöÒ߯à -7òùâ—ßød Ûþñ‚3eS3y„gÂZ9Ù\h£˜ÑJ…™òâãÅß:½·né˜ÿ:°Œ)nÄ©’Ykô¸Z§¢X¬•=-‹ÖqåÉ°b(êp¼1PÆÈÃñJ9‚Y˜Ãóµœ%Ž51Î<¦ó½F;NËL¬2 -ÎŒ’`¹ã¸™ÎbÍá]ŸÈÔLK@Oª¤óÌäóD0®­UÄÔ£Ý^>pß_määm ;šô6Ïú’ݦbÙì ã‰6í,ž¯óéLKeËå.o¨¨Ùæ‹âWÎe¾¤·EEÏØbÕ—¬4‹ÁíÞ Ÿ÷ùPÌ£§YSïwSÉ£EXÖ7(N˜T:ø®Þ¶EíÕÞŽ} XMê îêvMÔÏo?gV-QÀŽƒ“Ywœ¸Í7À'Sl3Q‘7Sx¼Âé8ºC#÷-ŒÛ¤cÞ:…<òóÙv[â2÷®®Ê'Ï^ÓŒ³'Žu@«X°$—Șá&Ÿ¼Ø»Û;!fð6I£Ýü ›®74ÞW[/ó¡(ó{tNw;`ÇhÔ6a1˜5éGÂ׆±±±Ì â«C_ÆLsûmd%1‹ÀÞ—ï4¬8•FL*!¦„}!Ä|,ô7M#1]¥ü¿Fú’Ϥ‘X(¦´±Îäu™y~auX`‚H NGäžÂhG3Ë:÷üUÝÑì·½Às3yÛÕ= KÑéf!·,<Ýe/t¹uƒ0¢„ÐÔ ùOø_Þú0="ýSþ:àüùCD0(wúßÙ©_q*D4f þb¥5|¬Tü-C0µä™o"}ÉgBÄpňâþcžSRÎʦ©¢ZÀÁ´Áv—UÍ -³|î*èùRš@³¥ã°ÖÃã*m!ªÏÑV¬^ªÏ€®Œ_q:<ú'üu ùöá1Ä¡äúC1ÒÏkHÔR:0lÁEÌìe8þYW95Üó)°Dî€ò]ÓÃjGAib¸3  º¨8ŽÖYCÄ&_¬³ªh6~Œ >·eærØW¨8‰VÙ¢˜ -È™mÖæ4õ‡3Å1uV¸!eZ eQ›¢õok¯„R(²oê}åë•_PgKÒÒ®³v,wöt¢7¼ÉH¢|RDóÔ´ù ò<̮견]Fw«\çç¥a“õä¥Ôôü£s|§ùSθ4¢ bkíøåÎ3Íú\§ÁÐq¹˜‚ QÔëÆöWZý‚òŽkDû y(ËdbŽÔ¿Í±¯\±”)vJ&Ñ}Yße%M•EÓåNÞ^}ðÌP§" @†õ¥Ê69Í4ùî`$ýÉÓZZ阸C“Wžáúf~õîDo@CvŸ7¾‡|#1òúØy\çUþàª?\mqÆWÞ¼5Í.êíQ„IË;àsj3àÂ5_¾ÂbŸú(rí@A· Q õ¤ö -ô[¾$Ž°~ ï;¯éúãX0é‹Ú=—L¨H îì3&ZçåÖ“ÎxæU³ïÜŠóäm `çîN€´Û»ñ·$Ðÿî±(K¢>ï‹Å' Z^¡kAò½_ã\OØbVâ¥É hûlìzqãb1+A$æ8¼iã.Ú݇Z¢6Ùw9=7Fœx,PRy¶XûÙ2É9³‰V¡f ãë(( Ô‹Ô„âß4©p™­È+¯ž2^$Yð9X”y¸Ébc“áñ†-'Ü9¶R§x`Mz5pòù*Û—uE“Faæã6ºZÑ XöÜ"N™”&þRG$pÅõ¼ó(¹hHå}ñ{ÛŠŠ¦²P¡²•.ªžë’Òew@ –Ÿ Äý+[xÍ„Eœ©U»bI×VÈø†t kGø€0tAU—'ƒ/u-zî€8æèÉ”òØJüx–Êèïkt‡Ò|Ô ©e:}/8§½ƒGø3Ð*,ÒÞhª¾@´õ˜V -¯ê±=à1 Ë+ú~@‰„º¼®ùQ^'§kØ€iÔ.­‰ _7ž›f,ƒ:%¿ Š’©Dˆ²}nŠnt@Ü9µ2T ˜éªЇ¨ÄÑÊ]Üœ±™gƃãÔ6¥çºxÃAÑöçÜ©‹Íì{ùfÛúÖÂP¿ÂV¾ÑåiÜ6æ³EF…$¬~q²û1Ä•ê|÷Ñç:Ý}t\hú&û}š<òY[lòYQ=kE’”Yëó–t\#¦ `-³åI:´åªºƒ®ÑÝèu úhª .âG©Š®í𺬫{ºôkŸ?‰¢ÏXQª'Z¹)ª}›ûi¦”*[’ï6ÅŒÎ9ûb‘Ñ^AT.[ÎC~6Ô;àSHND§2 B¹†ëQC'>çQlöJ–©W›=õ¤j®Ž4žG“Há©ÒÐÔã:ƒ¦À5Š¦bYŽ£)fÂÀuì¬%׈)C4 H.©Úr@“èÐ$†hˆŽO„$ž[g{}hp–r]‡,Ñ!KçtHÒ.ѵQƒK ̵ò(‡|9¸âSØlýÏ %àn!°Âœ…VŸë4´:®Ó‰ªÞ·Ï°UPÇÐœ5¥ã±eˆ-¨{080æfßzpA ×H¼ô.°0ì§*é®ÊVŽ›º=G~ aÊQÝñÂÀ÷B@ÝU}@Y(JÜþ§€ú“g+¡$ƒÂòB¶êsTà:­F!mÔƒó¦t\#¶ !…Ÿp“#cR<@Jq>ÈW\ò”¯à9’¯`¡ËW<`‹Öº|ÅÅ0_ñ/¤\¾â^Î%`1K ‹ Bþ?r„¸T/õV=¦Óð -L®‰ÏwEVÎð7¹§Ù¿°£*æLÚØœÕß1=7`€©Ø0™@CÕ·àc™= ¿”<|˜€—!™Àôl¬—ÅÂ]ËÝ;g.½ÜdMëR•ýõ’î·ðtŽ–ÄP»ß8a²XÑ„OŠ¤»È¼Âj¿¹ó_6'3c˜R‡&‹Pµ&›SáwÌ{‡/-ãè/ûn¾Ù* 価Ÿ<­û¤:x?å¿FÊ”>Páœÿ-Ä•FÚåt–èè;/­ÊÛÇz÷‰wYµ|,–ízô Ç|je„®rï>Ž"~ô…¹Î - Ø‰Ä‹?Kã-XŠðçÀc{"›#™W$Ý«{\ãuqᢇèÇ`d ߆pÐÐUV†»rS€økeþùÅHy÷³ËWÿ%Hï«zÂTšÊq¸+³TÚ$…î7êØr£RWõdÄôfŽ¢õendstream +xÚÍXÝsã6Ï_¡GyfÅ%©ïÉSv›ì¥s›¶Y÷åÒL†¶èX­,¹’¯Ûëÿ~AʫͦÍË‚ ?¤…Çá'¼,f<Ì#/Í#s{óÕ÷aîÙ°2 +¥ÞMÏÞ^…©—³<‘‰7]èÊÏ2áM‹;ÿý¿.~œ^ÞNs?a“ N¸ÿîúæ;âäôyÿÃÍÕõ‡Ÿo/&iäO¯¸!öíåÕåíåÍûËI ²XÀzi5|eÁÕõ¿/‰úp{ññãÅíä~úýÙåt8Ëáyñ ¿ŸÝÝs¯€cÆY˜g±·…g"Ï¥·:‹âÅQ:Nuöéì§AáÁ¬Y:æ¿8ÌXœÉtÄ‘8p Œ%‹„H½4ÎYÊÐxðnÝ´ý$H8÷ËõîitNŸ{<£ˆ(dQ",cIkIdÓé@U}зªîº ºfÓÎ5Mît÷дus¤*ú£©uÐõª/»¾œw' +FÌÔˆC5…êÕLuÖ€®oËúñ¹ÅG6¬Ê:hõ¢ÕÝ2èË•URoV3ݾ\‰úü”ˆ/-éÛÝkíxŠMÕ—ÁJu½[ô\@²‘t ¿ÎÝ4.F{÷‡Z9 ïæ•ê: Ã?ÍÒQµýn=Ä03èlfçÏœEUU³ ~ßèv甿( TÝÃJõóåCè#þ_/ðO§Û'€¼U¡»#ÅwCbáü‘¿cNùs{‰‘½ÐS£ûàÄÞúû—âo'ÞiœåhœÃ×ÆYžÄyÑ´[ÕçÏøÈŠÐàó¦®vÿ]”m×ÃH¼÷Vn¿Ño•Ð†úhûBWúâÑÔàÿ6óNì<ÿ&:Þ^Iá ìšíˆKRŒ-Xfй5ŽÚí'€¦^麧áwúÎe]â¶ÄQuAÄÏzÔÃ>û懈X‰è`&ìNÿvšNrðóò뤵 Áaâ…"ƒÃÉüEÍCûÎããÞþ93rë«ûÓ:ª,éV« +†#2‡‹ O^°÷Ë,Ëàèn#¹Ð¶rµ<O#–Š<ƒ=PlºDÏæ®x½TU2Ë}Ec×^ž7ëQÍ‚„z§;QD s,¨Ó`XÛ²ªˆšé±TS³ÊF½oè»n'"󛧲°jÓ/›¶ÄÊøäXu·5UdeÏN p›ð}ûºx!0DžÀMYŠ¨¿»â«Hs–ñü«€„IÓÄ“YWG@W©'=ÁÒPØð_`LR+kH¨Ì/;â(úßëuUÎÍSü‡ù$V ÕHJ°/ó]òœ¥QY3hm7bm˜²T:k©yƒ×z^¶šE)Ü}³è=X‚´AêÛò&·ÄX5t]ÿH³¦e ›. +fåÂ.p‡1Ê+Ð/Uï(»‰s&ðæPwÇša¯æ½S`°ø›5¤]VÒdâ’m0$q» .Cî´Þ3ÖG ¥k²S¥jb«ªkÆÒ ’0Áµöú‚$nj¾°k‹d6DÊðq¯Œ€ùïvÄ+ôBÁô Eß½9ìåÜÀ£y¿ ,_¹©ð©yËTúqHÓTàK®Âä¡[. pOG†•3+8_ªúQ4 Ú„2eÄöîl78ƒ»ÅμXÂ(Bì‡QlD†»¾#w¦ÎpÎŒ#d!hôB|&Z#[“¬sÚZ›uÁPÆãȇG–qjÑ;®EPda´' +bye™îZxdqz°|ß`Nm1~EBP3”—t˜TDζì—DšŽ¼é§ëDý¦whVÌsÿzaÕ’.ÌðÊjÃsâ×ÄǤ~ñf4ñà\ éÎÄQ] ãÐö%œšY‘-´˜~XØ8fS Cp1l é‡›PUEªìF]FÈĈ‹˜ZdÈ¥µ­j S,gŸ8²65Ø´ +|}¿ +á)ÑöXŸ“ndnÕ­±Ï©—\P_tÍ›T™ÂØ.$cYÏ`Oßfaœ‡k >ºèˆ=@i´h³&!º!^K«r´€ÖP+mÇöå~ Š+€01·N"Må¨Ý–E¿D îß4NÂÕpw_áŠ*Õ£• ¬îÆ=óî*R˜‚F]wÄ2É œå¦¶YV¸™…•]6›lëèý³Ÿ5I­M‡b‡|a‰Å7MOãÀšij¡M`‰CѸß6A­ˆ åßT7œêæK½²Òö*%‡khAaú£”¼"¡ÐןGæVëJ¿Ùß-¡\W@›¶Ë\•Ïì¾æ‚p|÷‰Ëàá`¯ú³Ùƒ,GnIÆâ8“îÖQ>.{Úe]©¹výCÛ{…ä,ŠåÉ3Éf2Ôehî=õW•µ) @)ú ‰¢Ðc ƒG¬$ã©Œëß>€,ePe+¾]jÛ_¾Ô +PE{Å#Ú¤`ðHtî°B'0xv¥Ççþuc€Õ‰"ž°¸Û†ˆj‰ÛÛ ŒMþ.³ +¡Ãð ™4úØ8e ÀzÁ! »dóªCÔL/•»ú?™?Žêªf[Yº\Ðw×lì+bc³ß–œMѲՃbéŠ êSÜc¤(máëØN@Éc&sÇŸ÷ö×="|§žQÄÂ4ý³™{Î7¯þk{ÿ¿?\¯áæ'‡§Çñýœ',“yê…1]”üKo¸?ÁØñÿôZ<»endstream endobj -1342 0 obj << +1855 0 obj << /Type /Page -/Contents 1343 0 R -/Resources 1341 0 R +/Contents 1856 0 R +/Resources 1854 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1322 0 R +/Parent 1853 0 R >> endobj -1344 0 obj << -/D [1342 0 R /XYZ 85.0394 794.5015 null] +1857 0 obj << +/D [1855 0 R /XYZ 85.0394 794.5015 null] >> endobj -378 0 obj << -/D [1342 0 R /XYZ 85.0394 460.4475 null] +590 0 obj << +/D [1855 0 R /XYZ 85.0394 385.7919 null] >> endobj -1073 0 obj << -/D [1342 0 R /XYZ 85.0394 437.5053 null] +1858 0 obj << +/D [1855 0 R /XYZ 85.0394 355.678 null] >> endobj -1341 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F62 1062 0 R /F63 1065 0 R /F21 714 0 R >> -/XObject << /Im2 1051 0 R >> +594 0 obj << +/D [1855 0 R /XYZ 85.0394 355.678 null] +>> endobj +1859 0 obj << +/D [1855 0 R /XYZ 85.0394 331.2666 null] +>> endobj +1860 0 obj << +/D [1855 0 R /XYZ 85.0394 331.2666 null] +>> endobj +1861 0 obj << +/D [1855 0 R /XYZ 85.0394 319.3114 null] +>> endobj +1854 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F21 930 0 R /F22 953 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1347 0 obj << -/Length 3382 +1864 0 obj << +/Length 3279 /Filter /FlateDecode >> stream -xÚ­]oã6ò=¿ÂoçkVüÅÇín¶·‡ëvo›â€kû Ør"Ô–\KNšþú›á eI–,Z°ø1$‡ó=#ÉY?9³©H½ò3ç°‰´³åö*™ÝÃÜwW’ahчúööê›Úͼð©Jg·ëÞ^™H²LÎnW?ÏS¡Ä5ìÌßýðéÃÇï~úòöÚ™ùíÇ>]/”Mæ>þû†Zß}yûý÷o¿\/dfåüÝ?ß~¾½ùBS)ïñíÇOïiÄÓã̦_n>Ü|¹ùôîæú×Û]ÝÜvwéßW&/òûÕÏ¿&³\û_W‰Ð>³³'è$Bz¯fÛ+cµ°Fë8²¹úñê?݆½Ù°t’~2J§j‚€Jõ˜Ia½·3g½HµÒ€õ®”¨yûPàe`‰ì-Q),Áƒ´)öe¾Yü~(öÏ‹}ÞÆý3œ*µ¼ Þµe]½¤œçTVmq_ì‘ „Ʋè.ÉH®hI$=Í­¦î¤@ÿóJÉðÂHíÉ._þÆ¸ç ˆë‰(Ó“5jH”SÜ•t#ÜÌù¹«›¦¼Û0(D`5ÏÓƒi$&åP ˆµ_+õ™Kí¸äÓ·ug’¡W=F#¼,AƒoÐó»CËÈñ¢ºÚy¹ À%ÑéHI"Ça“ÅŠ‚êkbÜìŠHAó°Ã'Çù8äy$­¸/ª%fàB6ÐÐDVó Á9R´œÖy ¼VndȸuzZ¯[,46u¾*moj2)L ž!,ÚžU “¥Âû—Š}¨ó -ÔA ‰Þi-Àç!›¾x|5qþPN¼pκ!AƒŒìeã؉dT˜†c€ «öH…°ÕS!'‰ BظcȾ -!è"ÍÉ„t©rž’ŒÀÃhÕC¶€d­i›(ô,þXBÐÃü_ùO96ŸÊÍfhòiÏ5†Ò‚ým\7(%±sUéTƒµÕfw‘Õ«Tøœ§V/Haê‚F¨¡FOV¦T&ŒÑò2ÔÃ$R ™Ï¢°Lz¥!è+ƒ\’ÉÑœc‡d[=Y Ý -ŒXqèŽ!Odo°~ÏF35SãàdM±âç)€W†°IÛnëPê€>FNÔb— µò|eß**F¨”Oe4ßjÊf ï\Úó -:y•Wjù¯0‹qìdÀÉeÙ v«ïÀÊœ›ë:ÁgH®k©&|†¤Z0NvA½<ú åØg`u¹%8ò8B~Jª‘wè)Ù; z‡6}&â11 Òcâ) G¼×\¬í…Ljz¦(úÈô ÅñšŸ9Mа”ÐÐ|&0@qèLj ­Ñ© À«Ë>BîöD\ÄmM§MÙn?ªüm¡.æÒ©ÊäeÙ‡:o#;¨“<³òeqj" dî$:¨°Ê£H¼ -‹±0Ñ\£Æ®¤ƒV¬@¬éèc¤å<_­¸âÁÈ%j¶™ød“ С²€åó£¡Öí»ÏÔ-®Š%¥Žâ$ørŒ‘öw5ªXzZ-Õš2Òpžf¸þÔ™ë9½êÕ¸FVkˆ†¹\#ÇlH“ÁÚ~½ú|A8¦G 7S•zª¿Û”+rù&8èóÞnþÓûÏ4‚ù›a©.Ô×ði AøÔìÁÓã™°8V!â~«g°Xå’æ»hæíZÁ¥Ö‚ï&7‰ÊHå®ó©.¿o¨¦‚ñÁÅÎÔæ·ä7›€ŒEgÍ(zØ$ñ‚Ö¡90±¼pÆ7†r©¿Bór-C± Úø²q¿Î—¼æ¥ÌrS7‹©ÛAˆT€ j„Ã6‡ƒ«Ex¿h·ÁœÌ%ÚâžùnWä{-+>ç÷î­qïLÖJd*¬L£o¬æO”ãœ0‰„ñ”)öÀZx æz蛑µŽ”FúS_}‡ÊÞ¦órMÝ¢Pè€pùËK~3'†‰æ¢é¦% cÍ¥÷Ž:A«g§Š8—ÌžJºH›ô ÈÉŽ©7Aœ‚À.%Ž&ø­ð0 0öy>§ntÀ%!`Oq†k036Ÿ "”Íß:Âp>)à6Ô×RDŠD¥fì=£L@Ìa²QTöT¶eu©Jeœp6‰d7>=œ\ª\÷…À~ªæ ¡uj#r>“û$ÎÇ8öÖoà ¯ËæÀô èÝöy|#’„úó¦8‰â'eéM×Kp@ˆ‹ß£dÓp€‘q68Àúì^´.½¸W ·ZDìB%›%ƒªãÕz–9¡øUm`³¢’اm -YRÂo݈®©œß¿šŸ|Ù‚µq¨„ÍᲡ7û}rd|ˆö’A;ÜõHƒ0ðÍÇ­š½¯áF³þ¥xãEçp©ôä«môLRY˜„òÇzƒVU†*ÄM~®„’šTž‡FÁ0›2ÄÀ0¯á¡E¯á¡Aqȇ@tx¤h[R=è±ÆQÒ): >{謯!Èa»:r-9Œ"–×*™ÿ†hè©4© -ß‘õ¹ü×GiSŸ€•?~Fô×Ä29`fn*`©^x- ê4¤ËãêêŒ![<¦'¡µÎðuZ:ëŸpZG¨ DBÉ‹önˆHWÞi([§ &räT@hþUf8E‰ïª¸oŽ¥©‘þ<)lM}å®_`L|ÓQjz6%»u‰}u=¨ ¬‹P˜´‹×¤EÖà;ß‹ˆtP˜ yg„ñ`²¨¼Ewì¢Tì«ð‰vi¯Lˆ“ƒ÷ÀÐÇ8Ÿ¤óN.F6e^™¨j*Q– ii÷ñÇ«½qªã’u^nFzò;ï>¥‚}ÿËÃÍun¢ÇO?ß_Ïu¦¢»Oÿ¸eèû‡›Ÿ~ºy¸ž'E–D~¸ùçãíYYã»O÷Sò㢷w··÷n¯üñêö1Üe|ßD¥x‘?¯~ý]Ípí¯Tœ–E6{…'e©g›+“¥qfÒÔcÖWŸ¯þÒÔ)þ]Ä™-ÒEg‰1—÷å=ì+ ¶i¬`ôñ¾ó"‰­ÍQ:ÊÄeŠIFBI´ŠKXh–gelS’Túaÿ„¬y§õˆØqn4nD7ÀË4gZ€lôß®­×ô2ÖlšµÛñðÐ1ÒÉØÚ½Ô‡‰ï,£úKUo¦VN f`ÂÝuRDõvÝTn¨e®]¿áYáTó$‰Ë,Ót¼a«§ºŒî?ã³ÉUGÏEσݒ¿n\?Ô;FñuÛ´€u‹ãaýº^û0õÑØè³ðñôlH‚ÇWIäüT­TÔvƒ`ù½\»`ŠlÝnà1<bèˆøxÿùïõƸÑêaÑeí†ýßoëªùM)]Ÿ•-”Ä6Ãûdc#k6Ûu½û»¡éÚxê¦Ä`‹ñwNuU®eÜS͈}_/ƒ»!¦^ƒê´ eA¯hk¦Ì¢e·cÔóz/Ë°¤Í‰¤§ŽÕàÒÅ4±ÈUšÒŒÑÈ €ú˶¾N¢¶—wRxn\|hÚ¦}–™Œgó@„_4Ç}voS¼i#gIu“ëßIØðlݦöC»ÔT¢^,øü}Oj(¸ Ùï±±[ºÈÅ€q±E\uírÂÖÁäà„ô9MÓèqÕÈúûÞ=ËI…W™k ÎS{ÌiRéìÔ e +³ !’…@[¿2ÇAU|ÞïH©zð iV2gpœµ¡’ý~»ívC?)fÜ»°ì#"Á,"‹PË: à^ÝÛu’$xÙÎúIHeG€ÌûŽc’ÒËpÃεý²Þõ²Ór´~P¬ù”°IÛ´õŽF[t4ÕzOÌA<[¨×8|æÁppIo݆IľZ5kQ‹–1¤D@#~ÕzW5Á8tš«hS;²Š\Ñ<¼?¸ b# úõ¡ÊîѨBsÞÉôªÛ¯ >×´ø!d4¡^›aåéÚùÔADȪtnùVftÕž±,_„ð`8ȼ„÷è4ÃÛ àIóÊìÈ àÀsXp¬4)Ë@·]Ó²ˆÙ4_Ð:¸ñŠö2ânðž8ˆŽðÍ_A—Â1b…¢ËÑÊ«fRÝG +œ*´VYjÉÃ1VG êÇ<|ˆ?¨äG`™f7ÃÌ?L8bT”­\Ï‹i∢ŸÊî•lžÖ]à9“4rë5Kˆ3!gP^–=ãY˜cÊ£3€œFܺ捻ʑ…"D¼o6Ž}½ø_‘|§L…;eêìN_‹ŽªÑ@ŽŽÐI ¢8© +'qLˆ?Ø¢Û8>Eä‡#åÓåÓ ¾[ïÑ¿†Y§sèëòè¹yA‚à¢Ã0‡pA\BÜ#¡áXŠÌPšjOi¾S à x4¢Û«n×`ÒðR{椵Ýqœ·yæLæ3DA·ŽýÀº§f¯ S¶»æER ˜R¯Ýî~Ù÷óét×·6z¸û”IÁ/£°+˜¼ñ ‰ ž§zÀXq|6äÖ°ìœÎÃ÷É¡7í»ÝÖMÄð2!j'Ã)µ² ,…8àø”J|À'$2õ®uk¦–¡g©¤`Rsø÷›'4Dz&k † /l¸™ò1 Ö±ø´23…‰ ›ÚÙ¸žùÆɨl¹K–Ä*ãúì¯.ê§\*¼4”~¥.ìtáUXffJÈš bæÊ/(­MóQùU˜£)€H½§ƒ!ÊÕs¨Â +N°éütžg¼T”“ˆW‚Zvëu÷Êðõ—I3ÁÒ s¶¿aòSúÙeX:ľRÉáJ9?¸ú7~ŸŠò äPZ’®´LLÉ×äQ Šƒ3X-„Pk @pŒôaVK( ²DG¯+òx‡Rb¿ëÉY"%žŸm]å;È䉒TñnÊ‹ý¹¯wrCQõ«Í¡ZQÀ€[¹1?‚<ËP—ž¡@»î€cP…ÓJ5ád³'sªL¡U‡tb-½KØ¥".¬5.0`zÂh’a‚!âÌæ…PMaƒè–ü„ ç’°Á\À„×hZàïÆqÈ"„³àþÏ¢+óüߤvYªDí2,å{Æœs G_ÇÃâÕÀê§,‹ËD{‡*üÃüÄÕׄقÉŒ‘IÈÝ󕵎ê.,¥UVÄF•ÅIiE2;ß0M ÊS™,&ƬêØ:™WsOu’÷ל;Jó!* àéK]ÎER.à9€Fúù(-†8#I¹8W¢^ 62l‰”kB–¾È7è÷°Ö÷Õÿ ücÌÃCÏ(¿Öœ SÂ^mÕT« ý‡¾®=æ1‹ýf‹îîBó†3dÍ“£š_ŸÞ&$[äq•¦c×.*™ ,žžc¦;¡8µ´Í%x¶FÂIçŒXbeYÒá!Y'¹Š3{"kX oõÁeÀ,v,ž⌄ä”nàø ó‚[¦‰óTû§uS1Œ<š´Î{JÊ ¹X´vÈ!È[6” Á8éI\ÇÔ Ð°M× ™dQ©–lPñD¥? :.ªØiiÇŽ_Åß~¥VÑ!6bä3îJXŒÞr¬Y5OÜ[ y­¯ U5¢|:„˜~Ûq[„‰(ôp;y´»_>ß~œdë禭¨­šJ¸€;JÔMÅc‡[KÔüTÔM!7îxØwv5Û~ݺ°‰«H;¦°î +)ZEÛµ#zHƧ9ÞÁûq¼ÓÊ·OS¨wï˜6‰°ã²,Kçy] è輸¨O·hª©c‰Ä„ë¨? +Ráa¨7[ìn¤:¸(Hr[žv)¥Jli5K©·6趞k`Ù +6ß±ùO]¡"LHK1Oâ—mÝÂûì%?ï~ÄO7¿<þ0YIÞ:vn' ÄI[šÞ5‰.½5Q¿]¹÷¡„z®ÛŒÝÓ‚3Ÿ*[©ˆ½kGøصJ €nä–R°3§/4ýÅ +`œXc²~¨ˆ‡™²Åÿ±h˜r©H ¬p“>½ëÒl¦MÞ™3¡n÷êv‹‰`çq®àÎ!ù7¦Œ~ÁSä"QÞ8Ào”­*öŒ‘F¾SùnÎt‘£5IëGé¯_¨D»ØÙômdÄÇRÊ_o&âce£±ã\åüî:ó*8}uà ÈB oÛ©œ øV@#s/ó7-b›þÛVåäøÀžAîb#7±~VÆú  >mËuœ—Y~Ú¥›<vÏ‹¢8¤‰ï}àh¿4‹smŠãû`<žhá§1$Žgl{'½WɇŒõ~ ·Ý’Åcƒ¥c”ÅœH$° v9¾xâ‘Ê}®8( +-$ŸÞxXèòЙË)Ÿ%M±Ñ§¥ º©d9Iã ÷þ+<€,7â'xáØ,†”;;VÝ|’lž[‰2 9ó¤:‰Ÿ8Þ\7½-'…—Xp !üúÁ5ú8ÿýņù.|€”0—fX‹Å6IË“êêĘS“$N‘Ê`k¢„‘Î8¢8©2ÒöÃ^ï¸_aø_‡Å„ÎBTåv5ô«cžx"N’¥ï~ŽôÿrËsœG|cn‚¿5jBR&RS¿HÿÂäoþýËáÇA&Ó¢Ð!:~y›IÉ)ÿJ}öëœDÅP–hO5:úÿ_A}ˆendstream endobj -1346 0 obj << +1863 0 obj << /Type /Page -/Contents 1347 0 R -/Resources 1345 0 R +/Contents 1864 0 R +/Resources 1862 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1322 0 R +/Parent 1853 0 R >> endobj -1348 0 obj << -/D [1346 0 R /XYZ 56.6929 794.5015 null] +1865 0 obj << +/D [1863 0 R /XYZ 56.6929 794.5015 null] >> endobj -1345 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F21 714 0 R /F41 939 0 R /F62 1062 0 R >> -/XObject << /Im2 1051 0 R >> +1862 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F22 953 0 R /F21 930 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1351 0 obj << -/Length 3017 +1868 0 obj << +/Length 3218 /Filter /FlateDecode >> stream -xÚÅZÝ“›Fß¿BoÇV2ßÀùÉqÖ¾M9kßzýp•ä ´¢Œ@håêþ÷ëžžA !¯SÎÕ%U¦™izzzúã×£å3ÿóY¢#&S5‹SiÆõl±¾b³G˜{{ÅOè™Â!×÷Wß½‘ñ,R#Ììa9•D,Iøì!ÿ9xýWnî¯C¡Y`¢ëP|{÷¤ôxýþîÍíÛO÷¯®c<ܾ¿£áû›77÷7w¯o®Cžhß 'áÂonßÝõöþÕO?½º¿þõáÇ«›‡~/Ãýr&q#¿]ýü+›å°í¯X$ÓDÏöðÂ"ž¦b¶¾RZFZIéGª«Wÿìfí§SöS"‰Œ4ñ 4‹$Óük–•‰µb2½,ƒS‘‘Q2½,‹¾c Ë‘þ‹±¨38Cef¡ëh-ŽÇ+ÄŒó(…1<_Îud„Šg±Öpè†øMlYÓHÅ-'‹´ -Ä#ÇûëÐðàþÁÍé P)t2‹a¥D -k›Ùo31•¦’¸´ÝíÑ -và»Ûµ˜ýÐÀžfÃmyÉáP´Ý—·å¶˜0Ð@2`SVçÛåu( ׂÍŽ^òŸ<¨›Žöe»"ª[DdUWlу:ëÜX·½æ0S·ËkÉœF)m³Û.@P*…ÝÖ.Ïíò 0ÄÕ‘ HÈÈ$\DBëØ`¶Ùl› ¨ÍuP®ªÃ5øt ;Ê‘@y4×<ØÑ„Wik,$òbSÔnp·ij\•uK9µÉ©‹®+ëG°cœÀ2þÙ¢ýönvlž-pŸé ÍhŸxHü˜ض½l‹å¶À×ßvt¨;3:õK•Æ³r6 Šo‹3™€È’NxÌß–B‘F8 -¥±–ÓÙ›E £À'ñ1ºùDòî¹ìÁ÷žÆâ yÍ¢ŸÌY'öffÃEÎ4ñLªŒ¼/1‘‰c9Öå•õ`[øÚ«g߬Wƒ¢ ;˃ré¸VŽ½©Q•mWäD—µËaCƒ–D¼ÓÅÀe3œhŸ¨Hqå?[feÕ:ÅÁùÏ—Q*cæ# ÕâBARND¬Æá|á@¦ÔÀJcs&~W¶T!gœy:ùŸGU¹ìD@ ¹¾àEžë<)>v#8zƒGÿ%ez® mFŽ”‚¿©ÄŒÕùÔ¢ $>K$éÈ¥püèR0yt©–¦7‰-Âl¦m±À™§²Ø·N¤ýÆ l7Å¢ÄTdf»Ué„åÅ2ÛUû -ò×¹‡„51zä u3qè@ ÷¾ÔÀþ¶P¡ -:ú²£ç`EͦW`Å"ÕNÐv>±V)©<Ï/L³¥µŒ»„‹f½Éºr^VewV~Ñ u¬"iÄ3N8äºì„=Ù«+—‡Kn§4rê//ßs=³>×É•LžQàÄžFFRîì™à’ë²F§“LûU¹°PCU³È*¦;œÊòœü®m=ð„J4²6›®lê¬ÂÚïŸ~ø@ßlšmç˜÷eåÏ WÑ4”²SPR \|¶¶²Ä îÞ?ܾù®Aì±h!LŒ‘Áƒõzœèé8wX¤íÔfSd[¢!/[™®p™*{òd±}Âøÿ·v‡¥I#.z ºÎ Ýo§üX&‘Òçë?°@¸ ÕZé“°[TÙ#JJe>­šR"N9×ÔP†¤ªªÙ‡ä -ºè4‚ºçcŠÖ² ÷ƃåÚ2Õº¨;÷ZtnÍ4Ì -àsj¼!¾Â !e&¾|ù=fÖ3€@YçÒà%;§Ã"shÌ€XZŽÑÜÜ¡±Nl[æyá"Fíè±qÕáW§]¶Ì`ŽÅ‘ _k³(¢À=ËzQíò#pœ*ë“\+óõæ`)ó'20=Êß—ÈkÒfÚø`¨ài3!²§2'htãƒ5–þó^ –L‹³NDÅàt0€„ ǘ±×»4¹}tåâ~xµìùÃáçq|.×ÖˆbáÊ>(çüý,¡hDÈ t1ÃÎJÏõŒ"}Nc@hîî™æüU³?Á(ÙSVVÙ¼r¯ÞÀ8Ó7Ù¶¯uSŽÖå,xãÛÑâ÷l½© -—b´¬°l–lœEÖq_²J@Z¤ÓHÿ¦Ç6« "¥ˆMB¤Ño^ýŸ—ãÂÈ/EÐP¬‚œÄ^ž-¡qØ-1à %NŽâdÔŠÞÂRpu8DÁ„#Ǽ‹ã”wq|iÏ¢YOaV(½"éï¢êl]äSVã¹\/*Ü8¬`Û,á®ð†Êþ@ŽçˆãÖ,íß·hîml¶i…y™Â/(™@{*>v{thd>®+Š>"ÿ³¹F“©OøìOU<æWÿ‰ÄM¤J¼i¦ó/Mbiþdþ±¾^,ì=;ã”™ðÉŽ‘ÅpdC÷„§~®A -Bëÿ¥c†ŽŠõI¿w»ÎbÕ4-Å!¬fS,Œ–6Þa4'ÃÆ -”Hã1šecEÙ˜(,(* ¸ -”í"ái%»eåZJ< DKÙßìþ÷¶Æ1›bµ¯£åÎ¥;kDÛ :§Â…M7íK÷Ýr xj¯8Lå‰=… ‚iÛqe\ŠÃ¡Œ£{"` =q¦ß³}9 ¾2'~1ûÈT·{Û3½w¿JÁGÔ4ÀØcÑ ¥šã—§†$iù‘k¢M@oÂKÞ_üH-úuaxE7CÚ…7<Éb–/{ÌÊo¡¸ -îš®€œ ¹pÁ|^´%i䤹ŒŠ¤ $²ªmˆ}î¦è˜ -ýçM]¹•íQL'“_éžK ÚÖ‰]€`&þxg¯zìQðKWJD‰ã<3æ°=Žhº}lIn_¶ñÅ™}Wç™õc²‰ž{Œ†#`Û¶xéŽwUÆr(kÐ+IDZAGÓ<•y‘ûRï@Á<[|Þ“„|â’ú$Áû¬¾iÚ¶œWnº-WôI'6}ƒÐ_üSh_(MGꚎ÷›AˆG&mW¬ÝßF¾Ý¦Vd]NñIgò°r w|êpoöèf-Ú4»Îêƒã÷Kí~ôà SÂé -•"<†hw‘U=?eÕÎvDqø‚œ¸Ò`¿*œD× !&Rà©>¸ž Õj+c â¯î=œ¨ Pš¸îo|øÛ©_=ÊÄrX2q­¹[ÓÝŒUÖ`¯Ì½€9§~e‘<^÷qËXñD¨©‹a :棉þZ@;&|É»¦­Z|„«×N»Çò1›ºó«½”ëÿ”eß³þí›ÿbæøçD*Žd’ˆéFA2è½±À;¥pãZ_nNÎTÿ/`å÷endstream +xÚµZYsã6~÷¯Ð[䪃“$‰gâTÆžxœÚ#É-Q‰THÊŽ÷×o7 x‰šìdËå"4ÐׇFãà3|ë€I£f‘Qf\Ï–» 6{‚¶÷ÜÑ,<Ñ¢MõÍÃÅ×ïd43 E8{X·ÆŠÇ|ö°úyþö»«×÷— ¡Ù< .:dóonn¿¥CŸ·w·ïnÞÿtu©ùÃÍÝ-Uß_¿»¾¿¾}{}¹à±æÐ_¸NtxwóÃ5•Þß_}øpuùëÃ÷×.m}9“¨È?ÿÊf+Pûû HëÙ ü`7FÌvJË@+)}ÍöâÓÅÍ€­VÛuÌ~JÄ ”À2Bòè4[bÁ€­+F<ˆ$ï1]pÎÆe8[„Œš¸q‰â-—pe 5}µ B)¤õÉ&Ëk4Ì×ï„h‡q)Ü‘èa“‚%9ŸgyVgÉ–~TiM…b_1//y’<ß®§„˜¯‹’Z–Û¤rD7·o¨@*`7¯)”‰¹{»}¶MW‹,§ŠUºNÛzÜd š gø=*Œ¿tIˆÖU q¨äü-J—V®/ÈUR±Þ$9•nn]¯ä9¥´~Ù¶FáFäq¢V\Ç^lÑ\‚ÏÚ3ò‹&¹bšaò.ŒBÅå_Ñ÷87 Bëqƒ‡ŒM1! + ôpFئOIù¢È·¯#!„3„Ü4!ÄÂI‹¹ÿ&VT²“ +¾iŽÈß.BÚc ZúÜl%Lêúà³sÏ×eRÕåe‡i³PK¿,nÐ"Ò +Dßt&[ƒ•ñ7œê !Žø”kÖÐvÔÉÍ…µÂÂsì¸æ%±$+ÝGŒõ)u†YB`K|¤¢hÖŽR"æ¥X< ™‚Œ€˧î[ÉKC¿hw°!C´í:¥*!d/FlÜ–HF +Zmƒ$ª¡‘£í®áh(ÇÉ`Ý +ƒ_ZÑú˜ žM-¡6º›YþO¼ Aóý¦A¿H´m9´)ja¢ÙBGsûÖgÍZ‰@† š“qHlLg±Ï®¼#Ó` +ù›Q\ÓJnh‚~UQ™ò,í’W*{ÄK²ÝºßŽ`]l·Å …'¨u­ }lnbƒ +³¹O¿‰Š™çJ‹µ“õ…£ +µhpØ¥+L9kÖbÖ´/‹Ò…%Y)ÅÃhºq¡ä9©\Û.ùÍ­)ø«XûPS¥­h +I€wóˆÊPdÚ›f“VY±QXš€é³ç9)”¿ˆ—­ÐX°k(Ò`B±ó $T`®˜avaÉa~}¸yøÊ ù‘~£8W`…<Áí¦ó›º+å1X•GÂÆ¢Ú$­Äc¡ãÀÜ2w<Ó 1šÖ"‰7aŽ§šm¦ðæéÏ(=÷ó#œÑA³3Æo¨Î 2moJAúwâöꈷÕÞ<ÕÑS‡=$Èém¹´0Óܪö]¼A|“Jtùÿx;jÑG›b¦ÄÚ8¨À»fžD›£?£òpÜ¿»Á +ËÁ´íªs‚ F›Fìï¢ȧÑÖ¢š@›§BŽä¡Å¾ØfË‘ì-`©WÓìªþ]¸I¼?Žº|jvsÝ=/^a~Âc|B𑿦°¿²‚#ývpÎçîøÜ÷!¬è\BÎ×–t +VžþŒjÃqGa;Äá¢)ðôV·I7TgŽ6 +« ŽÄXµ©Nê¡êOÿlð_’r…×Öýƒuvƒíã´ Õˆ$måÓĶZÿŸxÖS¨sÚÄüdlS’áÆÕt”žaCFýḟŸ¹²!t›öCCuNÁhÓ „´ÇÄ*:ÂÕ=ù¬*N‚À.Fu†yC5½{| ù]¤{ìïèV˜ù.MrËú°¥ßÙÞ@ðžOøOžz@ºdtdÚ…0bN~N©ìžà3 ߌ™tg–¸g)P°'Ó(e²ÜdtÛk;'®.@±Ôº’slGNÛD¨Å~mÿöö“;yç,ˆ˜êž…ÞÞ=ܼû×Øq\Œ÷þ8n—VUò„çÑÌé‡ÒO²Ø]‘bÕ 2+WsØÓ×¾ŠÚÄ^ç2÷Š øTÄžM3÷Å–Žï% ^Iø§¶«=:o²/³]Bg˜ôóË]lJ¼‹Àëd÷< îZz5 j¿Åsm,%ù+n>ºŠÕŠüàm¨Þˤ±'¢Cˆ H»„1­3?³h•?òÀCý8š_9ñŠ²¦’½|ÂÂcÚ“…®ñÉ`Hºt×÷tl‹ÖMy#âª0‘П%­°¥½´-{å`š¯\ 9.ö3PC8ëtŠ1#±&¥YÜ<’±Ãô7OtˆtM­ûŒ&›8ñF²û´aZSDJ«ÞMAs×߉5í낪>Ê[D§#¹'²§ñ›tùû§f5LQeÆfšsC4dÝ=^o`ˆjó¦K@ÈíÜõ*=EðuîRË=§À‡»ºÌèuóÓÛ€I ÚB‚ijÿòaE4Õk^'R¥ÅöKË:ÉçU±£²¢`å^K¸'Xy"ØRŒE ”¡}‘·µ½¤}Y÷uá0PÛ‚Ó`_䕧ë½Å€šÖ¥ ü"¡§õKQþn_œÆ.¬>N ø×vË¥»7³íXÅ©¨9z¨ÿnþ|ñãÔãË]°K;uêŸ8¡ÐÌF^L€;t,¢Ñÿ ꊹendstream endobj -1350 0 obj << +1867 0 obj << /Type /Page -/Contents 1351 0 R -/Resources 1349 0 R +/Contents 1868 0 R +/Resources 1866 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1356 0 R -/Annots [ 1354 0 R ] +/Parent 1853 0 R +/Annots [ 1870 0 R 1873 0 R 1874 0 R 1875 0 R 1876 0 R 1877 0 R 1878 0 R 1879 0 R ] >> endobj -1354 0 obj << +1870 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [471.1233 313.2012 539.579 325.2608] +/Rect [280.2146 599.6322 375.7455 612.3694] /Subtype /Link -/A << /S /GoTo /D (query_address) >> +/A << /S /GoTo /D (root_delegation_only) >> >> endobj -1352 0 obj << -/D [1350 0 R /XYZ 85.0394 794.5015 null] +1873 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [312.6233 360.3945 381.2953 372.4541] +/Subtype /Link +/A << /S /GoTo /D (access_control) >> >> endobj -382 0 obj << -/D [1350 0 R /XYZ 85.0394 371.6561 null] +1874 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [310.4119 330.5066 379.0839 342.5662] +/Subtype /Link +/A << /S /GoTo /D (access_control) >> >> endobj -1353 0 obj << -/D [1350 0 R /XYZ 85.0394 347.7805 null] +1875 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [340.2996 300.6187 408.9716 312.6783] +/Subtype /Link +/A << /S /GoTo /D (access_control) >> >> endobj -386 0 obj << -/D [1350 0 R /XYZ 85.0394 119.9702 null] +1876 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [328.1051 270.7307 396.7771 282.7904] +/Subtype /Link +/A << /S /GoTo /D (access_control) >> >> endobj -1355 0 obj << -/D [1350 0 R /XYZ 85.0394 93.6238 null] +1877 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [320.3548 240.8428 389.0268 252.9024] +/Subtype /Link +/A << /S /GoTo /D (access_control) >> >> endobj -1349 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F62 1062 0 R /F63 1065 0 R /F21 714 0 R /F41 939 0 R >> -/XObject << /Im2 1051 0 R >> +1878 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [359.1386 210.9549 427.8106 223.0145] +/Subtype /Link +/A << /S /GoTo /D (dynamic_update_policies) >> +>> endobj +1879 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [429.9426 181.067 498.6146 193.1266] +/Subtype /Link +/A << /S /GoTo /D (access_control) >> +>> endobj +1869 0 obj << +/D [1867 0 R /XYZ 85.0394 794.5015 null] +>> endobj +598 0 obj << +/D [1867 0 R /XYZ 85.0394 560.3013 null] +>> endobj +1871 0 obj << +/D [1867 0 R /XYZ 85.0394 535.1807 null] +>> endobj +602 0 obj << +/D [1867 0 R /XYZ 85.0394 416.2201 null] +>> endobj +1872 0 obj << +/D [1867 0 R /XYZ 85.0394 391.5178 null] +>> endobj +1866 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F22 953 0 R /F21 930 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1359 0 obj << -/Length 3265 +1883 0 obj << +/Length 3164 /Filter /FlateDecode >> stream -xÚ¥ZKsã6¾ûWè¹jĈÉÚÓÌÄ3;©d’µµ•C6Š‚lîP¤"Rvœ_Ÿn4@‚%e²år&ºtý øŒÁŸ)é,ÎfI&#ŸšÛ6{„¹7ÜÑ,<Ñ"¤z·¼ùÇ‘̲(Ó±ž-7ÁZiÄҔϖë_æ:Š£[XÍßÿøùçÿ¹{›ÈùòÓŸo±b󟾿£ÖÇû·?üðöþvÁSÅçïÿõö§åÝ=Mi·Æ»OŸ¿¥‘Œg½¿ûpw÷ùýÝí¯Ëïnî–ý^Âýr&p#¿Ýüò+›­aÛßÝ°Hd©š½@‡E<ËâÙöF*))„©nnþÝ/ÌÚW'ϳ(:ž8À˜O Ê"-baðPWå¶ìÌ·/ÄÁ 2‰Îà‚”û[žÎÍoÓv-ƒPÁ»ÔmÍl¥ófO#Ý“¡Æ6ÿ½Ü¶ÔÉŸó²ÊW•›Ë·Í¡î"Ç?8Öo»]³ïh¼µka ÅÁg^¿X†°òaƒ¤!¦æ?ÖnCñäZÄÀHr9Ïið%ß×ö€l§¬*Z{å–,Ûö€@fÛ¿Ñv¸ƒL'¸>Ð.Ð,õ­£ïÀO¹žé$Ž’4“gÐœˆ!Õy0ï©P²¢Ù›)ˆÈDsu…±'š`ê2x_žé#ÆKjÐ#¢(Ûì3§GAê‘ð°Ý9˜\èHXïÕâ‰!cÌ1 ÐWƒ'"wtç/èÀ)ò+—P]¸Oe%Ë»üÌ¥$èl.2öDŒ.%‘ ž#Æt˜.:än©m¯%cVDGj¶Íþ•Ú¿»–› ‡K“"ø —ÉKö“%ê«/  `dÍ«_°3C%ÄÐ'4P»5Ê­–­©çš÷á9ìKÇ@&´›“jþiCcî0— tégv·pT­£jÜ`v‘wî•píÒñ6¿#Ž:yzn_GøiEƒ›x9´gAN úiØÚ@xe©SVJEu§zÞö®U™üÙ­Ú/?lSà¹h zÞƒßØRçÛÏÃ[ea¢©]€šÕ»€ -ƒE‘1Ú5ºsçÛ¨íÇöt‰¦z¥>¨Ýæ€Ø­Å©§B)þËX\™ö˜oq?ƒÄð"_O4Á7ÜvÊ"™ -=æë¢Ú$L“y}Ø®(ÈLH]àé%´Î¿6„£‰4È6Ÿ½ðåÍÍ U45ÜAGÝx@\=·*®!i•ˆH¢ÿeW“e…ž-× Åà>T¦¯\i@uáJ=•E¢./¾LÆr€Ï¼ÌÙMp7ÉYi߈õtô׃@ÿY!­Çƒs™4Ý/ÅÒ_ -Á¢”©ôGÇ Yä¹Z+´}ȥݗž8¤ŽìvÁÃýÞ&\¾dð=%[§¼eã$ŠƒSqf|aˆs6ãÆOà,EMc_Á# è7îÅ> /Ôg‚8–ÒBî<¯]%w|Óº¾³&7©”]1©ê¼IõTÞ™”¿oì®Uó¸˜2/!­R^£§šcd` a’ƒÚŽ¡ÀWdb‘2"áتm*Ó™BĪ¥ <Âé¼(ÌÎ檶W¯Ýôcíâ07cËØ *(Ò¤4P4Û\Ǫ¬Ê®GÒwé‚",á¦|ÃãÀÕM”€$…Å¡ËþX hÒY§F©êQØ…ží(¥lÁªÜ©ÔæPåÒ=ƒêîy]R2â*»’†TtÉSÛå±1uEO4!À±1p]c ŒÅ i =Zc‡Il‘@Ã䶠-'8uÈ3û¶b­9-IJôùp(¡œ—jyžþÊÆN×ÕòP"‰¨|ZÍQ,•º|º=Õ)NW£ -Ôãv6;ÿÙ–ˆQBä3'HÑdÌ#-!<g°;WlÃP=ñA4°ÀZâ6ˆÆ¸;Œ–Sáªh8h]nøZS­MÛ¹Á}^·yáCQ±F’÷cÇ%—ÐZ¹éüÐ5[…Ââÿî¶l›ç¾þÞ›³a0ûq—cå q}‘WmC­Uï|tR dGyêâ¦v”«¼-Û³˜cõ%ÕeÌ©ÎcFO…›yjÚn!SW¶pÐí ö6$‹’D§—…è©&¤‡TQ¢R>ãN=~êdž¢¶%q ‰-‘ö@cˆußk—Â÷F³Ãiâõ}I &”eÂàÊ­û\YDùç¦#Òh…©[P¹ÝUf kù"í×xX©Hh~Å „TnÔSsÉ _»ð),tQ„žjB†±#Ð0+äXˆ©p—†ë0]uymšCKTdÕn®úÝ4_»vÂññ71B2-W5’Æ}vM´HÇð±2Oy…b¸ú ¸êÎ +sL¸m¤!œ¤gÊŽ\dQšqŸƒc¸>õ…JDg2¨9²xþÎ9• `qòˆØ -ÎÁF©½t4í>AB+§ÉM^îi`Uvá®ú’+†UÄÓþ`¸Ãðt¬ÙäS¸ýÊŠåM8ܳ֎Ûdq&.[{HuÞÚ{*{SÅî¬C ‘0ˆ˜/2ï©&¸Óò4Òi¢Æì—¾–Ôÿõ`çЦ³>¶sé•ÚË÷?¹Á¦®M4d}¡q¨'£ºñP’¦Ä}ð„”—¥GJý±Ž!1êÀ'M™'QIëµb —2Ò,¹R_ ©.ܼ§"S±ç°^´MñÅLÃ|¦.ów4ì!>\ŒùÛㄪ¿mÉé¶qÌðØö¿Bhö- ¸:•ž^³ùN¡pÈóßP·íÖeƒm•ÌMW^Bºê"/ËÚ˜µk¢¡ãsehÉUùè Ü’àGÐoêæðˆÆ,%ù‰)(iYUF¯É0o5ÆlMb“¦Ä³8ʲģ~垊(1U¹OO+ˆMŒUxX¾©ßL¬+Atï8Ž¬þ8yÈ")™×ÌÜ­ûb¬¥HÑÐÆ¥ÿèþ\® P¿ÙºôÇø >¶&÷E®üÐ=6î‚7dhüv0.IJßÜ·ˆ²†D¿'vÑ/~NÀdacö­ûDàê§:¬Ÿê3U8¦!í¯âñYcM‚~(Òx•µ¯kïºÎÖk!'®%kÓ)Ï0ˆÁ§8`e2„M9p–êLˆÁ3ŒbbKcE-K[#ž2lìŃË-‘¹Ël¤î+½öJ•“=Ⱦh ¬‡Ý¹à‚æ$G¶·9tôC‘àÞèW)>¯j‚_.=ùßËà{Üû^b¤%a Ô|¸Ïš6d}1LÇŠz2ÿñžŒ$`¿ÍwÙ©l]kÑ̈ÒÄ †ô]%TQ¤S à pNìWÅþPæû¼jó­ån~Ò ¢³ü©¨Ú9}0Ìšà#‰±HĈp舒>•ƒ!ž[ÇʈÝ<å›çdÿÇX°ÖHñTÅ¢Á¼¤ ) +º $Ês7~v’ÍÃ6o6ÇâÐuåêÝÜDK”¦ü°õõ‰e ¦"Šjl"á +„²®óø¸rw=k;ús§|¹›³aÆ{bðX%J8¢’, {Gµ È”›CýŒ %–Ç1Ö§ºŒ±ŽêÞ¤BLRüŽjI‘ ·8Þ¸uû >­OÁ[ :ÏxÜüñX´¯SÀÁ²Hy\~ š‘?¤JСo ¸cÄaHvHq)$)VScˆ ô VOùþÄAÂ4>úÕ’"nqÄ’/y¸UqêüÕ’"nqÌ ÐH²קŠ`.P‰§Ã6kóÄùˆçæy: +I¦Ð tT3* @Çb<éð6uÎ’qÉ…¢ô2ê(”†lΓ/=áúÙciŠ†|%:øÕ‚SnqÈQÁ—.¹¹UrÊHÜVM“oøyÎ_ÍLÕU9Mç,TªÔè¨fôàNhdÊöoãë.Z3)—¡¬¦’]¤×) êÀâúý‚íS¾Ÿ?N‘ä1±I訙r‹ã/…J_Òø‰"èóDF\{|MÚÍ!9æ»cÞÕe uTÖ1dmö5ùdN N)‹ D3‚‡N#Ž™JþtÈ7Åîõ:¡,l¶Rm7¤]ÌþvºþÚµ>xªSc¶BÍ“Ù +µ$M[M Ñc ~Ïú C³÷¯Òõ}Û´çOvuYÖ/S¤'ž1'aOFsìW(”XiXà…_@_¬ÖF{"Ý°ù…’ûx°=¹Ýå¥D­3ß™¹Ÿ²hZ÷dÇ^žŠ6oÙ&O¶yYì ÿ©\)±˜o1tüœ¦äøŒtÙæU[$n#:è=؇6›}r¢¥wðpž(Û ùÕµ)ë×YµumYõêšÓC“ÿv1î½ÓÒÓ9ûÝË!kìÛŽÁãÉl…5ê¸:¾ûÁÎ ÌÂp_}<êÆ Þdîç%{u®÷‘õØWž%ópÄ„*¥[ìv*ÃçóÀ‹öü$A§a³å‹ãCûÅÜŽ>Än%C¦ù•áGÃñpÖ_^ãuãž«¬-~÷â‹*Ùçûúøê^Ý(l“‡2ƒµu¯ASo2+Á‚Âò˜lÈê<È çöˆ¢Ì`ØÛìÙÒ`BgGë# ¯]àlý{Vžì) ¥g¨˜ŽCݘ „Üu;ךm·…ñíYéÚû…­·Gˆ£çödΈlóCžW®­,ªg»š pR»Vï°ØºÉð½9*´ç‰xý©ÞÏb¬ÉÌáGHz¶= Û”§m€àKÑ>ÁU_õp:G+xv•uq–Á€>¦^CX·Ð»w(SH¥|!îô©.ÇŽÊzÊ&ñ0«  HÀyTl šÛ_ ‚Ž9þˆ}£lºS~rꨈ$40Àg``l“*Ð/Ø:åûÙ9 Ñð&*>æÕ’"nÑ´†Â +ç‹è:EÀå‰ìôäeþ˜Ó“Ù¢(ȼH\zG4?܃§H:”ï»&LÒìÑ<óµÕĶf‡CY¸è)|\îÖúh) '9=¸'>›0&×·;ß›{zà0   ‡È×¼™+ö$TüDã…ñé°0*¯Z0Ã¥NFÖKQ–Þˆ²ñšûˆj7ðS­F™‚YU3ïõŒw¶¿ÞyÁ:Æç¸;žÍ.¨º'£ÜlÀè–úœzÖ6Ã1@*V+¢¢)[Z“}Òÿ`ŠÌ)_£Õ±®Ûd „š}Ç” 4š.É@5£ÇÐ7Œ¹E—¤9AN9‹/ÉÑå%ˆìmŽúø2sþª)"æòELh ™ +x{˜ùT¨Ð.”òõ>Ï*Hèw§ÒÇñk÷QœwÕƒ qM™ûqšÛìÔ§ Ì&à6Ú3»Ög®žðÉT„„íÂf ¡à+eØ^¶Y“¹É ¬ñ²:˺~† ãô®]g¸$c4†€ñpõe;s]'!æ:ËñÕ–4Db¿²e:1Ît:ÿyÛvŸTµk̪æÅ¥;&¿””åü`$Tw%(”3£`o9…Qx©O¥—Ÿ™2ÌëäZªú¸7Yœi +Ãam«][pED”*Á†Å¤Mùö2îSsÀDÉð{TäªôÍøŽ=OjîéøÇdwT3ÂÞleÊ,¾ô]í„}3]Cæy„Ï·>ùWTš'STÂDz~°£ mC  ãùµ EÐYø­ “ôÛ†®R +:Øô(2÷êK'ÓU3`¢\#I wÃÎÞd²«‚8%¢ i®„%÷°QíQÕÝ ª`™{/m»„Ún. òÆ?ÏÉvµõu#gÒI›ZÎ¥ún˜¸ÛøˆK,Ì:’ 9RŸê2.;*›þ±³Ú$¶(§:.=ÍHoÿ€Ó"Cñÿ½ÖÄ&ò +·‹ƒ5³1-®l5OÊuøš×&l™;⦷Êö¹k2HêuÁÃ|Væ3aC[Ö®ç甧¿Ö§#T†ðˆCcJJÏÕκiܾ‚€b㕵G8ZpI¹y] (oÿ÷þ¹G_† wËŠÇÊmzØLP§,b\cÇj‚\J­O›vü3Þ4ÙetîÂkož£ ¦™[‡C^yäÃëÏ„0ŸNöÄA‚kÒ]^ôëÊ·¬ÿµ*sM+f~óÄã +±KKÎYryͤöÔxáP¨OY3j°fÚý!ñÃ9¹q‘b|A‰ŽjF‹¡SH1R£[;Îýx/RmëÍ©9´îUµ¡ð?ßvVf§ëÛˆÛK¤úòÝP‰Èâµ½Qäf¨'²ò¨ïhˆk)Ä„š©ÐA¶©¹Ôl ôO7TX>ŠôvæT·–¾lÜ«›~W µHV6 ±¿>ÎnóÊTn)÷e¡ÂC®6Ö˜ÏC¯Aù%v?È9ÈŠ¥Öà çÒêE0"áHͯOÈEµ¹¼>^ŸÎ?˜ødÁâwüúõš©f7ÙCØÚ +å訒H¶|œ }óÆùÍðÒuºãñ‹×º98fÊâœÃÞGæ¶ý œàÏ{¶¿}©ÿü?`,¨R²8bî1*³“ã”2Úk6]~þöÿTõÿaØ—Úendstream endobj -1358 0 obj << +1882 0 obj << /Type /Page -/Contents 1359 0 R -/Resources 1357 0 R +/Contents 1883 0 R +/Resources 1881 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1356 0 R -/Annots [ 1361 0 R 1363 0 R ] +/Parent 1853 0 R +/Annots [ 1885 0 R 1886 0 R 1887 0 R 1888 0 R 1889 0 R 1890 0 R 1891 0 R 1892 0 R 1893 0 R 1894 0 R ] >> endobj -1361 0 obj << +1885 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [361.118 743.8714 409.8647 755.9311] +/Rect [257.6971 713.6209 326.3691 725.6806] /Subtype /Link -/A << /S /GoTo /D (configuration_file_elements) >> +/A << /S /GoTo /D (boolean_options) >> +>> endobj +1886 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [310.7975 683.3704 379.4695 695.4301] +/Subtype /Link +/A << /S /GoTo /D (boolean_options) >> +>> endobj +1887 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [308.6055 653.1199 377.2775 665.1795] +/Subtype /Link +/A << /S /GoTo /D (boolean_options) >> +>> endobj +1888 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [294.1999 622.8694 362.8719 634.929] +/Subtype /Link +/A << /S /GoTo /D (boolean_options) >> +>> endobj +1889 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [303.0862 592.6189 371.7582 604.6785] +/Subtype /Link +/A << /S /GoTo /D (boolean_options) >> +>> endobj +1890 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [332.9347 562.3684 401.6067 574.428] +/Subtype /Link +/A << /S /GoTo /D (boolean_options) >> +>> endobj +1891 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [386.0748 532.1179 454.7468 544.1775] +/Subtype /Link +/A << /S /GoTo /D (boolean_options) >> +>> endobj +1892 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [301.97 501.8674 370.642 513.927] +/Subtype /Link +/A << /S /GoTo /D (boolean_options) >> +>> endobj +1893 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [231.137 344.9998 299.809 357.0595] +/Subtype /Link +/A << /S /GoTo /D (boolean_options) >> >> endobj -1363 0 obj << +1894 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [347.1258 350.3535 404.2417 362.4131] +/Rect [143.8055 284.6583 239.3365 296.4589] /Subtype /Link -/A << /S /GoTo /D (journal) >> ->> endobj -1360 0 obj << -/D [1358 0 R /XYZ 56.6929 794.5015 null] ->> endobj -390 0 obj << -/D [1358 0 R /XYZ 56.6929 484.9636 null] +/A << /S /GoTo /D (root_delegation_only) >> >> endobj -1362 0 obj << -/D [1358 0 R /XYZ 56.6929 460.3339 null] +1884 0 obj << +/D [1882 0 R /XYZ 56.6929 794.5015 null] >> endobj -1357 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R >> +1881 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F48 1228 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1366 0 obj << -/Length 3380 +1897 0 obj << +/Length 2840 /Filter /FlateDecode >> stream -xÚ­Ërã6òî¯Ðm媃'G'ñdJ&³Ž³{Èæ@KÅŠÔˆ”=Ê×o7ºÁ‡DiR•-W™F£Ñhô €äLÀŸœ¥6:3³$3‘ÒΖÛ1{¾n$Ó,ÑbHõíÓÍ7ïu2Ë¢,Vñìi=à•F"Måìiõûü»Þ}|º¼](+æqt»°±˜ûðá{Âdôùî—ï~øíñî61ó§‡_>úñþýýãý‡ïîo2µÆ+æpaÀû‡Ÿî úáñîçŸïoÿxúñæþ©[Ëp½Rh\Èç›ßÿ³,ûÇé,µ³7hˆHf™šmoŒÕ‘5ZLyóëÍ¿:†ƒ^?tJƦ‘U&ž-´‰ÒxLjYD‚։͢X+ÝiYÉ)-*Ôò6ÿ²XæË[4ÅŸîtÑdìÕóÙüÕ„j €„ÕˆÄʱOw ËKQ”b{Øb#›çÛúPµÔQ¯™Àmëý‘úÛšp‡†G¯ë=÷~Û¿:@Â>ÿ£!”_é;€=/*Â=[×€qÄÂÎÿ³qUÏ”[FRe¸JeÖ*/sNÅÊK‡ßUÞæ!güzIðÓ¸¿•éÜa»A„¢¢¡®²Øí;„m?4,á·¢,C¿îžá²öß³Bíà×}ÙD@í5¶y{ ¨<úUŠñòžóÆ­Ðì¼ÆµX3Ï+jÿôø™7í>oÝË‘:šš°í&o C‹À¯zý¢UÕLä¾,[¹ì„Vf~Gd¯yyàÁ^ÏðcÍÎ-‹¼D½ÙL$¯Šêe¼(Š'$6ò\eˆÌƒž´=ÝÊ9i艨µoÖ[¢f#“ak¬«òHЛ‘§+öÄàéé'žªßŒI©žß6nO½¼ ôÉßXN\Ó7ïM:p¨“m;T^ÁŽIG¾g“(β†x¯5¡0©ÎäÀýËzG¼÷>@iµxÆÝCøP5ÅKåUE»ïöÌð¿Â -ñe2åPJØ7£ÐX±Ü9ŽÄMû`}´ØMþŠ¦‚W@“or4[¶ÔÎú -ú Qãw ›WÀVW® ¬rÑv»zÏmÝñx­è za^Y8"„*dµË—¸Ó‰°ÓÇ)ÛÜÕMÑ~AR“ò‘¡4óÒ5 µÔÏ õ󷼡ü°ñìè {ïˆ#5×2«šÐÀ%"ÌCE˜œš!ê ê­h7„ÝʶؕAʽ5Kµè¢å‰Avþ;°Û•…yÐhÜ.ÇQ©íÕ!Pˆ.`ZÁn/|Ì$'¾ûð¢ ʈ_¹uR£à©Dt–È9[ÆÆD‰òzJR]N©•4ËÝ¢,šÖU‹Ïw˜HªY$‘]— £ša”Tc¨G,äÒ‘ œT³9 B0I³Ð^W»vã“^ÚÓv -ô ¸Z°-*Ž ¬VDjû°%Ý Ö¾r%ÁìC í2ª5‘±>ɨË%ˆ„“@ªl½ýaK)ƒ¹•3çêˆê¢Ü‰P^bÚAhYW-…ê’û6õÛ¼:ôôÝÇŽº‚(QÔUXæ,e[„¼[¥)éoE8ÈñV¯¤$·'ð-ä¾Pñõ–û¹t -¦Zw±{ž]7n—7”qö_Òì…Ê’ù¿Ñ)8t`'…Oî#Bš¢JÂOÈÂ¥«Úr2:íó¢ÁÄLYehÿ e¢LÄXŸ&T׉§Çb[Æ‘”P| zݾ¨WÅ’<òéV¢äÍ'j>@òØCÄk.ù©Õ*26Ö×ýtHuÙO;*sYR±°(X„3GZR}]„ŽjB†±£&‘I³x,Ä›°šwRP‹±}&ƒôàë @ÖÏM]B0—sÊ+ñü#ÍkQ B cf•6dǾ’Dø­>”+¹"¬_™¬/NV]ö…cJ|b”Pj*’–>ªd… …“ €P8è@®ã„uÉÄFʘŒ‹–Éý:Qr*#abÊœ¢:pq¯>;â„}*€À¿¸f(˜_:T”ÑYíߥv õÅ9³êK GzûÛ˼õƒæªü6@7ÅX@®jš=¥z¸×¥ßq@×ÕH}é|×ù”—™UØÇÂDS±êW¬3×GŠ/>>‡œYï0 v)™x â 79ÓVœº‡—çQ¤ô“Ó¢žqðÜÅ4mbéÊÞ«î?¤ºìþ•/ ]¾oŸ]Þ^ñÿ8Ò©N¯ËÐQM1òÿDF:¶r,…O¾Fô§U#BêA,l3(~Kè?늉·9Ê\åÕÒQW ñ´¡>Ÿ_—&8®!Ü6ßBKDtÞLøœ†@®uwPXÁIä°›p4¨ÐÓ(±i66*<ù8 -3Iòs’ ƒàûã}3³\ƒ@W_ƒ@#ŒŽµþ c]ÞÔUþ\òЮl¸?ÍÁpX‰SÓWz•Of;<¿Hcð˜™Ø0%U"®¼EcW80©$÷n(•Ræa ²6B« ¼c_N!¡¯Ô‘Ä'z@<ߦŠÜ ðd -Ø34… /§jƒ±aWd{@ tØåòpÝqÇU¦¿r5¤ºì‰Êèc ÕÒOÔQ,ÍuÑ„ã<œF6³z,Ÿ"²Á…K¯À.é$  ²‡káhþ‰(»%PVÝ]ÊmJ H«P ˆ+*8OnÒ¦g¹Mkªá}ÊÒ‰ˆ´³±Mw^%³ØÛ'~Ñ«ðÛsRP@zExt0o µ%›÷p8š7~ɼ˜÷€/›7òFóÆoÞ y#{oÞž|>í4‰=¨øó6´=iÆW/* fì‘t ƒíPîãáâå§OJq0Ä7˜Àû.|Ë:§»(£ÒùÝÚFFœP.<ü -1ÀÓÁÉ;ÙžÝKÁ3ñ©pj-”¼µå{Là´±÷'f­ å@Rj ro%ƒ«¢YÖ¯®?𮳧†Ú¸5tùW¿+¢Â+Ç<úx‰²¬ß§g¦àãÛiºHÁ‡LjÙ(yu5™1íÈ4O¶„ï„ü•Aµ: RM[ºâ%”ÃuSÔËÛP±¼rø{¡Ø‰3¼åT+_Žy2‹  -´_‰yª+1/Pá²›–‹•as5è EˆŽjBŠÓ°'dr"ƺ2Ôî„Ãvw†žg¦.ëºéåò=ƒ:'S!`]XñDk{äLª¹H}‘@O›Èª$9ñ'6€Xœ^õiï’ÂýrcäÓ6^‘PÚ¶b”¶‘Á8mï‡u¨qÛñ…–x7®’‡Š[ö3KAŠ=³G)@E&ž©ÄDq&ì_y~BišN??Aü‚4ñ^4N/È1«Eb8cj†Øm -„´Q¬L2S±ŒL,h§> ¬ÀÆFzJHŽZ¶‚_ Þ“ó'ø¯æ÷gš¦ZAZT*Wû¬?û<Ã`–i¢À~±½<⛇­š}_Ã’fÃU΋!k¿®xü¬KLH  öÂвüÃT›Ç[Ç#nÛ]鶮òÇA¨èË›eg›o²$Šu¬gõþ½ ƒ:ÍHÏýããß3§¡ ¨(NíW‚!†­Ì3º0R|aDWDõ®o8N °]Gi¦hø?èàzE1Ÿ5 74„æK4D»ÏÿVdlx¥!bG”Ý! ËM]7ŽYäô©|¸ÄÞž’nã‡ûH¨þÒ£­¸*ô‚® ãùMTÄÝß®ãû -‡ú×»5=µÄšoð ²r“3qhHŲú‘º–%.¬ ýLß6®\ãÑÊtåäi²`56 ÷1íå 2vy÷½Éó|øŠñɱty51§‰“àýùjÁ/±:ƒú79¹8^íñšs"\Ì RêHÿWàÅWÍÛp–éYžÛ·”*‚NÛÏL¯ìírs&¤à(Bý… ¿&¤“RœÉ±Þ<Ï÷b_¢U¸R£++P¥Åé¯ø׆>üÆþN šý‹&4ú’ka9¿÷Ï:Øæ´(¡–(i,9 v¸2˜²æ©ò¦{Ä} nñ L÷]‹$Ž 0JÇõ懺ZTî…/ä” ì‘/êÿF¦¼Ïb;°$$?z#è+r%º^@Ñ+^èðJPá©XQÉêßËüѤ+¸UxÁZï™û$‹f*ZxÖ)ö ²ºÔüÛ .¤ˆÅ€~Sïé½eÈe°tÍw1+ÀöÍù% )x¶ŠÁ4ý}l´Å}Ä÷ª×Y·2Às‰©ñ¼4µÆÁ~«nšA1‡Øá^î‡#Æ‚~Â"Š~O2^/•nØö²¾¾v2_­ø‹©yÐņDÃz`HWNüú=¬Bׇ=%3>ÅTáLt åÀŒÃˆ¯bÉ OOQÁ¶.12c\Þ¾wHîKŽõË»K¿Ò6Â4MSDWþíßMõ?*3P•¥é…k- BPY„B=ÛäTr«ÓȦ*™ýǯҩendstream -endobj -1365 0 obj << -/Type /Page -/Contents 1366 0 R -/Resources 1364 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 1356 0 R ->> endobj -1367 0 obj << -/D [1365 0 R /XYZ 85.0394 794.5015 null] ->> endobj -394 0 obj << -/D [1365 0 R /XYZ 85.0394 590.4054 null] ->> endobj -1368 0 obj << -/D [1365 0 R /XYZ 85.0394 563.4931 null] ->> endobj -398 0 obj << -/D [1365 0 R /XYZ 85.0394 179.4044 null] ->> endobj -1369 0 obj << -/D [1365 0 R /XYZ 85.0394 153.6629 null] ->> endobj -1364 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F48 953 0 R /F62 1062 0 R >> -/XObject << /Im2 1051 0 R >> -/ProcSet [ /PDF /Text ] ->> endobj -1372 0 obj << -/Length 3131 -/Filter /FlateDecode ->> -stream -xÚ­]sÛ6òÝ¿B÷tôLDŸ'Oiâ¤î´NëøæÚ>Ðes"‘ŽHÅñdúßo P Ù¹I&ãàk±Xì.ö‹b³ þ±™Ò©.x1Ë ™ªŒ©Ùbs’ÍnaíÝ s0s4¡~º>9{+òY‘šëÙõ*ÀeÒÌ6»^þ™è”§§€!K^¿¿|{ñî?W¯Ns™\_¼¿Ò®TŠk,Æ­²Á¥ ÐJ‘$J*¸lGËD2tª/‹ê¾¯-5Ù®hÚ -]¿`”–PAÝ1™èÉ´¤"¡þô»zᎯî=Ï©³ŒéǺ*»žÞ%Úr½NP+ÍÜ‚^ÛkÀ²Z•»µÛµWQÁÙV+Fª½×Ÿ@7¦ªm›u»(×Èž—Áîß42ö¦U‘¥Fƒ ¾åQ3ž…’ñG ·ÎYª9“ÇqѾ p¹.íPT{ã©X‘‚øòáíóÄ°šixÎôLå9<~Iº ˜ÒÀQc¢Ê-Ä{à -K®ážX;À™å :%ÀHe™Á£gŸf,ÍdQ -úö®{؉³‹ Ÿ½iáF³àRñ<Äl/¥C[Ž à| 4ëAƒì´5…PîJƒZ\ˆPÊÔæ[ÿ°rCmÓönbs¿®6UÓ[Òùèé”aRƒŒLaf¡°¾Oþ¨iªÐ {ñ}Úª”IýT*æN¤‘in ãý1Ó)ãÂ2xNËîÚm¿®½!øЗ½å^ÜÂs™^ÇÞ&™‰éîÛ¦³3$I+% ß\~ ñ§]µ}¤î¦|¤Ål£ãaÖÚ!˜Ü€©AŽ£Úí,F³‹Ö¶ËŽ6¢Ñ¼ºê¬·P«v»©›[Z-ÿ|‹ÙUHg!ý1UAŒ"Á<?`±)7®G®ŽúÎ!â:†ö‘Ftl¿Û64&R¨ðûý]=^•‰=º~­lhc} -ÞoYõÞÄI³î^@NĽá}nvˆ/ËêŠ:½³cõb©QÊÛ¡í蘷[‡x¢2 - Ƹƒíå²èîÉ3Ûj]¨™ - ³ -N‹Û[g›®‚k€Ÿ‡¼‘ ¼Ð^$çCµpvˆñïCÐd`K8õ¨ç(9ÀæØZÄ í´Z¬ëS^aפM¸Ú.\w×îÖË®ÜnËæ6¡í :QHÇÁÄe`]Fª]Z;Ê’òžb‡ö~[ƒ´0ÄÈ5`){Z¯;;•'»Žžîi]g¹t¤v•ÃGvÚÇrб~ºMå‘:  TĶY¸=Öž 2À²¼ü !rº/bZN>B s¨2¶£©…}FÐY⡲Êk·ÔnÝvÚæà[c-zû¤íTóW–ñÛ ¾¼¬Hþ{W9Ô%aD,ƒÖ³ÕC™aÐuöÄÞÏÑæ¨@+Ž#F‹.dò䦢ö¾Ú¢U¤:'æí£í|r -èäMÙyàÖá€éÿîhH­"G?Sw~«åñjúiW;X‡iàq <ÅšÔ¨A¶¹Ä r^$_ -c]„꽑٠nÍZKoæ/yhã¤vÌèC'ÀÍ¢aµö7¤.Î5 ¼ò#ÞWÊ&F/á€ÃŒ¼¾Æì@‘È!jÈsó-„Ƙ#aÆ€q¢<Œ3¸1)‡™ -©Ü”=$#XVˆFÌ£qÀø Ä(s¡ÇD‘$(…Ђy~cʇ©!–Ü:ÓÔ;Õ=ÉìMC3›Ö[u÷Õ¢Fu^XOO†× R˜± -ƒiÅ7¥Ùw‹J ‹<#¨—"Çóµ€{ÙÚgÉjä¡ßÍ d4 C -E -øžó»~nˆùÝ)ޱ߼ßå‡zÍArW‡GDü®ƒzŽ’lß1Ÿ—6‡F1´÷ÔYƒp×Ä´ 7ë'%Æ$èQ1d+O›&¤Üì:¿ïªõŠ´Ff€-“z¬5hËEÎmÌécR}¹_׋º£e - ÚŠ0H”lEHˆÎåw¿ÐãSçŠb@D²E¥€üŠÊ\Ý×l6…·“ô‚'¿“1ÅS,kŒc¾½·* °ÛTÛlë¬Òñeòêõ¯Ô¡t{ö^ЖØ@J^u=Už¦Žƒc)C=ãØ 8NµR<ðà4Æyˆ2æ4TŠ2 Ž;60º…¯òãhôŸ£±àZ‰<¦‘’«Âñ›"+°µ•5~سÆ;ÎøÙ.&”V a€Ñ¶‹»jñÑÕÁãA~•zR3½-ëÆú}½!H»1VÛ+á¸9ìðUèîš¾v¡]I ‰Å m»jwÍré‘ßo3 -!]:‚!ù˜°< -w8rø®t@7•  gé©–øX4¤æãÍÜñWÎÅ’„Œ0„8¸GƹãmÔŒ[Ñ|D’gð@î‚xÁ€=‹~‡iƒ`˜VÕ›º¯?W4Ü–¹Ì§å4ðŒøÃØ„?Œ‘Bà®ö¶Ô‚Oï9º¿‰ö$|^L‹K¼ dÚMûy23lº©n릡4‚“šÖC¤69ÉÅ&tùœôÛ’W1 ‘?8*¼1Ae¥ž²>‡:šÃ€Ä-ëL(ã8k’Þ¥õ=18÷Ì„¬L/ôJH RÏe&žË$ÀÉAÂ1ãÚ¤J™‘I8Œóe,“©Éau{"•€xQrõãˆ0>C$z&˜y<•P¬1ãE+¥˜3ÌÒŒqñMñ½‚L`ßãRæãW«ÖÄÀidbÈ@ ²ÌÄÿÚƵ³ž{–]Wß66ß×de¡YÂ-K*Çà¤ý¦}QGO8bk¨ulúŽaÉ}4 6uSov›Ø™µCŒ¯ÞŸÞÆìáà6B#s+c#ñ(5cÜsƒ}{´…É!æ.ñ[à ,t*‚!ú‡Ú&öC©cQÕ–j‹„Êk »¬› ›ÔÒÙ ~.£žËlŸ*ÍØ»­ú‹Â›wT>Ç°ž<©æay(5?º‰µC]ÚV«Ön [.À -¬¾ÚÒ¤\—Õ—žà6örøáÒì+n8XÎcvtLlf_Úu%P“°sM“²3.iÉQ„¦ši§×X®z*´_ùتvÕÇÌ쫪%w(]‘0XÃÊþCofHû#·hÐyŠx)ç»»ö¡¡î ࣸCp¤¨s ”Vò[)‘ü1(&ÀO Å„QIÓ0A…\‹Ý*`q3Vmõ×*÷: ½ðç8v5]ìNU^‘ qÉ…)*£µ¡†òQMåa‘Zߪ¦¡Åó'"ˆ=·T1å–=ã}Æ㸅‘uC3Ž°b8]ºÓ}¶QSiÙ³Ðø˜pŸŸ9fŽ™‘ÛLß2Äf0ˆõÖ}ݯG¥l¬›/+¬!Ç&Ÿú'UÕýwÅéïWĘ´È÷n?QžÑÊÅ[üiPæL÷K]Ëò£¿ùzø[ft€ûúçóKê­ê­'vU»²H»ƒ#ô“ž‡ïñ+ßÒø œG"bòñ¿Æ Ô÷åxJì§þ9l©T”§LÏ“˜=•qØ_x±.Ñ“c÷õdŒÙì©“´‰ò{×9a¦ø;Ëí­›à“±8öË¡Rü V¤0˜ ?±øî_zí?»c]Ϙc_örxÜ8¢#ÊPîvHúÿJ“½endstream +xÚÅZKsã6¾ûWè(W@ 7gâÉ:µ™d=ÞS’-Ñ63éˆÒ8ίßn4@ñ­IeR›©Aàú¯ ÊbÁáŸXXÍxâÔ"uŠi.ôb½»à‹GûîBÌ*‚VmÔ7w_½KÒ…cÎH³¸{h­e·V,î6?/ßþëꧻëÛË•Ô|iØåJ¾üææý·ÔãèñöÇ÷ïn¾ûïíÕeª–w7?¾§îÛëw×·×ïß^_®„ÕæË°ÂÄ„w7ÿ¾¦Öw·W?üpu{ùëÝ÷×w-m{OÐß/~þ•/6`ö÷œ%ÎêÅ ¼p&œ“‹Ý…Ò Ó*IbÏöâÃÅš[£~ê˜ÿ”¶LKe+;Á'¼Ì×àµUª8ÓN4N–bÌÉ„>Þe¬~«Žû2Û®êâϼo´0‚).O“ÆÄ7 ¡|Ù’/Œa‰MlGyN^?<…Æ&¯×ûâùPT%uT¨UÏ—2hA)3zÒSˬÒÑ„¢ì[š€ƒ•æ²m)íÔ¸mÙÜÀçm¬J6¯OÖ!1…FõRR3!Ĭç#f^‰þJ¨Ð;p(å@À¸y¢µP3L‹¨¸G‡}VÖùþRØåêPìòÕp#씓FÍkÒ FTéÎBÜðÔvuùr¬›²¨§†ê§é û¬eÊYÙ1zŽ~ÆüáºSLüÓÀÔyvÔE†«Í²ÐÀöjÔ{–…mÔ4 Ôèž›í8 !&µqóš4¨Uº,L$0ÚÑåï±ÐM±°eQŸ… 3„O³P2§ì=Ë€?cþpÝÏg¡rÌ$ÖÌïCƒ:£Èpµyª&ì¶P3,Œ¨éÌQZÅ”Ñf^•5¢K—†Ž)…¤n+óÑ°mR_. ˜1nšˆ’DjtÇì9"Fü ×ý|"Bõ"ÏmDQc°Ö< Aõ:ÃÂj†…59FY(˜qæŒ* jD—. a4M{ÊüCGrÛ¤~6tL(Pcš„ +œ–êŽÕ³$ ø3ö×ý $ä,éü>DÐ5kÍ’Pƒ wól¦)A(®¬ÅÃë€nB‚f:™Ú€†R;d)’ÒtÄ~®”ïo0\÷ ˆœ"„>㩶mûfxÕÀç-¬:yÕ]‚+õ7 y-kͳJ+f„rnÂ4nõ¼Ü5"¸C4©˜µ0Ú‘|ƒþNUü -ûžVóŠšzªÈ:h¿d¡³(y¹É7ø¦—Õžºëç| œ+ÊGzÏèn‹5µÿ¬Êœf¡Í¾«™þ)ß¿p.×ÙI$Ý£ëâ±ÌVè$Œ. f67­ißG_#模D éùíû®ßR×ð:KÒ#@_žò†x{¥VF‹Ñ˶Ê6qÞƒ¨vô¶)êìr•p}.ŒUQD"5ÐÀ‡×“2ÙIi4Œw-ŠÑ€â©••¡s«“¹íLAÛ5Mâ$…B+9Ãáh†Â„š¢3Wõ¶­>ëz˜3“ø©bNzŠïYã!átGþMȆpÖ¶²!wßWrq±ª1op#ÓàJg–u¾‡ £öK±ÝRëcž?‡ñhp†Š¨¼‹ä…b64B8A ]åYà]±~¢ÞufÜÙ›ãî(çéž +f9=ºW§ž2eÊšXLœvf…áµû¢®Sº™±ÉHÁ‚t+{,k\Ó0®ž¤ÞR#ÎÜxÛ¨iÒ5(o)Ãl³Ùçu©§Üä¼ jDî þºÓÑãÇr‹1mõr—g%$¿‡#ÂÆý‡¿k‘ã=øô™C ³¼#rŒžÆçMxݦQ‡Ï‚Ðsó=Ñ^ +ÿ:s:i±EvaKÀéϱ¸ +³Ë°œ„üòõæÞ~ýµ‰óiLÙH¶–íbÝ9–ýŸðR¦ ‡¶ùMo«ªí¶z¡r‚\7ÊZ÷yÌP !ü{ßk,mµWêLiUÜ/:KZ›Ô5œh‚ÏÎHÇEbbæ=N^qìÈ,Ï)l ·¥çÄ×îžò’¤IŒYª65u6U ¾´]†ïÇÉ…-L%§5 È?…)e¶ËÃRG(ÿöþä‡Õ€…I¨÷ЮÔQ$d@–k ņˆ_hU%š³ÛÁªòPM==0Õ½RÓ'l`,½¼¼\:¹dƒCÅE¢øIØí·ô¼/Ôð¤LŒׇˆˆ­¢,˜0ÆLéçOàç ¶«;ÈÀ¡38…E8ò[A¦}ÓQ—0“G²”’h;{$·QÓGrƒêÅ>qeP Â)d“d^ƒ5¢B·Äos*íê@Çqbxç8NLd tŽc‰Ç±¤ã{ shf4‘Ž*ìÀ{6Õ.Ã܈}1< áË;%à +vNØ´›9O™§›]fëØðüN—ÙñðTí TØG! Åõü‹Ï@Ï´gŒÄäI“ 7ê +ÍHbë³iÒ>Ý?ù”€ËWôÄÄ«·Y1½[•HCw«á‰a“IóÛ%ê²ûôš0©Tü¦_æù&¬ê#Aš(Ò´¥5Œ>Áx`ï6_È妅€Ûeó8£kÔÇgÈ;¨…|u=½õ» e ² lÇ õq½í|¡ï³‹WÂñèvlìÁÎ*4î*£G}¼ôÂW_ºxDKî_Ãw“°ÄáŸn ÒnM”çl_¯ŽU¯XÜ +ÊvÉ›²]Æ\ˆ£T¶Kúš²]6ÕšpÝ*Mò‘B@¤¯l +uèò…º …:¼‡B]ÆX€®îöÊilŒ¡±­Š\ î+ò$MÇ+r„{ÂÃsX‘coF3Z¥ËøÔ†r[¡ìH#ïÅ~¡r3¦=Í‘#j]ÔG«t.™4Zÿ%F›D™ÿg‰Ç;sôñ£ÅÊé½çMöy÷i¶Ìû«ÑD3üSÏ‘Úþ’þö_”žþÜV¥,±“ŽÃ ä—F¥ÐB7ø¥F'–i+ÓÕÿ­™õendstream endobj -1371 0 obj << +1896 0 obj << /Type /Page -/Contents 1372 0 R -/Resources 1370 0 R +/Contents 1897 0 R +/Resources 1895 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1356 0 R -/Annots [ 1375 0 R 1376 0 R ] +/Parent 1853 0 R +/Annots [ 1899 0 R 1900 0 R 1901 0 R 1902 0 R 1903 0 R 1904 0 R 1905 0 R 1906 0 R ] >> endobj -1375 0 obj << +1899 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [213.6732 432.1255 286.8984 444.1851] +/Rect [352.4539 736.7854 426.1073 748.845] /Subtype /Link -/A << /S /GoTo /D (rrset_ordering) >> +/A << /S /GoTo /D (server_resource_limits) >> >> endobj -1376 0 obj << +1900 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [209.702 354.4169 283.4678 366.4765] +/Rect [387.5019 705.7889 456.1739 717.8486] /Subtype /Link -/A << /S /GoTo /D (topology) >> ->> endobj -1373 0 obj << -/D [1371 0 R /XYZ 56.6929 794.5015 null] ->> endobj -402 0 obj << -/D [1371 0 R /XYZ 56.6929 498.9148 null] ->> endobj -1374 0 obj << -/D [1371 0 R /XYZ 56.6929 477.595 null] ->> endobj -1370 0 obj << -/Font << /F37 802 0 R /F41 939 0 R /F22 737 0 R /F62 1062 0 R /F63 1065 0 R /F21 714 0 R >> -/XObject << /Im2 1051 0 R >> -/ProcSet [ /PDF /Text ] +/A << /S /GoTo /D (zone_transfers) >> >> endobj -1379 0 obj << -/Length 2398 -/Filter /FlateDecode ->> -stream -xÚÅÛrã¶õÝ_¡Ù'¹Á¸Ø<9[{ãLãmµÎd:›} %Êæ„"‘Z¯Òé¿÷àF‚e«u2† xpn887˜L0ü‘‰3Í'‰æH`"&‹õž<À·÷gÄÃÌÐ,†úîîìâš%´¤rr·Šp)„•"“»å§é»ï/ÿ~w5?ŸQ§Ï„ÄÓïnnÿêf´{¼ûp{}óþ§ùåy§w7nÝôüêúj~uûîê|F” °žz G\ßüíÊÞÏ/üñr~þù«»V–X^‚™ä·³OŸñd bÿp†ÓJLžà#¢5¬Ï¸`HpÆÂLqöñì-Âè«]:¦?ÁŠ&# -ä$R % î„F’Qf5ø¯ó™ÄxJ4ED*D/(ÿ¶?ź©>A“O¢8 i!è3˜á&/.ÜÇ›k£{T¥›Xi]»á»ÁzKŠ2¤ Èp -%©"Jwß_ݺѮÎÜÑoÜ Úú 2xgMh’1šäOÓ{¥ÞØÉzc§ê½¤7ú½Ñ×ém@€}I,n¾ò"ðHÂ˼Ùf«ÌO6iãFeÖXÎpŸ¥Àï¨&ÜÇ‹kJ£Cj$H3ª,ÌÝ#èœJ9]UEQ=ååƒ{;¦ëMá¿=åEáFù?·='jš¥uU¦÷î>{L¿äF"‡Ñš@£¨©GôXե岛ªÝÐy.sGfÑ{7³¨Ê^³å˜6@IOÕöל,È7½1„œæ«H¦u¾Î‹të&›Ê?-s¢Ç<¼U«Áçt¹t¼Ôµ›¨«mãð楛 aAN9Òè«çbžÕ›ª¬³°,+›>¿í²mžyW–Hµî‹çöÓò˜z4C§G3r›Ä˜š®Ò/F 3™–{70ò˜g‹£¯Z3Ó©Ö¾FʉŒÅ0_c垭楣åbd»*`ƨ[±vïu{S©{ L"> €çÓ½xK¨[¶ -¢ý³º†)G‰úSffêtõ°‚ð÷÷>‚ÈψÑ;ÚRx‚QY5npŸ¹§±¡l‰Ü1íÅÒö˜&·,òº È—%‚{\k!F©ßFï SÝ÷sxÔužlÌ€{™JÂ\ -`ò"—G0 œÏëÌkâÃv ª¯3ê©($N¸Eòócf½‚˜®wE“·ÎÉ›GeŸËÚ¤n6†hvÛÒÚ |ÎËà{ìbzÞ߉©ç)ó~Ðú³øñë#[²)Ò…åš3àÚ’åÜc€)oÒÖ8¿[5ýpG#œüív ;0«ŒòG4/0 Õ¶nÒ&[;·$7ÙvÛà -Œtò§MnÏ@X9áÙrÙêÁ…Xw2¦ -H@„a=ÃÎÝbë àY¼õñÄs’ž~Ì<|ZÔ•5ãzS äÇ\]„sx¨4Ɔ‰Î¾fðLp$1á&©š˜TÚ}Û>LÜ`åÞ|ÃÛÔ»O|ˆÕ0ñ¼¤Û[»¸3Ȇ q*cBõ8:¨Z¨9Äf8An?#Ô’÷SËrLïÒ:‰Wgk¨1ã„0 -N1‚e'UCi¥Ôx-4k1Îb”NÈsTÃ^óŽ°ÝòM¶1 JÇ"œ»ÜÇ„efŽóGÆ -ý´KÂê·Þß‚*5æýHðÉ%â–`1!‰ ²$žP ÕÓ§PÙaŠ¤fòõ g1J«±sĆ޶隉¶#ó¹¬ä³Ó̧f¿ÉF¤·F$ v€b¡)iÜé&t‹ñ¡)MäL¿Bê¸/µ€!úͲZ§yyàiÀJµÐú¼Åø‚àŒh3&¹FJ%º/y:G¤§ˆ*%cß0žAWoÌS÷ÎÉ…d¸&s*”¶f*?'S?4ç97§4[BeÆ”ëfÁ2[¥uü’zÔ}÷“I8ö—·ÿw Ró`»È¡sÌ)Ϥ×{`i“µ´ìÇ£¼é˜7u„·„!NÛöoòyÞ¬uF„@á.™"²ŸÄôÙ ÁÖ;BÏ®y Þñ8acŒc–Òž‘¿Œ°ÍA2ÈP€EãbÓº;©…1ññˆ†fÉXI «Šì!õ™û—´Øe­“ÞŽ0§`ìe£„˜è6¹ò‰êÛWÍÄxL¨ŸP‚µ:åð2®6´úþ·UÜ5ŽràÖaÀå‡aÅ0Z¡à`B-¡µ8_9C -²ž H\Þg è«+ü*…ÂÄÚšSé¼W pœ ‹ølóIl@â´ÝÍïõC8,`ÁÓß«2Ëèͪ"Ci˜HI'±j^§n³±P¨.}>eXq|1ìçì¥Ä°€aíªŽ´\ºÖƱ"Ö{›Í·(p[ÔÕ:À8BƒH’ðé3jäyŽ:µ‡.âé(Ê£j‡RÏ(ðŽ«jx"\ʸØ/Š|ñ§©Ý×ažJ\íÊåÌîìáf ǯ }3Í”½öÓa­í‹â§¼yÔ’ÆïÃOf¶59ó~cfk^LQº +¦£ÍÕEµÞ䶰dp®Mj°ÎLüb¶/ý¼¥J!6—y“ÛxÁð°â¥®׃MÖvˆ`r6‹Ç1^Ú€i¼Š³ö.¨ö÷£ý½…}ÉçÄVõ:K팿»Pú„-"5b epbQôªÚƒê–aé &gWr¼¶ —okHŽ”kK]W¾çç;æo4óÔ)D4_¢~^¨òú6Ø]»Üøk[äØÑ¥¿°i˜½1-?ä9A`¿oÂ%CK˹ÆÑö_å³ïû2vìrÁv@ökaº{ƒEj/w\Ïmw¿ºÆªL¢++£]íòɶç•d†FI“ïéšk…4\Ytieow¨¦`*$¤nCŽˆ ÎUòvw)F4ÏDêõne¸µþÇø„„Î1äÉ -aBe_§iñ”îë~‹ø¸ß}&ÈÙ×eh;GéC5žîçcÄGFnýxÜž;L™¹p~rKRš³7h¯ 6›,µ¼tõÅ~D¸¶û -1)H;˜ |'XT3p¸@¤È³»“‡¢Ü\¤tÏðäÅìÔûú©´=Ò Í3e”&ôóöbÿõÿß'þ‚endstream -endobj -1378 0 obj << -/Type /Page -/Contents 1379 0 R -/Resources 1377 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 1356 0 R -/Annots [ 1381 0 R ] +1901 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [381.9629 674.7925 450.6349 686.8522] +/Subtype /Link +/A << /S /GoTo /D (zone_transfers) >> >> endobj -1381 0 obj << +1902 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [353.6787 434.7534 427.332 446.813] +/Rect [398.5803 643.7961 467.2523 655.8558] /Subtype /Link -/A << /S /GoTo /D (the_sortlist_statement) >> +/A << /S /GoTo /D (zone_transfers) >> >> endobj -1380 0 obj << -/D [1378 0 R /XYZ 85.0394 794.5015 null] +1903 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [393.0412 612.7997 461.7132 624.8594] +/Subtype /Link +/A << /S /GoTo /D (zone_transfers) >> >> endobj -406 0 obj << -/D [1378 0 R /XYZ 85.0394 505.3435 null] +1904 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [255.0796 581.8033 323.7516 593.8629] +/Subtype /Link +/A << /S /GoTo /D (boolean_options) >> >> endobj -1022 0 obj << -/D [1378 0 R /XYZ 85.0394 477.7522 null] +1905 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [311.5276 550.8069 385.1809 562.8665] +/Subtype /Link +/A << /S /GoTo /D (tuning) >> >> endobj -1382 0 obj << -/D [1378 0 R /XYZ 85.0394 352.0635 null] +1906 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [315.9507 519.8105 384.6227 531.8701] +/Subtype /Link +/A << /S /GoTo /D (boolean_options) >> >> endobj -1383 0 obj << -/D [1378 0 R /XYZ 85.0394 340.1083 null] +1898 0 obj << +/D [1896 0 R /XYZ 85.0394 794.5015 null] >> endobj -1377 0 obj << -/Font << /F37 802 0 R /F41 939 0 R /F22 737 0 R /F21 714 0 R /F53 1029 0 R >> +1895 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F48 1228 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1386 0 obj << -/Length 3099 +1909 0 obj << +/Length 3202 /Filter /FlateDecode >> stream -xÚ­ZÝsÜ6÷_±Ú™Já—HñÑMœ{=çÎöÝÌMÛy—v4Ù•6’6Žû×H€úØ·½Ôž±(@ø€Ì ~ù"×™¶Â.ŒUYÎx¾Xm/Øâ ÆÞ_p¢I#Q:¥úþþâÍ;i6³ZèÅýã„W‘±¢à‹ûõωÎD¶,yûáæÝõûß^.Jî¯?Ü,S‘³äÝõOWØz{ù\Þ.S^ä_üü+[¬aÙ?^°LÚ"_<à ˸µb±½P¹Ìr%eìÙ\Ü]ük`8 SOíß@ºe’åü‰å"³6W§Å²EZÈL+iÏóÂy xQ3Θ³Wy–çb<^!œgúüùj‘IÃõÂä9œ¹Æó½ñ;(m–kÅ=!gY.h(>,SÍ“{ø+’£óžÌ³0 §"ìÌâó‚gLY+‘hÒk÷ t¼¹ÞŠÅ ¬h1YTdœN9‡Ei1±Y0U ù’• +xÚµ[Ksã6¾ûWè¹j…àIÉi2ñd'•L²ïe“8msW"'"eóë·ñ4AP S™”Ë%üØèFhtSYaø#+Q BQµ*G±Ú.ðêî}wAfãA›1ê››‹/ß°r¥*h±º¹É’KIV7»_Ö¢è$àõëŸÞ½yûÝ¿¯_]–|}óö§w—*ðúÍÛ®lë»ëW?þøêúrC¤ ë×ÿ|õóÍÕµ½U8ß¼}÷­íQöãŒÐë«7W×Wï^_]þvóýÅÕM°el/ÁLòûÅ/¿áÕÌþþ#¦¤X=ÂFD)º:\pÁàŒùžýÅû‹£»æÑÙù#QVЙ ¤t4’ ¡”X•B¡‚Qf&ðæ¾îk°ª$ëã%‘ëzÛ™Ï]o;+Ûk/šv¨mµß?ÙëS_ïlkèÆ2únÿài«CíDÚ]}tð{w»ª¡ÙnúáôÁvüѵ5xƒ•lý¦;úaÖnëèËrÝÜ> ù‡IØ‚”ÔXÔ×Ç3Ž*½Iuó`”Pr]Ù¿Ÿêã“mÞvü+¥üñññRÑ5ª?U‡ûm»ƒî¶Ï>6ý…Zý¡qý­ýüÐ Óµ %Ãê2Ö§i›¡©†Úbv§cúÍ™fó44VpQÄSÌ83z·= :·õ`uÖ7«v÷¥6qê€t¨=¨?ßþìÜíÜH}Ý»¡A˜ß×­mõ5ôEªÛ…©'¸1“ëÅ°>Ń텙vøÇJ¼¯ë0)¶±«ûí±ù¨™á§N+51H•S®`ü¬) ƒˆ¢¸{ªi§Ö2K²–Žì°÷Žw+Û¸Ùày»©Öðí³‰:Ü“1UˆSË3ÀcòJL%iή ã’-0n„ÊPΣ¼£à¿mÚ»MÛ«¾1ØYIó*ÔŒã8CöÅX‰¿Æ99â\bÊtkdzÀÒ¾1pQÈÚá<~ÁîT.PI •÷@@-h’JËDhY,o„ÊÏ£¦ÞÒŸÕp:ΰO”êÁ€¬5£HÄ>0Y1VÄš|~öÅöL•À •â<KŽ¤*XdqŽ¿`{*÷O0Hˆ’ä½P š¤Òò ÄuòR-0p„Ê0У¦ž>ÖiäÃHrNóÔŒ +‘Û!H*D¬Ãççž·d2| 3ÀI&ðQŒ +‰IdlŽv¿`v*÷å´c°32ŽUÞµ¤I"-K;Q(Ä +¨þ²´£ÎÓ. ôˆÃ±jûÛÚd™›¾;·)ó(”We¹ D@Íh1*Xo->ñÎØ2åÔ”¥È$yX"ÈXIdnŽ{¿`x*÷÷ÊÙ(L ‘÷@@-)’HËS’).%_ Þ•¡žGq×桘Ëø8 zÔŒ"ÓŒ©2VäocŸ3gšõqD ãÙ¬ORF"‹²>ƒ_°=•ûbrL‘ÀTäP Š¤ÒòÄ%*ðR};FeèQzÄj?l^ÿD,BD^‘€šÑ$f G\Q«òyêÜŒAS +Ä°¢BE¸ŒlÎrÐá¬Oåþ rð!gy7Ô‚"©´,y©ë”…¬o:Ï@Êøk. -_×ËTñ<é?V¶Z·qeçð¥yÄ'Ú¢oÙïà©,Lp¸ZNDpÅ2&´¥íhÛ%Lé\Ÿ6íR°díZš4Õ+W™áJÓœ®/{·uuòÖ#ÅꆺºýnüRÅêùEõ câëR²Ä­ý«—³H9˜¾ -hųMëIabU?i›QG«“!ªÊÜB@Ä€¯™Òä8?Ec…ƒQI¹él‰ôa[›M8´<Úm›½zßF›R¡õÃÍÝÝÕ[lëu0dñXV›=VG¼ðdz\“ÅÀÉMǪ89ÁòªtŽ³èÃþÍà7d´z6»Ý¦rñ||>”Ô}šp£µ•£YÕãÁnÆÍÃc$Iýœ1¸Eg†çX­ìJåg Ï£Ô”ê G°!“}¬Pí%ê9‚ô¡Æ=X%ú”Ÿ‡ž­Ç¦¥®®£>Z¾Tõ0eÅýˆƒjfþ&F­gk%P5¨oä|Äò?²96|Üœc<´™.”‰hÈNᄹQìÄå ‚#6?6ûvDÆÍ Q˜ÿŸæP†€×Kq_W!Æ$†ö«|!m¼ý"*CÔÂü=6»Ðž« ÊAMÑgÝo^GÚeÑ \ć fèº#I#h¡R‰'rŸ>B¼˜Îâ‘Ò -À„¿G¢óh‰â6ŸÇ"Ø"k!cyMö@t,|ŽD€ŒžI§¸)×ÙõôªÎ£‹A7º4ž?V«³9tñãt€z¼Lt‚€³®ê²}Áo”»¦«ú -B¥/.zÄŸTŠp¢µ@¢&MÁçî8†6Ý“ðlj/´È“gç>a—f°éÍâx™\bo I -º×aöox 7Ø»-_°±*÷Q–a¡@úyï誄ޞf`íÛßï®n—°Uÿyç«!—×?}‡sr<‘8yM¤„ܦézß²¸£öâ¨ôûݺuvŒ#··]8Vßö+ïöþÀìp7Wœõ0 ±½bZ¿îbSªó>6P'«ê´mš¾;r0Æ|¹D¾.z :!{æb¡[eÌ\8ÝEˆÜȳ옞äl´ß ¢¨%§êp§[kÅ-ÿ¼¯(€ÀQrÓ1n¤r]@@ÎkgR‹© ’< -•Iuè„åjåv=F¯¿Ÿw³ýÒY‘›‚®qâ’ɳàÈp -‰8\z2„õÅÉÄe* ÅÙÚ¦Æò?Q'ÀGI}ÔüœÃMW˜3µ»Ò‰,8XÉÿŠÚ]w‚dQؘËü/«ÝEÆé”óqíÎÇÇZ*p,& ™c÷Þ+3`ÄÛÝ&ÍÕo**ûPZö|)gºŸßvDö^[&ÿL)çu‚}ÉŠÂØPOVpżfp{f‚öu0¨BlW=¥!½¬ú—4 ?¼›2^ºYL[¤:¡Çì4Á¿ ùŸëqç«~>1 7Ÿ‰á€1#¶AgÀ63€Ð*7ØG ¸Ø÷û!å5>Æp5’ 95ôÂÂ벟dÑ0^îûf Ù fÄ©aY!äAùtµ¿½•Nž\íZ -áµìè‰⌠¥Hwx®_êr[­ðe¿ƒ¼ÞÑD½n=X; š3U2¾Ú{Šƒí¹×íû©Á}:p|Ç|1‚[Å*ƒNT&µ‘Ò~r¦Í‘! T¿£Ã17ª¾pT€‚?h¹¯;º™BUÃΫšªÃÖ7;¿Š’&cúBwNø¢î6;Ó`w½0CRßì¦Fé;>6ÏØØ4¾öí[ªø÷ ê ¶ñžÅ š]Ö‰Ìð‰Ãƒ}ùðRËäúGCjõKO{¨ô¢B™›XÛ¼”y£Du ÉÂB`¿QØÀˆf…‚'‰è¾à¼ºƒTÜÿÐwÚOèˆ`Øf¢ªN}ÑésÌÅL,¥A•CÂð&Ì“³€.¡€C#ó¸¶ÏÕÀ°Ÿ³š)‹ñ²aož‡ßG,֨剅Mt¶Å鬠Uð!¶‘§rv®2+xüøDë~OÕüPc1Ž³†N8õæ0 Í•`Oƒøïž­·Æ\Ò¡oÌñà%ä>$y,JÂK¨ï«W¶EDÆ¥Õx|}Ak6æßcí•Ík®¨s»Æ®ªöq$UwÄPÝT1>뫬(¢E#AU$Aé4üébkêð4j±Ú·Ø_÷‡B#;ä$V™NØU6Õ¶jC¡xRŽ]mšÕ'ªH|rϾxvŽ‹3@!òX?~+‘ċ×JØ‘Í:Fô>ÿÔ ?óA‡ÿˆÚS_ç v[p†j‡ß7†\%V¡ãîÃ%öŒˆï¨d÷‘SÌ&pKñ{§ÿ”f cšå(,‰õM8ð‡MüdàÙ–ñÒ u¢2ýú @ý¥l«f‹Ïp¬íÁ·‰ˆúh³p£ŸMK Øzù{Ü„è|‰â’;§u³vǹ©„8SñªüèX9ÒÈŒqˆd§Üág[Øc1>Å>‰ä NPYœÔàó溯'ÕÁ  7Àl8ÀP0‚žÏû²î#o -ò€Àopšgʘhû4+Üý†>­çªÿ8ªÝ36 püûÕ—œ‡q¾çO|˜Z.†’ëIð6™•¢8—šuÈäɳcCøÍÿè2~?†[ò“3ŸN!­ÊTLH)üØwlö l²¹cÕÿ¿íîendstream +ˆ[\‰¬"”j¿g‘ˆÁn©ò·p>*¥÷à  S6Òs‚ž·>‘úr2HÙJ̲> ¼‰¬<û8Dn ô¡2üó(=⩯7/‚š5TÏ[N™€šÑ&®}ªº"u>ÏF¼`TRsDˆ,2%0öÎÈðl ìð SÊ}99°‡°¼+ I¥eÙÆ UÆRÉ<Ûƨól ¨ÄQ³EFjĬ4£@òª… kð7n~—Õ¯Z)ó¯Zh5¶béU‹Æ/˜Ê}9çd ›£bùé¨%EiyÎAE ^xÓ2Fe8çQzÄCÓnŽõí±îï7Cs0_ëêï«O³Ý=ŸR¬ïLó%™lÁó&ÔŒ qžT !Ë26ÂЖ(G[݈h«;RŠq’DFŠe(ð *¦r#ŠieξÍ€Q3äýíQ š¤Òò£Tgà ߟQŽy”YÞŸnmºs{ì›]s«/ ªÛíÜ·áJ ¬:5£O\U@d¢ˆ2|”Ûò…<拾3æ` +‘xþ&vɬ´²€"“e* À*N"˳¥…Ã/ÌA*7"¤¶Ö2-.JÈ „Ì;# I¥Y>n +ÁÍq„wÝS Ö3î`ÉÄÀ|Йè¯tÆg4^àXѾ%C­w¨úòòÔq ªQxXeÏXL$˜Ò;·ßWs©–©¯BV¿½ïš­?–Q^Àêzªf_}Øû“Ãd{þ#œàØ×õ™ógÖ7-‚:|á•éu~}”¶ãõÌõÕŸæ²dQòüè43zœ%S$$-ÑðŸ§>KŒ˜fÉP–Df²d¨Øìãc²Y²Ã/ØœÊ=“±Ì a¼dù™¨5RiÙ½æ|¸6Be¸æQfõ†n³kû¾Þ¦LÃò–< fF¸FL‹xøÿÀzƒË `m»öWŒéÝÉ.Üí5Øtc÷ÔV‡fk/¾}÷^7Ę'ÛSíûζNúX•n ÷ÝùH÷vþ}÷h›Õñ©iï¬Äý%Yë¥ßÛKËtýêÁöHâð¨'ï ÏøYÞ€Vï¯^Û6ÐßgsmuWêvÐ'ÿևǡ)ŠS·âÛÖǮúz@Ãþ«™e§Ï¦I¤(‰CAkf ýzîí0øAgv~¬‡fèí3 ½i¹é‚žµý<}ÜUƒqcîÈãn߇?uëödNRê»ÖBóm±òñ¾nksrP_…ÇÁwG;ß^¹x;êûS8vçƒÓ¶;Â$x´ ±Ý9?iE,\ˆè ’”øùЖèó3Ça—£Ø[hn;%P…@þ-¼oŠÔ7” GÓðÿõì++“çüf»?íŒõÔŸ1¥@Ÿ݃)h¹þpì]»LË3ÔkÕOìþ{ê‡XŽ=šú…ë <¦Ø2Áx$è…41“Òu¿½¯w§½W¥Úú£¶faiÄÐECR#ú ××îPp¬²W:éë´ +‚ªœêº“”)L¿¾õøÍø¹o.¦rµ‘ÖePø®nµFr./°§œ(t:sf +P šp ÄaÀ²HGôøt DCJþ©ø%¹£©0éPŸ 9$?µ J*M«¢ÇE–›Iå$\Ü؃Ø4" üåD–qˆ€'Î…¨t9DŒU^ÀÖÏ Ïì‰Ä@ZÖn.Ë…½SŸåÚÓèt½ïªmÙh­[6[ïöjðöÛÍ(œ`‡½¥1Y™¹i‚øØæ•^Á`'p/šN'®ðI2´Ü¡qhA|±ؽ2…«9ÌÍçsöp™ÖC=5I!(Â'Þ(Œ©>M<TŒ/óH#e="™xGxx?g=R£I±Yh¡0ŸÄP™óå©Ÿ¨ÛlõMj'Ϙ½¬‡ÒÌÞýµµqž»àËÖÝvk2 èjZÛåF‡Të4¸ÜËqå÷¶6çÿ±ëìþÃ\A¥•ñ¤ÁsdÑ)ÍÉ0#ª­šL«þ©ìI„Ù-4—Ö@¡ºÞk0›×”ˆpBÒ}“N-RŽöMæì$…ß7M ’¦9~èo_eØû3ü \F+Ö¨lf×þDthëG{ÃÑZÆ)c=­{IñL‰[£ +±*&kÔóEJ“bé–‚qê]½ƒô“Saß ütsõ•Eݘ$Y£|’¬{mŸtn†›OõàîèWèl¶Þ}­ "ªp«‚\æÓXP¨¶ûºô?1?ÙÙ›:·Ÿ¡Î3-[`¥†:|J‹›çõ¶:í‡(]vd›s#3Ï‘˜\¶¾Õ/:æÊV…h¡ä8÷›ûHÿ°ifÓƒgë_þýÔóË #eRžùî–úü qJiÅU‘Všî‡V©êÿ4ÚÌendstream endobj -1385 0 obj << +1908 0 obj << /Type /Page -/Contents 1386 0 R -/Resources 1384 0 R +/Contents 1909 0 R +/Resources 1907 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1356 0 R -/Annots [ 1389 0 R ] +/Parent 1927 0 R +/Annots [ 1911 0 R 1912 0 R 1913 0 R 1914 0 R 1915 0 R 1916 0 R 1917 0 R 1918 0 R 1919 0 R 1920 0 R 1921 0 R 1922 0 R 1923 0 R 1924 0 R 1925 0 R 1926 0 R ] >> endobj -1389 0 obj << +1911 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [289.8576 239.4581 338.5646 251.5177] +/Rect [352.879 689.0814 426.5323 701.141] /Subtype /Link -/A << /S /GoTo /D (dynamic_update) >> +/A << /S /GoTo /D (tuning) >> >> endobj -1387 0 obj << -/D [1385 0 R /XYZ 56.6929 794.5015 null] +1912 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [334.0699 658.2017 407.7232 670.2613] +/Subtype /Link +/A << /S /GoTo /D (tuning) >> >> endobj -410 0 obj << -/D [1385 0 R /XYZ 56.6929 661.3973 null] +1913 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [373.9 627.3219 447.5533 639.3816] +/Subtype /Link +/A << /S /GoTo /D (tuning) >> >> endobj -1388 0 obj << -/D [1385 0 R /XYZ 56.6929 635.5371 null] +1914 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [319.6839 596.4422 393.3372 608.5018] +/Subtype /Link +/A << /S /GoTo /D (tuning) >> >> endobj -1384 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F62 1062 0 R /F63 1065 0 R /F21 714 0 R /F41 939 0 R /F48 953 0 R >> -/XObject << /Im2 1051 0 R >> -/ProcSet [ /PDF /Text ] +1915 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [307.1508 565.5625 375.8228 577.6221] +/Subtype /Link +/A << /S /GoTo /D (zone_transfers) >> >> endobj -1392 0 obj << -/Length 3978 -/Filter /FlateDecode ->> -stream -xÚ¥ksã¶ñ»…¿Už91xò1ÓéÌ%çK¯m.©ÏéL'ÉZ¤dö(R'Rö9¿¾»ØDR”œNçƧ°»‹}òZÀ?yÚHèÌ\'™‰¬özµ½×ûþJ2ÎÒ#-‡XßÞ_}ó^'×Y”Å*¾¾_ÖJ#‘¦òú¾øeñÝ_ßþt{w³TV,âèfic±øöÃÇwÔ“ÑÏw?~|ÿáûŸïÞÞ$fqÿáÇÔ}wûþöîöãw·7K™Z ó¯pfÂûÿ¸%èû»·?üðöîæ·û¿]ÝÞ‡³ Ï+…ƃ|¹úå7q]À±ÿv%"¥öú"’Y¦®·WÆêÈ­}O}õéêŸaÁÁ¨›:Ç?cÓÈ*_/µ‰Ò֘岈„®-›E±V:pYÉ9.{,ärWm–ð×T ýæýa_vÓÃ˘¥Éõp‡:Ö !j@ˆÌd¤Ò1ŸvåªZ¿€”]äôÓ?îodº(»Ç¶.¨«9lÊ=ÁíÍ“M¸~jÞô\Õ5÷•ûm˜%5wnB»*»?ÚøË!o–Èà­Œ´–2ʬUŽÖþ°%Uy~,‚˜…ÔÈéç÷¶)¯êGCMùLÀ»Ÿþ~ûï)å"¢žûGžT”ëüP÷Ô¨œH¾yo†U‰†ë¢pÉ’‚pƼfº %:ÑjVDÆQ"“WÔëˆtA»iª\ýË®Ä:¯é Ù–e¹/×`;—}µ-ßä¶ù×Ùn‡Ýï_Nq}çô: -,˜Í‹GX3gªÐeÚ¨ñ!@#;`3ܶE»ëA5VmÓ“µ¬©£d´®Ü?¡ÀýùSGÊ¥RX:MÕXŸÊÇü©jQW´^8)Ã/ víÍ<]èÏé‡-¨6‹_…_7rQî_ È/÷éÇ·¬ófSv€-y£ýp£>LÖ‹u^ÕN1î÷yÓ­Aýàfja?w¸!5õ í×ó…ã£ÑîY¶xÊëƒs@mYJ¬Â> @yÐgh UÐà=õõ$‡éšƒy)pž‘^Â$¶y‡—DÂënª'6EÙ¢«ó'Æó²sKËñѤ×êªîôí¾#%­«¾¯ÙCÔ;ZZÏ:©öG¬²é»(lp4:¬p:ÖG…Ó1\îºnŸ©ßËõjx¬¥_Ç ‡CmDÜ¢“v}MÁ½ùWß{¢yÔ .ÔïïãTòeåŒÓR5ß‘•Z¢˜ñBºž*p÷™Z¸nK:iÔbS·pÐïýµH=CpÁÀlE Љª Ô /WÄm -Ú ëÔ…Du¼=Ãe©óínNê½AH³8á–‹eÜBaÔqËɸÅÚâ\¨Ç;ôÈ¿ -¡JžKú}F7' œµÁi°±÷Œ æ»]à y¿¡©–ÚF&•)»¿©‘žñ—à àöñ’‚¶éÀ{7°ðtÑÑùú-&n Q›’•¨êJ(¾DäØÙ¾¢pÚ·Eôó»Ÿx8¬ñR®u`z7â‚0ÄxéK¿pK¿c{>Üñ8Ý%]°à._}«+µ9Ä-+ˆö8Ê4ÖZÈóG¶å_hÙ~é{3b`ã`ÀJE€#F è õ b„yÐn}W%¡qx -Ý{ ¨ó¹B/^SãwèÀÿ7½óí¸yñŸC‡ç) R4w)äc8nØfÍù·u*­ä Í+@ß¡;ä5tμsQ´Éˆ~Ì¥3†,VX,ðFãD+§·9Ž²ô;¦.žÁŸ¦m–Çã@Çþ~ʦdR,\¤éž!PâP² «”œ¤Ç蕵é:‚8‘o›Gêx ögL£°¸ò 1Ìχ×íê3ë}¾Ù‚ÜP÷iÔCžöéŒç8âOÝò3Þ暴`y6,«þØäœò“†ànÒYËdÀii^É8†Xç-SÀò†ö¼aŠ#cÓäòîkfû±a’àÆ»“YÒ)ûv ªñ\ -± Mf QH@`Ðå›’ÝU5D)! ko9f1£âò–£¥*[µtA*3ÓÈ"Z&B-â³%áÔEE&IìXŸƒB`(褮c˱§a»„ÐÐ.a;Ø%‡îìv³]B©Ž)gF´£Q¢R°H±e{‚cá -cƒ¯0‚´e4£ß´$Êl‘Z$l;‹„À‹¤’(M@yĬ6N ’‰¬MìÀ"áê9ýŒ,vøãpº¿~Š³HNá"l‘FhÎö8™BtOÒÑ‘EBÿ5´HJ˜S‹„H\At².-Î F½EÍ1ÞOë1òqù£ ä¡ šq:ç-pë‰UªHôÛån ÐÌiÛz¥Œà;çÎ à ŽÕftÂç(ƒ õG½Vð¼×ºîiGVëì²Qb7ª‹Ôsg~].álÉGŒlk¬£Xéô2k†ŠqÙÒ¢‘ñ)¤IN¯¹Š€‘F0Óç`”!þR•áˆÙù†]yZTÂÒc«ÑYhp¿¹&ànX^òø¯œêt]ò«¾"“.âHGÉ”0Z¨ÉeÞ¬W¨8]í¨X‹{S˜Œ)4‚õIç ¯RhÈ`|ŠØ—_û¹º«Ž2|&"¤7«8’fRé}~¬V -¿ð—¤í2øauÓ Ávd¶$wœ–Ã}Α¿x¸Ô,ÞW$}\·¡ß–Ê’ît´3!§ÕÞéDůœ4‰B\zt•HêË®Z¹‡k–_—>¯£8=¼É-…js•÷„+ïI¨²Ó°¥ŠWêq'9¿ƒŸŒâ‡åªÝî€îvœ!³‘z§¶Fã™êÅÇÖ½$áA) Åÿ„^‹ ƒ {Ðá/'öVc¤¢ -9Ôô>‚N#›™l¬þb«DŸ“ \°,É+¢FkíSmgÿaÅºÍ ¬9ÎÔ ÀKC)ãlä¥ñEÇÿB˶ۊ9ÔµÛ’ûÖþÌ•Õc¹úÌt°â;ž¶Xp­Yü<{Wî‘^+0(!—‹(QÉ$JÃÜLE`8Õåë4ÃA¥2”-ÎsPã¹pnøWßåà*W‡:ç’ë)[3é£Áp,X"s»9(ÁyélˆÛÑ>EK§jÚž:¨ôåÀµ¯)ÎU*‰yš¿ûüyî¨"Ò:™;© !èê&pe“*q™»:¥¥Â½UáéSå°“‡Õçˆ6Jc“½F¤±ÂŽ¨¤E·˜¾»Íx»¡Õ€¦„õe èêò-CŽÑÖåSYbÞy‚ý.Ãú%é¢Ó;)Ò‘æé3 --¦Íâׯ™‘6hBÛඛÃ>'ŠËsCé¸âb1x¾ÜRxg\u¼»DŽLñ9P x³!ÐLSÄuáÚ3UYÆgz×ÀŠs΄?ð˧V„¥‡ˆ¯ûª(œ™Õ ?¥ô(”Ž -팰¸z»yÈ;*¥ä4 «jVõ¡àg \tF>6‰ {RÿC Ե‹k(Øu¯âcÌ a v:&‘ã«uÆa)‰$hÙÅ©T%Ü&민cÉì:± -ŽÏ'(.G˜¤§úgEп3Q:–‡2 fçb”>Ä:¥,wê -_”–^à_åþeðŠ:;>¥RÅÀ‚^&3`ÍÐ9Ž‚¸0Ü#BýsŽˆù½NX_TÇU_¹š )/öc¬Î/Xü)ü« Œ†W,lðç0ì‚8™„Îc5”R¸Ã¾£$Î@·óæMÙøŽ0ßh˜_W3Øú…€ Lm$Ž†r,©–]"Ðg›„2Οç^¢äøäðíà›/øzÿæ˪æü}²h -Æ6Ê_έ™ rH®"“×þ™Tž?áà®CÉ€‡Á‡ñqMpµ*w΀!)×í±D˜- -ªìvüýØ”¢¨ð’8ÙÚÀÖÙ*8Q|´½|CÍŸ4áN=X"Œ+å_†ë5Aý¡a"¹,nCvãfÓ^æŸÍ}H* k’“"˜ß“ëçøÜn6Xëç*ÃÜWK¡JoŸ¬*Åä Q -1ÿHŸ{Äl»ÇöàBE€iQ°CÒêzÄ—c¶¤¸¡¶V%¶²¢èTÆü=JÌš@N?^Ïlò)2éUâûüsÉä:Yúº¶~*ç_Z)°n#ÇKµø°¦.¶½òøÑ[¨ÕÈÁ‘,¦V«’Â$ÍÜŸ‹Gñj¦i0û—lRaÅàj¶¥ß-÷ß(ñA*¦©(óšo„}GJæR£)™c»¶ñ–*^]=) t19ÐåïõèíرV³Ä`î†B#M¢×A^¸»ßqMµœÜtäÕßÌ>a9!˘R#„´•ûÚÁ¬}ez±§mJ÷hØ?\ƒ'6„ñÀcuûÌIeA.Û‡%¨ ¾äàÞú°ÒPBbê1ÆuÄÑ×ZyÕph;QÕCCV¢˜»§À×™´'RByËvÖ%Ÿ†Q OÊdØyZÍ6rnZ¦uNß2Wp`øµ¦¼@ÃóꊲTËß Ñ Æ ×Ìð5Óhé{xïgýÇ´}0š©N'ObƒÛ*fLiP¬)wMvž½N`Õ þþGy,…‰@Ÿ<6Š?(2*q<ÆŽM¢¼æ©tÈclúš–ævŽQØõÐ?rí‰æç ¡VÛ]ëªÌùe..–Òâww´÷¡Œ?ô\(Ámšÿô5Ô#ü -{&øáëÙÿûcïã—ð’?ü:n¾n*â(U®béˆr_vÊ)åC«T%3¤ÿšY$Vendstream -endobj -1391 0 obj << -/Type /Page -/Contents 1392 0 R -/Resources 1390 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 1398 0 R -/Annots [ 1394 0 R ] +1916 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [334.8268 534.6827 403.4988 546.7424] +/Subtype /Link +/A << /S /GoTo /D (zone_transfers) >> >> endobj -1394 0 obj << +1917 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [353.2799 352.7282 410.176 364.7879] +/Rect [337.0185 503.803 405.6905 515.8626] /Subtype /Link -/A << /S /GoTo /D (zonefile_format) >> +/A << /S /GoTo /D (zone_transfers) >> >> endobj -1393 0 obj << -/D [1391 0 R /XYZ 85.0394 794.5015 null] +1918 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [364.6945 472.9233 433.3665 484.9829] +/Subtype /Link +/A << /S /GoTo /D (zone_transfers) >> >> endobj -1390 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R /F11 1397 0 R >> -/ProcSet [ /PDF /Text ] +1919 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [374.6372 442.0436 443.3092 454.1032] +/Subtype /Link +/A << /S /GoTo /D (zone_transfers) >> >> endobj -1402 0 obj << -/Length 3086 -/Filter /FlateDecode ->> -stream -xÚ­Z_sã¶÷§Ð[陈%þ’hžœ³/U¦ñ]mµ“išZ¤-NhR);î§ï.  š’ÜIÇç°XìbØ Ù,6S:Ö†›Yjd¬¦f«ç‹dö}ß_0Ç3÷Lóë»åÅŸ?‹tfb£¹ž-YYœd›-‹Ÿ#óø$$ѧ/·Ÿßÿãîê2•ÑrñåörÎU}^üí†jßß]ýøãÕÝåœeŠEŸþzõuysG]ÚÉønq{MCÅ¡w7Ÿoînn?Ý\þ²üáâf9ØÚˆüvñó/ɬ³¸Hba25{…F3cøìùB*+)„§Ô÷½vè”ÿ¤ÊbÅ¥OŠX–M{™Å)cÀ”J'‰I/s6åeÏ…^nÚ¾z|›e¿MfŒÇÊðlÊ}§}àšPÏõŒ¥±–CýËu ŽOÓˆfÀ‹¾B&¢ªÁuåªmŠÎReôPö¯e9t5EÕ<‘€®ì;ªµÔM¶í¹ìºü©ì¨ç±Ý9§â?mSÂF™ 'ô˜ïêžU‡Î™Í…ŠMŠëÁXl”âÖ†' )iÿü;Q‰‚ÿ5Ýäc=ZŽ9—±I´¶B%WzØõLÃ?ØÌIûvWÕýÜúŠ۾”[ªW Xñœ÷Uë:шÎ) -Ÿ€*˜¶’ÇE¶&2m¶—,‹Ú—ª@ÙÞöÙñ­Ëz󸫉±¨ò§¦íújE³@B¿&Q»§5ȉÞìž¼6\ ¤= Æa‹æovM¼èñäÐÕ½¼H£MWîŠvÞ·›y]¾”õ¼hŸsdÍ—¡Ÿ™à±Vi¢PÂCÕNâiÌS&“hAuïWŽ›˜~+ Í—û 2‰M–y®UwBQÊq:g…7YdQnÝæ­Ë·=Õ¬«°›šÇ õR•¯ÔÛ®+Ëc ¥¥ˆS-,|PßöiF•»)¸ùßGò;©há}¹r[‘»‹¹x' -øCñxâ¸ÎÌâ½4ŠEz0‹PZ×O¬¢0±H3}f+c\:®×uµZ“ت£²+a±òß'Ñ#mþgê³»+{,­Ú0EulŠ<Éb {×i_ÜNLЗ¥’;–oÅ´è°Dôä:Ê›7bxªÛ‡¼ö˜–Å©`©4:~¨1`Ï—¶£F·³.0žSsf ‹3žùpËëº}ÿ¶+·o“Í"x‹–4nS%ßlê7ÒE®ZOуU=Tp’F‹G¢½µ;ª<–e=Œ MYŽä4U—?Ô’­K˜†#[¤#œ·úÀ“BgÑΆ°”‘ 28IHǘ}ixdÙ!Œ·D_ÀŽÆ !=±þpDÀÊdç ÎS•ú]â@%¿‘ҢĪ±'%Òó†Êò÷M]­ªžZ~œ"Ìʱm9çZÅifÔ¡{N !cÆCk¿Î{:¯àÔX­í‰ Ø'TYÕUÙôtb@™KrÀÐXðDŸÎ„B®ã™ÐÀeýVn;°‘^“ÄRQëx&´†~0pÌ‹TjuéF6¨·ÞS‡(ÄúºÝÕÕ)ª7í¶w£«œ*® €³Uʆ™Mþ\Nœ“<…ñ‘ó2Å|>Q«~í´¼m¦ŽL©b!ŒG©åOË)$ƒªð¿¡@”r¡q¾u.%ôü¢§±æÃÁŒYŸá.)‚Ê€ÔØ@ŒÇ²÷½äö¼¦Ö°dØò¨Û²ã¼·ŽpÕ…©ÐÑý¦\ArŠ19q4%¯eéh)œ¡ «” ƒ£˜tç‚Ìey+È…)mšÝ*qÛ*¸uªòDrg‚«3p@Ï…s]CZé÷æAÚ@*¥õÍׄêƒ]†¾•éH7…¡ÖûIØVïÉCbÝÇ!àúABÅ!T\áãªÖÑ¡Ìcq˜±X¦Ú¸Å÷:ˆ\õa¢’é0„äâ)Sâp—|(a¬:žLóy"þçБK -’LûØ눎g´-é¾. ’é1t+8NVëª xé¼ YühÜ}”Kcfó ’­Lzæ±…«¸T¦ö4åÒã(žÊÞO Óo—yÇã®±¹0˜ø% Øl«çÜnl춛Öf2Òa4]n%3…D®\iÓè„$¢qW[ ú¤”ä\š(•Ã½óxr³ 5­N(!'\å]O ò ªK2R‹«~çó›çï^an?  ×–jp@6uà`oñŒ«Ñ'9ˆpßN9æ«ÌÃû€l”Ã'2IWïÿ‚wRJ8·åi¸ ˜Ž£g -Òk˜Þ¼*Þå:6 òSª=Ï{Õ|œCý˜¥ÑâšÊÞ”úG¹l„rî8û3ô¬Êꅜѓ -·´žP»¤.ìÎÅtÔS0tnï×.|€B˜é_‚ %Ï$Ù®5Obnöíq´ÌÐë3n…‘ph9óع¸Žïoîþys7uMQ°€ú0ÙAÁÇ’Ó!ÿ¸¢¸£yMŠ{ûcàª÷àŠ"—äƒd=H°{È]ÌaR<ö·µŒ¹4£ÌBv ¤¡Ü#¶"aÕÂ4”9ôz ÂÆ€AV°+÷Düa“0k{ ’ú ^–%=Dî[ ‘3†¤Q:˜ú42 f™*~z–œÁfŽÌ‰Iz윚(Ü847ö­k²ÊwÝ‘ì@Ä=°ÃÐBéS™‡€@Òïa»Œtc#¼µ2<·œwDu'+’ì=Õø+1&OV;h²¦2ñY»²ö‰“Fr¸›9éÀ‰»ª„{¿ñATMÞ~%g±bãLûH^I¦62¢rJnÂäô;p:ù|ó¼éߨú¯½úÞÚE"ZÛ%PÒ?ñ)xV„VIÒ‘Å?PWâþËÑóÆ »½§ÒôÜT8mS¿áâÁriž ŸÀ¾턆}i£g;K:ˆ&ƒ|y¦¼Ž‡’JÂ+¾ JÝ®<›¢™#Õ§MFÉ– Ò{£ýKÔ^x0G5zBRþuIG‹¦/·MÙÿÉÉ! ð¨!0Až¶¤wå±A,³ŸV^2¹AF&ä0g ¯Z:T…žÄ Š!ÓmòUéúݶ¡þÛŸ®¿üxµ¸¥õv›¶éh€ ³„ eîÑJ$Ì$|¢®Vó©|sWçöªk?ÙðATª†I§ÞoP¡I Ž0Øpð­V®(Ü„i¶@ -ž[¡u÷ù ã,scìjïûT$ÜUè«ðæØꮥ¡U³ªwEyôÛ|4cÁf ý4c /¾¾h"Ù-HÄÀ êÃÀÚoQ䀳ã©) ô¡Ðƒ$ÕUóë)™ö…‡ô—,ò3'ÒnæSÖ=ä«_ÝSÜÁ‘`æÌNÔvͯMûÚ¼:28ƒ¸AˆsáN#¬å}€C »ý ,J¦g{ÃfeÊ¥Í-yWØBÔp¢j÷@S¼¡ü½êìWA¨ÛEAY® EõââÐÞô°ÁéX -”ª¾ls¶©ð Ž¢„¼nk¿í¿ .u~€a ¾€:#zç윊rùÎbûЯŒU…<ªœtþÒ/Þj·% RW]x9érû êþrìÃT#5ìô_„\ö®§^V±X È¢ï9pŽ”¦ ÁEð¤RÏô^éáó œåƨC¥I¼¸_]_ßÅWw_ñÿê¨Ý)äæJŸùë‡ë„Ýžë¬Ý§”îí+¶;TÊà¦ñaËU7JaÎXp°Üsµü”Ò½åc¥Ó–‡J¹‚ÄO›[o¿ 2qÆú€ë„õžë¬õ§”î­+¶>TÊcü þqë!føqû´õ× ë=×YëO)Ý[?V:m}¨_Ž!Ge&û¸+¼(v@Àužë¬N)Ý;`¬tÚ¡RØ°x">l?Üú´ùÓqë=Ó9ãOilkœ4=ÔÈ•ŠÃßÚ¯U,ø™Õßó·Þñœ3þ„ºÁö‘ºIÓuIüÇ~_õY/á}VL¢üºÔóÿÝÞápYƧ]ÀS|Ý!nRöŽÍß¿ùBÍ'¦þ_å/*endstream -endobj -1401 0 obj << -/Type /Page -/Contents 1402 0 R -/Resources 1400 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 1398 0 R -/Annots [ 1405 0 R ] +1920 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [292.0276 411.1638 360.6996 423.2235] +/Subtype /Link +/A << /S /GoTo /D (zone_transfers) >> >> endobj -1405 0 obj << +1921 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [55.6967 639.9582 116.59 652.0178] +/Rect [319.7036 380.2841 388.3756 392.3437] /Subtype /Link -/A << /S /GoTo /D (view_statement_grammar) >> +/A << /S /GoTo /D (zone_transfers) >> >> endobj -1403 0 obj << -/D [1401 0 R /XYZ 56.6929 794.5015 null] +1922 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [460.1655 349.4044 533.2211 361.464] +/Subtype /Link +/A << /S /GoTo /D (tuning) >> >> endobj -414 0 obj << -/D [1401 0 R /XYZ 56.6929 710.1097 null] +1923 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [368.9978 318.5246 438.8121 330.5843] +/Subtype /Link +/A << /S /GoTo /D (boolean_options) >> >> endobj -1404 0 obj << -/D [1401 0 R /XYZ 56.6929 686.1175 null] +1924 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [293.1435 275.6898 354.3435 287.7494] +/Subtype /Link +/A << /S /GoTo /D (options) >> >> endobj -418 0 obj << -/D [1401 0 R /XYZ 56.6929 367.6759 null] +1925 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [329.3035 171.0954 407.7186 183.155] +/Subtype /Link +/A << /S /GoTo /D (man.dnssec-keygen) >> >> endobj -1406 0 obj << -/D [1401 0 R /XYZ 56.6929 339.2505 null] +1926 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [427.0093 171.0954 505.4243 183.155] +/Subtype /Link +/A << /S /GoTo /D (man.dnssec-settime) >> >> endobj -1400 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R /F14 740 0 R >> +1910 0 obj << +/D [1908 0 R /XYZ 56.6929 794.5015 null] +>> endobj +1907 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F48 1228 0 R /F55 1311 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1410 0 obj << -/Length 2656 +1930 0 obj << +/Length 3378 /Filter /FlateDecode >> stream -xÚ¥]sÛ¸ñÝ¿Bs/¥f"„ @lŸœØN}ÓsRÇ>\˜3©ˆ”}¾_ß],@‚%%Ídæ´\,°ØÅ~øø,„|¦bŠLÎÒL²8äñ¬X_„³¯°öá‚[š…#ZøTï.ÞÞˆt–±,‰’ÙÃÊ;K±P)>{Xþ¼ÿç姇ëûù"ŠÃ aóEœ„Á»Û»+ÂdôóþãÝÍí‡ÿÜ_ÎS<Ü~¼#ôýõÍõýõÝûëù‚«˜ÃþÈžpdÃÍí¿® úpùÛo—÷ó?~½¸~èuñõå¡@E¾]üþG8[‚Ú¿^„Ld*ž½ÀGÈx–E³õ…Œ‹¥S]|¾øw ·j¶NÙ¯§YÉTgœ¶rœ±DD¢·2—ž•3• ZùKÈÓ}Uy(a“Lgþy\{ªC¶Qä±å!À2³å,ü©·ŸvyÿižEÁåÑ›S’'glæQ°™£:o³S\=›í³¶™ÏV±wì -t'ÛEßgƒhc~ÆÑ X¢ó8ÁÒÓç´úÏ+vƒš~ŸÖ!Ø' ŵ=ªz;ªóŠŸâêi¾ÏvZuŸ­b×? }¢B&“,=­½Ou\ûžê¬ö'¹Ú°Ô~Ä6û1í“%ivÆå}ªÚ;ªóÚŸâêi¿ÏvZ{Ÿíåi/C¦”’g´÷¨Nhï¨ÎkŠ«§ý>Ûií}¶ïŽj?[Dpn˜$À!c)@fÃõzÓ½B"çqðWSëAäÛ9W&|«».¬ìWÞI÷dÏ¥~!¨ÒϺ²ÔKÂ5ueÏ7ao3lm-ÝŠ–Š*o-êöŽpU¶ÈIzB⸗5 AEβ8ŽŒŠVeý¤·egNI°2{š5-6›®lê––Ê!AËÞ€ìkuCÈå `x°àÄl»ÑEù% #ÇÛ˜‘šQX3‚ê"Œƒ¼?˧yÖÛm¹ÜÓ‘¼žŽjlÐ>ª²í,zE¿ž¬ðe|Cðk³# Èë-}ô ÈfM7œ@PÞíZ…P TȲY5[ôŸùzSé¿£6oo$÷<;å, ~eœ­0 cÞ±MÂ0ø…ýò:b‹ñÊœq‹FÈ«jæ_g»¶¬¿žt@‚å’HŒOb›×_µ… ¼³º$„ó•7xwéÀ¦}jv•¥É+¢É—¯Äö)¶ÌhÎl-Âùã5’o Cf™ "6º60ˆ··ëhvÕ€F3O)wðÂ?Ù(•Œ2”²m"#èÓã”2ùƒ¹ëT[MΙ›|«ëŽ°pÍø,Ïó’y¬ -Vs@QèdCœ¨à¯¹ÉÝÚ’õ/P™—xá³N‹yUàR¹ý´°«—zKà‘0ï%U±¿WÑ»Ì^ék¬b '2¸éQ.©`M¥¬ƒ#Àp&'•ÚG‰Ü/é¦àíB!veÕ-Ì¡†DïIÜ’@Oó x){sÕc;‚Ôk 5î&1T!JƒÚ!Ì…A0çõU;¦_j½q†.ëÁàlµîåóÝYf)KD"f~(ý\tâ;gI6[ ÚŸ{;P¼*. ŠYš¨#ƒlfýȥʆGOŒÏz*¼!*,è1<(Ü¥dŠC­íŸ{X¸;ª ö£ð•XC]3âÿ+ĦM‘/&å d20¦6»nœ!ÊÖã•ã/åf虪1· æóÇK©h̯]49ëÚšGàAP?™F Y²lÁu_ –¶úôjÞ7}:ª÷žÿ7»ôCÈ @.EBý²—Ë)&à»ïñù`ßP’}çÙ׌ j{Œ7=à}'nö -W ˆ;xèQ ‰§OjÇaÃ#N‹ÄMã½×w<_€ë[ƒå¦ïÞ˵¦ -<êBD4AÄ¿þð„q5_ðšìËå²Ä±Bnýë³.:ÿ¢”OØ×6áPA¥š¤¡W  -cŸÚ'¤„gÃÅŽ3t‚•eÛI¾ ª*À•d!K9+…G•Èìù¦åEjâRÖÞZ±¬$´`šT@•ë õWÏV•ÎQØÆ{ÓÔ­]‚JlEïèÂÎ߸da•üèæ ó,4ÍfH£ú?Ú&CïÈTð_z!a mîÑ߆ -óáŽÂÞ†YAÊ–@ζÐõ8ÐË¡Ó‘¹=s0‹a÷Ôl»E±ë&çPX‰F©Í5øw iÐ1QÙ”fÐ çuû¢-öþžp×tÚ1É» —€è` ñ9—àä’+Kf¶²yJƒ$ƒYai­±5/Ûµ-‡ YËB¬MGSG;qóþk\šz±vÓ4r¢*ïöG}¹tu÷ÙMéœ@} o»ÚXxhC¼i¯È"ͼÈó]GÀ-/3µ4~pý ‡_“ߧپߣÁyà æ^ñûK‡úÏBoº½­÷÷­î,[pØ—°Á€Û4Œ#¿ýbÞ\ô2MèG]5/ 7 ið¸ëhÁ>«{!+v"»Òˆ¡v‹c]Œ°¯5Í„òº«^çœóÀoo-¯Ò¡ÉíÊbWå[ ›Ð š;à¸BMžµ+ù´­Þ¬.³­iѵ¶ØsÍjm¿wÄhÙåîœxðXîë¹Üv¯¶×–nÒ¥p*i϶ƒ1@-u¥¿ænº¬Ü¼— ÑÄkðµÚY¿…»>:`‚´‹²ŸÈáa?Éùéÿ{`É” E äa1 „©(KP&Š}Éc¡X¬¢tBôÿ‰)4endstream +xÚ­]sã¶ñÝ¿B“—Ê3 ì½Ô¹ø.N_j;Óé$y EZb"u"eÇiûß»‹]€¢ä뤓¹X,û]Èr&à?9ÓÊAÎâ$ô”j¶Üœ‰Ù +Ö>œIÆYX¤Eëëû³7ïƒx–xIäG³ûÇ-í ­åì>ûyþîÛËï¯nϾóÈ;_¨HÌ¿¾¾ù† }Þ}¼yýá§ÛËó8œß_¼!ðíÕû«Û«›wWç ©•„ý>S8²áýõ_¯hôáöò‡.oϽÿîìêÞÉÒ—WŠù|öó¯b–Øß /H´š=ÃDx2IüÙæ,T§Â °òìîìoŽ`oÕlÒ_¨´§ü0š-YI<­eá Z[Ä¡ð¢Hj§e_NiÙb¡–7û²-›´ióÝXd^¤µžõéœî°&Ž÷{ÇËP{Q,äðü»<'µ·kdy³ÜÛ¶¨+ÔÈØH˜$ö„&À”££#éÉPHF.ª± ¿óƒœ´¶[ÍhpÛ“Ø¢¿"ðU’wÙI†^)#Oð£C/¾:­x‡õÔïÀÁÙ‹b‘xqù¯¸Zë„«Y,c$cž_„ðË|ñXï6i{àqø’èÓL8¬ .Ç åÙøc§­ÇM 3â@KOÄê„ã©ØÓI0÷”ã1ú+rP=êxjÌPè'žR¯Àa½ÂÈ!µ“žÅÚÓRD§=¯uÜóž˜UM“/ðo¿Ëm½(*9ñ…ô|ßO³â°&xé‹ï гñòÿIx'%‡ÄÄuB¸ƒ<‘=ú„:üWÄ?¤ûÅ 0LÀ_ g¶ƒÃz‘jÎ GJ^„re€²‘§tB¥²ék/„bB1ÿæ¥J7Å’Døi›¥-[òǺ,–EÞLA€ÛD^)ʾ\Ç„‘©càÓì·Ûz×68Sóö¹&pZB–©Ò¶xÊ °ÉÛu54G1ßÕ.­Úâ\Ϋ–e‘W-c‘£Á`W¬Ö-Ãj:h›ï0y0srÁdoäjúèÀJ†²Hé%J‘v~¯«ü‚°¬+L‰«ýî\êyžôá¥óøCƒ=À„M¬iYÖÏ :}ê*÷=-B›QÓ*›¢˜xÆ!R‹-ÚæeŠ¢ò9fìÚÄ!‹CR4[tÙ§¼|9—R’߀5±"K 2ƒèJb¡Ìîûi 1ù¹[à5/ˆ¥e~Y¦û̈xþ\ï>544&ÅA“nìjúBƒ”q ÐáÍ·$ÅSQïyå)ß5 $ÏЉð‹.éÑ𺥯ñ+F[*Zï2zДÃQh]‚R¼Ëmà_›¢i\ÀG‚ï¾5iõÒW÷²6ßÌåÂ!Re$ÆQQ):¢ç<Ô˜%fÚI!’ä‹ï5áÞ6œó“¨âc-“¡{²¡Ú!H¦óºÒPuËÿáú“8™`,ö­KÄÁ<ÿ-EWoÎé!è‘ –Ò”óÁ[ŠònGMÅÑ2'´4ËX®† +>£ª[v)?ð|?d8ÚTæO)ªc®qÞ­Û_ý…Uæ"Ëé’šª£ lÖ¡«µ¾@‘:ö­7w…Æ‹­0ˆ¶YDsoó\´ËµÉ0«y€¼‡;ëÍfºÞó}(ÚÃ@c*P{‹`¨Â²^¦åÛ Q€žˆÅôÌ]›Ìï £…)±1HS™F³R÷D†‰IjRuÇÚ ‡f*ÄÊóC×áá½—Mð˜8²éÐDP]åà†t7u‡ò#8‘k0àøSþÂh& Â`[¦KËw;É?=t\péø^¨¥†'QS’k$d]oÓ8«m˜fshÊîòd»ö^$ä—HAÀ"ÿ#÷n†1[˜ŽÉ[EËm°a¯þÄ£âSÞùÁÛöu7ã-ÿMhëØÜÔ â¨ëõp†~Ù¾lsšýÜiô뎈]xÕ ®è¹ ŠzÒGQ÷D€½7Tî‰ Â‡ªâ©(óuUJÏ?VKÞšÒ§k±aë:å}Í~¹„èÖ¨¼Ô–”Ý^fÅt€Ö¸ÈÈ6wPsù0ÎvÅêL²æ(T³Úv)!Y2“—Á ªéû¸ß±ShÝ=ÏnW¦'¶ÏÀžîôK‚öªé„+yÝ“€ÏØš̉íM&rí4‰×>u„ºÿ`Ó¡—ø „k‰ÓY÷‰¸õØ­kK€À&ƒ0]Ú\›’qa¯´1rÎ%f…³ÊØF.\yŒ:ûá̾l"{ð1õ¤Øc&&Ÿ:njtXéºÁªSS§Ìf¦Â=‰ã*¶Ö&Ž ‚ê¿u@ØT×.·‹&/§r¢ô_º7ëIZ>´cÊ¢Dm%{>¶—„¹®Ÿó'‚ räúâ*KíÃl'>%3Ê +“€3óF(ºåÙ°O–·7¼xv{¨[ƒQڌȽr)>tb‡T~R{À‚½K¼¿Ëht";[ýŠXñ>§_Pï6õ öçU¾ªÛÂ^dæwBW8zàæûÃÝÝý‹;iû>Cðh‹†ó¦?O™`?èÒõôÁ‘KÓð&5ÿ>ß=ÐSTÝnújYlÓ’¦ô«…êvPË„Ì s½¯ œÚÞ^~ʼn½(q?~Âîþ‚õž—Õ›´¨¾šêé´¢I4xàñÙå-#‡5„Þ0°Ý©SÇ!uÀ‹£Ð"º\#Í-]®á‡©Ð užRèYt”h4Ý‹“ﺨ¦‡Bkʶ5¿¹¹›&—mÓªá7ñöó.úµ›Žm`ÈòTEîó×W[‹ÚÿMe»ï'u e´ŒÜ+ì å*áR(wxiàol©½ËSú˜òpñyŸ–ƒŸœ¤kÕ¼c÷(cý‰¿C€l»?ü7ÝL†pMj}ì|Däi?‰-S¨Š$s®í)íǬÿ¯‡ºoendstream endobj -1409 0 obj << +1929 0 obj << /Type /Page -/Contents 1410 0 R -/Resources 1408 0 R +/Contents 1930 0 R +/Resources 1928 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1398 0 R ->> endobj -1411 0 obj << -/D [1409 0 R /XYZ 85.0394 794.5015 null] ->> endobj -422 0 obj << -/D [1409 0 R /XYZ 85.0394 201.4944 null] +/Parent 1927 0 R +/Annots [ 1932 0 R 1933 0 R 1934 0 R ] >> endobj -997 0 obj << -/D [1409 0 R /XYZ 85.0394 173.9833 null] +1932 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [317.0267 736.8562 385.6987 748.9158] +/Subtype /Link +/A << /S /GoTo /D (boolean_options) >> >> endobj -1408 0 obj << -/Font << /F37 802 0 R /F14 740 0 R /F22 737 0 R /F41 939 0 R /F62 1062 0 R /F21 714 0 R >> -/XObject << /Im2 1051 0 R >> -/ProcSet [ /PDF /Text ] +1933 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [356.8967 705.9305 430.5501 717.9902] +/Subtype /Link +/A << /S /GoTo /D (tuning) >> >> endobj -1414 0 obj << -/Length 2658 -/Filter /FlateDecode ->> -stream -xÚµËrÜ6ò®¯˜Ûr¶D„x‘Dåä8²£TlïÊJåà¨\Ô Fà ->$MvóïÛ@rDI–][:h4ýîFtÁ]ȘĊ©E¢‘•‹Uy-n`íí u8¡G -ÇX?\ž|÷†' ETÌâÅåfD+%QšÒÅåúSF–@! -^xÿæüí¯¯–‰.Ï?¼_†LFÁ›ó_ÎpôöâÕ»w¯.–!M% ^ÿôê_—g¸;?œ¿ÿ! -?½8{svqöþõÙòêò瓳ËA–±¼4âF?O>]E‹5ˆýóID¸Jåâ&¡J±Ey"$'Rpî!ÅÉÇ“G«vë¬þhDÙŒ›S T$æŒ[žW˃pu³¤i°Ö N»Ú¯»,w(ÝVã Ìîó²/q²ÓͦnʬZ¹Õ¼ÜYZõ­.uÕ!pƒ ·'[¯ó.¯«¬0s´zÕåKÔÎWÙj›W7§ËPDfµë`ft Ñ‘DÑ"¤”()™•å@6Ü4u2Úm+‚F‚Ä‚+Øo¶¬ISFbªR‡RÕsd$‘2õ(y ¼+XAõª.Aøµ^8 Úõ£¼sÕ7ˆl•Ð\au–)»ÞÌ0ÇDc•¸£³Çåœ¤Æ m]kÇcUw{ - -šˆ˜œê±ÝÖM®ú½X°ß±ÕÌÜZÍði&ye½à8XÜ̬Ðfðãû8@žípu± A8žNh‘T¨)¡® ‘^☈Hð'³%"Žä“Y„y*ô¼Cž­7ÏYÑÖÙÕm›~쬫L;½Ê7{DÍ-B)"ÓƒaPõ»±¶ ¼"/ó£ üVÙÝÆtí6f£è½vØ};¯U&)‘œÇÞhÙ}è4ÛæÍé5á$â24‚²0(m±â>A /½§$.F)‰UWœ¼ÍZÂy™WŸ"ÐãÄ ‚KHIø¸•ÁÅx†‚9‘»sö´Ì™DZ1”µß–R~· 炤î»Y%IÂÓç‚„)’&‰G;!$IBc_ÿVûU‘¯æè¤D‚mÜ!D -s|:Ëo5‚¬›˜&&L -~¤v²‹ŽÒ.Š)÷S“–Ú;0¦(3è;(Ty·h¢*Ô’TQ5u{s^kTÏxðS}§o´"§Æyã£Ú6v$9v$Xù=ŠØ½ÍþÒ; y,ÝmµÛŽ!†;›¶;ÐÔÐò´8µ© p¼ƒÈÛèÃ䬷 œ«óSt2«,滦xÐf¥FÐÏ¹Ë GåÚáü¡wŽ¬wúýj¥õÚ´k~Û¸ì´î`„ÝdxF¡ÛÖº™ð#†tìWŸíòš¶„uc<ñ¡ÏŠ”P14e¦¯׸D?Š'Îib¹1ðnkÝ ÐûôÅ¡×nftÎy°¸øöKšMÎ’fhhXê<“p€ù! Ö~çüØË2ñcSW ëòÀ~åGªM£Þâ,ÃO[fQIPõå5¾À!~dä¢*Afá =ƒ§µÚaWþ’ƒÁ …ö§yz:%~·Í¡s˜ñdsÖQÇxZ¾‡1#ÛÃزåz;†®ä¨ô­“öu¬(ê»^î¨e®¯íË2ó5Ð×ÅÚ–A‡ˆÎ]dí- ³sÅŸAºŽ(O^–®Éƒ;%…dMã…dŒD -êèü‘Â1^éÌpÀšísƧS7O&èÓÇX3çOš& d1eà|.ꡱôMà >Ó: hðù¡Î=KeòƒÙQð5ÁR38ÉZo²¾pþu›½¶ÍØ:†šC…zI§÷ˆE›«'ÚÎc¬Çí<`ì¼*44ÍÕMh/! Ø“Ç þ‹=ÍÉ€5ÃÊDê„ÎS9åµÌLÕnnmàÂØ•æ/2e}뱺̶¼üpo(Ü”›ÜV9øRǬ¹™Âª -ß_.~ÅÍ#œ¬¸1ÍöÄKJ¨"­•š¦#“æ÷³æ&i$äô¢0«Ø>ÀH欧 •¥ï´iK˜reŠA=8¸Ô릌#œO÷œopÛS>jDF-LW´shúóz }žÅò¼º›&WÆ5§²;k˜Ü·Zõ¶Ú=î³,K´x&7±žðYõÈmašIXú Ö ãpA’H±€ÍCÄGÏ^0Éʺ·ï60Æ‚Êwfc¥¯ÜwX<9¾©Á·oA×'sß'ó!@×ÿp»Pz°¶ˆUð›m*ýk;É ¥‘8z sÜ™ö+˜°/ 8Ê«Ic)F×9ßÌ™ùÐãænd¯‹§Ø‹{‡–Cÿ#ë_8½‹˜£nn\»ØÂ}¡Ø;"µ?+ë¼Múì~†+ué›ù€úÞ4¦.‘ û²iÀ~|2à³Û"´„0Ëw6·Àì6×w6ŽŽÌv»"G½‚»¬e`x6´Ê\c{Üí5»ú'/ ž,B¾òˆé…Ò;¼œÐøÝ\ÚIˆâlÒbØè˜ÙcR@ÉbëR‰J†÷uš,CEÑH…Qð±Ññ}×>®7™išfø‘9¸¨€Ǿ-:1ÐËwŸ¡Z7Ÿ¾Û5z“ߺºÂ…ÿXeAë¦ÌëåÄ>!Æu}cžÍzƒÏuóÙä93ý?Wsúv›wM}›¯u˜ßoš¯¥Ñè?{Ýv/¥1B¯«¯–Áì ûõÓ¢ùÿ )˜ÔúRö»®åÝ´_u¼ßâ»1ÍMGu¥Cë7óÿz¦«½ƒ·Ã:=ô©SÿÐûÖû˜ý´Þ+F>=¾B¹r>ú÷‹õ¶u߬ôAÒ|'lx š(çÄÔb’.-¡Ú%IT’ÈÅ~ýÓ®nº!ªÌäj†?óÓ—é¿éÓA>ÃÛxÌjüUU2¶:ËjüM¬²ˆC NÔ,«óóÍþËjúÔ„ Ç¥x„Kñ• -M8tÁ³fŸðø¼2–ù?(“*JXÊ’YeB"k¦ºt †Gûp3 M—¶ÇÜ3F¡LDs^ëœeÿjrÞA–Éa°SOˆH…xñaSð”Kñ¬NÛ½\-ÐWC›ó=ï0³Î÷-j‘/>lªED¨”Îú4´®¡U9<ÜÕuqT¿¾ ñO÷‡f4© /'Ñï ·Õíë1ZálCñ÷÷ýˆÏ%1¿¼ÏÜ(¢ÁѾùþÃ?ÈSiÊæ¯&,IÁ¸@Ä1e{3ñð:æþà!ëÿ:šš¡endstream -endobj -1413 0 obj << -/Type /Page -/Contents 1414 0 R -/Resources 1412 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 1398 0 R +1934 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [432.0945 675.005 500.7665 687.0646] +/Subtype /Link +/A << /S /GoTo /D (boolean_options) >> >> endobj -1415 0 obj << -/D [1413 0 R /XYZ 56.6929 794.5015 null] +1931 0 obj << +/D [1929 0 R /XYZ 85.0394 794.5015 null] >> endobj -426 0 obj << -/D [1413 0 R /XYZ 56.6929 362.9244 null] +606 0 obj << +/D [1929 0 R /XYZ 85.0394 658.3825 null] >> endobj -1416 0 obj << -/D [1413 0 R /XYZ 56.6929 327.7284 null] +1318 0 obj << +/D [1929 0 R /XYZ 85.0394 632.0762 null] >> endobj -1412 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F21 714 0 R /F41 939 0 R >> +1928 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R /F53 1303 0 R /F48 1228 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1419 0 obj << -/Length 4207 -/Filter /FlateDecode ->> -stream -xÚ¥;]wÛ¸±ïù~”ωXâ‹NŸÒÝd¯{Úì6ñöÞ{Ú>Ð%³¡HU¤ì¸¿¾3˜¿DÇÎöøAà ó X\¥ð'®œIRåõ•õ:1©0W›Ã›ôj}?½™ú¦zT0ý’*ÔC+ÄЪÕ&¯©Ñl6ç5sÈtÍ‘ UñPT<~7˜šÏa>å¬oDHÅF_Öm¹eÌù¶”0‰Á?”Åã’réÄw±+”ëIºŸÁ¿VÎ'.µ:³xa›‚ݹ䞱¸ç.‡ýà—[5uAà°SHbÏN§‰³æ5‡'µ¸X¾E53– ºku÷MËË£¬GhC –aG»¤Qd -4žxPs\Ó “(z“8á§ÊЋ¥RÞ[ÐÑr_7ƒÖj›†ÃhÀC Ö—Æm8¢n–øc-Og^ÁŸÌ;¹Ä%,í ™ìm¾–ЉtZþÖµøvgËà–¸©À2€Svn‹]~®º6é OÐz: µY=5gjlË–ÌcøêîQQ•Î0¶þøm!¶Ñ¼âï¾|(ë=µ›3Ï¿Ë·¼@Þåȹ̯ùéK?²ìè7g,wÍþÌÍDzª¨Å.ä!h¢ÝO w§%›ú¯3xº`ŽÁ’‚A Ú+Ò`î„ÙCyuŽ–x·¨RS¤–χh\¯8ˆd·üÙLÂ9 M=§‡ù&oצ^“¤]’™ý¦ á!JA{ufwÔ€M#žEAÑŠ@³ááÝrteMbDŸ½¤¢à®ŒŠúÜ9ìe=¬B v'Àï¾jîP,LméãÔö £aPð,Ä¥ÀÊx=åLÎF5ŸXÐEÿòlT©Š^îDêòì¶Mâ™èn'É2±Y’N f ;™"š%„MXúÁ,Ḱ+GÉŽe¥–ÎGáqr¬Þ4kQëàXuêÍ”kdƒ¤Í¦rlV;Ò¶w’4›hˆ6l3ÛÓ ã‹Ššé2ÖÌŒ¥5ÌìÞŽù}QZ¡·Ù 4,X&@-{§õò±¹Ì\H+`/Ù|CÌ 1‘WϤB1ŒL9ÖMFX/Ãðe<ƒ(: -Rúi%?zó°f¢ôÌŒƒµžQF©9>Âî-w§qÜùxlNÜ; fQX~îšä1 ”|êÕŽL´îò°¡ÑºïEBÍÛ{N_w‡„8¨ÿ áåÑí.üºU]„VÀp¬>GZÀ›—”ÿ¢·/7÷ÔmÞwèûzú¡4BzlmãòM÷{héh¾¡«?^åFQÎ^ -Å4–w¼7ßt”ë~ÔDÆÚûæ\!•„æÕcþÔRû±9}AÍÉ2Žv<ŸŽ”ödž$óÏ™s'­”yµ9×VÆ ¹¶h(î•èe³ÞOì$ï«äßpÒ!ðþ6äBÔvɽGѤɠ33Ç)BNC]<=hôV™\^/óÐ*È9ÅñŽºkB] `l´B›dÁúÒHØIyàÅîí%>Jò¿bµkKñ5?`èi,™"2ÀNõ$ò1ÎUeò‘A¹;ï÷O³ -ßæ”·÷1ňVjÓœN×nu>vܵxûÐbæÌ Ö¢QzÖ…:-¢-.¶uûLaA÷òØõ¡Â4¸NLb‡ˆ^8Ž…#z€õ‰´9NÇÜ·ƒüôØñ´†~y»zÿãÇÏ<ƒâlåŒÃá\ƒÑ Ž—ü€†œÊÌÜ×1u‹aâM:­7>ŸÓ-¦_"³I*…þŽ0;f`¨Ì¹¯ÊÀd¯’xHëóö¸nË/Õ…$,šyLeCŒr¦˜¦Øž·úõÇ_x¢ -NÛÑ׶É·Àª®¤’|ß=-‘ '¡2ãƕť쥪Èøh'&ÜOœåõ1‘ ²S›äVÂOÓà¯×⚪ÜRˆRZÊt†2t! JâçWye¹{êH¾ýêï©IÇ(šsGBììîKs,äˆ&’XVã¡ DlÿyõÌ"Yª?ÜVG©ü*Â@IvçŠ`ÌB€r,EÙÞSgØ–N‡l žx Æ ˜±cÏOužÀüQ\‡_o´wäš3q$]º¯ƒD’vד3Í€7òø·ÛE‹ìqU¼Á!^™XB6–X×¥îG -‹°«{É&”±Å¡ÙØ‚c”Há>|U$Eû ¢PÀÿ¾DÆ­È!ÿúMýæ[¨™~§>ê·Hc]ô×òp>ÐG4¤)+;öm¸^¢ùÂӌ[&Bû²>§¶×z–û@U*­ÎM•1ÊÈEG0rNÎSÄþ`¥$•’/›@*ŠVQŽU»zÅN’\ÇKr,-ùö - ƒŠ"tª¢°'ÁJÐÇŒDòÅüF¥Ä~S€>£_êæq.jß/Ñ¿]LYÉbò¸pü†*ÓלŸ=þ4ñ^eS/§Ò,QÚ.ÜA^9TVÔŒ¡;ȈsÉÍ©qÉ Ã=4š-(ÙÚF—àÀ›B¹¥}¤Ã÷…LÀ»„‹õs#c¥ -HZ„zFK«ô4‘Br¢ÁÇ‘+É`àU"¬XrYmsMˆ•ãE߆/î–ö;î¯+,‡„Ãéïw!õzâM-"™KtŸU@fØÒÒ!³…åt½Òómg“Ç‘?–3(G K[ÄMüYÚˆ^$Îr«—·"û»Ë òö—Xð%!­ÅpáZ‚6£ÛÐãM¦I2ÞK5±&` ^s‘¾ÏõèèšfËð'‚ó[€xÆ?@\ò•aèÃðcÞmîcQŒ·0Ù5æ TÀ‚(æøK8±‘db@æ3¯WÿÆ48z藣ط̻'úàÔ9TɃ¾P;øq#lh‹œ‘D½D\/wÏ•sø#Où,z-Þ¯ïìÒBBÝÏš¨Sv7‹é:VñÒï[ÌÊ$uý½h]ROôBÓJêg6ê<æÿÅÊ£…ˆ”¢è­/׳ -4[뉟_¼%²‰ò=ÿG×¾¸Dðm\ÂO!*·³kŽ»b–6Έ˜%‘CÉñ’ 6SI7ÖIÛÐ,{m€Tå!” lŒ¿ QŸwTbç7àzs> ñ(ÂÊú®9m‚X ÓJh:©„Ž™ð§M3?º ¦T’·2ÎåË_0]²Øð{”Jݼþ<òس§)ãø4òl<º`@¾‰&¹÷öñšrY°$ä“C…§§y}dq^”2«©{Å‹ŠÊ¡›HRî‹_“Ê -##¿¾OÏÔLšÉy½ACÚ³Q µYz6áT¢Za‘ùC2‰M4„4Âòš×<%“‰wÎ-?$[÷×c”ñ•Ø8–­VJ +eY -¨„LÜpLñÖ–¶L‡~®‚®Å)3cÀœÉ)Ú&77hùR,¬ÃŒçWÐ"_K£ààÍGH?4ú ¯ ¦bõÄ×>Ó§^ÎJ2 ß~¾ùéíüT„È „̲pŸ¥¬·ÈBê<í¯¨ñiô2¯¿O žOoçx‘ŒÏE$ÝYð«æ‚šÌ$B¨ 1ã —(˜ãb>Zw—­º¼â§ x ×ð/·vZìpÙÔ~Y™®þ—ÙàÈû|ϤønŽ¦ÖÝ7WÁ›z^ÈN.ŠÂÉ:8X«²©Ä5Ÿ­i0­Ü×ywî«-¦/ý0øÝuq¢÷‚øyn‰ &V`Ê1!œ8R é~…p+4ŽGÈ=ã Ìf‚Òaé:Svõn)?›^Õ…m¹/ë¼ë­íÈݼ¢Î81âtÍc†ûþ’cý©¿ëËû:öÝ=Åõ"2äÖMË¿ï*ˆÿÎ{åtÊDbcÊÈ ÃzÞØ»äê|b3“½`»M’Š‹kVÄ -¹jóØR;lÎUW+‚81ÙRøB +ïOIv£LŒ†R½õ2±]rUAd:±/ÃFaEÅ\äìó¢vþBÕF@b¿bê´Y*Þ@ª¤w/ÝÖ(°YÏã]?d ¨!¢ßÍ/nðyUL -¤Ž7ýùåAˆ”ÊxÊ8ùÃ!Û-g…Œ“R¤ŒS$3ºí^bzVÊ!¿‘êþ™<¢Ñ1ÑHM¬^éÙË39ãú>hËŠ*ÊÿZƒ ûÐðëœ6Ú/B¦xõ%Þ.å:&Ɍ˾ëÈ×ý¬©†ç¬’¿#«ªLrõ¢¾*?Ê¡*^OÉlEóm<39»ß—³‡Fá9óò¶¤¼ÒHóÝ^G{y?ˆt;ym -üQ’:g¦Þd[tyYµo£ñ,fæu[´›SyÌ/¿´Ã7tø¿ß«¤Ãƒ×ç•ÔXõ”T -QÓ†qÔÆ+‘NÙ+ˆ,øí¨½†_Fsœ“è‡þ³C‚éHì1N™’#b." ~Ì·I˜aêK„KÿÞ¡ ^/­–öÿoñ_ÿëÇð1qçä2áXÀt"6&*üOÇE¬ØÿÈ%éÿ*[h”endstream +1937 0 obj << +/Length 2611 +/Filter /FlateDecode +>> +stream +xÚÍZKsÛ8¾ûWè(m¼ ìÍ;YOmœ¬Ç[{˜%Ñ17’¨i;ž_¿Ýh"%ê‘Ø©šr•`èþúC7(1àð'Æ2ë¥$^3Ã…Lg|ðúÞŸ‰8f\·Gý|{öæJžy+íàö®%Ë1îœÜÎ~Z&Ù$ðáÛ×ï®Þÿûæ|”èáíÕÇëÑX>|wõÏKª½¿9ÿðáüf4ΈáÛœº½¼¡.eü|u}A-žŠ=Bo.ß]Þ\^¿½ý~ûËÙåm³—ö~W¸‘?Î~ûf°í_Î8SÞ™Á˜NY¿±A\2i¤9Œ ›$> úð£!’nðƒuc™/òyºÆü?4Öès!ᘘf«Šúªû´¢Ñyl©¡ØHUFFª‚ +S…ÀP?ÓSƒMHÊ”Š·„G„¾ÒÈD]t§'…2f×É ôd[ÃV0ádM]´”ñª˜çÓç[Ëœ·õ±\V0x §¹ÒÕ*K×Èç w5ŸC{1yÌɽÆBÐ/ºº)8TF'Vt•…H²L(1äï +›MQµØù”O30žR>Ä¡1[¦“9ÍÑèaÛ`%:®6äªP¦TÀ&—3€‰pÃYþ˜6i<÷¨þ 3X}G8Sà(ó*_ÍãrÚ£ö´¯Jt×ÔOyu_ +ت>V6¢/¯¶#«±QrãÎ5äGO¨]¿ƒõæqýùçeÀ†DKï5°Hî xò|#`zr^jIJN…°“ÜjiIåÚÖœÙÍIŠÑ¨ùmÅX£7Šé¦í€>8à_0Á¹Q‡[,ÍÅø…Öœ±(ÊŠZà<º{˜wù‚øù¼xŠü€cª àÚ¾dÏÔ²ÊÖ}˜Š4â4QŸ«#2 7-–ÉFqÌ}¬X®;]ÑNµd·õTÌZ”VTĦ‡´Oå+n÷Ý“ +ɸãîÉØÚ3žSaB˜'ÎY®²i%BÖ¤¨víí! ä É­L÷·^“ϸÑ»prK‚”ái$ã´¬²u^~6ãƒ8eš–Ù~^n3Þk… ? iÖ@¹‰çGRà}•”GîX{SfÛ‰èü°nlRl°÷Ø3$òÈ1DtÞšæ&R$Ù¤H(½I\âÔÅ]ÏlB8Tÿ·ÒyÌ´μŒ·7“¬sãs)-ü…¯W´ÂÓ€Ë#HoÖRøc—è}PQ¼•ñIAÙ@ú¡ƒ1ú(T<ìu *Af€ +ÖŠåü9NÚMèé $‘šùĨ.‹Àj“}49(- ¼P (`’û 2ã+r žkm@ÔaxÒ‘«þ.TÎñˆÅ°ÌG……ÍEbó}ú˜Qm’QäIEHl±í1O©rûöUBfŽƒîð> [âEV÷„~D¼ 3ˆÕŠnøàá.ô z¢ˆâ·|™W9$Ãõ°«OT¦³êeI ù2ÜoÞ…±×½·‚ç7ìüæÓÈËáùæ‹C¨\}²í.íÃÁ^®Òi°xÞI;ê+K=m;88WáåPª’„IoÅ)Ÿ$$¸±bïÇ…Ä2‹¾s:LéÝœ¤^85gÖØöáF³€Rñ‹ók·†>/\·ði,¬GB tÄçGˆHÅðþËáÎGpá!4‘ЭDˆ  BÄB~Þ©‡½ntÞ\-äࢀ Ú›"¹ã¶à°'Û¡é˜Öf l“¾q_Uøy_¦5¿ë,Ü%#bת(Ë|2’|ˆ´Œ-ˆM,ËUA¤¸ J.°G^†•À ¹n9f÷3NqÐqË&/33Š;4Þü<àe ” ؆{¨™qÒ¿cîаy5ÆŠ¤[/³°t ¬ÁýJÚ˪þÖ¡ð§"ð65­ˆÍ0`ÿ4&ä‰Í'ªOž©/]>SCÀ V Á^fS¼<ì#¢ É‚ë«_/š–YõT¬¿P3r;6îykZ¬#¯Šå,æm(ôQÓ€tÖË¿ q³¸öôêç.Ï–³¸XÊê°LI8¯¶°)|ÍòâúüÃ%uÝÜ”YUvßœôHp„Ô_w>Ò³uY;µdû¹[*¨<·¯ÈÝò5¹[X¼ àúyãÚœåêÉ[8Î0Ϋ“w[ð~òÆ­%RëBßâ…ôÝ6Ë_œ¿Ý+P­æÁbh; ÂÅ:Û¿Bã 2_ü›·Í5°¶s²ÿçl`0PQÀñŠÀïÝÎ/òêÇÅQ­¥ÿãÜŸendstream endobj -1418 0 obj << +1936 0 obj << /Type /Page -/Contents 1419 0 R -/Resources 1417 0 R +/Contents 1937 0 R +/Resources 1935 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1398 0 R -/Annots [ 1421 0 R 1422 0 R ] ->> endobj -1421 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [116.0003 171.5741 166.1092 183.6337] -/Subtype /Link -/A << /S /GoTo /D (tsig) >> ->> endobj -1422 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [399.2874 61.5153 467.9594 73.5749] -/Subtype /Link -/A << /S /GoTo /D (zone_transfers) >> +/Parent 1927 0 R >> endobj -1420 0 obj << -/D [1418 0 R /XYZ 85.0394 794.5015 null] +1938 0 obj << +/D [1936 0 R /XYZ 56.6929 794.5015 null] >> endobj -430 0 obj << -/D [1418 0 R /XYZ 85.0394 769.5949 null] +1939 0 obj << +/D [1936 0 R /XYZ 56.6929 746.113 null] >> endobj -1304 0 obj << -/D [1418 0 R /XYZ 85.0394 748.8663 null] +1940 0 obj << +/D [1936 0 R /XYZ 56.6929 734.1579 null] >> endobj -1417 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R >> +1935 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F53 1303 0 R /F41 1208 0 R /F21 930 0 R /F62 1352 0 R >> +/XObject << /Im2 1341 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1425 0 obj << -/Length 3036 +1943 0 obj << +/Length 2894 /Filter /FlateDecode >> stream -xÚÅËrÛFò®¯àm©-;/`fâ“cˉS‰í•™“ír$$¢L4ÚÑîæß·gº”ìr¶¶tÀ‹“(±ÂδUQÌx<[ï/Øìö~ºà³@‹>ÔË‹<—zf#›ˆd¶¼éá23†Ï–›·ó$Ñ%``ó§¯^>ñÓï×O.µš/_¼zy¹1›?ñëŽ~º~òÛoO®/ÜÄ|þôç'¯—W׸•Ž_¼|†+?g^_=¿º¾zùôêòýò—‹«eËKŸ_ΤcäÓÅÛ÷l¶¶¹`‘´&ž} ‹¸µb¶¿P±Œb%eXÙ]¼¹øg‹°·ëNʳHÈDLPˆ)Æ6J¤^€Ëmæ˜PÞå6â‚í¦(›üænQ—Çj ûˆéD ‚N‹Í4FÉ™™Â¸øœL Õ@-‹Òõ.=ÖY âWñ¼>dk8î&ɼüê‹×ŸŽ~–:7]r3_pºÙøyVΦÄ#+€Û68º)+GÞlÁµŽ S1Œxdc ­c@µœï]zëÉ„Y)D+xå¾l²Q}Ϊú‘›YÚuÌ5ùçlwwÉ9ŸƒfJØ{DxTiG‰Û³HÂÞ²\ã‘:Ž°ñµ,#Ç;=áe¢¤‰¤b'2ñB;ñõŽ1‘mœÍßäû|—VÄÜ#»ñÌÁÀ3_z7 ˜sÌÁÂæ„}Ó6þ6}‹¹é1èñO²âY—<‰˜#Y8ÝVÄú´= 0_ÐfBþé˜U÷›“e,¹×œa¬¬@x–;-MrjMR³ÎšdbÑšÜ*ê—ykr{ø*þHÏšmÖÛ;àŽ6þ¤£ -´F¯&¬|€Ç(ŠNÎyј¡ÿùxêe™KP"m™j_T°o|Ñg™S"oò²Š¾ÁÁï.àN¨ãÉSŸMs´$“U‡1b^_·Š^w„J.æ› \+¹!\Y—ûý±È×)Ò.Áh;V€wmðõ®¾˜x8¸Õ®Ôw5Üãt³Ï ²Jô,ŽLlN^°)+’¤O=à{›‘,Óõ“žÞfÇ9Îó<Ê>íÄ]ÞÐ-Ùs‘îGã";‡¹CÊ“¾¨Ü4/š¬ØО'„kt0‡ç–Ùùj—õ÷Çñ€fà&ûã®ÉäDÐnéà_¢lÊu¹«Ã­„Ð37ÞŒe™ó‡ÞáØàÎ×-W=ù≢ÙùÄ/F'êG?/—¯qÔ -Æ9}‰~ôærVŸ †¸ö阷ºã ›mÚàˆ -YüxAÁ¸>ä;ŸªÂìKÞlq´ËWìw¬Vã¹k¿‚ºÁ&2«?…¤°?°ò{LCÉH(ÁǦ!L‚"0Ô›|·Ã%'¡C㉇ìsVè }ÜÁ£+ùŽ–§å‘PãcÂ*p]¥UmLÏ {iq‡ÐôBt]„ª›4ß…äù<=ɸl³ -õì¼<)¦œ®HBÂéíX¤€ÅÞVAeÑà]ŽVaÃc¸‰A1ÁbŠÓåÓ×8¯ËõGoý0v!+òâaRZF ÂB/NO%*ú2(L~8-¥²càŒ\6£$dÓ_QC¶kŒ™.-ÆE%Ö¶ƒ\ bŒµšw7; -½¯ UðˆÙàõ½³øzh8kÚœo,C寵ùëDÐb|@*ÖO=ÏH¦E ƒ¥:S‘rþe›¯·!åðÐÊ U³:ð'Þû;s*FaÅ'¢¸’à¨W€ÓS">c pîYÁº„ÔHÇ‘ÒIòÝ‚m1.ú(Ç‚íˆ çqwó}‚•P¼© Yˆ›ã,Dš@ºK9¡êrÂÓL;Ó³”Ë5S0à*¯?b²è$ŒîÑúˆZaÌËÈ«‚øë.x¨ðVƹ¼Í³• ½g÷VQ ‚"ÈäDJð:kh} “÷”àÿ°â‹{¾]úøˆ»Þ û…üR½S’ó·áBõ9hÔdN£æËK+æ%î£CÃSxKi¨Xã!¯ƒ€Î»×Äk¨.‚<¬uócuM@%´>ï ¹O©…Ic îKäwkk‹qÑG9ÖVõSœpÝÝ|¿¶Æ= ­Bé¦~øa*H‘ $ -¥ÐaåI{ä%’ež”͹œ³UŠNa ÂR“®_St‡QHT¨p^†Ô5ÎÞ ¡&¸–P¸©„ÙqávÚT¬†ª¾_Å9ŒHP6ÃBxHòX±,¸Ñü||Ñ:’pB‚ -Áù÷‡B¸ècœˆ.03kº‹ï °\·b¨J÷” ÷Ë|ôI°ÿCƒ_oH0òCHV~Å -Ì»ä´HÆÜTù]!¬¹zÊ}ÑzìÎ…¥»©Þä¾ÆÊÐ`ÃJ{Â~t¤u›Ac[ÍéSó§}é¯-»ë±(Mñú¤t°g ±wÉç;œSy‰“CVíó9´P>¥¨]Ö`ZKÍ™~$‹´hÃu F!× -ðrÞ\B½/ }wÈ }”!×BrìÆ-˜#Ó75F9'd;\$ê¯#²Åø‘^Ò1$Ò÷\&LBE‡lkÖIô†ðHà 'T4P ñšHqcˆàMSFàš©¦Z@àš3Ô(‡º~3q $nÂõmõIØôQÞ_Ä{YÎÉ¢i÷ —=íùjÌ ú)¶;òÂÿJ›h©0M¸kïlÒœ.ëܵ~ÝT`>äÌÛoúžÆÙ‚›pò“´Ío·¾¾oû©®Ù›àÊC¥ïuN&ƒ z•ÐZŸŽ€…nOÔÇ8T9TÔm[{¢ÎìEשŽ.x4õm½®8R±1}O:èX¼–œ? _­Q¡¬¢bÜsB·¹Hò±» ºaÇgó§zÌB*ȈŒ÷˜§ŽdS!=Ø,>fwßÙ\bêºÊ®@à`o'N¿òaÎÇý*«î÷áOéóÛ1Ü·ãÅ.sEï©í{Bû·¶}Å× -ùØïUI›ËȘÈì\žcâ©n›oBß©ƒé³—oÞ\=Åq­UÞÜá M·l|ñËø2¯²z]å+,Ù\÷u”ôye¤ÿ=+î Uܬng8¸îýG@ ¿èÿGÀ¯cõM뀙5 -Z&â5£ÿJh¡¢a„-HД'A¤‹îW2ÁlrÒ’ ò–¼•7Î0äísùLÍ¿l½3‘!ÂÀàp\íò5ŽA!p€U Rüe±HͶ„ûR -4°ü¯²Èq¸ïcQ~ñÑD†$,¶åŒWtÔ+‹÷Ÿø+Ü©—+Þð×èDöŽ·[\mz„£,V*¯²5¦n’ûŸ&°-Cç›Îâ ™›!3nTN£#<‡44ÁOÏ…›Žo‹ð{ù c¯|—δ݇„îæ[ײp+«Ìö$ÝûÝ’¨6tàRœ6Õ¥™{‹Æ¹CH`©I¶Ü)l¤fi3DÇ|÷Ù„Ûtè,IâóÏé.ßôD±Úõ²'Ú ÝsŸV¥DËû1]^—>Å=cº»ûu&8É5ýÓº@¥á'ÊCŽ«M¹ª‡yH~Íi)îœWtîÿœ$$RNÙ?kƒÁwÿT÷b -JUcÄ´#.“5€„ˆòa'QþYjLú­£Éendstream +xÚÅZKsÜ6¾ëWÌ‘ªò xñ•=9Š”(IÉÞѤvó:P$¤a… É‘¬üúíFR¢,;>lé@ ÑýÂ׉‡?±JBÆUªWqªYÈE¸Ê뾺ƒ±ïN„ãY{¦õ”ë›íÉW*^¥,d´ÚÞNÖJO±Ú¿gß¿}¿=ßœ®eȃˆ®Ãˆß\^}K””>gï®..¿ûyóö4ÖÁöòÝ‘7çç›ó«³óÓµP:”°€rKüúîꜘ..:?ýcûÃÉùvyz,ÁÊû×ÉoðU§ûá„3•&áê:œ‰4•«úD‡Š…Z)O©N®Oþ=.8µS—Ô¤¹`B†jµ–IÊB¡õËûÒöuM)Æès¾/œ;f:ŒAù!×,Mb1*_‹‰ò…V,Q*\ÅaÊ"%•Õ¾ù0˜®É*ÔÏWRN&Äœ¥R¡ ȸݕýéZÉ$èN“àPì¤AVUíCïfO·‹C8jê&7YmŠ…-”f2 +ýCKæÖt´ü°3ž–—}Ù6Ôkoiøag€£#"L‡@!<-j -ÁÒ–ÇÅ­ ä}îÊ{ÓPó°/²ÁP¥°\nlÔ황ۆÙø|‡-ʪÃ4¨A¨¶€6x!JŠ´¼­ëCSæÙP6wDz(‡1 ~&­NmT7ö{“¯çûQà”¿s.A­ëXª lè‹KY=ƒ—õ ®“rí­Q¦ÊáqÁ !„…”Â1Ú ªâÍé:Ñ‚¤Ä=nÛ®Îjãùðû°+ó6% +Nv 8Pbß×À4ΉyüLÿ³Y^ð0‚ðšÀM¦ üWôΪ֥ngXö2Íãú¯CV ¯Åɵ‰;n]§!`9f)@g:D¹äèŒôÅTˆžÅåñGºùœ—ö^ÂþÄÃñüß:6Œ¥và¾ÍwÆâæÛ˜¹ÙDÞl®/¿{Cí«k׸~÷v$Ÿ¹…š‚f#I-óÓ”n›ày†’éÆa£8ðH¨2ØPqŒµ¼:”0`ñÖÛ«_vY¤M ÐüãI“Ô¨ÃQ„ñ¤@vGAΦ8’Ô›¥Èw0|< «@JcÒ쉀DI¦ÀTÍPþ(¸j7æÒp vKÐRIAî©­`Š +$ÖY᧶D)Leürt<•¸äž»tÛ»ÑÐZI—ŸÝ’€Ž,YÊ)|Üœ¹$wtE º©+ز|çK·²FÈ7Ðí6acõ*4Sr#"Çj²‚¢àˆ˜:…Âá׶q»_”•9Nõ§°SgQ,Æ©L¸ÉSO ébµ¯Æ× ÞÆIúŸ/V}úsï&À][/äCBŽ\=-ࡲ„y"ȱTAçN¢ "­ÞŒiä¸i©àhP»*L‚[ê×4¾¹8#2ZÚ-R˜>ïÊÓÓUî¶òmÈÙ‘j ÷­o»tp\9wÜ›‰ãj³!c'>½¥{ÆØWépo!c+¡œ/ ­tc‡ÞŒª§kjCT’&ì7Uéë8±׎ d FVë†2?`LÚ¾Ó›&¸ˆkæm½o{¿€ß¿70ÓBKìâ;(hr»[,œŽ°Ž:¦Îy¡Af£HÜëšnüZÌŠJCkL¸É:±e2¦xÂNzNƒ½Ó—éî- k×ò:OÁLÕa±mͦG WZëå·~ᜨN‹/(ùHî‘à"HßC¦»?–"†’³sWÇdf}¨†r_¹éVWÒé #|§.ÝH(Ü~(ëòoç–óС {·ÙÈi>d÷‹w¿Ïû3üwý NÝÇÂ>“u7Ž™ÔIíÿÜÙ•>ໞÐ×Æ<-”–LD"^‰ÀlÙgsìîVÔØL!¶ç_O'<‡ØÏ×µo&w +³? êYA#Àx©g2=y÷\¯H¢aHÓb.‰»tfÛª®x~ª*Fþ×x¶î‹ªÐOe +y  +”UÅÈõŠ$ÏWCI\¡¥d2„3+!¶þj²ª,ÿèdS¼ãÓäx±Lp™»Æ¾~zÄñÇ¡¡Ž¹þÕš“ØüôÚç¥Áp'"|Á"ã/8v)%ò‡ÆÇ4%N(%â£)ž–€ît| ŸcŠÍÆ¿xP}hŠ—¦ò~™Žoô~ÿY¿Œ¹ÿ—ÕÊSúýãµÊiÅÓ—@…Á[T_¦É‹Ø- D´¾±ï,0࣠éò10«ÊÞy»4òظ˜‘Qè > endobj -1431 0 obj << +1947 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [432.8521 109.336 481.8988 121.3956] +/Rect [341.1654 175.0606 414.8187 187.1202] /Subtype /Link -/A << /S /GoTo /D (DNSSEC) >> +/A << /S /GoTo /D (the_sortlist_statement) >> >> endobj -1426 0 obj << -/D [1424 0 R /XYZ 56.6929 794.5015 null] +1948 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [434.6742 175.0606 508.3275 187.1202] +/Subtype /Link +/A << /S /GoTo /D (rrset_ordering) >> >> endobj -434 0 obj << -/D [1424 0 R /XYZ 56.6929 671.1595 null] +1944 0 obj << +/D [1942 0 R /XYZ 85.0394 794.5015 null] >> endobj -1427 0 obj << -/D [1424 0 R /XYZ 56.6929 644.745 null] +610 0 obj << +/D [1942 0 R /XYZ 85.0394 385.3709 null] >> endobj -438 0 obj << -/D [1424 0 R /XYZ 56.6929 559.2968 null] +1945 0 obj << +/D [1942 0 R /XYZ 85.0394 353.2653 null] >> endobj -1428 0 obj << -/D [1424 0 R /XYZ 56.6929 527.1081 null] +614 0 obj << +/D [1942 0 R /XYZ 85.0394 353.2653 null] >> endobj -442 0 obj << -/D [1424 0 R /XYZ 56.6929 273.3583 null] +1240 0 obj << +/D [1942 0 R /XYZ 85.0394 323.4096 null] >> endobj -1429 0 obj << -/D [1424 0 R /XYZ 56.6929 243.979 null] +618 0 obj << +/D [1942 0 R /XYZ 85.0394 266.7517 null] >> endobj -446 0 obj << -/D [1424 0 R /XYZ 56.6929 161.4956 null] +1946 0 obj << +/D [1942 0 R /XYZ 85.0394 244.4404 null] >> endobj -1430 0 obj << -/D [1424 0 R /XYZ 56.6929 129.3069 null] +1949 0 obj << +/D [1942 0 R /XYZ 85.0394 158.1241 null] >> endobj -1423 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F21 714 0 R /F41 939 0 R >> +1950 0 obj << +/D [1942 0 R /XYZ 85.0394 146.1689 null] +>> endobj +1941 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F22 953 0 R /F21 930 0 R /F53 1303 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1434 0 obj << -/Length 3304 -/Filter /FlateDecode ->> -stream -xÚ­ÙrÇñ_ò‹—UÂj®½¢'Ê¢lÚ1íPtR‰¬R-¹%`Æ.H1©ü{º§{ö‡"c›|Øž«§»§§¯œ ø—³<‰….Ì,+Lœ™Ì›#1»†±o$Ï™ûIóñ¬×—G/ßêlVÄEªÒÙåj„+EžËÙåò}ôÍw'?_ž^ÏU"¢4>ž'©ˆ^Ÿ¿¡ž‚>ßütþöìÛ_.NŽ3]žýtNݧoO/NÏ¿9=žË<‘°^1†G¼=ûë)Aß^œüøãÉÅñ‡ËïN/{^ÆüJ¡‘‘ߎÞ³%°ýý‘ˆu‘'³;hˆX…šmŽL¢ãÄhí{ÖGïŽþÖ#º¥!ù%:“\e*`RÄ©VÚ ðd½Žt}²÷-A¿ŠD”õ’‹f·;–ydÛmS/«úšºÿÝÔ¶…‰’šëªí,¯¨j” -ì-G{Ë"‰³"KbܵÛíqÁÜmJ³Ç”&9L.üä’ ìKk7~§®¡¯ý ÛHS¯iÉrm[æ©YÑ÷î¦ä™[F[wHÀ NdWdj6—2.’D¹½Ÿ°À¤Q[ÞK)#P-Šè]µ©Öån}O£«fG@é -  ^:‡¥“J«üÙÂÉá'7µ§ »iZ{¸õ ;hì[O…“|oËuµ,;ë10ðæüݧÿd¹è4.dšOårqÑÚ%!Eté–Á¥DúuK=oÞñMÃéÞUN@Õ w]ñz¤/v» -Ø-ƒÝ4ÝrÜ!¤S±H’âùR“©W©¶¦7xöÀ_-Ê´½îʪ¦ÞÍ~ÝUÛµ¥à%Ví*Û¾@QÉÈ–‹›~m ÍW¤`•+Xª„ÁÉæ.›M¿M]nì ’u–Åy¦’©¨B—׸Ÿ6I´u"nºfѬ¹«\_7»ª»Ù¸¶‰ÜÝÕŠÏ×ekç©¡Ñ–o5pSvUSÓÒ®uÅþÿ¾ -)áYZÔ}'á߇lLÔÎ.ö»¶ºµs²o8ÿÞ¶›ÝǺ¡fpõû‘xš-ÒòŠzâ8þ¢ ™ÿØ…Ã5󠀉þ€˜,–Ú -`žR€7õ³®í$÷ À/-Þ•‡æì@35J’mžÛþ!&@“îdlðV-}Kúl›;»[íý΢•_*£ýpeÙÏÂL‚¥‚¡E)çÚvS¬NÝêÖîníŽëö®‡én‰€ßövwOà²Záö+먘Óy .++¦çL9W™ùµ[ëƒh:©Ã÷î¦!À± ß²ý“ÐÍ::릃àíºj±÷1ô€ÿ"áLñN߀Ý@‰öÛyK q„}`·Œøly³ïBêzSÞ´o·¡°s²S$ÎöÀ¥’4NÑo=TÐ]$OhL:-‹‡£¥Ñ:]v^‚¥’zIõrÈÃ@‡ö ´èZ¨Ÿ!ŠpʵÖÖ]ÝOöi÷W.ÐïÄNÑIt‚!pZø&7d—gd‡\è Ô¿FéR‰ }:Ï XVfع·Ý‡D ±méÚŸFdñ "’±Há'D:Pê4Î2é5¿Y §ãTà¯ÛÀ…\*K…7Ÿä½XÅ”Š!<ÍC:ŠPµ†ô,õ€÷Þ·NÝsèpº†ÀÈÙR*››:V6ìè• (š'ýÎ*›ŽuÖÃHK‘ùW6Æ8£ )[ët´ñt-s“e=Æ'h{çxz"Óµ ô·÷Ëd§roóÇu-àªuú ]#UŸ„d”¨–s3Q8 ñ“":Cš´¦ vkZv»Äh?1ÑUÓ…ˆÔã 9!òq¥OM,Ó"óªG9áO‚£É“)Æ'X+pIvU‚c$NÐmâ×áAgJ^šÄFi5½¬”˃"Ǭ6K½|T&A ¥K—3é£êLø:ô‘‚ñã.ˆšÛŽ®HÆÆèï‚CÕg„8Äå?i´­»7LêäÖŒ„«EÂå!D”Ë/]PÍ}»`îRäq£Oæ.h›Ñ–ðVüm«ëÚjG]¿*•!d\d}äðHXÔÁ"èÊŽ§´Íú–J‘ U&˜‡+Iös׳ê¤!]¬…8¸}¡‰ÜõcâA̺·ü_ÈäTæEæ.ù²‡”@† 9­”ÓBÛ¿¸Ü)LÈ#ƒB»¤Ä1)Ph3#œ…~:Ù”ijÉ& e9Ãf¬Ì‚nÛr±›Y]¹ÔFÇþAW…ñ, Ýëª0¨—29Äm&{‚\ðå˜%Ð$ÐgÄë{Úƒ4¸0~‰q.&&©t„¹ûÔ'@´.ýÅ¡š!éÔ {†|{‘JWlƒ$bš÷²Õö‘®"FHؘqú×`¸‹¬¤ £ëMÛ³p7Pt±ŸKÌq¹üwËT û»º\#|PÐÀ.¸ÃÃ1Žª|åƒÂ¥ËÁRñeí*šKÚ_/èØrq -,«z˜Pl“Æ21þîy$ø"E­T¨¢½Õ½Õ\xÔ¾*ŸŒîÎ ‘‚ï"y¦ž6I€õt¸ã1þ ·µ}R#Ô¡ân·î…¿ŽÝÝ8¡4˜@òÐ…U™Ê™œ ¼ ”û[ }#Ç`’,úG kz~¼w° î,×{K`ÅÈÝá½çÕ¡âÉ#ç ‰ŸéïøŽ7‹UÈp†É2þ$ З>€"ßFE' /È7ÒuÅ)ƒr~ pSÞÚ -j8Vyî$qÔðÚ0»óDC¾“ÔÆžåQÆõQ.°·ì¹Öä‰d¾Õ.f¤g"ŽPìÒÖ îk¸î'úg¬ƒrÀ'*ÌæŒzÖÅòA˜À~Pç# 35#?N¬õ8Ï’Œž% eËýËì0q§ÑÓ¹½ò*iÆÃgçÓi0°ßà{˜Ã{Þt¼»wrþ¥ÑmVÏýòÛèÍÞE0H?kŒ7Y°;lcQ%ýKJ5œ™€ñ³ÊÙ¹·ÝÄb)[ÿä²ÙVk»œû#Ô—7kƒÖÛ‰/Á⟪Êrü*¤P´ÔXËgXFcŠP¼x‰ToP Ã¿Q AvrŠ¤¦Æ\©¾¼ßGåÐ7”úpy&9D›¸«Üw Ì®pª÷¤™yŽ™ÛY^(J÷ , "[ÒvÇœÔ÷ÁPÍÄ -ëÀ¢â rËâá»o1±:¸}SÓ€“žš-¬í­]SºäÑ$ùðiGIÒ÷'ϳÛjiý“ ‡ÔYœ%y»‹s~ÛËÝÃtGöP‹àó±ffƒ‡zA•Zr–ùcHf -,Pñ,ß!Š"ôÆ’÷ây—›‹ž.@z2A¹¨=ö¥BÐÅA5#°Ÿ!lZT]07àEöG|@è½vô¦ÌMT@nàs!õÐO( Á*YúÈÆlÜÐ4- ×õõ#X•±IžóbÕ{ -p8Æ%o#‹õ¼X{±°ÙãИ ]MâÚî~‹·ý‰ —ñúG$ÿ¾o9ï8Ìk o†Øê÷ñù—@q¸Ö±ÈM2}>ž¢¿òÁþWã§æƒS’ÕË—4åÒ]>„Ú›f¿^Ì9‚ø’â›ZµíîšÝ§‘ëxÖk¶±û™¿:|yVøP(ô„ºŸw\zÂÆn(¤8zíî¶Zp£kBDN(@·¤–ñ¢Éã·íWý– D‰? üòKôÏøwfÃðLC~©Â?!Ób)–ƒ‰roÜÙ!åýÒ’þ?àk&endstream +1953 0 obj << +/Length 2922 +/Filter /FlateDecode +>> +stream +xÚÍZÝsÛ¸÷_¡Gz&Âá`ûäØrâkNq%g¦íÝ=Ðms"‹®HÛqÿúîbA‰’-1©•©“c øÛïDÃÑ3–ÙT¦=—jf¸0½Éíï]û"Žé7ƒúíQï/~9U®—²ÔJÛ»¸j­å÷^ô.¦¿'–)v+ðä_Ÿ‡ƒÃ¾4<9=û”PÚÈäøãÑùÅ`D/lúþlxB=)5ÇŸ‡§g¾ŒŽN.Î>©{48ŒÃãÁ៿ .–[n–à +÷ûïƒßÿä½)|ݯœ©Ô›Þ#øDØþeQÓ‹‡lvŸSw}“ÅÎbšÏëâÎe^Ñ»Œ^Ü-…Oʺœ”3ê¹Ên‹Ù²¡çá[Œ‘°{An¦\ÇŠyUgóINOåµ5íeÙ&Kµqj +Ù‚âuð*í™Iíõ›û䘄‘žËŽ)ÃœiitBòŽû:µðpX)/“€M^•÷˜ÄÞiVg 4Ž›ÕÈ«rq‹,DV^S[ˆ**j맻øînx6Ÿ¾ÄER檼Íëâ6Hð+HLôXÝå“ -“Ìk¡²/æ­T²KÇqŽãnCÇÿ·YÍF„M™r s}éwë¶á™Îßà +ö VU[ä£1`Öiæ×þÀaDúªœÍÊÇb~Õ‡dA“œ¶–ñ¸e;ó‘ÓZû1@ØHaã¨F)Á$ÓhgGÕ_6Yº”t‹F‡;ýÿboÔWïS}-(¦Ý©½Ö&È â ܲ؂ Nnʪ&*›N£òVèßdšœÍé i%gCjƒF½Z£Ê …^j5šI|T’ìv˜xþÂo þ‚Ü<·Â'y5Y—ù´1Æ‘½§ÇD"f»î¶ Ù—ê6›ûþ%›Û?ê´ðœeUÒ“^Á?0·ZHÀóÁF¥Zãš¼=ïíôZûzÝ·®à†xk~Ä63¶Âg¼cÞYÕ´Ê)’ª#@ÌJüíà °]Eã5²Üe°fbéý³E]d³g Ð à›¢Ÿ¹¿ÂWèi¾­¼:.Znþ’+æÓ‚ÖÔE‰Z!h]Æ6h#óì6R7y´­ð(V#âÞjz +N¶½ÀÚî±woqc|]')èÉÛ_PH@ ½*ïçSÄ’§ÉàÛ]¾7<¯³YìjË&Œ.âl’M ¤<¶Êf›é¯¤ŸR #¬Ý-šÆ¥£¸h“OÇ'ïAµ¥çɧr’Ó!F^NãêÀÀè2«rê®òÅC¾Â+Å3À¡køVkûÜ@ˆª¶3aõuoؼÂKÆï0¯ÆfRÍëù'p{F‰äh]«ùšðSϬ¨êho7Q_™àC‘lµÂJÈ] ·¶¿/+ܘ}¢¬9ãÆt„2«%IÛ1$ÑÊAò€yO>–³iµ–]M‹ë¢nìë$_Pf:‘wø7@»Åï·µë}ûB;#,Ðw€«³Þ‘ß8ý6”¬†àm=+†\-Ø}é Zír^LÈÐO~_k=ÁªÃ3„ÖY0.^¯ÁCŠ8z«iÙ¨µ?ð gÈ2 ©:J`Ê!²Žâ×Çg' à<õÉ€¿“ÜWˆd9˜÷RÕ-®žB‚„7Åä†HX✨ɬ€aqF\ ¢ïrR€JLãÄ¢¾ÙMÔ˘9ýQ¢v\lg] “}qNƒo—üG”²™±sZÃvu‡Až 1‚%'p5È€Äò»Y6¡š’Kj°/A€ž–·Y@ è¨=@- T¹rÄ–@ÂÕ£mÌ€n«î`D¥R™ÌÊò+.¨R•Üß½ QB’‡Ðò +ÃÇ|öD#ƒ¶a +Osšƒ2¶ ¡¿º¿¬é9§!,L),\ üHz–ßÊU³sÇ]ªcйÈâ§q41YšÅq°ŸY3"Ú2´SzŸUôŽ~¡±QÐ1Áç…8´Iûë¦ÈmåÿŒˆ.á–ÖÉÂݛ׉âϵK’C©;„[YÆáË¢pÿ6ø'p[¥<×e r0ôN๻¿œ¢¿æOÑ5·ì ¾ˆ‚½šU×ómøêüO9_Y›þvûÔaˆ¸Ú‘´@د Ù«+W©…8Su¤Ø3¡L4DcÌV¥Yã“H£†ˆÔ$7YuCê¶hXˆ]…áÝšËБ…ËYfÉB¤‘…[ Ó[_û6*ûM%öäBðìò€òž»H¢?œöiíxéª Ãu=+/›8÷®¬ +Lú"®ãû»ÜÍb†Û˨ŠŸ>ï@´µÕ7Ù*Ë™“^t ê,“6¥3‡gÃÓÏ©ðr3².b +Äñù"¨ÌjƒŒÀŠ¿ +H +:$‚G,€2:j‹3¼ â _⶿ô ‡¸ +¼„®#[V”*“ÚðÝgçãÁqð&Ò)œÓ™ØÄ´Õš1ºÍë›2š•ù‚­›£^+UùÊZ-»oÁV-B¡ ŸÑ2½¢p¬¹ÜŬ +o™Yà&Rîºì‘ôLC˜NÌŸ û†‡Amt'X° B“‘T4X©§¡r­:˜c(žŎзŹËïpî»KMí/ÝC~B-Z:1VÇ ªâšåÉš½„Ö£0¥‚Ö`Ó¸p¤ƒ ïZ.ŸÉ…·f…È ‰˜çk’/U3¼˜oç¨ãu1ÞˆÖåþ+=ÐöB&4¥ž`@iZ¼5õ²ÀÓ!©|ry_¿”TTu1‹®/f bT Ôøì–¢9š;CjYó1k%vèJÕŽ¶Å¶ý“÷ê+á³ (¡£´žY°Ã$]ÿ€Ðæl:JÐþPcóM`|ý6Œí:¤o&–&hJ>FóÆ-kj½Cv Ö*å’ŠïàEë+ßpUYjÁ„³9—„üO)ðû!\=„°%9 Ø‚¹\:?)SˆÇÔ[̯ÊpH¢Öà…!AÔ¥PB‡ðÎÆ¡ëæx+º´móÆÏô$7L‰Ž¨P*ÉÜI eê¼~,_ã1z¾x(š›xÙd²:”C 7 H·†šŽï¸öÐÞ÷~3ç½Æþ÷›òŽŠ¶pŠqÕ ‹Á€õñV–rKyÍ°vL]шEÊD“T>ÚÕÔ½ƒï1kb­¶Eb= +Øm8Ú_÷†²6í’q ã¥p‘ ƒãPòM@®b¡]ÆÌôîy@ Y1]¢¤˜0-ð 4Ž `‘âÔ˜•í +öçÈb-ï¡Áýáf°'£^3ê“ËQ" ¦íó\f\¥¬‰È¿U½¹Þ á?–ñÅR¬ŽDëÛà鑾 ¨ÑˆZº¤[Þ# ý­l–:‚ÔÒÒÔ†Mõ_òË›‰?r.¶³¤Ù׉#æ ¬Ç;ÕL*ºp±yO“÷:Mø÷Þ_Ýž‡ )ï·¤³Ò“-ºl\‹J`üÙÅvÁqÓ²ÖÚû€ÊÜendstream endobj -1433 0 obj << +1952 0 obj << /Type /Page -/Contents 1434 0 R -/Resources 1432 0 R +/Contents 1953 0 R +/Resources 1951 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1437 0 R ->> endobj -1435 0 obj << -/D [1433 0 R /XYZ 85.0394 794.5015 null] +/Parent 1927 0 R >> endobj -450 0 obj << -/D [1433 0 R /XYZ 85.0394 675.8159 null] ->> endobj -1407 0 obj << -/D [1433 0 R /XYZ 85.0394 651.4464 null] +1954 0 obj << +/D [1952 0 R /XYZ 56.6929 794.5015 null] >> endobj -454 0 obj << -/D [1433 0 R /XYZ 85.0394 522.8339 null] +1955 0 obj << +/D [1952 0 R /XYZ 56.6929 671.961 null] >> endobj -1436 0 obj << -/D [1433 0 R /XYZ 85.0394 492.6901 null] +1956 0 obj << +/D [1952 0 R /XYZ 56.6929 660.0058 null] >> endobj -1432 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F21 714 0 R /F41 939 0 R >> +1951 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F39 1151 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1440 0 obj << -/Length 1169 +1959 0 obj << +/Length 2986 /Filter /FlateDecode >> stream -xÚµXKsÛ6¾ëWpr’:˜ïÇä串ëLí¤ŠzR5Šm4$Á€ e%ê/H)Ë5帣ñüv÷Ãîb!CÓùÏкh^`CG7-ÊFºvÇç®F†\Ô"Ð]õa>:»´<-€kºÚ<é`ùP÷}C›Ç‹± M8áúøâÓíåõÕŸ³ó‰gçןn'ÀtôñåõïSѺšßÜœÏ&Àðc|ñÛùçùt&¦\‰ñáúöW1ˆÏ3 ³éåt6½½˜N–ó£é¼µ¥k¯¡[µ!ßF‹¥®ÅÜì#ZïhÞÑ¡¦–lÇ‚ŽmYj$}ýÑvf›­Gù3thZ®y„@Ûè˜Ðq|[ólºž'<;›W×ÇŸ)yÀ1P|"’)brð£h‘D|Ù½œBa½ò bà;ÉQÍ W ÇìIÃy”V1Î祿8¦¨,QÙÇÇ9C4SÑ»'%+aUØÐHkÖ¼ëhòN ýhvXô]Çékö…Ü—…%õþ˜Ê NÀÒ Æëwb8Àzýs|ÒìNri¦ƒÚYêÑ=É\šò²ŠÕ›E÷’ÑT²¥åL›¦ìå+Q,:ëíÁq=`R•ûs‡Ç˜i@@OÀ)=ß¾­ãV*…g(©J)”¢¨¢%~ÝÑÉ#ÊϺ!%ÕM¢‘\þŸzs~îŒâˆ)–ÞÒý#’³ç­ÿ“<•gPTëGªF ¼VøS!`Ð÷½àmB@D'ð‡ÀÙ¥ihípR ç ÊÑ=«Íð¦Ã³¶®ˆmRð2”ñó—ɆYR×Ëzõ‘;а뀨ºµÊÃLvQ–å²Ç˜t•žEƒ[´QH6à[…è¶"ß­šZ¥¸dm´4ßå0L Üûu°ÆSXFüL}cm«"Õ5ò „‡JŸX1³3+Z)¿]@—§QÀ“%Núð¸XÕzKÌ‚PÖŽ×)A -X¼bWSi7˜ žÈ£¯ vd™„ÿÒ}Ò|—„8ÝỜPÄÇŒž¤—³Ç×ÃOá68£ÊlºEåŠÐU—ªS_ºw³íÀ`«b¦UÑm¯HÁÚ+b€!û´}"•j*Yÿ‰æêåþTõDäƒ7endstream +xÚíZÝsã¶÷_¡·P3'_$ÀöÉñÙwNî|®¬´7Mò@I°ÅF"U‘²Ïý뻋%Jч/öMýÐñŒ¹X|ØÅþ°»€èpø3®RÝ1©f1qg4;á;¨{w"B›^Ó¨×nõÃàäû e:)K™t·­±,ãÖŠÎ`üKtöþôzpÞïödÌ£„u{q£.¯Þ'¥ÏÙ§«‹Ëw?÷O»FGƒËOWÄîŸ_œ÷ϯÎλ=¡t,a†ø秫sjtqùá¼ûÛàÇ“óÁjÊíe ®p¾ÿ>ùå7ÞÃê~<áL¥6î<@3‘¦²3;ѱb±VªáLOnNþ¶°Uë»î“æ‚ «NOÄ&vÿïÒopøÝ@ZÅ›lÿ,,Û0}b5SB›•ì¥lÉ^hŬRqÇÄ)K”T^øW7çgªÛÓJÛèçÊ»=¤ò‚¾o¯n ~˜WT¬KúVn´\t…Üô±é0ÎGYíB»IVÕy=!*+P£YÇ8„ô³) +·€ÙHÙÌ!%ýd“ÑgäuF<¹j% Uí÷Ù”øã2ŒRÖD¸/yUo‡óà›3øOYà"âæ9&¢µ6(=ÐÚ€ê÷é[?ή26QFR!þœ +•+B‡ÛrÑ M_?©Þæ4È&òâ'Éýa?[ U9Îoqì[·¨ˆqë«œQéª+"hLZ.Jñœð ¼‡ VdöæŠåÌ- ?ȹ,ˆ7\ÖDøÝaT4+W«͗uVCûlê· 4q_殨ò{·ëçüÀ —aé·ŠŸ²#VªÅ4éˆPË£Ñ4'{f†Aq1jðÖU£E>t¡c^ìyÿâŒÐ"q̶áB^˜¬¯mdÏ3\0¦;=©X*¸þŠ!©‡:€ gšku ³T'b×ÝTF§ýÓ]#i0! ˜lbB0¿n: ”× Ù²ž”‹7Á}`­ ôÃ$MöcAØÑ ¾"zeb¾pŸåÓl8 Eœ ~—ÚŒšÇ +\ƒ?5ž¨ë–Ÿ§˜µ®|‰¿÷›ûuÍ9K¤é:–päÁ@^ºŸpJj¡‚†µM )l£aâ¡Hñ» ùÔºEߎÐ(ùHä#õÈ*äËT7¯µ ºA¦ß¹©ŠÀžîò׌\ÒÔ_©@¿=Ÿf£¦Óð‘¾W^a˜X™ô­<˜CVÓÚŽÏÛâÛ©^!c“0#¬+&@3¤ª›÷×蜀·¹Æßl=dTöéC`l溰f¾NójBÕñÖ­B¯‰×6Výî¿«ˆ‹X[âïÜb¾È‹ú©F'å+Û"z)M6“}úMýš”1Kb×hR¦Lê„ä4ðùÊ\ˆ&¨Ý—šý +H«’δ‘Û ¯;®àà¤bQûÓX÷Ù4ßÚ"u³ÿ²½CVö ª’Dü¯Ú +@_ð¸“î‰ÔðCéý~Ör…¢ PMnX¹ÏÄ1YVTž/ó²r¸É)‚lpÇ@øê»jW~d¸Ì§uouH†›u²ºvrÂWá¨u쎽!XТ-{z@!X€±*èÎ0Ó¸C ¯J„¶û÷d[Û¯8'”bGS*Â$nB øܨDÀþyï@Lc­Õþ’b­-ù›U˜G…±»wÓrN‰K—´ÆoI4B•aÆuï&<…-[`Z/–6ºôÏ_$½Å‘ÍŽDŽ¿”N5YßTûñvØ +õMØ +u÷Ù"/—a¤ê±Ú™¡­Ý,˜]fÕjƒýÑÛƒÙ,šÚ»Êž7 þø‡LÙº*¼å€=¸{­ôöR›ëÕ8 ãÂè':‚&-{Ï}¡Ö> +Ï/TxjFí"¨¼­]X³ù4åµÏãÚh‘…nzXá–ò×Xh˜¨Ý»Â–Âu¸|㑸‘ýð\ë¢ #»/ü¬ ¿9ËŠÇ];‘æöG¢{¿«ÂÛ3¬ÄÉU“!8j縓Œ|ˆì¡–£&‰^­ý'¡kë—ñÒþ =ÑÇšž-QKÿ(y%=Ü£BQŽ½ ®…öÙñ4ƒf€±Ý÷há¡H-½(+b­=2ݤtÀÜÃ3Ðzâ2ŸM¤Š˜ãœ°Vä*z0ø€‰%jâ@잇_áUlUû.X&¡@ƒÌ'?üôš±HÚ?ãÁ&ˆ+þ±Öž§¸ +S†Jìz9Ë;GóO}§»~«¬ „Uû€(®ñ8aV!]-¶ç+ $MÓ¬5÷ÿY¨—lendstream endobj -1439 0 obj << +1958 0 obj << /Type /Page -/Contents 1440 0 R -/Resources 1438 0 R +/Contents 1959 0 R +/Resources 1957 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1437 0 R +/Parent 1927 0 R >> endobj -1441 0 obj << -/D [1439 0 R /XYZ 56.6929 794.5015 null] +1960 0 obj << +/D [1958 0 R /XYZ 85.0394 794.5015 null] >> endobj -458 0 obj << -/D [1439 0 R /XYZ 56.6929 469.1685 null] +1961 0 obj << +/D [1958 0 R /XYZ 85.0394 229.6198 null] >> endobj -1323 0 obj << -/D [1439 0 R /XYZ 56.6929 441.8256 null] +1962 0 obj << +/D [1958 0 R /XYZ 85.0394 217.6646 null] >> endobj -1438 0 obj << -/Font << /F37 802 0 R /F41 939 0 R /F21 714 0 R /F22 737 0 R >> +1957 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F39 1151 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1444 0 obj << -/Length 1176 +1965 0 obj << +/Length 3016 /Filter /FlateDecode >> stream -xÚÅXßsâ6~ç¯ðcèŒTK¶lkò”KIš›^îJéeʼncû,‘„÷¿Wþ†@°L‡ñ ËÞÏ»«ow¥E†©Èð4-j.µ!11üiÇ4îõ³ë*ßÕK þÖ§Aç×+Ë5(¤vŒÁ¤†åAÓó1†g—¿_|ôú]€‰yæÀ. Žyöéæö·b†—_o¯n®ÿî_t]ûlpóõ¶˜î÷®zýÞíe¯ G–Ç%«›?zÅèºñåËE¿;|îôK[êö"ÓÊ ùÞŽL#Ðfî˜Ð¢1žõ ¥Ø˜vlbAb[V5vþêü¹¬=ÍE·ùX$v·8ÐF5"ÓƒÔ¦®á - [¹‡]à˜æY+1™ÏRŸƒ'§˜ýÇ$¦Hœ1 ‚´˜Yd&Ú]Ð2‰þ8‚®m‘é—üÔu£6¯AP!Z“ÙÝ’­u7í·Ì)Ë)Γõäýö0éRha—”‡I{ÇaÒ>ð0¹:ª¾õ↞ûϽԅØÉ÷¼pîŦ±åÒ»EZ¹µ†ö!ºRˆ!MuÝëZŒD®é| 0v!²=¼•3ÉÁN÷¶‰ªµ&ÊÒ;.´\lïZr\ŵ eSº_˶­žSGçF«}@«çi^ S4/ð¡Í‹m=I‹À¬‘¸¥ƒ¨¯òsG÷+WÍ\[óÛóð²‰q­i™ô0u+¥23º©ù²±ùVõÿª'Øendstream +xÚÍ]sÛ6òÝ¿BôŒÍ¿p÷”8vëNêö÷.sm(’–p¡HU$­¸¿þv± Š’)'×fæ2ž± `±Øo³þÄ,ŠýXK=KtèGˆfùú,˜-¡ïÛ3Ác.Ý Ëñ¨×÷gßܨd¦}Ëxvÿ0¢•úAšŠÙ}ñ‹ûÊ? +÷ïï®Ï/ex7·o*Œ¤wõÝ«Ÿî¯çÔóÐ×·wo£éçêÇ»›Ûož¿:OBïþöÇ;Bϯo®ç×wW×ç¿Ýv}?°<Þ–òûûÙ/¿³v÷ýYà+F³4_h-gë³0R~*å0ÕÙ»³ G½vꤘDàKË 9I9%§Hû±’ÊÊi“m;ÚÔ¯AÌßÐNñß+@êêVÙ0(]ë°%uYŒkŽú¶ç"õʶé-3vQšzI`Q¶ùÖ,ÊÂGaÂŽ.Eâk%SËÞ=ÒQÀͺÌj;G%‘]‘õFÞýý[ eUPôԛñh³æá•Y›ŽMM¿«fÇ} ­zYM˜ùœÚyÆcLæC¹a*¦>X)ÏòU 6§ +vàØ UÝ&…¯£HÚMMi‡¯n,ÁÀË6›ê‰p]è¾[5[Óey,©«ÈºŒ b ðþhê²ýûùe¨×qϪ–I¡$ +B6}wÃá-z^{á&é:>°*W¬ámšÊäÆñþÐl7GŽHTthY™$¡`­Žô¦YUZyYÛšem™¬åD‡{Y±6µi»mÖÁjõ@€:\ˆ Ýª$¦È('7@@—¦Îº²µ¬Iï_+S•SJjAøè©@®[‚¬I €&¿}‹¼#„jÃ_dxmþ(Ý„åw- ƃ3úùƒØm†eØve¦k§è·šv›U¦³jA”õHø½­»r[—“¸)· ÆuV£*)½¶_.˶£y?AeË#ЄZ¼jzër/¸ÛºÍ`„e­(·Ü| ß"{b*¤Çñ”îicò¬¢Æªi;ŒÒ2önynF?ù*«—å”é‘ÃJÍ\¡¼;0Ø ¨»É©0u‹i¶DžM"™}n­›­!^5ù¦‘afFzdØ2uÞÔ-ØpYçO„*ú-ù”$UNhˆè^PÈ$³¡([TY÷d€c³ükx‹Ü¨lÔÂYÕ—]UÍnˆÌC §Åâs²ÏR'¹BŠdÌáI…Pm™w¦©©a-ÇÍ[šiZBäÙvkìv ‘1’WÉ›õ—©ˆ +b·O¼L‡‚uk¦T4ëÌ1Ygktý ‰ß»ÝÃ1ÓeÖê­\d±’£Æï}Yw·×šÈxʯR†›Æ #¶j§éVN',̈…9ÖÅ›»w–]Èíb”Ûy¥|!FÕð%;A€ä…^ù±ëÑ›Jùq³-!Ô6õaÚFqyH\†¾Eh‰“ž´‰o8I€ìî5¥&0(F[g_D½ÎZ±³-;^Áò¥å¾¶Oã9&vMÞTèËbCß_} »®ž^dÒ²1a+³\Ù©±öÀ]›‚ŒQ;þ!7îÈ×v ‡ +jÆgôƒ¦CSÚrûh5 ؆]™Taø „:'´i +ûpñ1[o*kƒ±vBx4Åñ¢ó›+š Uhx11z¼»§ªd¢T•m©aƒW0ÿÀ¥6ÄÙb~×D1…—å »Œ˜mžŽçsÁ°”À<²s‹2K*!NvLÍ& øù„qlåCL;¥@›Õ°À‘2òÖ f4 K“ =²øÁõk­_Òö@©JBU¦¶qXB5RAEÖ/WÔ¼šºw! ¦áЖÀÑB ¶\oQñ²}K;xXmm{º"–±ÍQé Å>åÌDÙ•’ÞŠÅö¨¶Iö71s>÷ ¸åžŒè8Š +ò"TLLrgºÕhtVYýÅÊáìtbeÃ$ âë±*wZ8 +‚-ùÒ(´îO(ÏN ìí¦é[å|^#·:]Göæ¡åت/\P·õÊþ„“ÙÂ@Ýõdcí¤ænöé}›Œ +8=Æ1{;ÆWÆV`ã¡P¥\0êiSòx÷—W L¦ùp4Óî«ý a"#¨oË£‰ëº\7µÉÛ) %ú}=äèEóh#vÑ8ve,C"æ4¾½$s@?4ƒÜÇÕñ†Ÿíp¡ ÐˆyLìð†ÐÙccWP),{TÍA}ÎÖr &ŠËLDÚ† +pÜ‹Ä6÷ö´ÿÁdUêŽ +Ç£xë­•ì¡]#@»-†­ˆdˆÔª­œÆ°4VAÈÁÆÝÞ¹>¹/0_R+?á œ`»Á(û¬]I1d¦©ºÅV=”亣»àq{ÂqŠÌpê2°®ô 9›†Ï+Îp\q†õœ¸qÂœ~÷û††Nžàb4€êfW•Å²=O§î@'¸ïèÉ]€N¤eù¬˜Ô©+ΤоŠ…ü<ÓÊÁôçÔ’_ ̹=]Ê ñà >û#?t[| Féïý{ÿíÕ;ÿ‡Û{.(¥Nè@‡EøX ›ð/ ŸGÀ"gòÜ/ýW þÂY`БFAz* „¾°2Ðò•Pn¼ún, áí…XÊà¤HÆË}!™ü/IáËÛ¬€;uIA)`è󒂉$"Ò/'ÂÚo9 ™öåà3Ä—QD+÷a’ ‘P ÀJÁ„åO~[›Ì&3[B ú~á‚^žyø`+ÐK"A$š£ÂcJT Ð*'¾\ÃÇÏ&¾3 +fŸŒÿŸûUÓþË®ÂVšÊé8$¡äµi‘™BuˆàÙq¿R¼ÿVÁfendstream endobj -1443 0 obj << +1964 0 obj << /Type /Page -/Contents 1444 0 R -/Resources 1442 0 R +/Contents 1965 0 R +/Resources 1963 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1437 0 R +/Parent 1973 0 R >> endobj -1445 0 obj << -/D [1443 0 R /XYZ 85.0394 794.5015 null] +1966 0 obj << +/D [1964 0 R /XYZ 56.6929 794.5015 null] >> endobj -1442 0 obj << -/Font << /F37 802 0 R /F41 939 0 R /F22 737 0 R >> +622 0 obj << +/D [1964 0 R /XYZ 56.6929 622.0858 null] +>> endobj +1967 0 obj << +/D [1964 0 R /XYZ 56.6929 597.3835 null] +>> endobj +1968 0 obj << +/D [1964 0 R /XYZ 56.6929 411.8393 null] +>> endobj +1969 0 obj << +/D [1964 0 R /XYZ 56.6929 399.8842 null] +>> endobj +1970 0 obj << +/D [1964 0 R /XYZ 56.6929 231.7148 null] +>> endobj +1971 0 obj << +/D [1964 0 R /XYZ 56.6929 219.7596 null] +>> endobj +626 0 obj << +/D [1964 0 R /XYZ 56.6929 131.5008 null] +>> endobj +1972 0 obj << +/D [1964 0 R /XYZ 56.6929 107.0349 null] +>> endobj +1963 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1448 0 obj << -/Length 1031 +1976 0 obj << +/Length 3209 /Filter /FlateDecode >> stream -xÚÕX[sÚ8~çWøvFŠ.–eOi -Y:[ºKéK)Ã8XOM-±)-ýï+_1‡Ûfgvò`ùÈúôOs‚ ¤ÿ°Á,h9Ä1¸cB†03¦‹2æzî¾óo@ñ¨~õfظéRn8бˆe g,"ÛÆÆÐ5-H`K# æ݇~·wÿipÛâfsØûÐoÂP³Ûû£“î·ïßßZÛ 7ï~¿ýsØdSVŽñ¦×›YœìQ:èt;ƒNÿ®Óß5:ÃÒ—ª¿ÑÄ‘oÑžvû]AêØÌxÒ/bÇ!Æ¢a2 -™Iia •€•ÙtéAý0‚„Z䀀&®h#h! Å™-Jh*à¨,„š ÷;ˆ…Š×@ù ‘ÙÂÕâAÄÙ¸=ƉÃzW€1t#;«@ù`áJU,Z 9‰âIŒñCÄ# #(‡„B#³@Ë¢âW»Ø£˜N¬?¢0÷,MB·pt4 \)ÇÙËÏtéAXµ^æ+ýPµù1óƒü©b?œ”ë]öD æ®ò£Da°>C9\…™>ŠéWø$3ÃÄГ‡›™ëF±Ð6¼ƒxs“=û‘ʽÅ2 *áÁ—t&u¦×êLžé,Õêá%ñÜ ˆžÀ·•ˆ×jf÷¼XH9Y¸jú8 |™»÷ë%+˜úD®%×ÐKˆžï«eu<‰–I 4—ÇÞ‘º ?~e¤—E²Ì¢X«ºUF‰ïj»OÇÙñGƒhE½-JâÕfæÇR¥lŽ#b¹süù¬¿œ$Û–Q¬J{ò2ÞÙÂòwtr¨d²È#üܺ¹³¬—›s¾Š<ô`\‚ïª6ÒþŒOÿ-%iEÅn(g"¾§ÏÙ/K.U $E] -´\=”~V—ÖGôŽÃ%G­â©Ø‘¿4+‡°I!0w %œi$ÈMÊR ßÒ)Î-£bßűËol]æ@ª”áOð·U¥jíSu8$ºzxªQ]Áp§æŽWà,Y+h '³†«y)WÌXMîØãzTZB0ÄY¯$-á›69(íJ -P+o™N©Ût¢RéT"•?•—1ž«ÜW^˜LüP—°3 ¯(bÓ:ø|¼Ïäºbú¿®ÇË -îU -iZWH癶}<ÿ“úuµÖóùwKnZWr?ãÙ>Êå¦K°Qšg 5 A›sZvèD_åì²ú£¾,ÒF#{}«K_DB?+_‹zÙà“tç¢ÜhÛÎ&0È™Å+û@œïô¹ÜiØr´ÐK]v×4ë”Á¤Ã>ÐZ£Ò¯«ùí9L©m“²G'¤âá64m ’“J<ãhyÑñïSÿnQ{Àendstream +xÚÍËrãÆñ®¯àÁ¨ÊDæ |“m­C—W»‘•*Wl Q†W«|}º§{@€‚¤Ý¬\¶tÀäu÷2&ZåÝaû5¶m”×+l»† ¹_vži¶µòÕªìʦÎ+ìë¨{ØñLY¯›ý6ÇIèúnŠjÇhڮض|„¢+öÛ²æå÷›"¬ÛHr¸÷\Ê8³VùK\ó;—-}‡—Šûiœiåü‚·¿œÏµ– ¸¤»­ZÌi”:‡¯Œ-<³Ö"Z6uç!šŠ&VEU~(öÔkÖô-¶yY!ÓXÝlÐ6',í®X–¿ ¡ú²æmìøl ŽHŸÝ¾löeÇ;ûÇ¢ÙH V ÷0iTçÛŽ–ÁGƒ±.“ /ÙÒ|ù@Åžº„3G*—òW§æ€6ÛlÞÁ[ïºbl¦SÉÜ4Ú¥j›zìú°½ÅÍ•vpßÂϵH¢ÅG³¨»ohšïT-õû—ÅŽß +Á[ Æ¹Œ<Ë{Òâl[ì?Ð.±Œ-7Më9Ú{ v³­Î¥”ÑhÕ #ö8ÂÞésd© ¬§üÄe'vš9¢Ý5õª¬ïð¼™âk8Ñ®ƒÃÔ¾£n~WxÙv(¶ìsj™è6_þ›×5ü (ëâ#ã¨è wø&~ª?4ßßH½ïY—Ð;µ¾j¦x²n›rÑ&ÿ€[ª ˜ø†òÛ¶©]A½m‘×pg‚ùM©”†á¤¼'œ(5˜nꊋeW†MýÅ +ðí©‰âˆj !p´YØß?+À±xMñ+ ›R,lÖ…Ú8O-æ lzI±†åÁâë.7^!úц¾AæÆ€^ölxll݆mII‘ó™^ÈÀ¤fSf"&EƒWØZ†@"KˆÞ·É‰À`m’ž°tÛ6Ë2ï¼)e fƒßd¤½ŠÇ~V\PÓÓ¾ðÃ’ˆ'Ц_]¼½Ûâ3h´‡5"Eµ±,‹GÆ!õ|ãwHHT“£¨B“Þ %/UQ¹¦AÏ4Ì|Ðõ›Â÷¶ñ&2Ižp°Ä=¾"îV÷ úz|Ì›“Œ> 5< +éhì{Òé{tw<"í·àZÖ™ð̃ßò®nŽ¬c€ç5ØìÜ+q°$¬5² ˆ`Éc$#¤!Ò:¯‡^õf'fÒŸ¢æU ±ÃO‚l‚q`l×”u7ØjB Ý>sÐÅìåv+>æÛ]U|sêòei,-¤!UŸäó©,¶©LÇ>ßÿ·*œcð~Ož€Ö ÀÅÍ°bŒjî4·. V½?iä@üÁÁzf3¥K<5™Nñ²Ù¢†Ñàµ-À­ÖJ¯‚?ýÂ)Îç©`–تŽëÌlpœ/» ’R¦Zý!4K¡•%nšh`ûcðÑ2¸‹ˆ§'S(#ÇLí©£>‘<ƒ_—>ò5é“ØX`ã蓸8?â ú¨!}bôa»¸Ùß=CÁ¾aî€OºÄ¾$r6‰ÓT“{,@ å,§vž©bü—OÓh°û_˜FFÆJKýŒ‰L³žF'bæï"©§‰4Øþµˆt ïÿ Û;aì H‹tœgx”o€P'v*·ÎJ§Öèçó &³/É<¼%çÏch¨” ®Œ{W¾}H]²Ý§ome,Eb‚Ÿz">+0‘³"ø¬ìüœb+“Úl€T½€yÎ)§x z«ÞQÁkÔ|Ã>nF§õkŽZØùÂ(8v‰”c'Ì{˜è¿%G&èÿ®ƒ»Ñhpk—ËÂGÓØÖŠ'è–; –Ðí¨C§È¦b òÄðüX–ý:tâÃcżXö<«Áù”`ì % /æÑ`VMƒK À{ü¹è: +ðÛÍÍOíÄ!ÀÅ#3’Œæ ùkIÔ•ÛbÞ5óŠ:!¥Á¥K8C”xÏ¿¨VÔ¡ð€üsèj5¿-;ž§ñŽ(ž°_¹ã(¥`ÒC‚C]vípçœØ%„é­’àÛ÷[&>oó}éƒRD€Y¦ /Ü»¦Iù7ç`ˆ“b‰A0´–$Ô¼¾nÑ Çd‚! *5VE»Ü—·cÚ4÷Ô¨ÿÐÊ’€—·º-­Âغ9Æ?:ò$„o»iU3™’*ÛeÎR1…–"<ª€»ªšûž%º íÁ³˜[lÇò@×C^ìOåbxµŠ%‚Rz>>¬y}þÛÔE7…a?5RûÙÔÌ´3qjä§èkŽ©þ<}=½jàëÐcJ|Ž3VœØ þNà3$q¦ÄÚ\* Ž™¶3‚ܦŠdðçw`6 ¨’ðp&ªrŸ#×l lšim‚HjZª8×]ÀPw9'g,ñ³çᘀn6aÝ8W‰sÈÑÈoàñyfÉs¹µ}ºšÇTgPo¶(hÖÍÔìfR78†zþê—ïß½½X\…T„¤éÚ¢âû5vK¼öÐâ)Ùï%a›,·†F]d¬Ã‘\bH®cDÓ$rß*zƒ‡~ì1 «$Q³!C|“!;ká(pgò³P†Oó-x!B¾ÄµÊÅ@Êð|åu…Á,%¥äÀÓ˜V)¨%N$Qq³|ZqÎaºfG#>ݯBâH‰`‹”M#¹‡Šr„ $¸G1ÛÔò®O3ñªX燪;Ñ|=KGûj#˜coÝHáõÙ•å ¢¶èža‹žÞ_ö‚§La^“)¦ +²,y‰-„‰“àPRy÷\áTG—9&X•²4©,ÛBh„œµõÔ„Qû-}I¡)ËεJ:e}y}í=þœ‚cÁ5¶£ÒÓ“¬Aæ®8*:1Tt‚ïÂJ£8É‚•Ï°Àº¯ÅŸý&Ufà€§Jnä=[x°çC e4ø¿…¢>-Ÿq©J8èÉã±®°&ÅBî‚`_‡h½øšÆk¢æp·9–ôָꖷ*>îªrYz·Ç©V)!u‚Sü|=Iœ-¹Ñb*@‚ðÓ¹4ÄO ó(F0#,jd]fÏ·ùnw´sÌÇ‹÷ÌËÃuÁxt&BùÅeG'û@…jœE½ME„(‰Æ–*l´qæhÒqÕâ=ŽJšsÝ8›²ÊÏÈJ{p°Üp´¢ï£Xúâåôà"”ÁOŠ6'OQÖs¿j¢8ßïò º`¶'³!jí‹R.åZ²K¢÷7×Ô8)„–*]‚BòåU\D‹6l~àä~z´Ooab›¯Š1¦ªgC»mÃÅày8óÈ£jË»š Uüœ”©¹Ö‘…’z¾"ˆªXwçŠöåÝ‹ÉF¤Á¿„QúöeQ@½Û5mÙqUvPÇÉ€‹¡!PËh¹¿®(õ Ì« >9äUÅUÔû}ÙͧÜî¨}¼CË5˜¼b®ï7š¸’†=1ŸŸ.÷ MÕ»ü.`‚ȹ2m_E½#æÅ~íƒo, š~\hLÁîrVÅñ5ppȸ>kÀ†rx +EÝ㟩„> endobj -1449 0 obj << -/D [1447 0 R /XYZ 56.6929 794.5015 null] +1977 0 obj << +/D [1975 0 R /XYZ 85.0394 794.5015 null] >> endobj -462 0 obj << -/D [1447 0 R /XYZ 56.6929 121.4768 null] +1978 0 obj << +/D [1975 0 R /XYZ 85.0394 613.3608 null] >> endobj -1450 0 obj << -/D [1447 0 R /XYZ 56.6929 90.5476 null] +1979 0 obj << +/D [1975 0 R /XYZ 85.0394 601.4057 null] >> endobj -466 0 obj << -/D [1447 0 R /XYZ 56.6929 90.5476 null] +630 0 obj << +/D [1975 0 R /XYZ 85.0394 465.8716 null] >> endobj -1451 0 obj << -/D [1447 0 R /XYZ 56.6929 65.321 null] +1980 0 obj << +/D [1975 0 R /XYZ 85.0394 438.5672 null] >> endobj -1452 0 obj << -/D [1447 0 R /XYZ 56.6929 65.321 null] +1981 0 obj << +/D [1975 0 R /XYZ 85.0394 397.0946 null] >> endobj -1446 0 obj << -/Font << /F37 802 0 R /F41 939 0 R /F21 714 0 R /F22 737 0 R >> -/ProcSet [ /PDF /Text ] +1982 0 obj << +/D [1975 0 R /XYZ 85.0394 385.1395 null] >> endobj -1455 0 obj << -/Length 3466 -/Filter /FlateDecode ->> -stream -xÚ¥]sÛ6òÝ¿BôŒÅ ’Ó§4µsî\Üžã>5} %Êâ•"U‘²£þúÛ/@”LwÚK;®ÀØï]XÏü¯gy«¤°³¬°qªt:[l.Ôì Æ>^h™3÷“æãYß?\¼»I²YθÙÃjD+UžëÙÃò×èÿÞÿüp}97©Š\|9OŠ¾¿½û1>ütwsûñ—û÷—™nºcôýõÍõýõ݇ë˹ÎS ëPxcÁÍí¿¯úxÿþÓ§÷÷—¿=üxqýî2¾¯V ^ä‹_S³%\ûÇ 'EžÎ^à‡ŠuQ˜Ùæ¦IœÚ$ñ˜æâóÅÁÑ(-âŸ5yœº Äƹg[„‹ôt×ÿk‘?‡šÍMZÙ·÷çu -H È+’3Rs­U¬tâ@'’4ÎŒ.‚NX=Ò m“Øäy>ËRú‚J±)û¡Ú¡lÞÝ3šžÙ8ÓE{à´‡uÂ,TÔW»g˜OðºìÈ‹¨äßB‹àE·=0Ô­xÒàI,ËA¬:™ÆþìÚJh¶KF½ÔMÃÐc…çDæiijèhåcS±¢ ·»KGÝs½”r?¬»]=”CýìQmÿRízþÁç âs5M5°MÏƼý6y¡bè ”ü’²âMHŠS`ß[*f›en–™,NÒÄû¦|®¦4@ÇY¢EÞ£T2™K UÕ=cJþ÷«mS/Jg ãAM„øk ©b|d£Š8³™•cðÚ~â´I†ò‘iMÝràmµ¨ç¤7sc³ØºÜžêÏ¥LEŠE|¥Ž¼cĦãÛð¯ÛŸy´\.Ý÷aåJøËÁ4¶™0¬ËÁC²‰g&à];ŸRî¡\ ži·‹ö[0 YVó óæâü.ÅI¢¢OÂ=š <‚USmª6*[F—Mßž‰ã˜á<Ö¶åo nJ_Øu‡`$ExÜ«‡C€„¢ïŒ[V«rß W,ýa¹ - JÏö„f9iù+¶ó 7ÓѶÛá}2¥ cº–¿Ì -D ß¡jÀ–kR\Àó•aå£L\¬Ëö©Zòö”äˆ`ÚQ°€}c€É {ª'™ÁV=)¹/*U52Ü{¤$ŠUÛ3ŠŒ0ë}+V¶ô#+™»îö=œ­Jz<¤Ikzžµ% g‡I9ºX¥ˆË8p®XF¼:‡ƒD ØDû¾bDÉ¿‡—nÞ€Ê6Œ÷OÞ ‡úÅBã%™2>A+Å‹˜Mò†'%QõuRlåfÛTWÇìÜuH=F -hÞ.÷^>—})A8M~ íÍ ëS„ê+íƒZNdÊ„47>먟Öï²mÊEåãG%y$]65É©¼Å’Á/Cp8¾â¯º%ÇPÉŸ`‘8b XðÄé­‰UfÒpúw}œ<'Ó_Ö•Ä—×” „­=ž ftìà”2G™•›ÊNE÷ß=)x'–xÃ]À¾t 4—`¸ƒ$$ð›ìo¼L T‹€œÌèSç‰u î{HágkÞ¼¡ßëÒ'ÿ <†ú¦{i®Wü=t{©#öbípIøa––x–¥w.HŽâË‘e-Žoè`; ./&Ë.0Æ™û·U£Ã%Xdÿ„¦_òf‰©aœêÔ¼UbP\Âæ©åpPþP64짭,ƒäoTb$ÏÈyùŽ" Ž›GKÃÄú„ËŠäXšÈBtIú¼¨¶Ï÷ôž8 -é&¬šÃ”ÿfŸmŠèî3~óÖèKÎÉ#¶møéËD‰Clݶ\ž®ô1¡ -Ù ¬ÃÄƺè³ðñ\¹Åÿc( ™³—ßvYKþ ѳ]ò ‰œÛ’²f%áOy? -ˆî>Pƨ¢«ªöc|È­“™U烩ØɱU£CÃR„ÒÉxJ -Ä`‹ 1Ϥ’GÉákÉòµ€¡ ¡¥Â‰Ðk0àHõÔì… KÚžIzêRØuƧC®Ò’v`ôŸ!›-àúº­À¶½ü&uÐXô€s\A“Y6Dx¢î³›¬B8AJsvO°¸¤¾]ñ«òõÀD}‹Qk*(9çPe‹#±%Ä£v5aë)ÔñYZÈT*H¨ùk¡™Í“/j}x1¢Žu§ -@*$ÙyVÉH"mõÂUñi¿#¥¢Z)•öŽ³ö!Tð§ßo±J› "”BåŽ}A$øœ¥“cÁ¶©: à^JqûPøÂYoeªì}—cn¦ /KÀÂN*k¡k2g"m3Î;ãÐÑ,š=1ñlq ^ãð+†ƒ£ª¦ˆ7ÆÔd]7¢-cH‰\áýªó®jÂlYИŸnª’¬"ãtšrSÍlTßm$3^”\Øbæ -漓å‹nß,|ª$¡-‘Ñ„’Z‘æM7TD8cÈß -Á”®Ú3–å‹PÝò ôܱÁƒ+¼Í^º¾ñ£c'€Ìá3±B@ø¥<ºm. ³©¿¢ "8tpã5B¾SŠx駢'¢#<$4ðsUè+]Ž(¯§‹Í‘' -­UHùnÅXÉÇ<üˆ?¨àO`™a7ÃÌ?.8aT”q‡ÙˆòMöYX?•=Þ+Ù<RTq&Ò¿Q^˜°Æç *õtÏÂÏ<9£ -¹)Œ¼n“IåI‘eÜ—>& !öõâUPDDòRWwú«è¨òU.Ñé²DqRå>Nâ˜L.ùÃ¥r)öóHD¾àp¤|º¢|ÔwÍž{@²j*¡¯Ë¢§ú=ˆ¥.†9„sââ¨ì´KñƒJ½ØSÚ‡¿)†á<Í;íîó椵Ýpœw¾¼âf™d0JÝæp|D(èþ {öÊ°d»«Ÿ%µ€%T8»ßùǾŸOɉé;Ýß|Ð…ÎùÇ(ìÊLzÉ9¶jXÇÞz×W3ßX"ë. 5uª\þˆ†%oÖ]Ò!¥rûVÝÄgª/mãöx·{)wË©—,ÎTîŽu—µEôÅËK¤<@$êð/ŒáøEË´â$ð7™.|Ït“‘#š¤ÕˆCû „ŠÐØ2ï"°¼§>5õ -8õëÇ¢ TÆúkÛ@§­Œ$ÎŽ“  ¨â· †¶SQÀ7HwYû6“aϵ{„Póéÿ[éÎ8‰øÆÌÿ”Jg -2“BÅi–Ú©?¸‚Ââoþó®ãß¾Ù,NòüØ€>ÕN…=©"Ãà†´{Ùë¦;„è47aÖèèÿ@y"Bendstream -endobj -1454 0 obj << -/Type /Page -/Contents 1455 0 R -/Resources 1453 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 1437 0 R +634 0 obj << +/D [1975 0 R /XYZ 85.0394 216.4249 null] >> endobj -1456 0 obj << -/D [1454 0 R /XYZ 85.0394 794.5015 null] +1983 0 obj << +/D [1975 0 R /XYZ 85.0394 186.4354 null] >> endobj -1457 0 obj << -/D [1454 0 R /XYZ 85.0394 769.5949 null] +1984 0 obj << +/D [1975 0 R /XYZ 85.0394 97.1422 null] >> endobj -1453 0 obj << -/Font << /F37 802 0 R /F41 939 0 R /F22 737 0 R /F21 714 0 R >> +1985 0 obj << +/D [1975 0 R /XYZ 85.0394 85.1871 null] +>> endobj +1974 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F39 1151 0 R /F41 1208 0 R /F21 930 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1460 0 obj << -/Length 3003 +1988 0 obj << +/Length 2116 /Filter /FlateDecode >> stream -xÚµZ[wÛ6~÷¯Ð[és"WxtS'uOcw÷ì¥í-Q6»©Š”Sï¯ß H‘"E¥›îÉq8ƒ¹| Š‡bfb;éf‰ÓÌpaf‹ÍŸ=Aßû xæ Ó¼ËõÍÃÅ×ïT2sÌÅ2ž=¬:²,ãÖŠÙÃòç(f’]‚½½»}wóþ§û«ËDG7w·—sixôîæ‡k¢Þß_}øpu9ÖˆèíwW?>\ßSWd|ssû-µ8zœzýîúþúöíõå¯ß_\?´¶tí\¡!¿_üü+Ÿ-Áìï/8SΚÙ'øÁ™pNÎ6Ú(f´RMËúâãÅßZ^?tÌZZfbxF*‘œž–¦à0m Á%Ž&[Áâ8"vààØÙ6"Zt""$gÄÌãX¬¤ò!y΋ýòõ;);̱e‰–892=ã¯] -r‚Xk½Eí²*Œ½vDÖÏiAÔÍm•¾dÔ‚ÞÁçã>_ר܈>AÕŠ²K˜ñ(µh«™U<ë®É/Zåš+èŽ ä Ãb-ÔŸØŒ8™88g±´fõËÀ=Ì -vk'E2T#;¡bV'&°ànƒë{(Kàþ*“FTQg»"«Îu¬äÉA xC™BÃæ¤4ýT‡Åì7Ù BÁÛ ™·ý‹rSH¯TèaJ}Éä%­Bß&ý-l,ø«\5ɦÊ:ùÈA%ÃEæ“ä¦ñÞsVåårÄ`åwʶ9%µWŸˆ—%‘^i$üFŠÜ<|DþH¿Q&‡†+ðB‘â˧’ÑMÝW€Š¤pûQðzQ=§êcn,sÎé£ÈtUCŒ¦Xøð%Ýå¥/o¯Um*êY¦uúˆŽl‚{£j¿xÃh³£^=‘ûmþÝå­ ™^B`LUÒ³,ÀD­Dx냖g¯ŸhCZžßC¿û8¶4ÓÚ4ñkñHêµ(‹×Íä ¥y3> Šfº*BQÙ‡„† ñ%[—Û ½0AŸ žoŸÓ²‚õ„ ª”Z¸º¥q[rS].Ê5u-ºõ—T+­hØäKÐ(á˜a´ÐÑ¿èÝ z0DÄLÙðº‰bÓb¬ÚjJ™þÛ4`©xX…CÿCu`xãÚ·ß]Ýr¿JlÜ]@¡ê¥õ¹†YÇ°[8&7ÝÄ®Bbf‚Fw>'Wƒƒxƒ•ÒÌ)7¾7Ló.×é¦åò52¦ü9Ä?_ ÊéVhÈŽ“³·\#Ó÷+,ÐÒ›¾­­Ú¼¸ÌªÅ.߆…L qè^—0.u«c#ŽfÆ„¡¬nÖÌ°p³†I|Qì0U¸5üg,Ê%“ãʪAåfÐòLà[®3Š ¥Vn-Ø  -‚wÆä Ø:\`k¸qú}ŸíF°&WÚMOÞrÌÞÇàCĪ?ý_ ¶Öˆc¬AA¡ÚÊc kŠñX$=;'±øÏX<”ûùXÓ°h!§]ßrQd(mkª>ÃâœÄZ—ë4ÖZ®£0Á»Ñn„]bíôü-׈ý²ÖW åYOƒ¿nÁŽ£ÉÉ’$ŽO"NÁšqꥮ ˆkùÏ=”ûùˆK¾žñ~ËuN‘´iÄÁ~l­:¸ÓÞÓ!Lõ.-ªU¶Â§0““·LÃÙ{`ÃÂ">šþ¯ÄZ׈ãË °¶/qýW]¼¿üˆGø„£æŠÂÿþÉ+Ž\ô;X „ˆÂ© ù8†°Ãv¯{M密ÿŒiC¹£°’c°rx,˜œñqËuN‘´iXiͬ<“Ã:L  -LÇk/õŸÒÝ/¬Ñ»¹å\MjÑ2 Õèa ÌMlÇ¢ÿO&;²fä¥Ä8{:«i.Aš®ÅèkÙ§mHý씦cï¯ÂMF e:£Å±¬iàù3 ¦‘× ^ÃEѪÊS§Ü@= ™vrò–kdö~°9Ì~G®ÒE›,-%«ýš~çc@³¦{nqòxCi×=‰)ø%#:|f€Ÿe4ÝxE€‰«p:)]ø Z¦‹çœ.wýà4ôÓ}'Rë·0íȹšŒ Ó‰mîú¾½ýÎØÁG ×ýÓ»Û»‡›wÿ;x³àøöz`“UUú„'Ï<؇Ù§¸ 7¢ØF-hÌ2´ì·ôô_Aoêooyøj ü4ÄŸBóðý‰§ßGÀ ¼|h>…ðCý!yWÈv—oR:$€ ´ïðnR˜f‡·x{>A"Ü:«Æ hÚ®ñ©´x%âæÇа\RÂGúèKäñgŸCˆI¨´$¼3µÉ¬·<Ž×0,a£›³ <¾·ItÔ+w5Qþš ‰ÇìHºµ'w€ŒG×+t@‹ÞÍy#ê꘩DšÏÒÖH¦dÜhÛñÍà/|P‹eh¡ÀÙf¥jg½A‹a2šÛö£/æ ¶ý$‡XWÔkÔè¹1ìÐ1Þ=öÅK!!j£îÚ«ý^®é^ Tõþ±w­n³ÚÝ0hݽÙj÷Êl³m®¬pµ°SŸ*Xûj´j¿û/þ\ðð-¥N˜²Vž(ï›;Ù º+‘ÃMˆ3©b9¢ú5]ðÖendstream +xÚµXÝsÛ6×_Á‡{ fJßnn:u9§N,÷µ¾i’Z¢mÎP¤"RqÜ¿þ_)ÓqziÇ3æ +X,v±»¿]€DþH$$’šê(Õ LD´ÞNpts¯'Äó$)ésý´š|ÁÒH#-©ŒV·=Y +a¥H´Ú¼‹%bh +püûÕb6M¨ÀñÅü P„qAãóŸý²š-Ý„ô¬?ͯ܈vŸó«ÅÅüõ¯Ë³iÊãÕüjᆗ³‹Ùr¶8ŸM?¬~žÌVÊ}³fFß“wp´ë~ž`Ä´ÑüÀˆhM£í„ †g,Œ”“·“ÿt{³véØ1QFP*X”0ŽlßgzÊLYcÃÍÕZ~•Ž„"­×G‰b°3œü³²Ü: ²<V E].9E\rÙ¹œÒˆ¤… Æç’"–¥„ÁASn}¾0î°œ ɉa$ óØr\MIâü§ñçLœÒ4’RAl)n¶Ž>Fa®5sL=ÚÚz<;ðý|K£W5XõŒ +‚“¾dk”¤½8†ð.Ø_¥(å0e4^ÝçÎ*Éz¬àD,H°êWËùë¹·~ ’CD,=_YTy3M˜ÆqQ¹o â-‘OŽ?gÛ]X²½Ÿº5SõÞýØíë)ñ§bSTwnh]W­[Þz¡õ—„ƒ–piL£¤s)¨WWå#ð¿§4u”AqìÇ7µûVuë‰|7MºNEXžív¹c„8CIÐÅL®ÛCV:úÐdw¹1òŸslû¸›; ŽŠš|c ÀCÕïsÃKSem7ߢÚë¬ £÷Y(?Ô;¿¢qß}^fmñiJE|"³[[M ŠXºöÆß:h.5¢J«¨ŸMß–  +„–¡GDú6øæ<–’sžôs>ð 魹Π8Œq|´wý{]åô‹ÒS¯Š}¾†“u1èq"d +8”¦“œti—P¥âË Žzïh/Jéø¢Þo­Gaô!kQTE[d¥‰ós“¿Ç˜VÖOvÖ-]^œ»¨ÂQYåyî(7‡›&ÿxÈ«6H»ÉóÊQùç6¯6ùÆÄ,ÄÈõ½Ñj$&]´€Ý ƒÓèLºh›¼¼õtã¾ë2k< ±œïÌž•ç#±ŸPh]Ûï¦c÷\_Ú~{h¼°?R{:½›l›÷tA‘à5îÝ?.<ísÞöZ­ËÃƃ)ÖÑõ*¡J%CSzŠ¦ºÇ÷݈(Ž´",š/Îßüúj6"I@¥ô(ÉWµI9bL¥AæjõÆDB%”6!˜†Tåü˜ˆøŒX…³üÑ}Þc³6iŠ» +Hòr\ßÛ°cÔAPÌùFœ£€(³›¼tsfƒHf¸ÿÙ]ü ¦y¹1¶2Ö²8kvùÞ%,qKa´’تyûcEãæq{Sû§wîÓ@ˆ6'Ú­{7i£VÔû,Osæ¬=Á6Û·ÏÄçÆÛÊü»LÃDjC'ƒ 4£˜† û—cá}ÓtŽ·›À;åàiAà<†~ ý,$VJ=ƒÄÀ¤'Ñ"1†¤B„C[¸Œ‚ÆÛ#vR†4Á¡Sùa$â C£LãéÛº,ëný9î³¢´M‡ùµ©[h$c Ç©™!z™AO3#¤û°D¼œo«6ûüÏ‘ýìN¤ƒÑoâxŠ¡ÔómêmVTÉñ›CãH9ÑònDaiØt]o·&ÞG0Œ ÅYôaìøˆ†Ðdpç í`ì <j“Û $$ +ñ¦ÚB˜vå‡Ä…«'Ä×j;8Sã=‰ÍÝ}Ó:L ¦ @Á‰ÎìFÂW7‹`nÂ7î›ÙiÐØ뢫7$p6 ƒÜ1ÚHF¿ "\DEÊ"©Êû 0"HLú"G@B¤PU;¶Q‚ ÄK•g@c%¥Œ²gPDxGI•Ä dŒø/ÅÐ/¤ôÅ~!áØ\é žöã)†~cä½òrÌ(C»|Ý ÷cÕ—¡†JÃiHörG3€ Ì}wØv^q;^ÓìÌÚpÓÔå¡ÍÑHpB±Mᾬ œj M"†swBX£ùúú|cû|qvi^oЗgóEòv¶üm¶j·_:8n觋OYÙÙþTg<Ô¶G³ÿž]þòf†Î¯.‘SÚ«"‡š Ÿ:DC¤)Ò¿¸ ö¤…¦ño«Gƒ®tPB„€ëW‡7·ÐN?Sd4éúÜ«‘k¸Fä€fJ +Ñ#kó˜8àÉÿSÜÜóææù¥_ΖÐY¸}±4v=dm^ÜŒo!•ïïFÂ…@¬ +ÎÕWQTg~›_°µÍ/øýp¬)fÖ]Y¼zEe!bD/;µa²ðÂw5,1Іe<¿»Z†°ê@óy7A—Ç™ölA|“\ñÄæµI§Ï\C;e{8Ò;ò€lE{?Z4Á‹ŒÒ? iÐœÂk¸ôBÏ^›jþP4ù ¿TÀû)ÿ³:ãÍÊßåXšBË…Õ0F(p> endobj -1462 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [251.8681 599.6322 347.399 612.3694] -/Subtype /Link -/A << /S /GoTo /D (root_delegation_only) >> ->> endobj -1465 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [284.2769 331.1334 352.9489 343.193] -/Subtype /Link -/A << /S /GoTo /D (access_control) >> ->> endobj -1466 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [282.0654 299.4481 350.7374 311.5077] -/Subtype /Link -/A << /S /GoTo /D (access_control) >> ->> endobj -1467 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [311.9531 267.7627 380.6251 279.8223] -/Subtype /Link -/A << /S /GoTo /D (access_control) >> +/Parent 1973 0 R >> endobj -1468 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [299.7586 236.0774 368.4306 248.137] -/Subtype /Link -/A << /S /GoTo /D (access_control) >> +1989 0 obj << +/D [1987 0 R /XYZ 56.6929 794.5015 null] >> endobj -1469 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [292.0084 204.392 360.6804 216.4516] -/Subtype /Link -/A << /S /GoTo /D (access_control) >> +638 0 obj << +/D [1987 0 R /XYZ 56.6929 617.17 null] >> endobj -1470 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [330.7921 172.7067 399.4641 184.7663] -/Subtype /Link -/A << /S /GoTo /D (dynamic_update_policies) >> +1990 0 obj << +/D [1987 0 R /XYZ 56.6929 591.42 null] >> endobj -1471 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [401.5962 141.0213 470.2682 153.0809] -/Subtype /Link -/A << /S /GoTo /D (access_control) >> +642 0 obj << +/D [1987 0 R /XYZ 56.6929 518.3317 null] >> endobj -1461 0 obj << -/D [1459 0 R /XYZ 56.6929 794.5015 null] +1991 0 obj << +/D [1987 0 R /XYZ 56.6929 489.3118 null] >> endobj -470 0 obj << -/D [1459 0 R /XYZ 56.6929 548.1995 null] +646 0 obj << +/D [1987 0 R /XYZ 56.6929 437.3327 null] >> endobj -1463 0 obj << -/D [1459 0 R /XYZ 56.6929 520.4385 null] +1992 0 obj << +/D [1987 0 R /XYZ 56.6929 411.1024 null] >> endobj -474 0 obj << -/D [1459 0 R /XYZ 56.6929 391.3968 null] +650 0 obj << +/D [1987 0 R /XYZ 56.6929 208.889 null] >> endobj -1464 0 obj << -/D [1459 0 R /XYZ 56.6929 364.0541 null] +1993 0 obj << +/D [1987 0 R /XYZ 56.6929 179.8493 null] >> endobj -1458 0 obj << -/Font << /F37 802 0 R /F41 939 0 R /F22 737 0 R /F21 714 0 R >> +1986 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F62 1352 0 R /F63 1355 0 R /F21 930 0 R /F11 1442 0 R /F41 1208 0 R /F53 1303 0 R >> +/XObject << /Im2 1341 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1475 0 obj << -/Length 3204 +1996 0 obj << +/Length 1853 /Filter /FlateDecode >> stream -xÚ­[msÛ6þî_¡é—Ê3J¼>¦­ÓKçšÜ9îÜÍ´ý@K”Íš"U’Šëûõ·ÀßD&SOÆ#xˆÝ, „®"øGW*&×b•hAâˆÆ«íá*Z=@ÛWÔa6´é¢¾»»úö-OVšhÉäênßéK‘H)ººÛýºþþoþuws{½aq´–äzËhýÝ»÷?`ÆŸï?¼ûîÇ_nß\'b}÷îÃ{¬¾½y{s{óþû›ë U1…÷™ëá oßýóK?Þ¾ùùç7·×¿ßýtusléÚK#n ùóê×ߣÕÌþé*"\«xõ ¡Z³ÕáJĜĂs_S\}¼úwè°Ój_?+3!WS …ÉQŽHèmA çR‡Qftj”=ÊŒòö1Û>mÊô5C‹©àD*MWÝnGÂjB:ëH§B™Dñwys½áB¯«c›W%”áøºS“í°¦­°¦¾¦j5mo[×ò˜aÓö1­Óm›ÕXßd×tí0i¹CLóR¶é_XYíÝ{Yݦ¹“¼«X†T¨4ƒ³ÚpE&€Ï”ÇÌÚpH”Êåú·(b…} @ì·•køáýG,8 ŽUÙxVm³ü“5jö¶ª:àš…2kŸ«úÉ2YÁعê]¶OOE‹ŸÒ: -l·•íi——®¯ÊZyp®ý¯*3dûrÌ NaJÀ»€°HJQš@ÛÖýÜœÍ$s0Óã<:IAk†_|,J%DpJ]û4/&јô™UNŠKmŠôS6Ñ!‹IÂÍ´|5ÍŸÓºœÄ ì¬ùÐá¸Y-¡3šH:?õ»¨ËS? ÎSÿð×hÞ3þ*aó’jBtïûpð\‰’}Ù³l4¨Í¶Î`8?Ç«1¡Ü˜u-ˆ1‘¼*qþvd  ‰ê‰õà - ·s~ÁÜq¿hîöl˜Y‹¨$t¨ŸPÍçÇ= ÷6ϲX„˜.j†euþFÏy±Û¦õnĵXD$ñ¼ü€šP ï 4øg¥ú¼&׺v „'ðUµRÇ„"b=Sgð FûýlƉH“x~ôjA‘qoóŒc‚xɯuP3Œó¨ó—ÊË6{¨óöeL9XbEg¨ ú”ƒ°†3ÕWá5)×3dÈ9 -±(›áOˆŠ÷lãœÇ/X=î÷ 8'ˆdI2?üµ È¸·YÎÅZÁ–Âè.ê2çêü©šü¾0‘Ö(¤€%pV|@MÈï3ŽB«Ö}þãtq3²%'Jk}™oÌìiXßÒ9¾yü‚Íã~?UÕaÐÙìØ{Ð’þæÉ¡2…ÝÎÙ:¨²y”I³ºÚ”Õ¦©ÒMÛcÁW¢j^€šÐ O·˜¨„Ó¾ -¯C· C†„S„ >ãß|¥{¦Îú7‡_0zÜïðMƒOVb~ôjI‘Qoó”ã1¬¼|É¿uP3”ó(#ñtÜ¥m¶AÿðÔ<8'%T.hP*ô8—D$ÑÉ@‡×YT§,ˆW°1“ ý"ë$#°æˆž±s¬óø³Çý~þª -»1K=?þµ È¸·yÖE°ÙJøéΠÎ9×Ö/›v{ÜÔپΚÇ)/ÛôdVzÅ}‡X¯+þu<Ü„C—dfŸÊ9Õ Äë0ëà|ÞàQ¯_àÞ òÓf œöZÐbØ×,Ë`ÿ>™Åó4ë¢.ó, ŒDðé}Údã<ˆ€•¶ò³’jBtcL%)ëËþx̶ùþÅ$}*“k›„Ã*LRFg±½ÂÚ{‡ryR(í1ߨ×M[Õ˜ô Có|¦Ýthòˆ*òyDóÎù•}UÕs¯‡1×7Ê4fýdbw<‡Ž…ÃjyWü”½<»ü$Ha æ}Í/lyê#¦E[kSëÔ5¦øSäM‹%;Fx~ÌÛ¬9¦Ûl³ËŠü»W“µ—Ò‹sCƒI×Ö¾Ÿ.»¬ló æ}½Þ½¼¯yÙæuâœÎÊVÇüú‹4æ M]Z¾`¡9Ý7ÙŸ'ƒÏAK‡Cûñá˜6öÛ†àát€¼Õ¼:®ù>ë'™s>ƒQg˜ù¶¿)þ<§/Xh qÍl—¬†Þò,9¤•½PE˜Ž¹;0A;IUxðIUXµ;ž’ÏŠ|¾ô«ú¾ýj*« -Ó æ£C}cúãþØzÖ__Óuƒå2móON|^nÙ¡ª_ðGa·¹/RZ|ôš:ËL®9JÜëMR «2/§j‘FÚ¦ˆdØÛôÉ RïƒNŽÖ^;ÁÅúSZœ0ÏÏÏT1 Ǫ1¸ ›ò=Ö¦»]n¼{Z`}סˆõ®†¨]o&/n«ï³¬Ä:Ø>áá„0<©°Ö9,±n²Þ7'jöl‚®?V‡IŽ5éáXx†x¡gÛ3OºmqÚy ->çíã\¹ñU÷§óze,”á(£×¥7 Ëéû—^>ÿâÊÃ…"*ŠVž.êòÊPÖSæð£u‡ -𪠛—P‚{ëøheÎ{’_'º9ë?>ýár.û.#" Âï™8—}÷øcÇý~~`ÃBc½0굠ȸ·Ù؆Ã$ vÍðËìçÉŠì!5¦oª²˜H„J¢a;'ÜcÆÂ{“0ÅÍÙnW:zvmÏDyú`ÊñÚêakÓã±Èqù”na’ëÇÃØ/—‚’Ó=–ìQø!’õ»½kÍÏ5+ã°{ÔŸø½dÍÔ"¡<äP¿A§Ó¢tªy3Ü)Èz΋ÂQ4Ns·¤š¥žDæ ïãÑ¥aYMÛ3îÙþžO±;>/¼ÃoVU,å&WŒ0Ñ·àÕÓ¶ pH†B“ÑeJ‰¥ð›î c^Žû5ZÕUÕnèɤ$Rɤ§Ñˆ 5¡Gß3 {›,VPó²ºdm^)+¬LËæCc&Òl?Šé! À<哘~Ë11 -ö"P¸4P -'?5[1§Ö”U}0‘œ©òÃam«°Î{#–0))ú4²ÝeêG&ÉÏÙ÷;¨ò{T‡ýf|‡€Ã¾Ô¬hšÝ¿oñŽ¹¿Ñ“ý Û™Ë5{Ö°Ésµ®€ÛJS2ÛJ|(ª{;ÖPק 1®_ãZ¹{Ñúp€˜°ßV„½’×Á €HñÑ­,A&î'¨Äíùv¸UÓq'£L"‰9“aMÃM,¸*ä`f”n阆\ï¬F»SÛüB/n<_ÂùÒm CgÂIZNEû8N1¦1.ÒÒÄR% 1Ru™–e£Ó¿ð¶ÕæR(øe^|@MÈæ€$xº¾ÿ¹ÖÌb LåP-,IL î]MIaƒa°yl|îÈ<Ø17­æÖV2uš PƒÓJ],l°Eõ€-¿EqôGuªa{Eê+Í]6DÚïn*w/ ß:em.ÙÛŒ„ÇÉÀíZJÀ~ðÝßÞ,‚=°ÿ4þäeå.ÆaRHFáZ © ½mHR©õiÛ_@ûM•Lç&ºv"Î[gìFÐ8³ÒÑcL¸¨’ö²ãŒÈXÓîÅ-3»\moþ(‹ÅÓŠ™N¢8cÜmÅ ó-¹èƒœ+)wÕÖ&R|Ä]u¶¶>p¾M¬ÜÅÁwˆ»KP}q¤“„°Å‹zÐÌ]²r¬e ÊBÎJ  ±Ø¾_ℱX÷ä¾qQ‡ò3H±N’N…éôuƒÈÇXÀZ2+‹Ø_·àî²Òìá¢Ømí÷j×óºo5D¿$æ†Ðý€‰Öý@çÒ†--õñ™ž¢0"šFb4EÑE˜uÊòÅ%ÿº;7³¯Ý¦÷>Ëå7¦ý]‘Hˆ”B|Ù-Zãÿ&úÒü.ÿò[­äÒws/}‚PðçœÛß¾þ~þ¿0\© á7—ʘÉè RFû„5¹"±bÉ„êÿ›sÒendstream +xÚµX[oã¶~÷¯Š•ŠË«(õ©nâ¤)²ÎÇ-Š³ÝŦ¾$–¼Ûý÷g†CÙr¢øøœm ‘ÃoîCÒ"âð'¢Ì0®rÙ\3Ã…‰¦Ë`íª'OÒ0%m®Ÿ'½w—ÊF9ËS™F“y +c<ËD4™}ŒÏ|˜ ÇýD§¬Ÿ˜”Ç?_.h&§áüvty}õÛxз:ž\ߎhz<¼Ž‡£óa?J *@üûv4$¦Ëë›aÿÓä×Þp²S¹m–à +õ}î}üÄ£X÷k3•g&úœ‰<—Ѳ§bF+ÕÌ,zw½í[«~k—›v< S܈“Ä +ÉòÜèn±”+š¨×ÛÅŒ8ïÍm\U¯7.ÌóÚmh¡X‘[SÕÒUŠ©Ñ2øõìz” W”ì’]´°Àn~»˜¶ÉJ3%„(?€@mâû¾äñu×i\Ö4YV4Vå‚ìz½"ž/ ßÐ$¹ˆ½ àc¶^e`_ËÀ²óÐÅ¢Zù.˜” –PŽ5n‚ +O• MBYƒMBA_ëMÞ¯ëG¢ÖsA½eØ;y,Û”Ôð;\3µªjŠÛÖÍ»ì 3×W<þ\äz~èòºD÷H›ÅóÍzI”O&$0™~ ²LˆåŠz»q}1spD;ØËzѹe©‚´h×ê·•?6PQ²oaßÖœ;Š±bßPDDZ]ƒI+©ö°‘¦!œs—£^~6™ÜuQnÜ´.?»Vãi!R³\ ºûºª‹¿~ ŒmÑ +ÔiÓ¡<¸g2íz“)ËtÞ”ÛÌÍ‹í¢NêzÑ!9͘Ժ)ªh +ÛšÀ0]/—X'¯À™V Ð'ª +ØȬ…ã +(–+™‘y +MæœÊ‰ #}LúJx隯\Æk¢oÐ{žú“Æà hbj{_¹ç­/füÞôE»éÚ³Š&¿”XjHmW3‡íq…uãåMn*¨9 þ;Š.ek)JÓX¬1¥z@±z¹À)´Õ™Jµ¥™ +[Í*Öi~è³}¨¼N¡n¼Ž-aÛ&Á'ö2ùð „Tp¶ìd¶NʤÁK Ñ„àé.µÓØû‹Îû¢òmßßX Ñ5ü«v« +ÚÉÐwDb,„«áh×!pédø·WD“Ÿ‡R^'sª窩ŸVlU‡F²ŒËS‹£»Âš(6…áÅuaåLHc›B[U—F2gYfóv™½€1 rÖè\} +n: Ôo¨ÿ¤ü_*Q÷Ê> endobj -1477 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [286.0435 683.3704 354.7155 695.4301] -/Subtype /Link -/A << /S /GoTo /D (boolean_options) >> ->> endobj -1478 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [339.144 653.1199 407.816 665.1795] -/Subtype /Link -/A << /S /GoTo /D (boolean_options) >> ->> endobj -1479 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [336.952 622.8694 405.624 634.929] -/Subtype /Link -/A << /S /GoTo /D (boolean_options) >> ->> endobj -1480 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [322.5463 592.6189 391.2183 604.6785] -/Subtype /Link -/A << /S /GoTo /D (boolean_options) >> +/Parent 1973 0 R >> endobj -1481 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [331.4327 562.3684 400.1047 574.428] -/Subtype /Link -/A << /S /GoTo /D (boolean_options) >> +1997 0 obj << +/D [1995 0 R /XYZ 85.0394 794.5015 null] >> endobj -1482 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [361.2812 532.1179 429.9532 544.1775] -/Subtype /Link -/A << /S /GoTo /D (boolean_options) >> +654 0 obj << +/D [1995 0 R /XYZ 85.0394 655.4043 null] >> endobj -1483 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [330.3165 501.8674 398.9885 513.927] -/Subtype /Link -/A << /S /GoTo /D (boolean_options) >> +1998 0 obj << +/D [1995 0 R /XYZ 85.0394 633.1281 null] >> endobj -1484 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [259.4835 344.9998 328.1555 357.0595] -/Subtype /Link -/A << /S /GoTo /D (boolean_options) >> +658 0 obj << +/D [1995 0 R /XYZ 85.0394 552.1893 null] >> endobj -1485 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [172.152 284.6583 267.6829 296.4589] -/Subtype /Link -/A << /S /GoTo /D (root_delegation_only) >> +1999 0 obj << +/D [1995 0 R /XYZ 85.0394 525.0283 null] >> endobj -1476 0 obj << -/D [1474 0 R /XYZ 85.0394 794.5015 null] +2000 0 obj << +/D [1995 0 R /XYZ 85.0394 90.0274 null] >> endobj -1473 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F48 953 0 R /F41 939 0 R >> +2001 0 obj << +/D [1995 0 R /XYZ 85.0394 78.0723 null] +>> endobj +1994 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F62 1352 0 R /F63 1355 0 R /F21 930 0 R /F53 1303 0 R /F41 1208 0 R >> +/XObject << /Im2 1341 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1489 0 obj << -/Length 2563 +2004 0 obj << +/Length 3601 /Filter /FlateDecode >> stream -xÚµ[]sÛ6}÷¯Ð£=añýñ˜¦NÖmºëxŸº}P-:áÆ–¼’œÔýõ{!@òTžLFuxqîá%ÂlFá›)M´ãnfœ$Š25»}8£³ÏðÛ‡3Öcæ4OQ?Üœýí½03Gœæzvs—IJ„ZËf7Ë_Ï5áä"Ðów¿||õáß×o/Œ<¿¹úåãÅœ+zþþê—Ýчë·?ÿüöúbάbçïþþöŸ7—×ÝOºñÃÕÇ»3®û˜z}ùþòúòã»Ë‹ßn~:»¼‰ZR½Œ -/äg¿þFgKýÓ%ÂY5û_(aÎñÙÙT‚()D8söéì_1`òëþÒ±þ“ÊÅ¥†žDXíÆ{™Ã€Œd„1€‡^æl¬—Ê÷òÃâù×O›Õâ~¾mÿl†²™„*=KCh„O0éFä >5M×õ»/ýÁ²ÙÞnÚÇ]»^u'ÖwžÖ@Ž3„riÁ”ŽAóÆ«ÀwÝíj(Upå3k2­Ý›Ï³îà:QñÙeÜNöíA ÷:Ó€*89MŒ– -ïÿˆª1)¢y&¤°zï'Ã(Ñ’ÕL— ÓTHÖn³XmïšÍ³çó]ûÐÌËŒ0E‰²83B#³žRDi&r§³Þ”š èa bA ¥B±\2fÁ€¯È/ãNYÐ )I®‰ŒãYˆ¨ -‘2ê@m·v w`Ššv`Dæ¬]Þ:PbU8“ˆ¡’»ã —Wra¢hèBA4µ|Ú…J͸ÉDc. øŠü2î \Èw ÍCDUˆ”ÑpJÒ²âÂ…¸0 ¦+ÇúiWBx80à‰R‰¨.™ 5TêM’yÍbØKò Œ8èþi#È“ ¹l̈_é€2îñF†8ê*¦ˆ¨ -‘2nDæçBWŒ˜ #Ôtñ5"ŒC¥«P‰¨.y=´D: ó׌èÐz8nDç”p<–ñU"Uƒ>•;xE}õ&ä0Žð70–…ˆªð(£¡&TÖ£¨ÅM˜¢¦MQ¾ÅÕz×Þ=›µ’m-Þl4›*µŽ˜…æÍžÆnòÃ,û'ŒV“ÞâÜÃÌ"æŠøŠÖ2î䬣 S\I­Ãû<¢jDŠh¸½ &pSsׄ˜«Ò3_6÷‹ÂaŒq¢·hÓT¶U4fˆ‚ÙUÖøiž¬C ƒ–})uTOû îfŒLUb6 p\ouÒdªe*˜ -À0ëöÂi±p‹Á­a©%(Äd•¤h·žo׋ÒfRàÍGÔHû¹Ñ1V™œÀIv1h&“šr†XÍ(©Ôk=¾¢¹Œ{tIóñw8Öõ=¦Bb uš„Ž‚+Üi)jÚiå[||úýkST2LjÒoµÇŒ4:X¨PRȼÑ+ßÉF†µT8²oàÓ2°[»íάƒÕàøû¢?Ù®vÍjÙ,ý7u~·Þt§·Í-­]}î¾/ºÐvßÞvÇ®WMw•—»?/ÿÖlÚÿPÊo‡&ÁÝ{ô¶ý¼ZÌ}ÿøÙ9qRXo§ßkÙ=íG…gÈ=ÃîóÇŸ>]¾ëŽ}Œ=gÞñè¡ß¿4=n²çîhÑë¾Ü¯ËpÝÝþ‡õC÷mÙn¿’‹9Ìwý< 36ÁæϦéûÓéóm³¬uÇßÛûûîèkÓ<ö¿É‹þ§v~~†½á ¿§àÈwÖ¾! æko¿tgoý¿÷m/ŸÁw{ÏÃ×RÊž_²_>  Iª‡ÜÌý=v?¶ ®‘*^±l<°»c¼çV«Å®‰¶ÛNûŽR¢8«ÕÍ…ø. ö²ÚÏóo‹ûvÙîžç¾,màÛØ¢Ÿ”Þ}ˆá1\ô“\äÕ€ÛL XœÆxZ†Þ£D… õ¨õï:X&ó^ÀW„—q~›±¯–æh"ªF¤ˆ†[Ooe*¯ÔRb½€šH×ü›ñI¦*<"j„ÈpÄ'œÉ‰¼šûz9ÃQŸ$œ ‰Žú,‡ŠJ©ŒúöøŠö2îñ¯Ó('Šr…'!¢*DÊh¸™¢-+/‚*,†±ð]£0æµ-ôƒìí0ûÍ•íj¾iî6ÍöË~ƒï›N»ßs9vzÞmžKl8YŽŽÑTKŒ|Äìó‘&Ê“Òß›”¹Þ¤þ 3©?QJú]ÓÚoÞ­!~Šh”Ü0fæ&Ocr½NÁ‹ûQ–Ý€A9 #{),ê*âÿdm¤5øß¿jþËwø³A >·vb”éx¤… =)OÜÈò. „ ÍG¨ÿ(¾endstream +xÚÝËrÛÈñ®¯àÁUªDì¼€rÓ:’£-GNl¥*¯ ’(ƒ—%Ó_Ÿîé¼Òrì\R<Ì3==ýîòƒŸ¡Æ"žéXùãÁl¹½`³5|{sÁíš¹[4ï¯úõáâ—[©g±‡"œ=¬z°"ŸEŸ=¤½Ð—þ%@`Þ¿ßÝß\ÎEÀ¼Û»·ÐãRÂ{ý×ë¿?ܼ§¡]úëÝý_h&¦æõ»ûÛ»7ÿ|}©•÷p÷ßßÜÞ¼¿¹}sùéá·‹›‡åþµ8“ˆï?±Y +·ûí‚ù2Ž‚Ù ˜ÏãX̶*~ ¤t3ÅŇ‹´{_ÍÖ)2)!ýPr6—Êàü—+cék¦OËV°‚à4,ÚÇ–íºCPóhÂrðÔaµ\¼ÇÅXøq¤g:྿ÈÄ}R®3¤1¬½µZùqàá¸êa“×À—0ò–IIEFmUšŽöªM4OuVÕ~[ÿùHzu“ì›yÝT;»kOm7ÿKÝd;JïÎÚØC~gLìëñDÂqNÈ!jx +,ŠcÏ í¡ÎÒ+Ä9@tc<(Û —ÕYC¦¢–Ãé*½ë¢  s#\‰HZˆö +1)S÷ÙÞj s‘ q%ÙUuÞä™?j¥ò<Þôøc2Ò'AWgsÁ¤/¤Ž¿f»å” ‚ùˆâó‚Æ<‚øTlꊙäÌK³z¹ÏYÝò‘櫧2ÛÓ\™lÝäj´jÉ#/««ƒé,3úL³ËÊ´©=™íÂ.ZÒª¤ÉRJÜ®Ë#.T^—ëÂiNÿò ]J«Ð^éÕÄ¥#0\ÀZð; XZE²wp×%Ìq;:nUQÓà)o6yI}¼ëó³¹£¬[zNÓœ‡xÀ®©›=Ü„€&tyPW$Ë,5”˜ |劅zÚ)«Ö^Þdû¤1ÓIqÈP¯cé=\Æ«h~mÔ: ízE#¼ßZuhvÔ>Þ±:Ðç2ËRúÞXx 0É.ë6?'Έ“Óœ!ø¢Ì¡&ˆqÄf‘,?×ERoh+Wý­Ô0t”/'€ƒ¨GÜGs¢b/ó×þ0úš‹hŒ©3B68 ¯Ò _StÚSgÈâl“#Q£Ú5yU&EaÇF… ]4WOÈ3{$áá!£:á!&l«4Gãžík"ÈÓ&_n° z»1¾ÉL“j+c“A,WÆxãxeÄ´ÚÒ–vY+ƒT ©µ4>$+R{Lž6ꢟ°Õ‹¤F±Õ‹ü ¼ä^‡g¬{ª‡ ´ ¡‘–æÞ°Õ¿%ìåšù,äNXV“$%{6¢ÈV A\ìA%­‰€ƒòí6Ks0X…=è?·4×&9Иc[(qBSTì<8'Ú—Ò‚¤ž2E\…C* $tuJÆÝ‚Žñ¯ ÷>^!‹>}š€ÃÙa íÎõ ´C2íÝ“Dɾ$Û]‘]M >—­í_”Sj¬¢³,:'êp2#í~3gd¼ÿ­/ã0?!ã\»Â2,·µSX¹Mšå†&H»¼¯Xiž°Ö-Ì8:Ó6¶µó=Å9+·üÿNn{ñ³äÖÑþå ÝŽ“r+C?Rã•[Å|a5ö¸ûö£…)Õ"± jÊ]`Ï«‡ÈÝmL.þ3É‚E:—J$Ä01ñ¶ +v`ZÃ<]©ëÂCݦ(onîoÞ›ºÇÃÍTMBBî--Jsk +KzæÑÆ„ÝÓlö¥ÉJŒgí÷2u!‚5¬AÛ^µ…5 )•X쮯ôDh#õÂö± “46'Š øÒ;Î…ÀªÙៈš´rq}‹H )uåpéW+»£`¦½Çë·×> ’‡^<Óúã0)ÔP»o}9çŒ1ï:Móþ!·¹»Ø­¹Ø”šá“/ಗóZ̃”d.çÔ|þ¨¼ãèhŠ?Ž…8ÛÍDŸz3iSšÞ‰6}´‡P©ˆ~Øî†ëˆŸØ#~N† ¦ÐÉIE> »„)zþ@„«„3æ3Õ>£ì“§)GÌQZº’ @µ™Íˆzy>=N@²Ô•û¹SbÑLzììpµ¨ÞÀ'Ô,ò2Ùûëmø ®G¾}N³ÅRÀ¬À{‰ø“ d0he+Mš¤5¹/›C[ÃÄï­jµ!=~X]ðŽ£m²ÿ ”°sù–pªŸ§E•¤ÝlîJl¨§T7+”P³ÛCÆ„1&öûǬ}†aí"k ×è›P'î=K …CKˆœ¸>/ÌdŽ¤Ã¯©Í¾@ðÀ½%92<­¢va±èG®0ì +åx!‹«ƒ“—±É¸òVÄr`x3]ê¿jß°j”α +ÖÅÅ¿ã"'f&ÂYyX»sá­‰3B¤± ñ7Ú’£Þ˜~eÛÕhKz$ò% ”-iCl«fù¡©€ÒùÒD V `fà®÷ïW†ÊTwM} +ú&Ú7JƒV¯¡ïæ 0N˜G¶Pžz cüO“n.kÐ*âмSØq,$|Á"·‡<‰­PÃOø‡’‰g!L Úö ÐXŵ{ÕEÃjïEv:mŽcB‰h”šT`Ì Œñg«ÆåmöIY¯zy‚iŸè0T¨,Ž­Rƒ®º%‡Ø›Øw*nË“èå Sî4¦:å…¾QÞn‘3ØoÕúøt_SD•tû¶ÚŪªD)㒤̳¯íÀfŠx„9ëtå#ÈN¶'…¥ŠºNa->ÄqÊ{'üsEøÊÙ«‰÷”4ˆþfh È2«k¢ ‡„ ¹zS¨Â©½µ©-‡¶Æ¬µÖæ†Ô#®/¹õÒN¸/„œ£—©¦•—Ž"ma§*Û-›mLggݲ)Å„ðY1ñ”ä2RÒJô:ÉKß=F~H=ôP×E7_cáVòÎ%~Kþ­ÀlŸGóP›¿*I÷'$è”YóTí?Ó`qlìt—¹›¡}ò‚Îc•§E{ËMÞd­«Ÿ§™ya(퉘ÕE¾.m8R>rTÿÝšMø²]WîÙ?±3¹kMSšÀÇÛƒèaühßTaä¾ïªºÎ$dJÀ¸ 7A†"—ký­²þVY í¡v_rÈ:Ò¬ûk‚A©6ô2è·ÿ¹ê#Øö-hV†XÓŸ [R‡ô??œdLÊ€s MÙ&œAÃYÆñ ÛâœSbB¦žI 5ñ5²M>g\:zã$þåè°³÷Yuø˜‰VÏ!‘¥×0¶Ï„¨Úçø/Žese¸ívâ¹ÊêúHÃûYÛ3õžîu†¶8{Q¯1jþ©?õÊÀÇâNü—;Ywzé~»?=+ó' +1— àŸgB‡R³ðêœQÅîÿ13TÆendstream endobj -1488 0 obj << +2003 0 obj << /Type /Page -/Contents 1489 0 R -/Resources 1487 0 R +/Contents 2004 0 R +/Resources 2002 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1486 0 R -/Annots [ 1491 0 R 1492 0 R 1493 0 R 1494 0 R 1495 0 R 1496 0 R 1497 0 R 1498 0 R 1499 0 R 1500 0 R 1501 0 R 1502 0 R 1503 0 R 1504 0 R 1505 0 R 1506 0 R 1507 0 R 1508 0 R 1509 0 R 1510 0 R ] +/Parent 1973 0 R >> endobj -1491 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [324.1075 737.309 397.7608 749.3686] -/Subtype /Link -/A << /S /GoTo /D (server_resource_limits) >> +2005 0 obj << +/D [2003 0 R /XYZ 56.6929 794.5015 null] >> endobj -1492 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [359.1555 706.8362 427.8275 718.8959] -/Subtype /Link -/A << /S /GoTo /D (zone_transfers) >> +662 0 obj << +/D [2003 0 R /XYZ 56.6929 306.3415 null] >> endobj -1493 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [353.6164 676.3634 422.2884 688.4231] -/Subtype /Link -/A << /S /GoTo /D (zone_transfers) >> +1788 0 obj << +/D [2003 0 R /XYZ 56.6929 275.1221 null] >> endobj -1494 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [370.2338 645.8907 438.9058 657.9503] -/Subtype /Link -/A << /S /GoTo /D (zone_transfers) >> +2002 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F14 956 0 R /F41 1208 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1495 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [364.6948 615.4179 433.3668 627.4775] -/Subtype /Link -/A << /S /GoTo /D (zone_transfers) >> +2008 0 obj << +/Length 2796 +/Filter /FlateDecode +>> +stream +xÚÝZÝsÛ6÷_¡{“§ƒ ïžòa÷œ™Ú­íÎÜ\ÛJ‚-N(R);Î_»X€%ZNÍ\&“q-‹Åâ·‹Å1øÇGi1™Å#ÅQÂx2š-OØèê~<áŽgâ™&!×ÛÛ“×çR²(SBnïYiÄÒ”nç¿ßýûÍÏ·gק‘°±ŠN'‰bã·—ÑçÝÕåùÅ¿^¿9Õñøöâê’È×gçg×g—ïÎN'Y– +h\Û›[läZÞÜ^¼»9ýãöÃÉÙm7€pœIÔþÏ“ßþ`£9Œõà ‹d–&£GøÁ"žeb´<‰%±”žRžÜœüÒ jmÓ!£%2’Tè« >âq$c%zfK2š$Öl0ÒÓ g¬?Ò6o‹¦-f ŽäˆÀúl4i¤t&­gbÅ­‰•/ó¢já¯!jY· UÔwDi¶Ò-½¨îêõhuE y5§šÕú”§ãú¡˜'­1f—¾akÖwùÌW‚ªØ4fíhmM¤{Ó:á3àw=C%ŒGÄy”%‰°#jªe( +`Lo©&çyQæÓr‘~Õ¬ÜÌ=oYsÍêMu +’®@hyK¥GcG>Ü[QÑ×YR"Ý°àZ niòª¨îï6%Mµ–ô<å}Ij0ÈÚs‡S§2V5ôÕUóE8 0ÐaÔ飣L`Q2)ðô¬3ÔU×AÞšûz]|öÒµ×Æ »«Ë²~„q:Ùf†ršhÀa³$)-£T}™»òH3Õ÷Ö¿ÕÈ«€î$£ì`¸ v D¹¢oÑ5qÙ¨Ü5Îô6„œ‰Hʘ”J¢8㱇‹jV/;ƒ]›?7¦i›]{I =pžÂ¾NçNä ZËXD"MûZzt6®6Ë©©N)Îhë…~Hðëýå U2ÝølÆW1ùlAæ¸úùÝÕû³=ô$RGB%êˆÖ@¨H¦Õh²øÿGLÆGĤH"³ôLÆ<â)Òö0ùËƬ s’AGƒäA¥;H†J[HJ-;Hb!‰ß-$ñןnDö‡]¼°`a7Çk—Û´O+sŠG³Â7E˜T%É_‘oñ “4‹¤V/A‘«(Õ2µÆ¿Ú´÷õC1ìàëTÞBñ°ÒC¥-cÆ;(b¡h¿Ýˆb&¶PÄ* E,‚b"”…"•SµXÒã;ÊÙ–Žcaˆlsµ +37$S nê²9̧£¡^~r‰¤_çW> y(Ìãi&ÆÏ{Áñ&à ÈGLXHÙKN¤,R,£\í2_ºüêƬülô7 Ãþ°íêX‘ù öÞzÚz‚eÓoʽñW>‡ b¤¥ +Ó…>HiÛé¶(¸§€&y,|Ç€ŒY{Sñ"ãg™µþëÊ!Ò SåÕÌ|9,ƒ†Ëƒƒè€¢LÕ¦òø»§-Ýœ`©ôø³92Øý¶™ EÐÀ5DO»™r»¨fã“ÛÜQ>w¶l×yÕÜà|4Ó}Çi‹a§’¼„g – Š&×~Müb}-Ó8¨wáPﱊÇ*ñ±+*»„ ±K6v‹?€^@,àò/5·'R J)ˆàS +üµŸRL|0.L†÷ßÍ,Žfðoø©ŒTªþʈ|‹g€ Åœ%‡VŒ´ð§·iºèóþ­;ƒ¸n̈°“¯S{‹üÊ{ä÷§;K¶9v¦(Çš‚¥­¨2±É3~)yÆ*‘‰Ý#SPÝú+N`¼ÍRyý7!±;Ô„Š¹ifëbjüØiý`"ÜÙÞåE»&ôÀ£ƒŠØ_¼IqøzGgôHë@o®è=p€*k^ø¢Â j,¤ÝTàÅÝ'Mü¦pÉu6x· Ê‡¼Ü8>zmcm \vjá{GGÞØ7[ðƒ&d5|$çW14‹]Å@šÑXÔþy—꽇 +ÎË]ÓsÏ6%¬?`v +ùû®y˜È)íQ +ì‹üÁ-'‚¡rs ]Z´ªn‰êÓ@¥håQÚ/»N³Äh z.×BïM{m¤Ð.ða!×!i”øí|IAÖrtH¤îXæn±§˜Ù³UA)’[¯L¯ øgÕ“™’ÛXD ŒUú×Nj>Aœ*É…†V^HèñäÀBNöW¿¶Ü.ܘ‡§Ï­˜’Å‘”÷JÙ0ÈôþÆؽËÜ×ý U\endstream +endobj +2007 0 obj << +/Type /Page +/Contents 2008 0 R +/Resources 2006 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1973 0 R +/Annots [ 2013 0 R ] >> endobj -1496 0 obj << +2013 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [226.7331 584.9451 295.4051 597.0048] +/Rect [84.0431 269.7901 145.2431 281.1822] /Subtype /Link -/A << /S /GoTo /D (boolean_options) >> +/A << /S /GoTo /D (statschannels) >> >> endobj -1497 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [283.1811 554.4724 356.8344 566.532] -/Subtype /Link -/A << /S /GoTo /D (tuning) >> +2009 0 obj << +/D [2007 0 R /XYZ 85.0394 794.5015 null] >> endobj -1498 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [287.6042 523.9996 356.2762 536.0592] -/Subtype /Link -/A << /S /GoTo /D (boolean_options) >> +666 0 obj << +/D [2007 0 R /XYZ 85.0394 769.5949 null] >> endobj -1499 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [352.879 396.7158 426.5323 408.7754] -/Subtype /Link -/A << /S /GoTo /D (tuning) >> +2010 0 obj << +/D [2007 0 R /XYZ 85.0394 748.5408 null] >> endobj -1500 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [334.0699 366.243 407.7232 378.3026] -/Subtype /Link -/A << /S /GoTo /D (tuning) >> +2011 0 obj << +/D [2007 0 R /XYZ 85.0394 686.2137 null] >> endobj -1501 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [373.9 335.7702 447.5533 347.8299] -/Subtype /Link -/A << /S /GoTo /D (tuning) >> +2012 0 obj << +/D [2007 0 R /XYZ 85.0394 674.2585 null] >> endobj -1502 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [319.6839 305.2975 393.3372 317.3571] -/Subtype /Link -/A << /S /GoTo /D (tuning) >> +670 0 obj << +/D [2007 0 R /XYZ 85.0394 255.5751 null] >> endobj -1503 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [307.1508 274.8247 375.8228 286.8843] -/Subtype /Link -/A << /S /GoTo /D (zone_transfers) >> +1658 0 obj << +/D [2007 0 R /XYZ 85.0394 232.5802 null] >> endobj -1504 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [334.8268 244.3519 403.4988 256.4115] -/Subtype /Link -/A << /S /GoTo /D (zone_transfers) >> +2006 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F48 1228 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1505 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [337.0185 213.8792 405.6905 225.9388] -/Subtype /Link -/A << /S /GoTo /D (zone_transfers) >> +2016 0 obj << +/Length 2917 +/Filter /FlateDecode +>> +stream +xÚÍ[ÝsÛ6÷_¡Gj&Âá“ îÍíÔÖId¥×¹¦´HÇìH¤JRv}ý-° EÉ’iÙjFã\‹Å‹ý 6 ðÇ*$¡áf $Š25˜ÎOèà|ûpÂ|QSiÔ­õÃää_B 1!“Û¯ˆÐ(bƒIò{I†À?\^™áˆ+\O†Z§ößäòzrùþz82&âÁûO?MÎÇX+ì4DŠoþþãÕÅå‡/cÏàã’Çççãó«÷çÃ?&?œOÚtɨ°ÒÿuòûtÀX:¡D˜H à…f ÌO¤DI!ÊìäúäsË°óÕ5Ý +£„‹oA³m¨)CBÁ…Cí+çÚCUÇuVÕÙ´Â÷³å|¥U¯TQ£àn¤fpÝ0FŒRÜöC#¡cT·ó†#FéÓ>Þ˼NËʳái —ÄH&—É]: ÁƒÛb6dÁ¬xÈòoH©ã›YZa¹ZÂÇù<.³ÿùúU§K!X0mºÄ¶wqtœ{K3HX”CÅ}–¤•Õ¥‚‹¢Ä*i<½ÃZXéÉÅ-ëFXíž‚„êŠu fém=/*+³âÍ–ó¿d>}UÄ77®¿ô>‹ëFš ½zœß,®rÏ=c' cÍâÇn•F$ ³°V¾:2©|OØÿrW<4"å Ït}PÜ ªZ›_Õo‹r´ÚqXañtšVUšàgbÿùÇÉäRÖ8Á—é]œçéŒX\#Ô[­Ì¾Ýyô\-§@ûú-»O½$CKƒÙœ–Ùb´M|/§f;®¹o¦Yºw–¢ƒ‡»Ì*ýh'ÊÖŽgU™û˜o°Z¼¥”ÏR¬dØͲv]„¦™¯›Óå<Ík/⨪ìföˆ²úT3‹Ë6µ›If;œúIJÀ’*±p“ÖvŒ®Œ +'ñM6ËêG»Øü™à4I2Û8žaͼ¨Ýòƒâ<~Ä"<ñÙYN R2ß=ŽÎ–Pùm7œÿ¹K}…xÛ\ͳ$q¨qÝ.[Nÿl+,ÃxÒÔ}-þ•¯_?݆•EVkV#µQlÔÔ,‘jQ䉳=HFµp/¸ôlÉ©í¨iî¬Ë–QDhW*ñ Ù->ãÅb–M­!­©]³‘B€¥íx@ÖÚÚ+”ÆZö´¼w2ªç-pד…Œh!ÂÒ`Ê#¾È•IA$ø¡5OöªF´vöí(°òŦÅ:«Q3"ðôü¥”«ØÂt0 #ðÜFƒ· IÄØko_Ci¸›J?m ]pɃ34,nYm†Tm´V]¿m46 +^Ról¬ñ„eÓb'@ÂÛF´)I¢PE¡qú×2­ê{ nE Œ?oqé Gž ÝÙ6—Ÿ°ºô¶Æq¨O™¦°°&bÁ˜™GZEÞbØzhg,·+,ç8›¶:(qæº=’ÝÓÕâmØnN—<ät1E$ƒùùéÔ"¡Ö¦+ÜoºÂï4]ü•ÓÕâPÓÕèÏ̓§¢°gº¨&Tz$`ºÎ“¼¢ý“4n§ÅÂæ(Ÿ]]ÛØ‚º ½ƒi3g;1íH{(‹ux“¡,  äó˜J£5 N?ĉEå×!ƒxÜ㫱]æÕr±(ÊÃZKàv+Œ)_ xw(G ¸hdÄ{ :²u“ë˯ÇÙµÞÉŽŒ‡Eòæ@†š(#zœ­ÔØÁ¨€Š7Xhý*cЕõˆuS) +mzU†p.UǼI;³ü>žeÉjŸd¥®EùöôUö-ë%ÎÀ3ØwFuÄØï0â=±ˆ”šðЈÖ.¼ÿd7àtŒ‡Jöµw\›ÍØ`/eîˆzÄæA@‰ëžhA +E“-œ.ë»Ïåã8ý2“Hª`üåámU”™MïÓ•çÞk í>]i¯ Ò²t ø?Óiý,ð!±&3C´æ}!B51Å´]*Æö—„ÕãÓ×ãÙ‘ôˆñ„€6bº/b6’ +Œ~»-š¡‚müå·‹q?œÿ-rd]ÆyuÛì{ì²½àvÄ>^pD¶Q؃­0†H ¡¼ÅéË"‰ë•5äàJ?¼gy<Ϧ>ðu<Þ†¯—üÈC +¬¡aOH!"M¤MHaw +íŽ#Ø\ŸæÕKŒ6òVi^?]G¨#†NÛ +¬'"ZjQ˜¸´¬\æÓØæUýáÀÐX•‹‚¦EG÷Á´#íc +±«1¡êÁ4DE‚µ˜Ú¼”î­„Ïn"ô ‰r¹§‡•P{Îø<šŠ‘G+}a¶°ËUvÐaG¸#†P„„ö; aH¨;¾4‹ÝáÓ4¶ËŽ”‡Â2™ˆÓ}ìEÓb–<Š 9R}‹›k¢™FgaçõÒ¬ö£ù¹ 0!hìãræ,¦¤þ€¾Äø¨ííræÉyõÐ Û½Ý îíBËy£‹{rªŠ‡µbµ¡+ÚÃSŽ ç~‹ñqõñ|<þ8Æ—®!÷¼@ý­³4vgêJ.$´/=”Ã`<&HœøãÇÍ3>O¬ ÿÄïéà–'S܃[휅Q[s ›Õù¡Â{û\4‡üŲZÛG¬Öëu®«ìVú®:½MCÿÉ4ÒAH`i æÚÈo‚ÎÛ”õEaÕç§IU£ó¸uã[Ÿ¦À]}߉pGöã5Ñ<”©ªÍCmïÜD ÄWEìAq «æú*>$âíîÂk¡ï êxÏS¹¤xÉžì+EL¶}œBòZƳ}Lº”`[Š3éíÏÔQÖ¬¹2¢±…R>±…Ûìzáíí–r¡BT±Ü=pÊ`ÅC_ñ;ÄÎlê”PØ$v/Û´Ø©3 ®Ò¦Ï +N¨E»\ÿ.Ë*­÷YŸ\o®O dþ2Íʯªµ±¼¶w_üš$®c²M[Pµ˜yªZŽh•É=·*€ë¥ÏwS"µb›Êd9[%±Ïue²{9Hx%lÄ@!#³½N¼ZÛ:óø6Õø'3’Ù㘥Êhë®ÏÇÖvüza7íO/0" +>â"Îfs¶`Ø‹¼—?;ˆãõÃ,¢$ìÛIb‘£¨Z_pñqü ¬D‹H¨àó²<Àž÷3¸®$>^ËTH éÙfbšA©jíåog9½¼Úö,¼ïãn™Øt·Ì»[øÒð&øê]+[Ò æìߎÔi‹5„xòØÖ&Å<Îò-‚ˈH±ïæZ»“p¼®•q +Y„è3vž0”­Â1wNãîÌÚ ÝñÅCòyOeñY¯S‚xY¡Æˆæ~·*QÓ |.ÒÒÞ¡îj[#È…qÊ'Œ=r†š‰c&)2²½ù›'ž†—Ô=CBºê&Á·õžê-rÞq¹½OoËî86WÁ$Pùý·£‡òÒʞʩh–M‹]Š ÆtOHÈ'ŠËÖuœ-Ý b{N#¸PÁûè-M»[¶÷èM««¶×u:_ g±u +|®´Õ·¹YÖXH²jëüiác1ÜŽ +ÝìÓÝêv·®í›ÝH²àß0µ%'œ-Tîî³-]~òŒ’Ä+ïöŸcØû[î¸l·©¸ .Ï Uá?׋¿Æv)Ù¯ÓY\Už6k.Î?â·›/‹‹Fe‹í#w?‹°WßM»%¥·­9øºçöU†+ Cí'2içË2ƒ©Ã'©—å Ë£a{gÎþiMÚƒ.¾ŽZ¿m¡Hi×€Ð# #)¶ý\Šzw¯^úã¬ÕÏÕ¤&"êÞ†ãk™0$öÊ`2€ê„ÑOi~ÇÕÔëHÿZð½endstream +endobj +2015 0 obj << +/Type /Page +/Contents 2016 0 R +/Resources 2014 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 2022 0 R >> endobj -1506 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [364.6945 183.4064 433.3665 195.466] -/Subtype /Link -/A << /S /GoTo /D (zone_transfers) >> +2017 0 obj << +/D [2015 0 R /XYZ 56.6929 794.5015 null] >> endobj -1507 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [374.6372 152.9336 443.3092 164.9932] -/Subtype /Link -/A << /S /GoTo /D (zone_transfers) >> +674 0 obj << +/D [2015 0 R /XYZ 56.6929 741.8766 null] >> endobj -1508 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [292.0276 122.4608 360.6996 134.5205] -/Subtype /Link -/A << /S /GoTo /D (zone_transfers) >> +2018 0 obj << +/D [2015 0 R /XYZ 56.6929 717.2979 null] >> endobj -1509 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [319.7036 91.9881 388.3756 104.0477] -/Subtype /Link -/A << /S /GoTo /D (zone_transfers) >> +678 0 obj << +/D [2015 0 R /XYZ 56.6929 609.8545 null] >> endobj -1510 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [460.1655 61.5153 533.2211 73.5749] -/Subtype /Link -/A << /S /GoTo /D (tuning) >> +2019 0 obj << +/D [2015 0 R /XYZ 56.6929 587.5432 null] >> endobj -1490 0 obj << -/D [1488 0 R /XYZ 56.6929 794.5015 null] +2020 0 obj << +/D [2015 0 R /XYZ 56.6929 587.5432 null] >> endobj -1487 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F48 953 0 R >> +2021 0 obj << +/D [2015 0 R /XYZ 56.6929 575.5881 null] +>> endobj +2014 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F39 1151 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1513 0 obj << -/Length 3476 -/Filter /FlateDecode ->> -stream -xÚµZ_sã¶÷§ÐäIž±H°}é%ñ]/iœÔçL§“ä¦(›=ŠTDÊ>wúị@R¢$§—ŽÇCX,vßþƒ(fþÄÌhÆ£TÍ’T1Í…žåë >{€±wÂÑ,<ÑbHõÕÝÅ—o£d–²4–ñìn5àe7FÌî–?Ï¿þë›ï®o/RóyÌ.:æó¯Þß|C=)=¾þáæíûw?ݾ¹LÔüîý7Ô}{ýöúöúæëëË…0ZÀ|é8™ðöýß®©õîöÍ÷ß¿¹½üõîÛ‹ë» ËP_Á#Tä·‹Ÿå³%¨ýígQjôì^8i*gë ¥#¦UùžêâÃÅßÃÁ¨:µJ¦¥Šg -™árz“9ã6m‘(Áâ4í7YŠ©MöT¸Éå§ÕöR˜ùbµmÖ‹e¹Â—U±-ê¼h÷·@ÀJJòd6\è@œ@5!Èç¨4’çCQ\.¢XÏ»GÛPóeÑæÛrÓ•MM#Í -åÚSNpÁtªPˆW©µ'Kš2.Täg×ûšÃ±Hq=Òœ·3jÜö ПكC¾´ y¯."WÄL실bèŒetú0ÕA¹¡ `2±Vó_¸æ7MN&ëèhðŒbiYÄ°¦,ÕZ¾öH”IÂL"݉¬³¶+¶ÁþéØ“eõr‚“H&ñ‡ÛVÙS1ÅI²(1±£Ê›å²!³‚ôR7ë}ÊÊ*»¯\æº-p±ñï¦v­ªx**»xpˆÞtaǙѱ:mßCªãö¨PÅ ìõÕl_ìYi–J®N/¨&ÖÙ³æ,åÂŒ°=Ú—‘AcǤAÃñs ÇȧÕØ[;ŽàðDrÜ~¥dÊN†*œ²_OFçC¾#û¥È…ö{ A3ƒ xrëÕ91¸‘õC[ŒS„œmªhóTÖLwUW.zcƒ-b±1æôêjbùØ”aqÂÅxýÏ[êÍžûXL(.ŽcM@žt¨À)¨9ò3 -p=´Ã@Å.õéTçä8àvj -†Çg 6 :5OÕG„_8—U±X5Û5øß}ÄW€fN ¨&¤!.Äqf#1þ÷vD™= ÀÈy¢OOCÈL£‘º§€çÈÏè}Àõ(ðôAŠ"S¦õ¹Tg9äw(¨6„‚ELWP œ2f -JÎùü›—:[—9éðÓf™uîlª2/'óD>[HÅ Ï$ëªÛjín³i¶æ -2¥ç†º³ -Ž·Îºò© ŽuÑ=6Ë–^ öù°Íꮼóú:òª,êÎQÀ ±-;××ÐB›b‹¨¡ÎeÐ ^vV¯vHâ f¨Ë0?ÃtåŠ6 ojÄâÃŽòž%õÞ¿ôHŸJÀ1äÑYU5Ï Z}ʇb5²õ¶9Ú´M9bµØàÙLfšAŽçÓ·ÆÚŸS‡´h7ˆYHÄ^.…„8M(ÂLªSØ‹„¥‘Lìô»iS–Dú• -Ú„Äçœy•íZLŸy2n¶[jR6[ûÑì…™£)± àñ|CZ<•ÍÎ<Û”to"|"$5ßwô´¸rd°55=ºì>°¾Ÿ²ŸøZ—m,Þ ž»ÕdõËp»óÆ>—ÁŽ‰j«1¶Êz"of¡çOÅ°4 …Â+`5gºw.2ŠæeKϺxv(X$½‘COJ„+5nÚº E¼¡ùÔÅv¾¬ G VÕYš¦"Æ œ =Û’ -[½½"Ç’NHä\ŒOÈJP,ñÀe4ƒ¨çmaKåv]Á‰˜ù®¢jF“¢Ð‹Q¢ ÅÒJ b€ó)úbGÏ‹,ñpÝ%œÖ–<ºì‚[_uY¸¾;®cå©\}ÔO {8áž0ÈÀhBŸQóû‚ÞiÏ–®ó…:‰96¶408 è-AÄ®ì@JØ;pçó÷+"#EïFÃDAl~ÛmGƒ X›=¸ÑÒ Ù–tòÐÆúÙVÍ#½((•­óReçí!¯vK_zö; ÆC»ïß9«rÐKp[aNØ ö_íY™Û€—±}†a+¾cŸgÎDïCŠÓá¡Ö¼‘«Ò­ÃZœ *gx;b²°89QDÄxr¤WXv¢„)®øæ}(H„3ݱ`€ëê…º×EV—õÃjWÑ;a¨°äÈaÅbþÇ¢&û‰˜f#Éž P-ÆâE¿^³4Òžºí€x ‡‡ØŠÞZ@]SM€PdôÚ÷Ì¥pÐYlÉ3mé•Ô6ÇNFb&^EOËN†œ ®ìFé'FŽ d îy’‰Ú0ÉCÄ} ZÒ$+‘I4/>eˆó–úÉ: ;X¯¨/£Wç þ<ô&8£¡d*/ˆ,[.^-”n ¼^"<É[*Çx¢IUñ”ávLÉÒ¹ÿ|lžGþcàÉÑ”m¨*ûl¾jšíŸÜ5šØË}S†µ9®ƒçrCm5ÿCp-/Ô"„­ÞßàzóîeSôoÔú™8ÔRó×#Y8J燢\SËìU‹ã>0¡…;3)ÆŒª|*«âlY›ùuî¦fôè;L}Ìܼv—ç0>‚¼Ðe]þèZ6ÅúïWQ‡Þî€iÙNźr½.–%@Ò.`RR…¢‰7Ò”tYR›ü4ꆞ«ÝÖ˜1ˆÿHÛÇÁÔ3%c›A@o¿ðBþà ´„Îgô{¶åfêb"ÆÑL[„$¾Ž1ÃÝ6.T6±@äòD• ™„ñ$ŒÏ€ºmdÎ,÷10£Ã…±g©\ŽNNWœìŸQˆ”n´z ‡‘ÔaÙÕQœÊ}{fNˆI¿i°"¸¡HK{JØ糓2Ôn8ŠÝÚ‘ŽFV3*š.ß,Ú¢ZMœ,’ázušTt‰ö$qר£Ì&ÓÔ;jðNÅ)!\Aò‚C®—™¯ z½°æq$ël³)±RÆÑ/éábîÝ'WßE ‹"}tx]õäNn×vƒ3<™*MŒ ʶÓ!4ÍËõH¶=½>—Õ2{á}–à…í:«\M{Eó: -(ÆØ\F‹¬ö†\Z9X”VN˜õÇÂÖªéj¨%µ0¢£XˆL×C5nRhlRht<à\leÇ2zÜ}wýOjŸòǬ~pS­Æ% i€b¥¦—= à™ÓaIǶ}ÌzÃ@A GYÓ1+Ôøf‹mÅûá[5d릷nÈæPÑ­¬Ýcwf5ÚxÔVT‘[V; ‚¹9)>œewtBG¿¿Q±Ûxé\ŠÔXæ¶ õ8“€,¥xhºÒ2´F{¡Em’ -[te$çï>|X ¾®èõù±$#“ÿtÙ}U¶ÎoBbä.¢}£_Ø¢ƒ )ú£÷~Wl煮mZêH_çå&«è÷ŸaÝ„ p܆÷GêΦ~–&aqî¹¾e·ylÈËf ÕþOð„é4öŽ–a~.ä½ ‡U¥Ì~@)ߎCî@—ÄÊß“_ƒŒ‡¾†2ìT1eÔž;t•Áž£1'« ܦûyçÊ„†:¿¹ù0Í -*ŒO›¬n]%–Â|7Å¥ÃÜÍ`Œ®*ê/OYPV±¿Ïl<é°’Ÿ@÷ÝäÞŠª’þŸØ\ÍY$BUÑ;òQÐÀ›ÌÇr—eÛôpñÛ.«FŸ@Òß¹kÈÎ:±¹þÔ}×XtÃtª¯¹LãB„Ñ.89QlIϧ¬g<•õŤ 9‚‡Ka©‚ßÄÑÕüú'òBvÜ>Llx…™y5+´å”þ 3øÊk…šÎVH5õ{¸€zSâfT {#Tîóû¸½×Gs±³»½P‰dJ&ñجÖí1–¯Ñ35Á¤Hº€0øƒpøÂã,?ì·D°äõÂJ‰­cPžˆ£žœÌ‰Gçpðkª€,Váo!Bkë×|{)Þì}{ö¿Íòb`Ýí,ý¨4/×ô3ƬA%hᙤIøÕo¼‡*‚ØK#ô)?”p–ÊÈcåúS–w —ÑGx S¬ñ¶ þØpwW‚#!øàK¨ãð… -Ý(qw9Øåß5÷…­GúF–ã‹ -39¦!ÃQBaÄýÞ·w%{$,,ûËÑc~9fý— -ÃÂeô+-ÞºÅ`aÃø¼ÃEE¿âøà…£ÿKÕ9¼Hûœ8qÆ ñ÷gbxO&†µ½ð—¾`ņÿ=Kô(Cˆ¹g›ÑÃJ´˜‚QŸ 4««ñEÿ‚®>BÂÆ•T(„góGA(ÒÌÄZÿ–~ÆQAHã(=ƒ ’2üEûLž±ŸIsiU¸@9¶ÕP%$z?_‹bªãñ’î(¦¤;mÒqÒ=ä ;ÜeAP‡M“ýb—ÊT9p‡jè•ôîPI_WJ}¤tÐÇÎý!…»¥RÑþd¤„–ÎeÁü<5Tõ8ÇüyÈQœ³DÆƘi€åÔ‡,ðï”ùìOÃûïæá "cä‘OsxŒÖ– ØÀ‹v19ø GGP2Ù“ „ÿ/¶‰âøendstream +2025 0 obj << +/Length 2524 +/Filter /FlateDecode +>> +stream +xÚÍ›[Sã8€ßùy4Uc­î—}£˜ejº³Õ5—‡˜Æ³‰Žhö×ï9–+äâÒU)"˺}::G:2¬Gáõ¬"T8Ù3NE™ê ''´÷Þý|Âê2qS(K}¸;ùÇ¥0=Gœæºw÷´e µ–õîFDÿuöéî¢sE#MNc¥iôáêúÜç8ÿóñæúòêçßúg§FFwW7×>»qyÑ¿¸þxq;g9Ô—A uÝÛ;¬T×¼½»úx{ú×Ý/'w‹„ƒdT ôßNþø‹öF0Ö_N(ΪÞ3¹=ù¼h0x[U]MJ ¬¸éÅŒsÂ$ßÜ­ï‚B·uÒ)¢%¯z®½XN„rí,pÌ‚HJ³žQŽhÁE5 Ÿg/ç³|:MFÈjð ³$>´*ÛO†óY‘>%§±04ú6OfiRø‡‡|† =?¦ÃGŸW>Ö%‹dö”Ì|z”ߘ ÓªÎ ÃΡ—˜1â”âUwÉ÷aRÔÝ eóÉ}Õˆ`Qþàó’ïiQ¦ÙWÿäÛle„‚­ŒðÞË lM‡Å`Õ×Q©Ÿ éTT¾LëÌA6ò‰áxP¯òžëù§b~_$ÐwVŽ_–{òº?ª +WØAmw)¶ „šß +&š‘cGŽ¿A ˜ÑŽt͸Fó„ˆÊýø« /ó È3ÿ"ù>Ò ÛÄ×ÏiùØÖðújÓ‚-jõŽSpO=Š%zY£UqSmIH$¹ÚgÄr¦ë&ƒïñ®½0*‰ãÕêÁªù´Ló ÈJg¢?©¢E’àƒõ00w”ÃY:+„0)š…«*œ8lˆ@µÁ}>/_Û!$‘––¶†8Ê*‹â_ξö|¢˜‚Eù8¬°ºtWÛÝ +<I2° ÔÙ%‘VmRSj !ÕÕÖP@@T²Vc4Ìg^½ŠižêÌJk諳]AR¾RÑF%áB5s<ÌçY‰ ?.üz!žÒ|^ø0>…×…°\àyÈk†J°ÓBõBû>‹ ƒ$TC“qSàPN@P\fùv' a :G]ã.éx>KºÀ LšQ­"¯oÔÑCUÝO7X4­t­ XnE°j¾\¯ œQb´tu§¥‹%—Tf¡ +à‹«)–`ö—Uß´ª€ï}9Q«æ€*ÀÇF×y™ü†ePÞ´XgÒ=¢C«Fnšó§tÔ¸º ˜×ñ‹»ð™÷ƒáŸUÙ‘5Ì'ÓA™Þ§ãxEOKl‚ÉÚBcÊ;[H,R°v”¸C¢3› Æ㺅ÿ™äÿ§?)åY²¶ë¯³ÆAÓ ºðOÅ=?¦Å:o¶T¯Q¤³yùŠ×Oþ^3­°EáÔšºèzßÀ`Ãj7'[‹™c°œŒ~eÌ%.y=çóqåó€Ç¸È}æ@òyiVÖy¥7oJ…Æ*5ððM8é?a–n°²áÀ5@›V1Õj]H…É,/}â>ñ¿Õ~'sAu”ž²¨ª[­´²ÎÌ|±él0\;e:L6ۻЖÊÞ5½ïÞdScƒ½Ó €ØnàXœ®ÆüåaÖO¾çY²Ëž¬\Qúþ‡•ªT9dŃ×}xÄ;NJÜÏm„Ù +ú¾ÿ@–ŠK퀩ÀK;)+@¿MGƒ2L—Ï;!|iÌkj…·†±1ƒ[AR-II‰…£@I û:áøÉbúF”è^‹dO–œ‡eÉÇ’[bé8Ö*Á‰´’p€#îkºYž¿À‰/zról@±Î€ö¶ò d=ZÝdš8É»L&§Fãž»™Ì50÷0’lGË–Ö°~Ôe„ õñ­ÊXì¨|^0~Ì𤃖EÇé<5ÑÌê€Ý‡ÁèÓ,™%ßÞÐÛÉ¿“á¡ױZÇFçÅÆ9¥Eº°ígóÃ;Ô ´¡ÄÎØ$Ô‘š/‡&ßT©ƒÃr4Ò8g9bpGDV¢°ã$–cih8.7l$š°«„F-Õ~‰`Žó§1£”F¿/6Z¿Ây£L²A6¬3nK8°q­'õcsy5'LÐ&ÝÀ‘ëm:ÜÒÒÂ8ØáúZ ô€«h1¨jÑÚ áÂsjª#eàŽ´_H·/“ûŽ4pZæѹvU­×!#˜£A%Ú.Þ'4âÔÚÃÁÂnTmRµ 6ÂIæ7­pžO^næå“\cNìÓ•lŸWŸ P¥hpKñdÜX“"ÉJ²^ ×1ã3j;Ý…Ïp-š¿Â§wÁ§ß„ÏËeŽ:)¥ê§5˜<Æ|WÙ»”¯¾ìHÒ§5;‚–b Þ1STöîNtQT’P£Ü2Å÷èàŽñŽ™¢€§¬‹¢ä„qjŠëÃf¯ f°}¯îÚ6ƒô;«-   ’$×°uw]´§Uí[oÎöu'PÅ'—”;XÅV²cVD&‰æ¢Ó%3K8£2¸Ïb~À@´c&H9ÑÚvzeØpó&”{öå²ßO¾í¥ƒXg%·u‚ñ +æpÚ4Lt¹e\¥l‰ß>*¸7¿P°#Ö?nà@£l—Cæ–ã}­wÈWoп«½ù‚3?ØïY*º\17Љuf‰ß>ú·?¿@°c^¿°Ó³g:®,‘B.nunçCüd¨“ßï+·8›n$ +l1m%ÚŠzÌ + ›>ëx'Q©‰4N6D7D,ߊsC³eHy(˜»‡Ï~Dì‡iGDõ…Ï~4Î81Véí4fxc£‚š¨hý¤ÈÇOÍTì3óAZ¦a,Ûî„~dÈ‘>æÌ`ŠÀ_,k‚ÎL1Ðj#WceøAˆ­AÖùTu[ ­ë^Ø÷A"Âúð°dªã²’ ŒÖr¿ÙüŒßþ WJëèöòyô¹;0ßúýî{ 0î°wCɸ$\ÓŽJÆ x +Àzo€z€pG«Õw…ªãJ’1î¹úË ß*%©6Q¿¿®¹2ß jq¢-N +Uí¸¡dT'êë—N½Ný^œ¨ÇŠÓZüÞÅm§é  ˼+¾þr~óëÙÕ5~n.UÔ‡çn˜m¥ÝéU’õÊ6¿péø¢ÈBY®kÏ{ÑÇÿØøÏå©RÑÙÕ¿ñ»b+£þn—çXêAmü׬½;Ì@Ôc¥©%~ãÒᨵ%Ô0ï§/oú¿^ÀRŽe¥ˆ—³Y7ÄE¥ÝÙ‚½—ì—¨äÕ†™*¦×}¯N{`wýö˜¤³xøÝtHHPI„p¬'Á¶£n•‡%ÊrÓ dÿ?ýÿendstream endobj -1512 0 obj << +2024 0 obj << /Type /Page -/Contents 1513 0 R -/Resources 1511 0 R +/Contents 2025 0 R +/Resources 2023 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1486 0 R -/Annots [ 1515 0 R 1516 0 R 1517 0 R 1518 0 R ] +/Parent 2022 0 R +/Annots [ 2027 0 R ] >> endobj -1515 0 obj << +2027 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [397.3443 737.8938 467.1586 749.9535] +/Rect [333.4761 684.0956 413.3061 696.1552] /Subtype /Link -/A << /S /GoTo /D (boolean_options) >> +/A << /S /GoTo /D (clients-per-query) >> >> endobj -1516 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [321.49 696.0508 382.69 708.1104] -/Subtype /Link -/A << /S /GoTo /D (options) >> +2026 0 obj << +/D [2024 0 R /XYZ 85.0394 794.5015 null] >> endobj -1517 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [317.0267 666.1628 385.6987 678.2225] -/Subtype /Link -/A << /S /GoTo /D (boolean_options) >> +682 0 obj << +/D [2024 0 R /XYZ 85.0394 447.7394 null] >> endobj -1518 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [356.8967 636.2749 430.5501 648.3346] -/Subtype /Link -/A << /S /GoTo /D (tuning) >> +2028 0 obj << +/D [2024 0 R /XYZ 85.0394 422.6188 null] >> endobj -1514 0 obj << -/D [1512 0 R /XYZ 85.0394 794.5015 null] +2029 0 obj << +/D [2024 0 R /XYZ 85.0394 422.6188 null] >> endobj -478 0 obj << -/D [1512 0 R /XYZ 85.0394 622.0858 null] +2030 0 obj << +/D [2024 0 R /XYZ 85.0394 410.6637 null] >> endobj -1118 0 obj << -/D [1512 0 R /XYZ 85.0394 597.3039 null] +686 0 obj << +/D [2024 0 R /XYZ 85.0394 197.6003 null] >> endobj -1519 0 obj << -/D [1512 0 R /XYZ 85.0394 168.0037 null] +2031 0 obj << +/D [2024 0 R /XYZ 85.0394 172.4796 null] >> endobj -1520 0 obj << -/D [1512 0 R /XYZ 85.0394 156.0485 null] +2032 0 obj << +/D [2024 0 R /XYZ 85.0394 172.4796 null] >> endobj -1511 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F48 953 0 R /F41 939 0 R /F53 1029 0 R >> +2033 0 obj << +/D [2024 0 R /XYZ 85.0394 160.5245 null] +>> endobj +2023 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F39 1151 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1523 0 obj << -/Length 2578 +2037 0 obj << +/Length 3512 /Filter /FlateDecode >> stream -xÚÍZKsÛ8¾ûWèHmYž$pôø‘õÔ®œ•5µµó8P±"‰ŠHÅñ¿Ÿn4HQ6í8R®ÀÆ»ñáCwÃbÀáO LÊR'Ý sš.Ì`¾>áƒPöþDÄ:£¦Ò¨[ë—éÉ»+• s©LÓ»N_–qkÅ`ºø#I™bCè'¿ßŒ/‡#ixruý/È ¥LÎÿyöaz9¡‚4Výåz|AGÉùÍøêúýo“³a¦“éõ͘ē˫ËÉåøürø×ôדËi;åî²W8ßÏ'üÅ Xݯ'œ)gÍà>8ÎÉÁúDÅŒVª‘¬NnOþÓvØ) MûÔ¤¹`B5 ØÔ>?.ÁaܘµŠ¥6}<ìHpÇ 7Ð}j5SBg­îµèè^ôÍ™q,URÝW~u‡šyw%e§nÆ™“ -GÇJÓeQÁf¸,Ù m²_yüH“u^Ï—>–Ü/ý†rõ2–oòµ'ÑÌ›$Üoyí$?êÛÁL`LPsÆÈ0ø¼ÜÔ~SC%%uRÞQ+¿»]¦:&…Èâ´‹´+ꇞõÁ¸v*Vü“séW D–’°Ú¾®uÊÓM‹°´§ÝÊŒ åŽ{¥ùqþÅÇM¹ -›øÅiX-,]3‹=­z¶¯¡Aj’jYîC'ŸyLiñT4Œ¹¼¢´_/Bsf Àê5ŠÑ8‡ÇŠI>(æVÐdzfÑÏài$5_¤Í*E«Æúa‹kЂt¤e².«š$ûÊßíW$%€¡4_­Êû(ª³2)7±§Oþ$[¿ëÃ!SYPe‰©Š°<Ž´X¦=Šu–1CÝBíePw·(î”úîVzvR¥I=IIÙYí· '”¯xú *…À£Ü¾bcDÒædܦ€0N³Úúy¶<”P=Ýo—2ËSÜH–i¥CÿèÝràn´F†¢cI2<ß7çUíwEõ d‚$E,©ã`nžWž=ænmà4g ºŒ÷c,ª´e -®$˜·bNpý]R õ1§œi®ÕËÄœf†9Šö UûÙ+¹YÂØr3(>i„U±.VùŽ„öžý„A••/Ÿ_™2íÒ†?ü×¹ßÖ4@½Ìkêf»(×y±‰C—w=£ aQýßKñ*h³ªJÊ…ói¼V^@Jg ~l[#E½)RjZ(N½2¶Uá}ÇùuHQ\‚°E -~ô#l6cô7‘â`©ú HÁ\¹Y=ÄA;˜ %}˜ ©™ËÌ£+ò¨rÇoózœ6à­`&“ ¹ïè³mò,P´Ë˜´Ö|)Ò¢½I,]Ï·£WÙ{gxÁ¢Q梾‚…fã¢x™ñ”›y²û,ìÇ&–~)rÊLÏ?P&ß,¨ÒX?Ar¿,æKÊ>s?V5´ÊÃEî#æâv.{ü¸ %åš¾ÂE +€¤¨‹¼n«] 4_,èN¯*›º˜hôýÝÌE_ß—»O$FvGá3­æå.’ð¶Ü,¢ßfD¿hª/z¸¥nt†Œh^íÜÀæ~³ŽKJ^¦9é+ŒoI„3Äôb|öïK*šL*_WÇ-g½W\"~Ñ÷1§Ó¿ø]ÕP;Iüóì­\×ægåo•*ÆÓŽÛò k´¹2-Þ¿Á#a -í¸·æïnÇÏó·ràW‚7ÿSòww[~rþvoÊ߯Ÿ$¶Éxö(Rûÿµj‘™:¦2 ^€$sÜu#¼O"½° &µT·N™î)zW°»–\ëæ®Aêô@8=‘OC ùðd×5jÓÁHÝW5åBèî!N€’»=}ôyŸ¯á!“çv°h4apƒI$¤‡¸¤;¨ÇE²))ŨR.ø|ykC¹ÿº]ó¢Æƒ…ߘ®_ˆ&4e‡€|´¡dü ÅÓ-@<™Ü^¿?¥üø6fnoÎZÑåyì(ØùÐEŠõÝMÓ¡ãIÆ:˜ÎÜEÇQ5,x TÙ)º½öš¯ötbÉŸpÆÎÆÿÃ$ -¸á  ö‡•B ­¤õa -íJA—b£ ÖˆÔi%EŸL*g³Ä+d›l¬ŠFíbpr\Ö±,†ƒ 6ÅkQF]Ù$¯k¿S1@Âu¾hš–$Yø•oº£å02§Øù¢Š¥UUÎ zNCõ2–<p=}rk E_íE¹:'±àJÇN¾šïŠ™¯¨„,Jl×aix2¸ûá“Ž=ÏcíIgƒ°ž«É„ÂÏ¡áfÑwÄ‘”bŒJ´BE, ¬ˆeû*ìµË’[8Ôž¤4[h°ÝÏ€Ýò`k‡’0cHiÉi–,Ñ€“—¯H¾ñ÷Ô«$¡ æ(ƒ…ÿdÓg¿6û]¬·+¿†Ê ¾÷¸íã[Ö ÁÂÑù8a‰¾bœ"ö'à §ÊàÚ¶™/`-Æctl{ý`>>ºð¬«‚ŠÊòX¥\xÜ«’KÚ·(¤=骃K@†-â ! -¤Å˜a7p—²!Q, wŠþ¦HCðÖ·=Óe|¿¢Á!×¢opÍ»ƒÇ—±!â7b(¡d›ïÀnÝSœ¾£ÞÚÇ7`½r ÆlÓA3~å¡ep%ñ 0ˆo¥ Éø*Õ÷®®ÀóUJô=ƒóAsº~øÑýð:cÊZÙoeµÖX3+Tw–>™;¾TyÝ7ù¿ùë`endstream +xÚÍ\[oÛ8~ϯðÛ*Ø5Ë;EìbN.³ì&mâY`13Š­4Bmɵì¤ý÷{ŽHI´#[ÎØ-‚j‰"Éï|<’6 ð(M´åv`¬$Š25ÏNèà|ûù„ù:úÒ0¬õÓèäÝ¥0K¬æz0zdÅ„Æ1Œ&¿EšHr +hôÓÕõ¹=rE£»Ñ©‘Ñ{ügtu7º:»;Zóèì_ï?Œ.n]-4t%¾ùÙÍõåÕÏ¿Þz7×®øöâòâöâúìâôÑ/'£fá$8ú/'¿ýA˜ë/'”«Á3¼P¬åƒÙ‰T‚()D]2=¹;ùØ ¾VM»@“2¬™¡ˆ‰T*ÞÞ­ë‚B·þ‘1b•Úìu¨1B€D3¢R™FœzÐ1ÌÒšQ–hÁE¥‡›åcº¸X,ŠÅéP*Æ­Å‚Æb +E g¶ç?Y9K–ãG ¥U&º=_Íoû!m[qÃ<Ëy‘—)²Ól²s( F©ûêpí®ÎÿöRÀ_JìúñywÊ"\`XaùèknÈ®Ê6¥Í‹ÅÒ=MŠt£^õŸXA먞6<>?&¾ð9)ÝCúužŽ—nÊ*ŽunÚðÍw‚2V¥º¯¾™H ÷^,º:¯¤[MÒß)åy:ÁWÝsÅ8U§±PÛƆ^À)¬êü¥Z90‡‰r•Šù2+râ–‰4FYéúš%¾³jÄð›äîC–O²q2¬†=d”K©\× +uk­xp¿‰û'ã +xœYYäYþÉWX.ÓÙ|¹}=†L?lñ|O»¦ 'BÙ»¦"VjÖè”wX¬òq<ê_‰£S‹«-ŽêshWäÞþ"ñÛõZS"©=¸jA¬¥ÎÎý;™Õ E×[=÷"ëZ t“tš~JƯÃ2åq±dÇÄ%)-ïÁRqBÁ¤UÈܦKôž˜wà0>öƒù±u¸¼å"«™9OÅb¶Ê`o˜–Âm˜òn$%…ðœê–÷÷Ýƹ³ÛÔ«}²òD]uxS,k[äK8NwÀÛüXèBŒkõ;R·ØŠ.8Íã>cÊá+ÙÂ{WŒ?ï(^¡  GÑ»¹ßbžzçDÛà‘b 1þœ.!n_(£›` D¯Ê!«m"àó9”[›É,*>ïr,áàß®cQ†«û˜ BZ½°~5Âú¸·cÃCxS÷ ¬4t!å&‡÷ó.ûr·Ý–Ø k0â7Œ+;±8vã*%‘ÂòMæî«>"®Áˆß°Í…('¶¦'R‚KçÜÿ[%–Éô½K­ûq=¿¾»»8s¨=%Ól„>?ß d0Ä7LP¦!÷æ}¦•Só±k@Þ|> CˆøÆi:Ù‰a0ºcaÈ!)Þ¹ ÿBdÝb†Ò‚lÑçÿiL”f ÂëôÓkP4Ò®¡h|PŠåy•¡?¥®4Ë1£ ªØî·OÁÜCë{’XÆŒP£{¼X¢µkØÏÄî¢qŸA w4;@ QV¿Ê¶ÔM¶AKÚc ¤áÄÐعª‹o·üFy¾Gvé|dù¸ÚLÑ2¹¯)ÌÝr—Cº\}•O| H®ü¤ ¥{ÄmåÛSa cÜý+ý¹JypR¾¸½ÒEù‹|áËýb>X7[ÁÝR`jí«”ótœa.ˆÃ0êjË]0 éï¢Ý€œT)~Xù‡'ŒLEW¹kç7²Ab0·k©réZbÒàL_λSksI)¸&ñtØi÷9‹äÄÆqÜ}9l$C‘/ù#¸ÑL¶=ãYȺcµþÖ1IMX,åö9*A 7~Ä9Öûæˆá1‹×§Èû§K¨@H×d0AÒxûl-š[hr¼ÙÖûfk5žuØõéÎ:¦ qÒf}ºn­Hætµ‹Ò¬5|+h^­Ðöx4{@b¹2ëd@Šmhm62w¾qˆ¿3[[äÞ†ð(_Íîñè[€™@«†e_êP|y~,ÊÔ}m¡û˜ÔÛcørŸ.ŸÓ4ï²y`Ñdlv€«HlÀÚK¡‡Ü\/qŠìX¤ijáÑîgÃ>F¸4vݶ³ÊtXnˆ_-¯UPÉÉÇÓU “wô&]4DKʶ¯@Ð>ø XöàAâØèÃW`-qŠì²7Œh†Ö¼®¶€ +ê1Ì>ýúbö³l:ÍÊt  ÷s•Ñ¥;L¦­c²–h*͆cJ>#Ó´;ßÄ_ò”æ™÷VPðìëÜ.K'A¡Úèíd„>µÔ$ø—‡“±–8 Ev‘Aä(ahM5!í4uªn'ã¤ïýä)À +Tr°`š”Kp¬FglØ4¯Î™D,¢ò±XM'ø,<(sk|îC ¨œú +IÙ‰¯$¼u;]øÂ, W‰§Øh™Ç×K†"»ð…5¦ahMµÊ•üµk!Ó›ˆ| 4K˜áîB2K“ÜÛWf$šq¾±ÅïÜãƾ‚÷Çòqk_±ÐÛW,_·¯ø±±¯øâ²dêÊÝ BìnaàïSºèÐÅæ劺àÁf`]Œ˜_îÕ‰ÃPäK]pHÀô4•¶9u?øìšMëÆc[*¦¦-m.ÔÞë½Tm Ä_èO5jÔÄÀµKH‹ éÀ´È„Wñ^\Éã&†é @6‚u« ¾/(Àkq¥š{ŒŒÈS¼bB£;–…ùçÕ»«ϪÊe6ö›~gE-ÓEÙ¡<ภë³~×yqøPâð}\‹«Þ’öümí^¾ÎÓ…È]~›§ÕU%ÊëÊéˆM,þèÚñþzþAv]ౘñ°ÀµAÅw¸ÕŒž­+¢V VXÕŠÕ¯«·‰KÙ¡0ñúÒuÛ@ÖmL *î¶.Ô.*ë×HÕ{Iý5ϾvI¦è8„ë 98šób–d¹^åßÝ!”eÄĵW¼<®®u¤Eâd#ƒžüñ²ë Ow«|^-Ël’º—6mæ1o^«‹ŠfÅd5­‚ q¸®Ro®tíTôPL§Å³¿ˆ¥ýE5V¶æMÑœª&,üG×40 qÛè.:Äpˆ¿µ¬­è?»#W¶îç…Ë/ݨ7Úpª¸àü$¯«Ë{ð=™NÝÇv1W­[ouž’lZÏ옾‰Žcûj#ÜI¤A×~­ÿÝ_Ûý:NçÁÕ¡ /Š· +ë;™ßN[>nœ¬gá±{:}¹Óƨ% þ`FÅ÷sbjÄë|Aw«zôˆÍœ†œsÜ|h½µ°k^Ø%pˆd!ˆtæüÛ쾘b¬iytÀ¸ðÁê—Ìbë¶ÃÆ ŠµÛ–‡o·P0ð0ÞöÐg}EÖPa-“;×¥Ùg]Êu¹UÊÍ<íÚ/T`ÐБÓÀËVÆŒÆÌ„”åÃj:m¶%õíÓ¸ñ½®iæE¸+¹ðÌçÓlØu»fì÷Wƒ«QÝ—e‡Ä…³}L´Ä­ŸàT&f«BuFMV‰£²Êà•÷ÿ:Y± +¡Þ¡ü@Rm9žX'Öúµ-A­ß0¢í…(,lïj[òäÂJ ¹°Ræ%Tä¯o•\ÖŽE®£LäÒ0w%{¸¥5aÒ߈üAä:›bv»¿É›”Ød²C%í\åD¾ƒ?e +·cÛ£éVìs¯¤’Ÿ²|ò'Ö{øw÷™?nj#²r‡Â(Ž«±ã®!›¦Gc’.èuûgEž¨±1ˆHÇËW(-@ã-+k¢ã¸'Vc°qócÝ**­Wag^-MÚ’–˜ fåc¯tm[U`q,•ízy«2ˆpâà"P·Â €ùÛ¿?HaïǘAþ‰u¦„¬Ö™"J*!Õ2Ãâ,³æmÜhÛ½7çôå²û +Ì™¬‚§S¹àÞërœ3áâ§:T‚U¨åÝ¡SšX«e»;Õ½!õ¨wº·\@OÖÊþ˜ /ô®äF~_eðÛÝRå0ò}W>ƒ ·ÊôX ˜©üÖÊç^._5ÕÂ-± nì¯2AU¡cyõç—LVršuþ5iòKãB~ü­(‹!eñ)[ýn¡,ío»›²xW ¹9ÓMYÎÌ!þN” ØpàŸ`@ï†kt›–(.;ÿüžz}ê¾ìßþï¤!€Op†¶¾÷«`ÅÃ3 eU§áŒ¾8‹ÁýD<óÕ‚±ÿóÿ?endstream endobj -1522 0 obj << +2036 0 obj << /Type /Page -/Contents 1523 0 R -/Resources 1521 0 R +/Contents 2037 0 R +/Resources 2035 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1486 0 R +/Parent 2022 0 R >> endobj -1524 0 obj << -/D [1522 0 R /XYZ 56.6929 794.5015 null] +2038 0 obj << +/D [2036 0 R /XYZ 56.6929 794.5015 null] >> endobj -482 0 obj << -/D [1522 0 R /XYZ 56.6929 237.323 null] +690 0 obj << +/D [2036 0 R /XYZ 56.6929 328.1878 null] >> endobj -1525 0 obj << -/D [1522 0 R /XYZ 56.6929 204.9886 null] +2039 0 obj << +/D [2036 0 R /XYZ 56.6929 303.0671 null] >> endobj -486 0 obj << -/D [1522 0 R /XYZ 56.6929 204.9886 null] +2040 0 obj << +/D [2036 0 R /XYZ 56.6929 246.6387 null] >> endobj -966 0 obj << -/D [1522 0 R /XYZ 56.6929 174.9041 null] +2041 0 obj << +/D [2036 0 R /XYZ 56.6929 234.6836 null] >> endobj -490 0 obj << -/D [1522 0 R /XYZ 56.6929 117.7253 null] +2035 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F11 1442 0 R /F39 1151 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +2044 0 obj << +/Length 1362 +/Filter /FlateDecode +>> +stream +xÚ½XmoÛ6þî_¡60±|§ ÒÔn] y±]`C׊Ì$Âɵäý÷;Š”,Ù²³,à "¥ç^x÷Ü`ø!A$fšJs$0Aò4ÀÁ|û8 Ö °z¿¼›0h¤%•Áâ¾¥+B8ŠH°X~^~º¸YŒg£ +<”h +‰‡ï§WÜí—×W“éǯ³‹‘âÃÅôúʽž'ãÙøêr< +µŽ(Èó–/;_X!/9_L/ç£ï‹Ïƒñ¢9@û3ëýÁ·ï8XÂY?0b:Á6­ið4à‚!Á«ß¬óÁm£°õµí Ç*X +Œ8!§­: ¬ú%eH[?»FCÂâBÙ,òä/Sºwèr«|m6q™æYù—.S/˜äÛ¬4'äN­ ­`*$i!he³XçÙ²p¬)óž“p8+­rQ¥ÿ”B:EµÆ¼Ušß÷)UˆIRǧ¢~RÈnR¡C +sà°’’íÔ¿NŒGˆAÂJ HŠ×¨¬%N3GˆÒ +z%úÿ$èÌ$ϯ%(ÅŽ Ó† öãZbÒgã>vxJ5÷)_TÈ–b÷%ÏÜ3v$Ï2“”Æ£¿~¸ñ +jgaåeú'Æ@“®OßýtŽ3÷œ^~¹q«ÆU·}2E?˜3 ݧþmlÚtßf_êÛVFauзÿTí‘1m4¤ +aÕí÷G}Ÿa‰"ªU`û”%^SNÖ3IB{T»°ó 1 + Æ0ó§5äü.]¥¥ÏÎ.-se{òpÌ&ò¨Åtê$B‚ÀÒ·?x]û*zÊ!$B",™„ss¤9á•à—¼°í™B%”à]Q¦‰íĔԭ°p_ËÇØãvÆÕ‰CÅÏqºŠïVÆ}„²êqÛž)ÅùžÉ •”îÏcÕÅS«"÷®n×ë|SÕÇI£Ç9£¯0ª½Q€â1ßeSU›NÐYÔ-ôø.¯Z‡H6&¶m0‚‡ŸšU5ÙÞ@?Ã@z[úɆ|îÓP©­Ò`W˼QàÅ×k{¡4«á¦8pèð2…p¹°ˆ¸àý7F +Û¨ÓEРª=Ù-g¿ÌíïCÛD€^œ5Þ z¬·SI$xIUÔ5¿p`\¶ »=µ¸pA´oÛÌ‚íIâmaúè¥)²©¿ÓôP‹^ s™ï‚·*†ñ2_{,Ãê© v]_D˜îŒ]qáuUÝçwK +¡´d\w¹¹‹7Ë4{èsRœÕc9.úNKÔ’¼êÒãiš.OsŽiŒ½À¹ê çjTŹ‹ß'Çl#Ð÷%æçÍ6¨»¶Aeœ¨®a?Ø—­/Ǻ“ÆmZu˃2õc:Kò'›¥jw»5›´î\€§ƒ‰5"„¿TÀ-Ô™`Ö¨*˜ÓÛ£Pbè~XÊóFTÕN(á+‹”îšýoC93?¶¦(ÿa,¹Òpç‘â|,Û¨Ó±lPU,¯×eqLL ’€{ÊY³ ªÇn'š–Àö®á¢Ù ‘Vÿ³Û3ýnQõš– ëÉeÍ&™Ø„Sk…þXß–{rmïÁ›Â‹¬Wqr|Ÿ­Ó—Sû—~O„qP·Ë7ÿCaÿ/û×bÑþT1(Æ4©²1"„º× 5U=¾ÿ 16.Éendstream +endobj +2043 0 obj << +/Type /Page +/Contents 2044 0 R +/Resources 2042 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 2022 0 R +>> endobj +2045 0 obj << +/D [2043 0 R /XYZ 85.0394 794.5015 null] +>> endobj +694 0 obj << +/D [2043 0 R /XYZ 85.0394 665.5626 null] +>> endobj +2049 0 obj << +/D [2043 0 R /XYZ 85.0394 637.9713 null] +>> endobj +2042 0 obj << +/Font << /F37 1018 0 R /F11 1442 0 R /F21 930 0 R /F22 953 0 R /F67 2048 0 R /F39 1151 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +2052 0 obj << +/Length 69 +/Filter /FlateDecode +>> +stream +xÚ3T0BCS3=3K#KsK=SCS…ä\.…t œ;—!T‰©±ž©‰±1ƒEV.­knj©g`fA‚!ÂVŒendstream +endobj +2051 0 obj << +/Type /Page +/Contents 2052 0 R +/Resources 2050 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 2022 0 R >> endobj -1526 0 obj << -/D [1522 0 R /XYZ 56.6929 95.1854 null] +2053 0 obj << +/D [2051 0 R /XYZ 56.6929 794.5015 null] >> endobj -1521 0 obj << -/Font << /F37 802 0 R /F41 939 0 R /F22 737 0 R /F53 1029 0 R /F62 1062 0 R /F21 714 0 R >> -/XObject << /Im2 1051 0 R >> -/ProcSet [ /PDF /Text ] +2050 0 obj << +/ProcSet [ /PDF ] >> endobj -1529 0 obj << -/Length 3258 +2056 0 obj << +/Length 1238 /Filter /FlateDecode >> stream -xÚÍ]sÛ6òÝ¿BôLÄâ“ îž\$nSÇg»3w×ö–h›SŠÔ‰Tœô×w R¤,ŠéÙž:ž ÁÅö{Ÿ0øã“X‡LZ51V…šq=™-ØäúÞp3m¦]¬ïo¾;“fbC‰hrs×™+YóÉÍü—àøÃÑåÍéÕáThDááTG,øþüâ„ –ÇŸ.ÎÎßÿ|uthTpsþé‚ÀW§g§W§ǧ‡S.•0ôSü÷ÓÅ)!<=üí懃ӛvÉÝmq&q½ÿ;øå76™Ãî~8`¡´±ž< ¹µb²8PZ†ZIÙ@òƒëƒµvzÝÐ]dÒ2u,Ì: ±‹NÚ†‘ÒÑ©\ò8˜§«Ã©d6(ïèyuUQ#+è™Àƒ³ Jk÷ýEéUv_d¿2&fIáAI1÷Hi:ßB¿Mé¹tßO«tõÙáÀ7n¿zÜdá‘\ïªzoB~D™w`e³þú¶\ÒL9­ÖÂís™¬jX²`±Û£\@%ÀÉÅuH åc -³¢4ÀÄ‚› *WuVÜ÷G.Öy-s?ÜÑJxš `™®Y]ã~ðõ‡ýå²ÎÙI•…Ç\¯–e•Vþc-fú%YÀüïví¤.Iþªe:Ëî¾ÒKýÔÔJèûÍfë'ù:¥¦·Ç€àÌ4šÔ´jº75â8½èvS¦NÉb‰”â}'°­84 Qž=œêàydÝpJ°©Ìü…)›Ãœâ1˜;ªÖ`‰"77OÚ2/óÈ™-Ò)¸KLóì³:Z›†ÖFƒ¬‡¹ypâ Ç®|Nà˜Ð«žáÊŠ:½wZ‡xÅ0»ÖEæl 4ô}xVÀ­bî<¿b*!8óhËU¶HVYþ•^×Uên=¤´¹èG  ÃVqPăY2sÛ†&D-èá•ðô#!6æi5[e·Nbáõ¡|Ä òÒEBJšIšy jܦ»B÷ÙypÜ•]›“ù¸¥z(×ù¼”̳j–øuŸPw¤åyøªæG[ÀA»Ç„š³PNáù,O*àB$•òöÇvíOܱ?vcâÖþ@P:ÿÛ1@±ãm"ï².geN»d·CŠy“+ËŠªNŠÆôl9õî´Ã,ëÒâ¥ìÐk°Ìðs+GX¦ã(Œ""ÒÕ %“øßÑáTÙH‘†ÉX´J»1Þ'uºáÞ”d,ĶKÊbN&«@-—†Á“| ¶~ešù@uÈu,R´ŒÞµ; ƒA¼“U¸4nó:Ty)æmòÛ¿#Œã‘ ¥”,yÈL?Ñ~:Kõ°Ï@jFJÈý ·@8fu?8¾+ó¼|¤Ürê"Ñ¿;“¶; .9†•·IEX½…µ€ÔŸ°¥“Í›˜®Ž£5©¿1Ž~õU¨—’²ƒ}ê I7†2ÐÙȨŸRHð}UM­d>÷ê‹ŽS œÔCz ó z:ÂÊ„B¥u: -Pz*WJ×&p/w|5ب|âÝó¼1ÇžÁgÇÔšèaíí奴÷r [âÑH™8‘ÏŽà˜\ÅPôsä«Ç7,iŒÒ/ Ó¯³°—Jv€_q¤õ_˜²1L?‡1×jŒ~V:|1ðH þaêñ&LFבÝx÷jOIþdBrÊ;›õv¡»ù²qA ãtÅ. 7›óÌ'=T‘Z¸Ò˜{:…„†/!B«“éJÍ7~m5½9OÛ ·zàê±wW‰‘0»»R‘ áˆOŸK»råé—e ->DhIîA]áT 'õ'õÑ;€Æ:; -¿M =×ñvÊ!5ÆIJ+1,Þ]¹yõWa8D’rÌ6 Hül¬¼mº¸þñô?Àop„Áuí«ÖÈåîCàc¹¾Í³µOýùz×æ`‡íÍ(¼+ÑоBÀ?Êbcq¦Ã²>bŒ˜Ü“tÉð²žD½(·@D4ž&p+’!3Ê£kÌ]…îqŠ[¯%Üêà!©¨…zÏ„0&"È1Ñõõ‡òLlGé–‰ØF&2¬ÇØgq¯C–7œUˆe´1zŒ{Ò†#Öíîô Ǻ<6¡ÑÑXæ Î96ŽÜÆÏ/¯OGFªà’Ê>Cl[õÌÑ"­JoX| Ö¬š~5ÌT¥{Õ‚`­V®ð†oÈ o›Âá:Ú¸E{¸Õ%Ãö'˜–1‹Ä eS~~}rq8ÕLŒm›[ŠEíëNZPµPcõžPE¯\˜b>È9ÄŸ[•{†‡ß_yênõ¥8ò -Õi–ÊÆcá×:TÍÁŒÓ Q?4w ÆcÛ¹q××qãøNn¼3ÊÅ_ØðŸŽtðsÕ g{JР÷YáÍêýOz¡å¹ŒhNº¶¡Û RÐä¡·™» "ãàv]ïJ.ª:˽÷ó¶opQl ­ëó÷XœfXz 7ª¶¤{EwY¹'›íðí ——Á|@`ÈÆâGÎmqÑëÇCüÈ%ßv– ÿ®â7ñ=0öË R7ºø£›û½:n«±êµi˲_”}’µÉ½„d{˜ÑÙ掭9×cÆ×â¹ ýCÈŠ¡Kpæh ³õBXˆ¯ šw¥;7‘=ò -º·ŽDJ€«Š$DYN­FÎéļ9îÆmµ€Þ ÙLÓ^L‚¶wŸwÓa‘÷§st«(æí]¦˜ óòÑ©[ìï¤ÆxÕ¬†pÇ´Á;ݧpüÇÞ¯ô¤ÅÂ0:ÈGPs=–£ßuÁ¾É7<% ÕPâÓ8kÔ»¿t&ßrñyb¡ ˆÐ¨²0æf×Åo6UñoýqÊæ:˜Bà4ž´×e`Õ8Òؘ'·Ö›_±x¬ÎÒÿ„8ï"endstream +xÚ•WKÛ6¾ï¯0öä"š¤ÞÝS²iÚ-‚¢h¶§¦®L[ÂÊ¢*QÙ8Eþ{9R¶lÁ­aR3ß¼‡[Póc‹,&4Ì£EšG$¦,^»ºØšg?Ý0ÇÅ!‰£04›™§Af$ÎxºŽAÞ=ݬ>p¶à”$ O›QW’¦Äe‹§õŸË‡R´Zvwé2½ûëé‹Hš¥ ĨQ‘šç¹x÷øë{äÎqù$‹¡«ôwªé«µì„® 5ⱈ„QÂ^b,I^JØ]À(¥Ë·E!û~„Ѫqó±êµ‡â‹œä ORhÜ£<²H^> ”¿cÙ0à1 /?Ó˜¾}øØ›•áCaY¥Û¬×¸õX;¡‹Éú€¢K¡ñp¯$ +Ñ ÑK÷hh‘Y4k¥Ë×ÒIÛα:ü @Ž;¨^v FÖ‘$\¾VºTƒv0õ Í0Û'݃1‚fß®¡Œu`íw@ÖÒ ÀEª¶)×ý@ª ®¿áz44dOFíG!}„‘‡ËªÇU`ªÂü(UÜð™Ú*µv"k)æjˆ‘,O™c‡D3ŒK@âLÂ4wã'ŽF¦b2Á?; L‘‹œ¢Nî‚„åfšî*mKÏ…ÃsaK?ï±èLo²$bÓü˜4ÂÕmE§+Ÿ ,È…¬][ ÷Ùh<è[¥lé¹lZŸX˦õ4m`SUHŸ÷˜¾WŸð:°¢Z›ÎuºÅVTM¯OKç8$3ÙþYúqÌ•Çrnȯb×ÖrjS©^‘°-5º¨ZÙÕîrmëIÈîX;¹MpóÔš±Z™|Q¸£5а‚%°$ ÅÖHÞ>«íÐ7R÷·x€WP¯U]#õ\«âe®Ë¼Êß?<°œe¸é[ÑFÍNM¯v6šë#Þ7N_YÁÕ dÕÏ݈^[¡v;Õ@p¬—½«ªÔƬµLæì…÷ÐG·ÿXæ(5s›¦SJìo•Ý#+;ÙóÓç9œ˜ÿŠG÷s^q3ãQ$ô"g:RnZÈ1~?çhaI†,ɽ»=æìÿ>Êó䌆WÖNanpÓ ¸*m=¦^—UïëH—þL^ª¢N +—˜´¶P‡Ý³ìNsǦ¹óVøÔÙå+±?ôésßg©Z|—=*ÿxÂGȬQgÇüìÝêØJoúE“Nß~®¸hÔá•åqì„‹6yÈà$8l¶Æð•ý›jœª[7‰éäÛ ¡F4½oÜNôæÆŸ5hSy?nw«cøûkò!šýÔíKþÝüø4~˜ùÏ-xÁ2osŸnž%8ðàwÛäýšo§0gÈö6 OÕŸçúþ×’¨žendstream endobj -1528 0 obj << +2055 0 obj << /Type /Page -/Contents 1529 0 R -/Resources 1527 0 R +/Contents 2056 0 R +/Resources 2054 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1486 0 R -/Annots [ 1531 0 R 1532 0 R ] ->> endobj -1531 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [341.1654 731.9163 414.8187 743.9759] -/Subtype /Link -/A << /S /GoTo /D (the_sortlist_statement) >> ->> endobj -1532 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [434.6742 731.9163 508.3275 743.9759] -/Subtype /Link -/A << /S /GoTo /D (rrset_ordering) >> +/Parent 2022 0 R >> endobj -1530 0 obj << -/D [1528 0 R /XYZ 85.0394 794.5015 null] +2057 0 obj << +/D [2055 0 R /XYZ 85.0394 794.5015 null] >> endobj -1533 0 obj << -/D [1528 0 R /XYZ 85.0394 714.9798 null] +698 0 obj << +/D [2055 0 R /XYZ 85.0394 769.5949 null] >> endobj -1534 0 obj << -/D [1528 0 R /XYZ 85.0394 703.0246 null] +2058 0 obj << +/D [2055 0 R /XYZ 85.0394 574.0823 null] >> endobj -1535 0 obj << -/D [1528 0 R /XYZ 85.0394 522.9001 null] +702 0 obj << +/D [2055 0 R /XYZ 85.0394 574.0823 null] >> endobj -1536 0 obj << -/D [1528 0 R /XYZ 85.0394 510.9449 null] +2059 0 obj << +/D [2055 0 R /XYZ 85.0394 543.8373 null] >> endobj -1527 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F39 899 0 R >> +2054 0 obj << +/Font << /F21 930 0 R /F22 953 0 R /F39 1151 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1539 0 obj << -/Length 2765 +2062 0 obj << +/Length 3283 /Filter /FlateDecode >> stream -xÚíZMsã6½ûWèªjÄà‹¸{r<öŒ³‰Ç++»S›ä@K´ÅITDÊŽ÷×o7¤(DzÖr•)W™M €×ÝÝMðƒ?Þ‹t¨c÷L¬Âˆñ¨7žŸ°Þ=<ûpÂ}ŸAÕiÐìõÃèäû izqk¡{£»Æ»lȬå½Ñä×@‡2ìÃXðŸOWçýˆXpqùH\ªHgO¯GçCz }×.¯ÞSKL—³OW—~žö -F—Ÿ®¨yx~q><¿:;ïÿ>úñä|TO¹¹,Î$Î÷“_g½ ¬îÇÊØF½G¸a!cÑ›Ÿ¨H†‘’²j™Üœü³~a㩺&ÅxÈE${iCEöðÏÒO0øY/rÆQ´û«ÎâÃ?€–ÄTdjè…h@Ïy*kz&ŠC-…tÐ_²¬b’WÉ<%Ì’u9ÍWYùD·Ë<[”é -qð%gÁû´¯²ÛtB²…Ǻσ‹3’EÌ#P ŒØÁ&*ãD6Ó}RÙP‚9¾Ã1QU*d1‹:PU&ÔÆA_Ýœ^¨Æêà”ÐX¤åc¾úB7EºzÈÆÖãqZ  w HwQ® æ†éxó>¼B†q«¯|õÊjÄaxô´LtÀ+£Ð{xû͵ FSQšÚ`“2{ðM ²fn°^'ßåN°AY äó$[ è,Ú²k舺€$Áâ­‹t¼Ñƒ¹ÖBcy/ƒl£05+Ø·øM5â ´¡Œâ.#,çÚkáPVÙà—ƒ :Åëû«x|›t[æt-ÒñzÕç6HgOÕ€I6NÊÔ÷›&%Iáú˜•S’’½Ún2ùãU¬÷ŠWB¸É`KB—qº*ju/8n{HfÔ>Éý[ò’„ôϬ(w߇ó`Ûöðß|‹ˆ4ÌsBBcmp÷Hki8¤kù´Lq•0¡BíKº)Ò…ଖ^MW7©Áö4ˆlqïØÁÖ•û«ÃÜ4—™ÛÆ‚­ µÕßâÕˆƒY ,e»k γ¸¶` *•™ð›3a%jSªUâ$»Ãwߥ«‚îÜoås¸ãqEK‚ùµ2¯×â¯~v0»bß <喇õ´€•Y¾ ¶ÛuI‚3 #ƒy^/ZÇù|¹.]ÿdælº¤.ÓE›ÓÜÝ‹A)·¹³7唚ª½ eR -þ) ƳŒv‰ "R‡†çKg'ûV[ó@Ä£–¬é`/sÚW'"­B£;h ²ðLÙ \÷cœO†ÐB늴§½MÚÓ^ÓÙÌKN+ ì#ØT«äÇi6ž¦oé¨ñ|݇†µw¹›‡$›%·3‹sÁëºx.ãwhzá±BÈ9Œù¦l§qXÑ à³¦#pŒ ɱR„íç$ŠK¯_ecb [é—ÚP¼ns=õ®øÐõ#fÉq= -Äõ(ýÅõÏWbUq½RÂëÝÆ2oºÏ¸fl%Mýnè·—³d\ º}¢+mþ5{~ºvègú dím>Ó°Æ—Yø.;ªc²£²vœvµ§b͵‹×^aÃùr­;R1Q¹a–P¹þ »ØgpM¡ÐC6AOÖód¹'ów·iù˜¦ º!Ø@°BਅϡbÌ·M&Þ¿‹´çÃîÃ!ô>¬›Æ¢ß²n¤ E¤;öS0±¡$cxít#‚ËðâÜǑˆ º.!’ÍÝ>7ë%4d´ÁC#U- Œ¤ª…ª…1Á9—n\‹ãds çdöL®ãܶ)«Âq•u\®Iª¨‹ë„ -­5ÄuÃáÍåØ…€î‚³|QRüÄÑ ÿ”A‘Ý/’r]mƒØ4IÊàål»Ž„(Æ߃jÏ›‹9æ@–VGßâsÕˆƒ˜C®¨²ŽðÈ%ŒñéG_š`„NbÁóu™Ê)ñØú~Š…¸(¸ÅØÄ… -RW5<Ló¢,H¤H %Œˆðê""×+¡’ vJ3?°ÃT6ÉH¯c ¤$Æt“”$÷`„¦E]÷h›'¶rÌçYcëÝ}Ó¾ÖêŽMÌ_¦Ç×5 i ¨Pî(uý¹q¨8gŒl7œÑ`Zëcu”w<›*OD™‚IãËÂá:˜<è‰u€)y´`JN&>ñdM.¢¦š%ÞÁ½ä¾TŠ2sy"ôYãŒöDädÖ mxëo,b þñN¾.6Á©Ï “êŒä-FÓÐƱŒæ6\É%„9ª#’"…Ò¤½›O§˜äk\NÀó²ß.2|³¥ QÝ6|GׄºPb´õ þ†é¾€™í/†¯­ ßž6—ú†wUa!m‰ïЋB)# -n®/ÐeÓ³AÙç*å›t1q)1È×ù,?‘|±‚$Á³,ÃjL#ˆÂç5($‡q¿ÏRï1)„M37!ÔsJäð‡U×Ää G¯¸ÕZÙÁÀÒ$á©nØ¢à_˜jµÂJ ÉÁmîËZu!ìËwW'Ö;dUËÆ©/ !Å5¸µ8¬¾ÿãÆS!j¢3Ï0V´hªÁ[Ö”‚õÙA{VqÒÍÍÇ üèŒqæn9r³:xLžèÞ• ¡a»Â…O–ëÛYVLéqBm›^~ÔÔ)}IŸ¾+¨‰vÑ’‚ܧ«åêëÜ]N´Õ(›K‘¯px@H2ˆÞ: •fŠØr䊔¢‡Ö¤Ó?KÂÃǤô­aòܪUûžÓœÞ># ˜9ëâ-ÁC­bSq€ˆ)ógE"ª8 E*Ѩ=}a£§/kúÂ}½k©N­ñu. -óqÙÍÏ£ë>qðΗê)OÁÍ]ÈŸ Y/—ùª¬Tû1+Jˆ;Ƙ;Tà™73p d˜­nW ôŒ©TÿYD3D&¦sµ÷XI¥E¸~±+J›Ýnvó1Ãâ|ìpüÿ¢êHs±ÇÒÉæDY×5c˜Ù9¢öÿª&ÂuJ#$؆ ™Ù>ÚöÕ7Ø€A1T™×µWçï¸Ô¡±¾ZF'zã»|6Ë1眿¿qc¤V0K«àçpÈx– Š©ßÖ/`V A#ÔÏ…ó59íhÕ1¬vÝóÑ ¶@º]”30î!™e;FRV €Tðo»6R{G®mÙ×ëj”½Êf‡’Öq—›s_=D¥\^õ?ÕŠ¿Äo àÉ-Öø™cmZ¯Pï02´¬+OâŒÃ ¨pö?€uM“¼ÞmSˆµ:Å­9æe>ÎgÔ2öe©ÒQÆå%=øùrD Î<«Ô(̳ÉÀdE “FhÈ%U.@ª -ÒД¹Óz³¢ûåzµÌ‹— ÕA°™^¸çExœ÷»b_]ävÍÊA½GV‡ùœÏ5+êЀ¹{áwÚ4¼ß)€ÈP*Ð ‘¼«€á!÷0ˆá°#qß·åßFÕ/³,ŒP;, çû³^§ï>÷Èòæض2¡´öÀ‡ Oé§ïB4Œýê@5gÀ·ZT½Sÿ©„·‘endstream +xÚ¥ZëoÛFÿî¿Bߎ,Šû ¹,¸‰su¯Hz‰»¢íZ¤-^(RáÃŽú×ßÌÎ,EJt b.g‡³¯yüfVbÀ?±#?Jd²ˆí‡›ÝE°x„¾^æY9¦Õ˜ëûÛ‹õ;/?‰d´¸}É2~`ŒXÜf¿z±/ýåï·?®ßÅbÄ+?” +Ä#Ï›>~øpK\‰ÚøZÉlWïßÎIŠ|©„fžO×·w7ogD “Ò*†¼úùöúãr%Ã渄5Þ÷70‚¥$ôøtýæîãÍí/ôöæÃûO7o¯?^-cíÝÞÀŽsq};ìÔx7E p›¾\üú{°È`S¼|•˜pñ //’D.v:T~¨•r”òâÓÅ¿£^ûéìéˆv ’3Ç#åÜñ„‰)Ø|܇ÛmÑ.WJ(/-Ëú™ÛÍR/ßôM[<åDúÒçM‘sý€Oíu[îmóæ)o¨ý`¿®wô6°Ô}׿ôU™·çƒÕ‘¶)÷ÝçyECí‰í©¨û¥ðÚò@ä¬hWx +°+!ü$ ¥]Wz_æ™?ô?ÒØžwuCǹ«I$½ÕCÝìÒÎÎ î¹­Ÿ©ÑÕôì[þäêÍOí´‹&Ywù¦#¡îy4Þ!ÐœKG`1¸C¤¯Éè´”~l§¯WwŸÞ€º†¡Çv29Zû& ó¦ÙSÑÖÍħÝwô…[ÍJE q»ÍIì§?ÕèHûZ‹xƒ’éÌÌj õ~^¸Ö¿ŽÚè>X¿°Ê¨ÇãŸÉÅѺýwë5üõÓ¾ÝäMç×Í#´×ûþ~ͤµ[Ýú꧘màÙ$~h?«ÚÓékfr2ÿ×LRú‰1fÞ WƒÄWFë‹0™.0«Ïg +?HÎvøÄÆ®óQ'Çz. ‡ý«ŒXí+ ®Âjx X¼éÒ•‰¿^®D€»Û6uÍzœV{ļë‹lFÁÊ$j”¡!? õ˜Ð»{ó_lEl-j¢½¢#*zäÛ×m[€ÍÕÚP›¥WA4vÎ@-Xv:c6RÄ>žYÂfK 97gùa;æ¼z*ˆ½ÚåUGcü„AßÕ#OÌÙªïº"ßè!œmìÆá—ð_Ìk| ³?ôÕÝŽe¶ƒÞ¬ã‚J|Hí\EÔvŸoŠ‡ƒ“Ò1{Xm¼ß¤Ô4ÚDcá 98‡U73!ç9‰Åʱ¢ë=ùC”îqféT :Y¥»ùü$b/DÛ(.ô€èMZÑxÛ¼ÜS«Ø±/}âŵ‡¶ËwÔÙb´(º½Ýˆc_¦›aSH[¬$žJ{ +¶ëÃTâi¸À%· ä÷õWl²‹~Þ›-7‹²¤VYìŠîè¹m#Kwé£kו )l<“@]86µ[ç®h_XWU á‡ÚŸ‡g¢…÷§]?Ä0a@Í l}@‘!lRtƒwŒàÈÁV;%í„ô¾(í&[jMÏÁ"ÇÃdi¾s‚S“ò{_í›â©(óGÒŒÓ@ â=Aƒ™Q_ IÅ¡SßžXB5V_ &¡³'+ñ\'êÁ +ÐÖ|D÷Ÿe"hûÇǼåÓ¥¥VdûxŒ­ó…ŒÆ+sÈ qš“;®v0ïcOÀÒ[z‚®ŠpðgØ@ÜQJÞV,%„4´¨˜à4>!Ë˦ÈÉï™^š¼íxR›.gνMOÀ.Zz·5(”°eáÖZÀÐ¥ =†@±‰Y>ס&Uê(°îô¨ªM÷ÑʀʼÙúk–96§ØäølRøv|àà(Å1Nq„{{E*6äVîöYÚå®ôÍUÇ?)~“°+vîöþ«žÜƒI/sòí=Ë·÷f醮½QÛÖ}™¹[0úÎŽºd[ˆÄ³Z¡Ú|©XÆŽ`ùxk§XžÞÎUåaƒ=[°–(Îi´—Õü¾¥L +´ÝÆ€tŸ¶”)òí‰vi”òn~&Bše„O[þˆ.å8µ·­)erƒ_ [bH9f£»dëâI–ÅÀª©N÷ÂÐ3+¥ˆ…6ÖQÕ@†•.N²ý%Åï¯D·•Öмxû:NÖ²7«+>êÙüÔ˜Á‹ýÁåcÃé‚qr±É»¼ÛÖOƒi r×™`æÆçÇ9Zî¶&×1= ñáX#Wd-“lå˜Ai±}÷w7ÄòÉæ3a3L+OÛÂ&1!]ÀXVaÁzWe[óŽ×Ý0ÕÔ‰x˜L>¦SœN:çaìþR Ö*¼x2*Q¾”,|ådVûL^ÃØ"’­–Ð MÓ‚Õrì G[¦OÌ:Ü +`µŠAV£@ßò¯¤["@ó™R;NÀFR—‚/´{ϦÄqJ»r±fNñ7TÐ&7#C0Z,ksú ä´ëðl3ê¼gj;d‚¡3óPTC34s& »êKjøN W+z¼Fꢋ–Q¼þÞ +B¼T<±lR\¼^'°N§†ù|ÚÏä9ÇA¸3Ýî©,ÂíÜ…˜iÏ/äÃИ_¨€QðW3W¿Á€ÿòIŽRcvgäüïDì…änR¸…B賩»ŸœÏýÿÒ-'Œendstream endobj -1538 0 obj << +2061 0 obj << /Type /Page -/Contents 1539 0 R -/Resources 1537 0 R +/Contents 2062 0 R +/Resources 2060 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1486 0 R ->> endobj -1540 0 obj << -/D [1538 0 R /XYZ 56.6929 794.5015 null] ->> endobj -1541 0 obj << -/D [1538 0 R /XYZ 56.6929 133.9784 null] +/Parent 2071 0 R +/Annots [ 2067 0 R ] >> endobj -1542 0 obj << -/D [1538 0 R /XYZ 56.6929 122.0233 null] +2067 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [63.4454 707.8911 452.088 718.0529] +/Subtype/Link/A<> >> endobj -1537 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F39 899 0 R /F41 939 0 R >> -/ProcSet [ /PDF /Text ] +2063 0 obj << +/D [2061 0 R /XYZ 56.6929 794.5015 null] >> endobj -1545 0 obj << -/Length 3132 -/Filter /FlateDecode ->> -stream -xÚÍZÝsÛ6÷_¡·“g"ð wO©c7ê¤nÏQï2×öi‰ EªeÅýëo» (™Š“6½éd&Àb±Ÿ?@–£þÉQ‰@›p”˜PDŒF‹õE0ZÂØ×’çLü¤IÖW³‹¿ßèdd„‰U<šÝ÷x¥"HS9šå?Ž¯^¿ü~v}w9QQ0ŽÅå$ŠƒñWÓÛWD1ô¹úîöfúõw//“p<›~wKä»ë›ë»ëÛ«ëˉÔa¤€fÿýîöš&ÝLß\_þ<ûæâzÖ‰Ü?– 4ÊûëÅ?£N÷ÍE ´I£Ñ:ƨÑú"Œ´ˆB­=¥ºx{ñ¯ŽaoÔ-RSH!U¤G“X Çêü¶´EÛrSG"£èdW8u"Â(AÕk%¤Žt§z¥zª—¡©ÖÑ(‰ŒˆµÒN÷¯ß^Nb'ã×…-›üè+ ÇY ß$—õ}³]gmÙ0ÁÛ‡rQP'/ŠªÙ9uçôýv:û›¥æ÷ÛK™Ž›_ŠE‹ê%¡0Q„BKl('ÂËvUÔÚL¥ãi{9ÑJK‹_=ÞYd”¶!Š]eŽkÁû"âx6ovÌä!Û–ÍŽ9ÙG;qBÇÛ·ÅÚ’—äY›Í3[ØÔ·»ÅŠZÏi¶~tIgÛm„"ŽÒ3>ìc6Nc‘¨(vœ­œ+€†÷u±¥f­™HŽƒ÷mQ3i½©ÊEÙ‚Ý´NÇÛ ×µ«Œ'¡W•õ’:žˆ^n³Šz›lÛzæ~9ïzw'¨qÓ0çâCÛ¼ç:«‡œ‘äÆÄH#gJ#·ï¶Îªê‘Q8jµ ÍÃͺÊìŠ(&¤ãÝ¢ÝÑDÛ1àõ+^ÚÛy“-PNe4{1«¬¬iæÝ3SË{êÔM^X8t(Cg‘Ñk`ä«B ¼ð«œ*-‘ºèƉŸ‚@}p™f¯Š,G‹Ñ@´'p¨Ç‹*³–Û³Ù•4o¿*]4‡”[´hj[Zp‹–ú¤˜Šöây^¤¦`jÉæÕÉ9©ž‘_`Ì£pw¯¨bá/YžÈyZ7)P­õÔ‚uQäLCç:cK6dÒSçiYaÛr^ä¢/F«´/ ͺÈÈ:‰È…v$€öˆ‚òUNN0šñìrÍÓ«r]¶Dt™¾«fÏc íB…)hwì/2ž;g6ï‹ s)ë£ÙbU€Å)våÅ ]l7…›"Á1CâÍãi®– i×®šmÙBùx(h‹µH€`ü[SöŸàÙh-1ó¬²Ì -5‘êx ”úñ|Ç{ÏýƤ]oÃ{6åŠÍ Ç›S“—=r¨d9.&t¢NðË™§‘Ý › -cØÚrY;á€ê$1áG–Cžƒ0€4èr•áì€K6¢Ös%—ßíõ$P責³Ö¥ƒbå?«²L”AJ”ÚR˹6æ} ` ͆_x]þVø ÔŸƒ.Æg, -TøüFâ6Ý6ÔØuUÎËÖñáÄ(ÙRYU¶eÁ3]DÂwêÒr1耛bë€I½` bwËea™PôS«°<]ÈòäU³«øÌy˜ŽòEFa¶—ˆÂ¶Ü½§ož=2²c dÊrAõ Òhc[»âñ”×fôl_/MF« K…únÁa7`n -üf†=O‘NóÝ‚ÀAìD²Æy=6,LoÐô<{eÝ¥òÅ#‘òÝ–«7™rè(Žï‹¸†`”ZÀ•mOˆ96[¼çiŒêJŸ¹ÑØ®&Aû!«v…'WU³ï2s—Ãió“üœò³Š)l¹Òûr„£¢B$ ›pzÌ5ç¹ZSÂBÂ"ÛnKwœ˜a-~y¬YÏ1p™‹ì¸ uûÈÛ´¨X¿°fNy³Î¼ˆ$¬ÒøÌŸ¾›Tó˜¹+ý¨9êüºƒúìpáïü‘ÿ¤T¸ixcûØ: !;î½]Olñêö­À¦ìM^k!%ßRñ^)…‚kf y)%€ºv‡Ñ„\Š›m©¶©Ë6š€˜«cæ -.C€–s²“Q=@‡Ú. wzC¥ 't†1ÊcB£xÔ{‹Atµx_´¼ƒ“˨Ã(ŸæsNl›ESa,öy,×Îî‹žÒ‰1à«r¹rKc3†pÔ˜S‡å‡Ú¸§šmNÔ/™žÑ‡1k0Z&jÃ_“*8ADÝiMK8–ŒGæ–z¬„‡2?ÝôîæŠVÊ@‡/†r>fÏ’wûXÜ„,Ue[ê¸ätÉ?ð¥ ilÀwAãù¼œ\ØÙgÜ(@Øæñt]¿t[I¬#{¿)‹©!/ssE¾à€ÞãØ釔vÈ€tÝÆ´©¢ñºÁŠ¦`kò`izžÜ¿¦¦‹ I¶ÃÈ"UA¤ª¬]V€F*@d»åŠPÖ²Þù”Ëpª¥fo#0[¡7¯xÛ¥Œ‹<­v…Ö~,ãj°AwhRîÓÞM´Û[j¼°hOFùî9¸Ò]±1å‘ŒøxŽê" &f¹/ÛUo VYýÕÆáêtfç’YâÛ!‚Ž¿-œ$AK±ÔK­‡Ê“Gû½®P–Ôø -¥¥¦·Õifç«8×Øj—û¤N°î†“åÙ¼Üõèríà]ææP^1¶ÉÉ¡AJ ÇÉ<ïOVÒ%W‡IÝBdF­-N®ëbÝÔåÂÞ\ -Œûº«ÑóæÁGì³qìalte=ãÚë(ÈÐÆ÷M§÷>z Ù°Åw;¸î™‹Q'€\›-»ûÓ·`©¥“Ž” D"õ§½Üƈc}æËíà*/HO‰ŸþíW<ùm‚…¿ˆ¤ÿ®ö¡6þ†‘F‘©T †Æeúv*®_ý€>: Æß¾»œ$:Q€¿€üß×·×w/E7íôuÝH‘„4ÚÛû5>øçh(ŽEh9¬!¡B…‡MRCnûT%/ßu -9¯ÞN_Tò‹ê# -E¦Ï9L”ŠP‡ôKÀ±C¸Ÿ LV‰A©T©óŠ9lùö“P‰Ô¨ô9? c\@×ËN° ¨ úˆ -zÜÿÂ:Ðäî$~Î9tg ©…€¼¾k€¤ •œWKoÿpÈHpñTEϹ†R"ŠãGÊ?¡ÔÉ$‚jcÌçþH)A#QEÿ‘R&ZDIoáÏИ²µ - 4 a•=ð½’>ZîÇkµ°Ã?eáT~÷dVô¬é7Ëx2w?X©Þ­çôP¬ùM’ž^ù¿HwOs8„ï+ÈËòœ˜=ÁBîÖÓÃ?pµ®s‚ ¦ßŸáA/ Ç/yø@*­è|ƧøS–A¿ß®Žßå±4¶üÐÍÃBº¢£xûæäÜ^ð"ó§&|y—„ ^n3‰ƒ‰ú;®`ô¬Ù>õ¯Æ9&ìS5\Tºâ£#¼Ðj‰9µJ¤SwÕÍê‰þ?¦·bendstream -endobj -1544 0 obj << -/Type /Page -/Contents 1545 0 R -/Resources 1543 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 1552 0 R +706 0 obj << +/D [2061 0 R /XYZ 56.6929 690.9391 null] >> endobj -1546 0 obj << -/D [1544 0 R /XYZ 85.0394 794.5015 null] +2068 0 obj << +/D [2061 0 R /XYZ 56.6929 656.5891 null] >> endobj -494 0 obj << -/D [1544 0 R /XYZ 85.0394 513.3136 null] +710 0 obj << +/D [2061 0 R /XYZ 56.6929 517.028 null] >> endobj -1547 0 obj << -/D [1544 0 R /XYZ 85.0394 488.6113 null] +2069 0 obj << +/D [2061 0 R /XYZ 56.6929 489.6469 null] >> endobj -1548 0 obj << -/D [1544 0 R /XYZ 85.0394 303.0671 null] +714 0 obj << +/D [2061 0 R /XYZ 56.6929 373.2709 null] >> endobj -1549 0 obj << -/D [1544 0 R /XYZ 85.0394 291.112 null] +2070 0 obj << +/D [2061 0 R /XYZ 56.6929 344.9674 null] >> endobj -1550 0 obj << -/D [1544 0 R /XYZ 85.0394 122.9426 null] +718 0 obj << +/D [2061 0 R /XYZ 56.6929 184.6919 null] >> endobj -1551 0 obj << -/D [1544 0 R /XYZ 85.0394 110.9875 null] +1721 0 obj << +/D [2061 0 R /XYZ 56.6929 151.8489 null] >> endobj -1543 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F21 714 0 R /F41 939 0 R >> +2060 0 obj << +/Font << /F37 1018 0 R /F71 2066 0 R /F22 953 0 R /F39 1151 0 R /F11 1442 0 R /F41 1208 0 R /F21 930 0 R /F53 1303 0 R /F48 1228 0 R /F62 1352 0 R /F63 1355 0 R >> +/XObject << /Im2 1341 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1555 0 obj << -/Length 2939 +2074 0 obj << +/Length 846 /Filter /FlateDecode >> stream -xÚÍ]sã6î=¿Â÷ Ì¬Y~I¢î-ÝÍöÒÙÍö²éÌε}e%ÖT–|–¼Ùܯ?€eÙ‘³éµkò A@´šIøW³8I¦³YšYKÏŠõ™œÝÃØwgŠqæi>Æúööì›·&e"Kt2»½ÑrB:§f·ËŸ¢Dqdô¯×—çsËèíÕ;h)cc½þÇÅ·—740ê·W×o’Ñçõ‡ë·WßýxsqžÚèöêÃ5o.ß^Þ\^¿¾<ÿåöû³ËÛåñ¶”4Èï¿Ï~úEΖ°»ïϤ0™‹gБBe™ž­ÏllDl úìãÙ?‚£Q?uJLÚ(‘Æf67V8X~Œô9uÂ:£A¨q&£Í T­§„j4²Ø õvUu$òK¾ÞÔ%uºUûÀðþ¡¥F¾\nÏ•‹Ê®+yì®Ý¢¼¾ykÕh!•j¡ ¬$ýŸ>‰w¯?Š÷W·âòÍ„À˜3"q‰fôWÌN^¬¨ÕÞñúôYVwÈÅ]IÌ4=‹:ï:ÁÔÕL)‘űFò0 §2•‰…R2ÔIƒîH)£7UW캮j›Ã%ßbí(‹v»ì&x—@ÞŠÌ*ë‰^€`L¢£eÙÛjQ.±k¢|Ñ~.ac&þÛu^5ïÊíçrËsº¾¥-ÑXÕ€t×yï™ÂñœñòanU2ùEŸO»ó¢¤Q‚D}Ùy> x<ûaUöˆ»»*Ú¦žñÐòçŸM¾í«bWç[îW%.ˆM/>ølÁO]´; 2Cå–ºD3aáA~÷Ô‰q;ÂÍ{8îM_.Q§SÔt¼JÝ> ‘Ml¤Ù­¥÷,.Bn;8湑ItåKÆ÷ óž¼3Äþp¸ØñK!z‡æC¾Â²sì ¡âéørI.Ú‚´Û5»™ƒõx&|¸_»ç/}ï–í%?匎ÝàÃ7m³¬š{ä7Ó¼ g#:âõÀ`m{êæ÷t:´ÜšqîrjÙh‘¿ò¼–¿dS~a51rï Lóþ­’у -á:§ŽÐ—íäQzw Nm•Æ%uJüH |ѵõ®/©·.óöL8?k8 胠áȯÁpÛÔŒ„X}õG, ·¥¦¿ßR#'ƒÜðúþXÍkj“llZ³±ÅvoŒÐfï -Ö lzK‰-ÛCŒ§[¬¼OôЖ¾Áæ½íÅá°±µË’5’/gž®zŠ]L6Š] „´Ò¦!ðZïº~"ÂðFÊ,a$:C\&'9€N@Œ'îH¥»®-ª¼÷·Éað8và{LJ0¼ë/8ÛÒ÷þð‚fÒ ã¯/Þ_^ ¤g¼î|„ˆn£¨Ê'÷ƒó ¾õ+$dªÉÞT¡I熖—ÂE~G@¯4¬|Ðõ‹ÂwÑú[2IÀXâžnWk†}½ ->AæÅÉFObY!ýrK>}‹Ž'dü²Ž‡=D¥¨<ø­î›v¯:tþªk;÷NnöYpD0å)‘ $yŒç`p½ØÞŒ®IÏEóÂj~ÿÙ„ÖlÓVM?ZgÂ:œË¬Ê‘úÎ!ƒ®qô÷ã0q"I]:³.*N²å€:qªÒÃð›ømê$4O-n†‡¤æaOs›ÆBKX2䌩 Êغ™…3uÎxi²œDѮѽˆÚ®®1n•tPÐp‘’çóT²«SŽÄ ·p±ÊfcV~ßîPŽ*Å”øOXy£Mâi P¶3›$ÂAœæ%v,ž,ˆÇxñèʇVNþâòlJgE>±.u'Ä£Çâ¼ì6¢ÝÞ?#œÑ²aá˜Lȹ¿bmV‹LóEõÔ~ üß›œ‹àÆ4Ϋ”ÀuZD£ÅÿÂ"Ò©0N}EBF,M ™\zψHŸ-®þHíë|ÿK ÎIcPÈô°àøL-Ñd uiÕóµD•ÈRE÷Â{ - ´%„Z« ÜðRCêÒ¥}\EƒV2±!:=2ƒ‰HÕ¢ ‘*‡<ÇT3B2¢©¿BTI#œv!HÆÕG'¸‹†78$Ë©¾âT…#.L}…K”>ŒH*®06eÅéȨìØc -bÙ¢(} -íkŸ{¹Æò„ØУ²±ØöþsJj‚Ð9Žcæ0rgu¢¸š(¬ÞÚ§ÅUÃÅÕeßSVÔnoß½ ŒzKqZõÕºœ÷í¼¦, $£4„r W†î—õ’:”PP]£ç‹ªç!ïIâ Ç“NMJŽ#=Ø5UßWN r- 7ïü‘„€~X2Áœyo+Ÿ‰"¬. -IG%Ûš‹¾K™ˆ ™/´Š¼ \KŒÞÖ±˜R¥F¨;3¥Uû@ºõJS¨NIty©E9Zh`wí>é1‘!–žWí®p¦‹eÕ9[&FÉp¨øjP×íàýŠÖàQ¬)v‡ö@ÛC]¸ÁŠÿnžj¶*åù¤°9x4øOÛ”!Ç”ŒýøpàДÌf:•Âe2}‰»6™©LÍos×Ó³F1¾7¦åo‰‚ÃŒ£+(ì ü‘2öä`þ\»:Ñ"_æOïã¸0-x‘pf6ªs_‚ˆldg†Ålƒ5šª¹¶€>PhÊûœ‹11©k€W_AHá9ÊÕ&q •U-‰ÉŠ̉<Ž‡ò4÷¥9°ËàÙâÁ– Ù´sð°«ùðö0tñןÞ|xquJñ¨,‡¯_*GÜ®IÍÛ˜2ûÁÖù—j½cltsû5¾öâ’cqí †>`ŒÛn_@1+zÐ8qR8s•ÁIÊðû´ õØHçðµ(?÷4ú„d˜qJa .¥ì+*«,ßó>ÂbI’êopÌèÜH¢þ…¥§/•Ô§o7ñå}ªÔ ç-r4Œ²;Èb`¤:ÅÒRÞu&4˜]fy—ïêþÈã úPîïýð‚uzOÛ;º¡”RêÊþ´NŒåýûŽðX+ì©X°™yV+T&Eš)uðjä£nS]Ò»²ŽiPÇ|B#Ô§c/Løð°ßÑ—œ™Ž9 öÞ!B§jŽ0on|@8< ,ÄñÁKÓIßF·8l#89¹wrrìä$ï…FyTôªžÓ€‘lÿ( xyâógܤ*ƒ¸;ÕRËj¢^˜ø(鄱§|Ïð#ŠTè4!-»ðøŒéµãw‘æ!p‰ÏOlâ©% Ž0DóÕ(´Þµ»ûÕ²¢£ÆY ^ªü²©«¢òÁÂGUUO)!g‚Cœò¼šÈŽî+µ2r*-‚œÓ¹4dâÔ¯f 'ÀŸºLüÆEξZ:xé/jö¿*²˜½;=}tÃ3Sȸ“O8WRh,’ÎÇ›!Åb +?—‚P.óx)s"(qÝG4ÞÃÞûˆLz¥×¨·UôË;¾Œ%‘EVÄÕ·+_%¡eÉâªùœÜÿz÷X­Ÿi&h²$‹T4y»yX¡Eâ²]ß|ÚTŸP»ÿýa»Y­ŸîË<©6 -Ò¼¤%œçÁÃêÓÃÝo›{Ä|\!týÊÛ×êC´®ž ¹.–Qî«ø3úü•Æ Ôü!¢„ËRÄ'P(aRfqå‚‘s~±tÑ6úãÙáÕî|ôy‚—D”Ùò{Yv‹=!IÁ3>³÷ÎL‹”Ó"qmµ—É´`e¢•5ƒ}–Œ&' ëæ=3ì»ó5¶6}¯‡æâI9”Žc£œ¶¨ì‚÷z:Îì'5ÚZuè¨HÔ2˜œŽv!F¯Õ`=ÕPoÊ‘Bdsòæ´£È7@Õ®5ƒ7°Ä¶ûA¹#&gô… +Zm7ïaeaÕœ©ßl}¥Y‘{|$ Ž]QÇdAòd:Ç…¬Í)Åêúšè"#’É2€ÍxÉ+KìÁ»ƒw­ ÁÍàI˜‚üÐö]ŸQ,Q‹”%=ÓÉ`ÜLL£$¼Èò³yÄ9UM8°3 `òýöë ÝÉLßQõ…Ò짶Àg4¹ëœž€Æö‡†ücÉD{Ž‚Ó ²²\ZpêGšÒÑtm}¾Å– bÉ‹×lûZaâ­nÖÍYC\Àг%‘¦ßŸÞš~†Â¤¶+.’ú`Œ fgü*€^=¢z‰BsTZÛàÆÊ¿3B9…R; › Úã®1½B+¸ÂÉFwzïgcã´]ðé­‰Nx‰™r9‡ÕêQMè +´¿Ì  ^’êÐZDžÔK—òK—Àî̘všør¥Ú âµÃ>èSëï_‡ÇBµ>ö±> ¤B¨à»ÄAó¯ 0p9o8w0ØΓޅ1E¨/¿CÉê釞ìeÎtø¹Ç#þ +¢F/%b^°ä¿^j.ˆ^o¼«ðyÿïWüåû–æ,³Û4§9á\²KRž/ÆÄëÔŸßûçþ7rà_endstream endobj -1554 0 obj << +2073 0 obj << /Type /Page -/Contents 1555 0 R -/Resources 1553 0 R +/Contents 2074 0 R +/Resources 2072 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1552 0 R ->> endobj -1556 0 obj << -/D [1554 0 R /XYZ 56.6929 794.5015 null] +/Parent 2071 0 R >> endobj -498 0 obj << -/D [1554 0 R /XYZ 56.6929 723.7047 null] ->> endobj -1557 0 obj << -/D [1554 0 R /XYZ 56.6929 699.3651 null] ->> endobj -1558 0 obj << -/D [1554 0 R /XYZ 56.6929 499.5106 null] ->> endobj -1559 0 obj << -/D [1554 0 R /XYZ 56.6929 487.5554 null] ->> endobj -502 0 obj << -/D [1554 0 R /XYZ 56.6929 352.0214 null] +2075 0 obj << +/D [2073 0 R /XYZ 85.0394 794.5015 null] >> endobj -1560 0 obj << -/D [1554 0 R /XYZ 56.6929 324.7169 null] +2072 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1561 0 obj << -/D [1554 0 R /XYZ 56.6929 283.2444 null] +2078 0 obj << +/Length 69 +/Filter /FlateDecode +>> +stream +xÚ3T0BCS3=3K#KsK=SCS…ä\.…t œ;—!T‰©±ž©‰±1ƒEV.­knj©g`fA‚!ÂVŒendstream +endobj +2077 0 obj << +/Type /Page +/Contents 2078 0 R +/Resources 2076 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 2071 0 R >> endobj -1562 0 obj << -/D [1554 0 R /XYZ 56.6929 271.2892 null] +2079 0 obj << +/D [2077 0 R /XYZ 56.6929 794.5015 null] >> endobj -1553 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F41 939 0 R /F21 714 0 R /F39 899 0 R >> -/ProcSet [ /PDF /Text ] +2076 0 obj << +/ProcSet [ /PDF ] >> endobj -1565 0 obj << -/Length 2487 +2082 0 obj << +/Length 1965 /Filter /FlateDecode >> stream -xÚÅYÝoã6Ï_¡‡{Šå‡(REqhšuö\l>.ë6‡n÷A±•X€,y-9Ùô¯¿!‡”%[Ùlo X1Cr83œßÐ, ðZ*Ò8PiL$e2X¬OhðsoO˜[ùEQÕÏó“ïÏ… -R’&< æ÷=^šP­Y0_~Ïþuz=ŸÞL".i˜I$þ<»|ƒ”?gW—ç³·¿ÞœNTÎgW—H¾™žOo¦—gÓIÄD,90ŽÅïW—S\t>{7|œÿr2w"÷ÕbTy?|øHƒ%h÷Ë %"Õ2x‚?(aiʃõI,‘±žRž¼?ùwÇ°7k·Ž™I -M¤æjÄNœŒ‘TJ>0”LI"¸°†2ªÅ '¥4œUù¶ÉQ¿‹l³)ªü£¨ð;»~ŒÒÀš÷®€I³Øò¼É‘Ò°ÊÖf¤Óp;a:Ì›ºÜµE]áìTÒv•µ¸¢h¾›D1—a»Íª¦ÌÜ:˜¹·›ë5îš]#5[.Ó'Ú'Ì¡Àš!µhÜòŪіH½{Fê:‡³Tß;6«µéPËΚ eQEö|p’m7Ùˆ]àöX -Ë©Ý°¬×YaõQaV)t^Ïop€Š,jû]6àoŠÓpZµÛ"opnN¬xŽp ‚œƒlqb-ó!§2Ïš6jëh]7­QÀ¸ÊìtÅpjŠ‡ªøƒR¾È*¸+®yèÍíépm­êÆM/³6C¢ñ¬ÜŸ‚2(wÁa¬ý€ââs¯ziïZ¬¢c -j<ʤ{ëŒ1¤Šp½+ÛbSº ¨ "‰Å=~Q*ØÃ&,ôç­2·r]wÎf×£W€ ~¥ÑǸ–HÂóz‹´üs¶Iœ`žc¹r©ùƒ[Mõú#’0æ8,HŒAZ–*’X•&úkJ’HQT”¤ÿm—¤§Ê‹à> -¼ÜÐﲊ:¥¢DH¢c–t/f½ìË8#B$"%ÈhÅ\ÝÌÞΠÒK&h8 ˆ.÷m(©&RòV¹YË•FØßPÐ"k=Õ¶8r¤žMÜŽ¿ÛÜ4h/xv{Ë¢iM{`ƵSþ¡¨Ž²^œ*è ÀsúáômjrL“ô¯d½/ç~ÐCžÓT¿ÒÆç &Ê®/”®/¼mgüŽ(Æô¿EéFoŠm¾Ë¢Ž´† -zXÆ»°¬ª¡½SoqìX‚<´¶7 -Ô' ¨´¹ò¢-.y÷NÂ<,‚ÑS%…¹rÀ-ˆ3eέ¬ñ›UÏ8ØUŸÆÙ·>\ÃG^&>ƒŽ¸Ó‡-sÊløný»¢Wez†Rºg“X÷„bÈ ~íCŠL°]±(Ú±’ÃÜA,Æd;FšDðoÊŠ *0—Ê (¾=KxŽQŸåH–ħPæºe¯f‰ø K¼¨)«ªD™Ÿ ƳˆtYD²ˆÜghŸŸä jŒÜŸ¢2D1ÕDq¦†/€¾6ôœ:'ïU˜}Ô@%Úä‹ž»ïaVW_†j\‘¼.á0áôÃnÝa½â~¼¬ÙÌêpg*ÉɈsB½…¦6Ö&3’H¥‡o[æéæðÙæ°&ßÞÞÚGmž]ž^˜ßº4Œ/Ng—ÑûéÍoÓ›ñD穹RYÙé?–™e…ãÉô?§×ï¦äìê‚ ÐN”d(Épá ?ºAm0¿”üDFƒWß¿ö¹~Se…xÿ!¥W1hÓ eÖìèñÌÿrw,úæí endstream +xÚ¥X[ë¶~?¿ÂoѱV”D]Ò¢i³§I¶EÒ g¢íé-imõH¢#Rv7¿¾3œ¡,ÛJS »&çÎá7äˆbÁ¿Ø2Œ’2ÝäeÊHÈMÕ¿‹6{à}óN°L*“P¦I“îV&E(‹8ßl—F¾zy÷øu,6qfY,7/¯³¯,/Â2IËÍKýàé Ž¶¶±Œ‚âáŸ/"µ4Ì‹\ Z.d˜—Qá^„Á¨§]טƒÖ¶ö³šHÃ$ÍbVË’0Ï"òS„âa+¢( +žtßëþ0j0Ó›‹–Rz Ÿ‹Â˜M<ÛϤ ´¥ÁYŸ šßÐì Ï4¨{{¦ŸQ隣¡™ž¼öA]™=zØÉ‘Å›2,³8ãÀ =e*RJÈ,%©v±42º›l‹‹Ä™Õ3õ„Ér“va¨®SI5Ô4¨ôÀQ.¸­1ScüøÚ¶UŸ8Šãø Š 95ƒÝSûF™‰8¬¹{Ã¥ábæœÃbLc݆nã<¦#þfA§÷û™ˆquh9»æU“ÕÄ‚å2¢„°ÞNÎêS[³˜"ºÑ`ÅdýJôC;Xvçòƒ´v¿=ç96X´Û0Ø5× n“ijÚ_LÝn+à¤ÓÃÂ…ïÒS +i ·¥Ý3éÀ–yíˆùðŠ&Â8K<æcø¡›‚hïCû™<»úÐŒ­êhüýÔï Æס\@•‰ó÷w= vVXƃÓÆ-ÈÊ@͉ο&DüL|Œãœ¤!š7¢±Þð+Ôʲb@4@™ þ@ŒN³¬CX;6úØÍ2\ô<Ò스‡yÑ· g°È”}sɘ†€G€"6ù93À͵úFtür²e€h$Òßàï»ïÞ¿ÿñÇ©*e§^[ú¤ïÜvzW¿ ×}kì…{½^¬0‘p‘ÒyE?°)e™í0‹Óàu² |d ‡Æ‹o<ÐĪôHÒÕßO'2ŸëaÍžÑ_5±¹Á’FŠ ÈœŒðiÍZ W +ŠØmT¹,(¾ÊÞñ‰}q´€¨\Â&|&d¾vKÈTÝVŒÐhÆKI›S?s@Õ+6¸k0mHšŽµÇrRϯÄ'¨›CZÙN,HÉÀk™ôjY`:ujˆN^®5ôÛé³'A´é°²\¤A®xYöÊ`3§Áçs³‰uÿŒ`°¡¬mú£]­7>)34n-_³•>¾ñ±ûzs„ašÃÙ`M t9hðÃ|K>xÌ«,«DM¿Š~|ª`x‘â\,Íq.¼éÓlŽò{½$çF.ÝÁÌJö¢´VËlo>ͱýãÓh®o›ÿ+Ÿtc‹lѸÄ"'ÛCv0 +ýf3GÕ51b‘æi‘diNŒ‘Œâ±ˆ±0·"ð0àâÄßZÕ7’\sÂw"ó‡&0ÍåþF—?$cRÍZº”í(õåŠ:éH^04g¢°û(½À ÙWáÓ7˜¿S,[>°úŒ¹…;î3`ô¦'bÕÀ¤Ö^ ïöEy˜]¹œ­Þv‹íçÞa¯Úák@n@þzh|ÇütÓOÓ0J¿mºã—¿ÞeÚâš(°ÁiÇEðá êÍâÀz҃ѣm§žæˆ§çOŒ$ ¸aѯt ÇtéùL]%ŒFèŠâ¹Bˆ%Ç#¥ e/v­Î©­XKí)™®×âX°Åu’_=ÿ~-ÃÔ¶GYðþÛ§päÏH—@ +­è×ØÚ:‰óÎÐÃBYn?z·XdÌqâd¾©Üä¤ÚNí:ørðï»QÕaáƒL·CÕMucVìâªV.Wª4 Û8Hü»Uoy)”@»Zìo+B)ˆ×­©ôD9ƒ©;B.ÊõTyåvÂ)Î6™îZds§¡ÁÓÏMí­µ°r=¶öä&vÓž®é^/yr€¡¶¯ÓP;«y Â1{9B€FãŸà{ËוÂM>p\×-ž‘7>å èWˆÌ¨WKÐÆ 5m"û¿À¥–€ã6WUŸÔž9ZØוå,¶VHbžþ‹'¯´=Í\¦pÀŸ'8TÃ[WyÌ#‰6Éyè5µÒÇî:4 ßál 3,•ßbÏ[œ+ªë/WF".ƒ›ËÊ?@”€/jŒu“1Ô¢+l',{_¼2ãâ•sä®ÏñÛªÊ ¿&–Bú–åç !G˜ +¥Ìrcø-Š¼ûãËü +“¤%œ¡i±Iæ² —â~ÚøÑŸ/¯6³Âv¡ámÒ¥ß;»è½‡CÀê/aïoãã<,EQ^Çsór4 ÝÅpµö;[ÃïVÎy7G)JΑOü©5­¿|hW°hpk·IQ„"é5¶ÏÍŽûª‡]Ù)C™‹_Ú‘Âõ%KÄQXDñ¯oʬ±]ªÜïʽe×SX{üâññ|>‡¼+¾,}w¸ÉÀdñ:Æ›š¥îãºÊǽµÿ¶Uø]5èTíŠË°ç§ð6hÿ˜ÈŸ%×"ö"Û‹ ½H.ƒH"h<H# a(Bä·îæÎ{ÿúhendstream endobj -1564 0 obj << +2081 0 obj << /Type /Page -/Contents 1565 0 R -/Resources 1563 0 R +/Contents 2082 0 R +/Resources 2080 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1552 0 R +/Parent 2071 0 R +/Annots [ 2089 0 R 2090 0 R ] >> endobj -1566 0 obj << -/D [1564 0 R /XYZ 85.0394 794.5015 null] +2089 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [348.3486 128.9523 463.9152 141.0119] +/Subtype/Link/A<> >> endobj -506 0 obj << -/D [1564 0 R /XYZ 85.0394 769.5949 null] +2090 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [147.3629 116.9971 364.5484 129.0567] +/Subtype/Link/A<> >> endobj -1567 0 obj << -/D [1564 0 R /XYZ 85.0394 749.4437 null] +2083 0 obj << +/D [2081 0 R /XYZ 85.0394 794.5015 null] >> endobj -1568 0 obj << -/D [1564 0 R /XYZ 85.0394 660.1505 null] +722 0 obj << +/D [2081 0 R /XYZ 85.0394 769.5949 null] >> endobj -1569 0 obj << -/D [1564 0 R /XYZ 85.0394 648.1953 null] +2084 0 obj << +/D [2081 0 R /XYZ 85.0394 576.7004 null] >> endobj -510 0 obj << -/D [1564 0 R /XYZ 85.0394 449.4639 null] +726 0 obj << +/D [2081 0 R /XYZ 85.0394 576.7004 null] >> endobj -1570 0 obj << -/D [1564 0 R /XYZ 85.0394 424.0768 null] +2085 0 obj << +/D [2081 0 R /XYZ 85.0394 548.3785 null] >> endobj -514 0 obj << -/D [1564 0 R /XYZ 85.0394 352.0618 null] +730 0 obj << +/D [2081 0 R /XYZ 85.0394 548.3785 null] >> endobj -1571 0 obj << -/D [1564 0 R /XYZ 85.0394 323.4047 null] +2086 0 obj << +/D [2081 0 R /XYZ 85.0394 518.5228 null] >> endobj -518 0 obj << -/D [1564 0 R /XYZ 85.0394 272.2519 null] +734 0 obj << +/D [2081 0 R /XYZ 85.0394 460.6968 null] >> endobj -1572 0 obj << -/D [1564 0 R /XYZ 85.0394 246.3845 null] +2087 0 obj << +/D [2081 0 R /XYZ 85.0394 425.0333 null] >> endobj -1563 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F39 899 0 R /F41 939 0 R /F62 1062 0 R /F63 1065 0 R /F11 1397 0 R /F53 1029 0 R >> -/XObject << /Im2 1051 0 R >> +738 0 obj << +/D [2081 0 R /XYZ 85.0394 260.2468 null] +>> endobj +2088 0 obj << +/D [2081 0 R /XYZ 85.0394 224.698 null] +>> endobj +2080 0 obj << +/Font << /F21 930 0 R /F22 953 0 R /F11 1442 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1575 0 obj << -/Length 2175 +2093 0 obj << +/Length 69 /Filter /FlateDecode >> stream -xÚµMsÛ¸îž_áCöLÍò[âÞ²‰Û—ÔéK½;;ÛíA±éF3¶åZr³ý÷ H[ªÕ®û:Ì„‚ˆ/ÒbÀáO ŒeÖI7Èœf† 3˜¯/øà̽º‘fœˆÆmª_g/^ªlà˜³Òf˯œñ<ƒÙâÝÐ2ÅFÀÿº›NFciøðåÍ-@Bi#‡Wÿ¹|3›ÜÓ„¤¿ÞL¯ ãh¸º›¾¼yõûýå(ÓÃÙÍÝ”Ð÷“—“ûÉôj2z?ûíb2;ˆÜVKp…ò~¼x÷ž Ýoœ)—›Á|p&œ“ƒõ…6Š­T¬.Þ^ü÷À°5–öšIp&••=v’¢ÏNÆ1«¤:ØÉ0fáœgž4|v3½ºýý:îºÜùyS~ò¨/p•-®|0–š9-tà÷öó¦)þù%¶·W†a ,@ºÃШ¶œ†q«D$\–+¿)Ö}[0Š€}‰ð]+YÚ²Ú•ÊM,·&‘½'ûØ9&¤É"ݼZ¯ý¦éá§ËõA÷HFR‚q-³ÁXdÌ)™‡É{_,`?•‹M²áv7ù°šûº¦™& -s.WѺmZ!x‰ÎÏ2™Èó¤Bw(—´uÙÐ÷“2ÄmËÍ|µ_ø(^¹iª~¹ÂtѤÉ22ßV°Lq;¼Yö8† -âüñߎ‰ƒ•‹d‰}½õó%ƒ¡5×,7 -˜3†òA“<û ,ÀŒ-“5õT6=²¢¥¹±¢ßÝß¼º™öù@®w «}Clƒíp|,"æS±ÚûçW å}"ŠÀ|¿£9¸[G¦ N?Óß+SR~:32Ê2È$<ïú(%§“ 0¹«N^ ]GÈ0³¨ÖE"î ¢ùäw‘*XäÈ''ƒÔÄŸ ûXÄý¶»²Ú.íÉ7V°,ëÏ7ݘ€|£uò«j3÷¶àQ²’s×£ÚŽôXDc>x¿!ˆô,È´}5Âj…iXŸU$„dÎÝ_$ ;Ť´îë¼h^L+º¬Ž5×@ªÐÜ´j‰úf%S™°«L‹´}ÎXÈP蜜T’Œ{7[1œÁ9<)žÀ’g M.¡Rð w|`ÚtNQ ªM/nÖrp]Bƒ–N‰ñ¸Í9èdÛ~íPeËḥç—W£±ÎÜŠ¹(ç­|SÓ…2Ažh0B ½U˜!…"êÇj¿Zåƒ'ÜÎ×Mµó[,ÈÀa¢ˆ™ÐvÊš’ÌšcÄßLÇ1€ÓÄøpT0ßrüŽÂJcýL\ im†# 9e×6Db®À±ÆÊqÕ†hž=¦-B’ 8š>R&@rÊY²ÀŪ®âþ1è’p˜Kf‚rb•‰ýšÊ ök -Z´8_òò)AÕ’Fo×ÎBBäœÄ+|Bmê†ÎmïÄ»ˆä ?R½Ë‚LÏ»&oJ4ÌòárW­ -΄:Ós‹H„¼|Ñìw~{ÆÉç`D=NÒˆ¶ŽÉÜåƒv þXìc–1ðãc·ùc™©›Nx+òz;S# Ëx®[©>éLg³ÛŸ×•"óÓ¾OBBÐ.5t ¿,ö«fÜ4«žmΤÖâܦô;»HXE n -ý6´.u Déc62ÂkŸ¾œVߢõô77”‡Ab¼€zÿPû{*ë.¶yÆEMÈÐ.h¿YxL›ÐIá~³ÛbNƒ‡ÿ[«²5ƒ‡~ЬI™NhÅPl>D_àc)t¦seuF˜Û,jÖsÒ¼k³ãQw¬Þ=êÔ#µU¾1ÖxŠh°i:îÙ*“ãÄo Ž&·׶ѱwÎ×EÒ~¸ª–©µ˜üÓøM éäÈ;¢Õ>{5™Nàf -&ýÄ{Zg—Sg¶Ð»s•ê{ëlVu_¯%YÎå¹ÁÑaé¿óº¶*ê>‰¤cp!rí0ûò> -"çIææó6*¸ëUPÃyCüÿ”ðÿâ àFå  sɯ³¯X7?I–«Ú.M¸šji‡óØÀ6žð µß•>. - -#QÖÕ>¡}§y¹Ó½oVŸ ZÀõH–Á÷á{I·±5±ñÅü1® 6Á‡¸´ØÐXBàPùñ™¦/öÇIëN‘þWSi&¬HG0ÇÍ”µÔ$Ø,Ú 1h3} Òg‚?ø ÊiCÔ"n‚5A¡'©;á$!?îK:ûd’·Û -/Pãþ€R·Ã«Ž½TR¤£ý¯ü‡•C’«ç»òáINd1 ]a0­è…f ÿ¼¼¾¾g—÷oИ—‰_Ú€õ¼Yð/Ü6ÞZÇr"´ -ÐMHÖâ{ÉúÚ¬x‚˜ÿpËÈ€†é[ßNîÿ˜Ü?c“?/_¿¹œÇJÈŒÀg4\M/_ÇÉgŒ÷gضF©và)–ê'=|ÃTœÐ}&èÑJ|E+ñ½Œä7Í#¾Å¨e¢;óøä™LåyLIeÆúÙ¹*Dʯì×nÂsh\wP’ 7™;§cVÐ}g<ûâÁ÷ÿ[ÕzH˜çßÒŠ/Zö¤ÓXh(UŽ(N{v0Ë3ÐœCýtªUþO##Ót<¾'…а9¥T0¥âXmQiDóTíèºÆìWȺ)vÍnzÛ¸jGãÿ:©-¾9Z…oŽÄê1n‚­Ü®nú|wÁæÓQôˆIþ9&= P\‡ùm—ŒøåF-¯±ÃËÕŠÔÕ:2rŒ*¸ôœ¦ëõ¾Ž<|ŸCo«ºÄ^ïôfÎ脃³iàù„–áƈƒÒ”qºï—~è|øwãÅ-ó\¶Ÿ¡ZÍ[–3hÿƒÜÈ í’Ë“·ôI¤j‰þ? /Wendstream +xÚ3T0BCS3=3K#KsK=SCS…ä\.…t œ;—!T‰©±ž©‰±1ƒEV.­knj©g`fA‚!ÂVŒendstream endobj -1574 0 obj << +2092 0 obj << /Type /Page -/Contents 1575 0 R -/Resources 1573 0 R +/Contents 2093 0 R +/Resources 2091 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1552 0 R +/Parent 2071 0 R >> endobj -1576 0 obj << -/D [1574 0 R /XYZ 56.6929 794.5015 null] +2094 0 obj << +/D [2092 0 R /XYZ 56.6929 794.5015 null] >> endobj -522 0 obj << -/D [1574 0 R /XYZ 56.6929 769.5949 null] +2091 0 obj << +/ProcSet [ /PDF ] >> endobj -1577 0 obj << -/D [1574 0 R /XYZ 56.6929 751.488 null] +2097 0 obj << +/Length 2544 +/Filter /FlateDecode +>> +stream +xÚuY[sÛ¸~ï¯È[•™µ««e·Äé%í&“‰Ó³3çô<ÐmóDUQŠëýõ  ¤dµÓé˜Äå¨>ü .ÖÉÒ²ø"ÍâeâÉE^½ó/°öù]À4¼È–Ù*\ñ™!\ÎYß²;êþp™(ãí`ð# c8#X{?|?Ì•(‘Bk»ËÀ“Uת>Åj3¿Ñ•P5ïEÅÔíÙt²b‘<ïÛ¨o´ö­ù “êÞêÕô»Rå¢SºŽ†;â­È®dÉÇO4Bìe¡ÿØR±—k:grXŽ¼Zžˆbœ¶@< CÄBš¼U;«3ЭÎ@#%B Xd½‰ÄžAJ´¼\D¡ï}²ªèjØ%fm4‰%µú'VÁW7 É—Yè]Õ²ƒÈÉbðWâÛËड«‚© ÜÚ’pkú-Äù½ÁIâÝÖla hy'së7 –¦³7Ç Ú å¯F¶ +#œ‚Ľ;¬/²Ô »)–X+Ïܦð~EAŠC1øžÉÒŒ­‘áWÐO+U”gš€B`hC»  ŸUM”Ä×<éö™¹ëE>¨ñà–0[y÷6`™½ÞIrÔÌDÛ©U]'­N+örR¨š£  “Ωu)Qº£èˆVéBaž9^ +FXЭ‚dƒ\#åS¯ÐyOpBŒšÈª†¨n4\Tòi¹^¿È=õvÂÀ3v·Ù”¹<ƒZˆLPO–`š8I9³€øQ &ŽÀ6 CÆg”ñf±Ñu.{4ÐÈ,0ø$rUªNIƒb¼Ã°:Ý>±‹átûÕé°Ûª)å$ +£ÄÁ¶‘¹µ/!. N…Ùzê°Wâ.pl „ÓÁº°â…!R߸“OG•y—²œ ™®Õ+Å cøˆP¾·ëU é6É–+?£ÂôD˜•ZŒnMG“Ñu Æ »Æ51ŒŒl_àêiìYpɼÔ$LK­¹¿JH\ç d`L'±ž¤žÛáoAØAv¦ßÑcÐ&kïNçÏ¢‘ fC4„ˆ¹@tÙJ\ô õäã†Ovº1‹Ð'B%ò£ª¥!¾Rƒ‹é"kÏfWâ‚ßk×6ª;óî{bØêxZ>s#JÚÕJ¼g]ok˜WƒZ «Åœö²Î­&q2¦S]ß±•¿o7‹Ûí-a,òPÔÃ`ûxKl„àxàYÄzÏq?`–Ýzª6Åƃ`»ÅýíZÇý QÇ0˜º£À뜉1£„Sèײ}–¥<ÓÌ•šQÑÇ‘†Èö‰m ™)€Ð8HÞÚF’‡(ÉњGboï¬ïøX1ç‡a_ßÀmý€ü ¿‡V=A¤B÷C#¬Ù`_ +¼ +–a“p¯Gkଯ ëÃá5³îǪÿêÄ- ÜȽ¬Í|µ/^ÄwxÒH‚ +D¤<ÐÎÿ—yÇ‘sU@E…ÎqÌ*Š‘×8P”Ì Ë¿/@f4áRÊ}^º¦ÖÒRº#›Úv°/×ˈÖFtÅŒ‚þ[åSr Òéú@Øèªé)ŽL½"Ÿûæ¢@ù<ñpJµÙ>~æÜpËLtGY­Fgá±[A —(-̃ÅÙ¶Ä ˜Þ°)Ëx™AaíF¼¨‚ÕáPâ¥V)§8·º>@ÌÔ4ûôÜÄP‰BÍÞ(dv P&máªëæßFD3zœ`·“¢ÂEàÛ=ÃBj{ †rh®ÔÐq½ ‘®³«zß&Å(uùJ¸8…B×ò5ø?Š²9Òp#ªf'Ë’•ú&_æ ùM_—¢±J6iðU£ª#E}ïãÏ^5X*‰eÃÏÖJ©>KF\¢P¯SSŒo&Œ>Ï! ·LÝ–è@±¸ˆ¤ægH@Ä9³ZI( Ž:ž()6Sq +UŸiQc¢õFêƆEiX*×5ÔÏ]OÕ-ãÖXXE p³Í‚¥¢o¹‡šMÔºõÁùˆ4òs®øbðج–×y­P°M”`à· FAˆ½Ž¼m¥uGKÑ–‹;ÕAŸ^–,y§ž%­Þõ½1,ôUUD¼.µæ!u[È8ˆló#_÷'k®ÿ1,°Èq‘<Äa U®ßù³{”ül>Â1¥ƒÏéD}ãX/Í›·ô(òÄ-O¿õÄ7‹›.f2ïeO˜ÅËŒ¶±|ïÛþjÄJ˜±Ò¶ë–BºfÓ„È^'Dö6!2‹Šµ>¹Õª?DZ…Ú™ðì DðFÍ\¥Pà1ª~)‰ÅïšVýØ^ .-㤎Í°·ÁqÏGß5p’³:ñLðÊçaAêð0xšnþ5cµN¼‡£*itUV`+c!ž¡z'[´Úzå},ÿdêUi‘دšèœ7³v«êœÈu{d¤ÌcIÀýj~ÅžXfQ‹gR`sdß׳=¥±iˆ%†zߊêÁïªÂ÷UY*»bI뎺,hùAØ7{pä‘Å?õ°–ˆV¸M¯jjK€ü­? % ÊGË _¾(XàëÿšV@%Ÿ£J4ËÝh^ý]žÔ‹f6×níƒ+LÍìS2vDN?š`®…8ä9H3ð`3zø…$ÛVÂïå4ýˆÕÕHƒ®\Büu|-Fc˜¤ë\5¢œs²knTuü×tè«ÊeÁ?Mä' ÁÙX€p†h¨k.æÍâõñkMb q‘ÌB° ƒiû†sk(ß½üdÚÿÃlhßp²ÑoC;àÐn;Õ£ž»¿¨Î…?^Uè&ŠÌ(\¹'HðêÑáC5mWp}cŒ‡XÉ„?)â’éÀ9–ÜI[(‘î¾›¨Â^5ðù©‡m7ïÍlŠR͇蕽M|1x: t´yãizaÁSBïHæ >Ëíé±³Oâ"HÓȃ…×UØNÉø©|hÑçò Å™X]ÖÌ=Î÷¯»"L1œ¬ù‹Oï×WHÎÔšæÝǧá#¾û4á·óhö3¿cYŒ<ôú9¢wEYà6B=ƒ {{Üð'ƒ¿Ÿ÷ñ$¢uendstream +endobj +2096 0 obj << +/Type /Page +/Contents 2097 0 R +/Resources 2095 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 2071 0 R >> endobj -526 0 obj << -/D [1574 0 R /XYZ 56.6929 529.8403 null] +2098 0 obj << +/D [2096 0 R /XYZ 85.0394 794.5015 null] >> endobj -1578 0 obj << -/D [1574 0 R /XYZ 56.6929 507.5641 null] +742 0 obj << +/D [2096 0 R /XYZ 85.0394 769.5949 null] >> endobj -530 0 obj << -/D [1574 0 R /XYZ 56.6929 426.6253 null] +2099 0 obj << +/D [2096 0 R /XYZ 85.0394 573.5449 null] +>> endobj +746 0 obj << +/D [2096 0 R /XYZ 85.0394 573.5449 null] >> endobj -1579 0 obj << -/D [1574 0 R /XYZ 56.6929 399.4643 null] +2100 0 obj << +/D [2096 0 R /XYZ 85.0394 539.0037 null] >> endobj -1580 0 obj << -/D [1574 0 R /XYZ 56.6929 191.6116 null] +750 0 obj << +/D [2096 0 R /XYZ 85.0394 539.0037 null] >> endobj -1581 0 obj << -/D [1574 0 R /XYZ 56.6929 179.6564 null] +2101 0 obj << +/D [2096 0 R /XYZ 85.0394 510.2426 null] >> endobj -1573 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F53 1029 0 R /F41 939 0 R /F62 1062 0 R /F63 1065 0 R >> -/XObject << /Im2 1051 0 R >> +2095 0 obj << +/Font << /F21 930 0 R /F22 953 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1584 0 obj << -/Length 3620 +2104 0 obj << +/Length 2811 /Filter /FlateDecode >> stream -xÚåZKsÛȾëWðàªPUâd^ÀG­Wv´µ«ÝXLUª¼>€(¢  J¦}º§gð(ÙqrŠU. óìç×=3bŒ«XÏL¬YÀE0[ï.øì¾½¿®ÏÂwZô{ý´¼øë;ef1‹CΖ›Þ\ãQ$fËôãüíß®ÿXÞ|¸\È€ÏCv¹B>ÿéöîg¢ÄôxûûÝ»Û÷ÿøp}iô|yûû‘?ܼ»ùps÷öærÇ‘„ñº7ƒ{¿ÄAnäýòöíýå§å/7ËöýC -®p÷ÿºøø‰ÏR8ë/œ©8 -fOð™ˆc9Û]è@±@+å)ÅÅýÅßÛ {_íÐ)¦i©X(5[ˆX±È¼°,-ÁaYסaÊH=Zv!„fq`@!ç0{ÔIBŠž$„L)ÌL³PIeEQlkä ô•½¾§ p ì³ÜæõåB >O³z}ÈW™}óf›½z*³ÑÊd牛Q¯Ã¥ˆæY]mcÑg¢®+ûLÝBMEÏ•ë´¦^I“¥ ÷ ;ƒƒã&¥ÝâuyÂŽz^çåC‘¹#õ¦6îHo&D‘ëð'xZErðó>”@îí´[UEM/Oy³ÍKjãYŸ¯-t¢ ¤›{šç"Äã®OÝà$4iB‡§jï‹d¥– )%‹…–CŽ¬€!ÒDÄ}iÌ–z"åA¯k-†Ê³«ÒüOÎev¨‰!OÛ|½Å&Øí6)2"“iClÔrS£öàûƪiµ£!m·VÁ/#«šÛeŠÔ-“§Í–šI™Nú*©Qm øøß`“—bÞí36=S‰CPÚ†¶‘×öÜÐÍ¿%â†3 -¯,›I–ÇJ„=Qd›†f\À$‹€…òÝ.KspX…[ø¿p<70M z4P|ŽUl©åKÑ1 Dð’F@„ÀK’zÊ 'TÃ9\hè朎ûà?^Yé}¼B}ú41s k‡wÁß`Š›ù;ë²€)Ù—d·/²«‰-…ªõgO¥¿õT ɯÔU:åb¦Ô 'H >®œÈeÞ] 3TæT¦Í•\Î%ǧêYRÉßy}¡ChÔ{!~ŧ­UÈouã¬ÇÑ=Èù-*rxÌ)ÁL¯a9Ä~wˆžq¾²j¨‘¬êª86Ö|Cª€Þ7ò)I‚ dìOóæ÷·ïoï¦Îd`uiF«' Ï2mA#ÈÓ˜.9‡T‘eÐŽ h~¸É4¬WV2˜¯«Ý>iòU^äEˆéc–ŠÜª!J2©§¸0†EqÜƶ©à&$BýSá -u“Í2ÿJ0'°NŸy™æ>úBâq¨†'_ÃlôED¢ç}ÞÐÃ:Ê>ƒÈ±qvpg€;û9Ù&zՙ ”@mð=súgsÇ ÔÌ„ê•Ô1ˆ%“A“²4Å«©ãýÜœõ ¨…Ú%ƒ¶‘ï²ES-ŠüÑQlüÀ/ê|¯‡¬DÄhã~–+:„pë’}A£nWMýªäƱìÉ*Êq•yo³CÞøç’¡M@´òj±\þ:—”k×ëpÍEV³×Sž5ä.S^DjƃأMˆÇ¢<ïi¦E!@kåãÑ:)‡GoCŽÞÚ+yvŒÆkõœXžYè~^Ý{jôcšù¿Uv·1¯J‚ÒvHŽ^ÒKúx8(7ÞÒ(õ¾õµèZ.Œ«Â`÷ݱn¨ç.iÖ["ºÉäükUfSºÞnìZîðWîè=»ù?SÛžBü·ôV*¿XX|6¥q^o9Â#_Ó[ -p"ç¥OûìUµ½nHÇö.i°Y†>s‡/UióX Õ «ƒUVü€ó×ô¥W§2ó?–®ˆüöîú·›+¢þܶ£ùõÕd%þ¹0\:ÁÞÝ¿ ¹K~ŒÍäüv¾#d»g%§ar®^œŽCÈΣÐ2âÈwÄmë¹ÆDÀÒ>Êë°KZío„álv;2x’wµÎêÚ[Qï M; ´mÔsˆpîy!ôN÷c ëdÐÑ_«ÊãÃͨ*ÿŸòAŒJ–(2q¿šÿ¬ª¯xÈ" Ðt¡CÉŒÂNÎrâ.DkÍ"¬#Rq=›öc‡ßßÜÝ|°Iôòf*ÁösåÁsš»Ò´êÉÛiGwÕ’}i²QùÈäJ¡†$‡f˜Þ·8¨´“’Í»Q6ô´…ŸécvŸDž-"É„¾ ‹$)¸ãn?‘W߬mĹ1üvÅÎkÏñö×ëûûA­¢ÈZ·cC8t!8mâ>3— Á9Ÿ_§iÞ_ä]îöÎlÊ6a:ˆ‚±„nñv@Á¶ÜTôfï8”; 6† µŸ@>G[$Pžè<["9vƒ‰?õhΤMÌz+ºË·ˆÍäà™wûa?’'¶HžõT&h¯> Ū(êb“vŠÀ%PA§áz áqÝVæÉÓ”¨-]efuùœËëz3Õ»!åëêLý 0qÛLzâìöê¶z;š>¡Ç*/“éßߥ’°?)ÌèæÅÝÐt¡´M!zWœñP QL«[iÒ$Þ¸l±nŽ]AŒ÷LN+„˜_µö@V'Ÿ}àÛ.9|N8Z¾sîþñyNSTIÚQó~Òß³S*ÅÆT'ŒmÝqg#cHº²ÃcÖVöyÛÉ9hµN!vǸWé*‡Q€ýÚàvF98Àgzí°“×ô̾öó5!k\­¢çÊí¢¼áµW{…¹ý·68yWRÐLFBMÜÀÆL—‘°¬Û’5Æètµð.Á¾fl½—‡¾;pŒxM’‘ÚnË"> /9ùW+Û®Üs3’ž`ùš^p ¨[Ê% Î&l÷cà¢É×öŠÉÙ@~ájpþsU¨mlÛß¼´v mOdðH°÷6¡:wÁÇøÓÞ…Õ`U$¡Eg°ãp,™ä‘C‘ÄkaÁ§m6uÁbr£Ã¾Ø&¦V *aüE!:Vw.òËÐh³´…ŠŸDãÛ DæÆÇíMã3š.Æ6‡¤¬7½L‡ªï¸o´ß§Ö¨ÁV}—ãüŒ«Lt&NpÄÖR8)×~5®;ã…6]´¼{Ävk†ÐÆÛàšš ªdCØv¥b,¹U¥½ÂP¤en™Cí^\¢‹KØ•±ÚX>‚îd” U©¢¦ÛNg°n?nŠÓTºqFŸð¾>üNãìÕ£{Æ tME& A¤M¼ -̈D«·Õ‘.TÌüÁbïÐapã½µ±'¤IÅFÈ_Òö¦!ë„óB²=R°¦ÕŸP#o=c{È¿­˜¦sÔS×mÊ0!ÙÒ\~''… -†œtýI ó7j²Ê Õ÷ºhàäX~VâLpŒÅJ¼<À÷©1ò€9µMw•ÿ] 4ʬyªŸéeuj¹«=ØWºýÁÆc•§nB{ëmÞdm¨_¤™­Ô—nE¶w‘?”®Œi&$`þPwt=¨å¼®üMrâ(¹ÚJ¬¢û@xß­Ò@ ñ£» Ó²ý¾¯ê:_‘’i=šÆc€Ü‚ M!×Å[íâ­vñžÇÚÉ!ëH³î¶Ûn©¶¿²ÛoÆ36Øú¾}‡wQaHÀ:Œ¬c¯@†ÍØ”i ‘¤‚whHµ6ŒÏ( øñªÆ„\?Ó˜ÔâkXd—|Î{éøDüËqïγéöc ­C&kE€_]M¢²Ô%ÐS0퇮}Fíl}dáý¬í™ù?O÷:GÛ"ÎêµN­—liÀ;¡O¶4g2T‘K¶´Kµú?àÃñ5 ŒséUÄ ?Výô1ö—ƒ!–EVÃÿš¨Eeãhè*¯@©»Ù-=/I`ä†Cg¬ø¥…Ìiæf«³Gw-dB`Þ$kÿ‘@Uh5ýàh–“¡t?­ÂÉ׈ØT碀¯¸·Q ôBº}•*ê§9ÃŽôž—ëâ˜ú¾6MôZWÇâgC{U±wÐzÊÚÄãùjÀÓq:DD ¾aÞHwYR‚yoŽÅ°nÛËŽ®Fi|ÕUt‡¢² -šŒªZ Üè\Åa,8 y–= ï¸3µT»À§‡ê@׌.‹› ýܪ…_5–c`_lâw¨qÍBƒ%ÛèÛ~†*˜áátåjÁ!zF!ÀJÉ8N<ñ3T>{µÂù­?zí~¬í/_ätå«­©€á\ÈöH=«'ªˆ‘l{õ¶þoêG,&endstream +xÚ­koã¸ñ{~…¿ÕbEõ̲»É6w½\š¸hÛ*K´­®,ùD9Ùܯï g¨‡­ì-Ð&L‡Ãyq”˜¹ð/fA脉—Ì¢ÄwW³lwæÎ6°öéL0ÎÂ"-†Xï—g—·2š%Nzál¹Њ7ŽÅl™ÿ2¿v<ç(¸óO7÷7×;_x;ÿxÿDƒÇ›Û›Ç›û74½»¿ýùñ§ëóÈŸ/ï~¾?_ÄQ̯nî?Þý‹p®‘ ëZ臛§ó_—?œÝ,;Ž‡R W"»¿ýò«;ËA¸Î\G&q0{‰ëˆ$ñf»3?NàKi!åÙÓÙß;‚ƒU³uRKÂu<zjò¼)5‰JO5½¿»ÿÒyñüY5º¨+œ$ó„`/©¦As.â¹*UªUNEE+OjߪÝJ54õ\×%„´Ê T0”à»ô?u3¤úÒ­¢µzM •J›ò•·•%Ô{•µLÌb¶[Þz¨reè-Ð( ™…Nž³|-ª Y‘%†Qjð³-ŸµbƱ»=×q£h¨#ØÁ:Ò4óáÇ·‚Â<’U4>aòÙu½¬I^iK®ö„”¥­ÊÁ­¤pç÷5ïÏó¢…SÒ’æ¹zVe½ß©ª%€Q(R©+{Ju,[oMÃè„JŒÞÞCR1%ýùKÝ|¡%ÃüîÒ\ÑÚ¾ÖºX•Šàm§¯4\½YzÚ­½-ö´bìŒ p^c4“¬nöu“¢’ô‚"6ÂÉ ©Ûº²f+2ã0RÆVëºiug<ó[vä[õWŠ*/ž‹ü–Úè ®š˜ ß‘>ÜC¸kpª9>ÞJFç WcþIU,Ç(©µjT•±9ï*`bgäë‰[! q)Øqé“¿{x;/j@FÅ v÷þàW0Íal@3CðLE&G†ŒQ“ŠãúðâŪhi¥ÈÁŠsaüœ‰ kãi€[T­jÖiÖ26ƒ­ŒÆad4Ž”F¨Ñüe[d[ªþ|ƒH–É™Êí9´vâ”HëQŽH¿pNQmj¢Ìu––)¹+Ìî•Jµ4c7h!œàµM¢ùrÛ3épÒnif§¯{#PÄ‘чú½"ËÈd` ~– @ +dþU‘¥º0¡N$;<¼q*¦cÈ2d¬‚ÊYÈ(†b|M VK_Ì5ˆ‰z¾Û›äÝ—±çÈXz|øuõú“ðü“2”†IãÖð +h»zxXÑGWø ŸøxûpdGS—é³çùŸ˜Œ3;¦`²ƒ€[sƒ›&²K¼C*Ç!@þ®Û(Nê'¨u|6çfÀéà&€S2Z÷ë„c€‹»ÞÐ1Þ<Ós l³ˆú°¢àYcè>§'„)ŽN°ÕEZME‡È ¡äå-W}×q‘t¼@Ú½”î¾ç;~ 7eh˜%¥ç¤×ŸŒô‹#ýU1¯Ô0Mˆ†ÊÒ‰Müñü°×ÈUº’3›‚˜<¸wOçJ¾ sêOLŽc®6ÛòÕ¤:³êö (/rÍG×= …8£?¡prmRXÖ”aÄwâ ´QCɵµÇ¥«°¥«7¾µhÒjƒ—VBF_Z¬Î‘`|΢‰(%[”uf,ÕíDC¡Æ¼h¾;˜d +KÌÄ­tg¹Ñä äh&ÆZéI¥”»£-¹! ¬nÌ<³&ÌK‰”v(À°˜ñȇq㑤KYÖãcõq1`®/Ö¦"ØÑ¥±õoJ?›âY1„zg+@®Õ h]¼¨VP$ÛøÒÖvç ¶Á@”¶[ÅÅx»M«1ö.…¥Rzª'¥ÑØ,0ÏÒ}ºÂš¯YrˆŒºËZ :WÀQÝ÷-!VpR}å¢=ˆ:Æ̨¥Ñ€ªfôä#¼k¥, i +À¡ìLLÑâÏ©®ÄA Ý] +ûLµ³òa¹lIëÈz1] L ¿ÊTk.üaj +»õ.µÔ»h &î>>b¹`:&Ðô‡ù¶”ôçËÇ)IH£5xrÚv €‰°*V e“ œ’1/ã_¬§è^µ#÷ƒ<†Ý‘fþÚBÞýz® ¾é>2 +ItdöW9€°;˜ +#";"2ôoÆG‰Fõ 8ö ¬,ª/ >ßår—Ñ÷ } –Óµ*§µôÐÖX“d=䌩†ÎØ"I¬oèØíKµ³Ú65 ”Fe»Å¼À(-ÿjúíXÁÉ ]M8OÀo *nŠÜBí±¹Z§PNÒ¤7Ò^Óo¥àªë´y=ÀÖbA<¿ž +EЙ­OƭܨŒÚ›-—e]s÷Z_ÔU×.Ê‘zE)míë¹®¸ÊWñ•¿ÉUêº0¢Æ÷j­bqå­¤7‘Љ’-9ŽÂÐákq¢ŒuB«×­‰§ fe°¹{ º ©-žC*d"&Äðwî¿õ½•èšÖÙ ñø-‡ÏڦϊЊ*+T|$ô…m¡ÓŸ|-Úvi×»iÖüŠ›ƒwhJH…–×ògui.: ñ¢ÿûêêOt¥¡ý1 _~tG‹¨eÊZ˜ ¼Ï7Z7ÉR,™”·fT+‹…ÆhËÊÌ&œ‡=ñ™Thn„u5eÕU£Ç¾ù}!’_*ÞƒlE½iÒýöµˆ[O‡ ªÂ²ò¨Òä¼^|ûEDv/" +â”mÖöÑëC½Ã1xVGßãÈÓرtˆy,Ehµè €“mCøŒ`.nÛü„ ú®‹Æ ­»’½C›nÒÍúWX߃Ûzkt…kÌÃ>mø4ã0¡ÿÖƒH§"éÜРWÎF*2­0!ÓØ´ãð —o[QÃiU·¦Á dÀÉ÷µ)&sä?çíx™´*Ÿ-¹N:œä¦£¨Lb€)v¼g²lïÕ Wü¦Ú@í¤š.&/Ϭp¿Ðì–JžŒcÊxw³¼åÜ›ØÖ"‰YæÛôŸÚ~Ï?q7²§E¢ÿô é;„*¥Å7•õ +cåàföí÷¹àRõvùÀw²½šÈöëvuyùòò‚*p +]8*?\ÕÂXé[}ãú&?kÚþù+üM\O:‰p-’Ó~å‡1ÎCN("ÛÿùøÓ‰øN”±iÙE˜øô­ƒ–¿ÌìèÇþ»G·c1Üb¾{øÃO)Ô1T~ß!¯½<æÏGþã8:âïè[L‡uÊÓH§Ô§¿Lå]ÀĈ90&ºÒK÷ðxj7ˆ†žÄ˜-t|×âÚv ª{ô^Ù¶Ä>±t‹à-Ö‹i¦'¾}¤¥¶Ÿ4žÓÂ>©]¶£÷OtJµùï‘ÊøÙJ„b¤‡7 +}Ç÷èUHÇÁ{‘Ý°î8u¢º¦Nh{'RíÚ©›Íe³ÎN|Çs#'qå1WG¾Óa²2RÄ)µ·|'r"?Ž†<ÇéÜ4†`“6MKÎü=B¿õ…S~–œÃíóÿüõ³ÿ ÌÉ8ö¦?lzQ7ÆÌJ <÷„uûô”÷ÿ“ð4endstream endobj -1583 0 obj << +2103 0 obj << /Type /Page -/Contents 1584 0 R -/Resources 1582 0 R +/Contents 2104 0 R +/Resources 2102 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1552 0 R +/Parent 2112 0 R +/Annots [ 2108 0 R 2109 0 R ] >> endobj -1585 0 obj << -/D [1583 0 R /XYZ 85.0394 794.5015 null] +2108 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [253.7995 149.3637 417.685 161.4234] +/Subtype/Link/A<> >> endobj -534 0 obj << -/D [1583 0 R /XYZ 85.0394 408.8853 null] +2109 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [63.4454 110.455 208.8999 120.6168] +/Subtype/Link/A<> >> endobj -1399 0 obj << -/D [1583 0 R /XYZ 85.0394 384.5457 null] +2105 0 obj << +/D [2103 0 R /XYZ 56.6929 794.5015 null] >> endobj -538 0 obj << -/D [1583 0 R /XYZ 85.0394 174.3152 null] +754 0 obj << +/D [2103 0 R /XYZ 56.6929 662.0717 null] >> endobj -1586 0 obj << -/D [1583 0 R /XYZ 85.0394 142.2096 null] +2106 0 obj << +/D [2103 0 R /XYZ 56.6929 624.1661 null] >> endobj -1587 0 obj << -/D [1583 0 R /XYZ 85.0394 79.8825 null] +758 0 obj << +/D [2103 0 R /XYZ 56.6929 624.1661 null] >> endobj -1588 0 obj << -/D [1583 0 R /XYZ 85.0394 67.9273 null] +1515 0 obj << +/D [2103 0 R /XYZ 56.6929 593.0972 null] >> endobj -1582 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F14 740 0 R /F41 939 0 R >> +762 0 obj << +/D [2103 0 R /XYZ 56.6929 294.2701 null] +>> endobj +2107 0 obj << +/D [2103 0 R /XYZ 56.6929 255.4568 null] +>> endobj +766 0 obj << +/D [2103 0 R /XYZ 56.6929 255.4568 null] +>> endobj +1241 0 obj << +/D [2103 0 R /XYZ 56.6929 226.1045 null] +>> endobj +2110 0 obj << +/D [2103 0 R /XYZ 56.6929 53.5688 null] +>> endobj +2111 0 obj << +/D [2103 0 R /XYZ 56.6929 53.5688 null] +>> endobj +2102 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F39 1151 0 R /F53 1303 0 R /F11 1442 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1591 0 obj << -/Length 2761 +2115 0 obj << +/Length 2826 /Filter /FlateDecode >> stream -xÚÝZÍsÛ¶¿û¯ÐQžD,>H€|ï”8vëÌÔNm÷òÚ( ¶8‘HE¤ä8ýÛÅhQrÒèÉd‚‹°Øýí@ñƒ|¨He"è,ŽÆ“ÁdqÂÐ÷ë w<#Ï4 -¹ÞÞür!õ ‹2%Ôàî>˜+XšòÁÝô¯¡Šâèf`÷—Wï²Ó‘HØðöîTÇÃ7øßÝåíÝåÙíé(ËR1<ûí͇»óâRÁ@¢¸ág×W—¿þyã&¸¾"òÍùÅùÍùÕÙùé?wïOÎïÚ „›äL¢ôŸNþú‡ ¦°×÷',’Yš á…E<ËÄ`q'2Jb)=e~r{òG;aÐk‡ö)-ND¤D¬#G)¬ÿuËòH3Õ¿*Œ„Œ2ÎâýSÑ8S¹&Ϧ%:RœƒpZ&‘˜vľ›XgÃr½›¶ÓauO´b»'x{wuKÝ«Sžým×}µÂ¢18²$vr“Of¤ëg×ïΣ ²ö”ñ#ªÁ*I£- ÿÀŽƒJyLT‚nc.ù ¨ -,g=¨ücmV…9Ê`£ò Ð[P†R[PJ-[PbA‰Ï-(ñí“Û’}AÚ†^ o\mž–榆Œà^©J’oØ‘±ŒJ'³—ÀÈ ÞC¸Gå_¯›‡ê«±Îÿ}"o±xXæ-¡-cÆ[(b¡hŸíŽb&¶PÄ. El‚b"”…"µjS6ØÒÃ{a«…ã˜"ecVe>'2Eẚo@,HùQw*4~Ïaü™)i}iC<46…y<ÍÄp¿Ï?qHV ‹Ò˜¦ÜïJ©H¦d÷«|a\½gVoŽÛ&oŠº)&"XêXÁù°ø­C„ò’Ž¤TÃIµFXº·| >AÍ NKÖ }Þ°$ÄOL]à<š~0P³zóE‰äñ  ŒEÄ´$ýÿ¯**mÄ0e^NÌ×C3XðhÐ<¸‰-4Ã]t°©:ØT‚¹}N ™J¿Ø­#ÃÂn}Ô‡Ï@ÄPX¦*kz¯×¾ÈÍåK«Ìf•—õ=HpÑGÓÝO\l$ƒ#‹~ Ñ\GZÅ’ò«O_ âpc‡åÞ‚8<q¬âıJ|€ÅŽÒf$¶¥ÀqÙWf¡"Y` 5‡ØŒOA¥|io»¥”N± ½Þñ/+Œãiü‡~¬£T0ý ;ò#öB\œŠÃÐOR%Œ‚ΠätèÝ[wqS›·á"ß'w€ýƒ‚·ØïHNÕ6€¯­¶¹¦jhn¶½¤ÎÔ–ÑÈDe4Rþf [Vu/P‹¦Ø [’ m}ž€AF@* ãÔ“—S×qü3¸¢­Ë±=®îs¯º©ÈgпҘü žä_ИI°9Í›|œ×pþ„³±+ô¾ºè¼éh6ü‰ëõ#­Ì^H$‰”‘H9Ùö¶š|4 Yáò—ë¯Ï'ÁRÇ*Š‹¿õ)’·(Š³°(Š3Ýæè(MóX­>à<Ï›~\š 8Ūæx›ÿ1À(œ;4×€É42NÃÛí[n¡Ó(N¥éÓ,âLí¹qðWð±f‘N5]~½„1e帶°ƒ¶½eÜŸÒž±ß ÷œTó¹™461Ã`Öì̳걤æÒÏáJVhÙ‹ l<Î -[ØÂPÆìÐ`ÙYîÖi{óu3«VEóÔ‡˜Ç™±• ¨€*:â:N€™PŒQÝñ­ç. -*SʱÛ&|X{ÿl*ö Ü"‰’Øy2}³Z3)RÇ‘YBd†dT·@¨bXgëCØK' -Ïê´ \E3#"¨¨XuÞ Ð°±ÝvÚC9#ÑYòLv3Í¥›»®ü5Âr‰«ñiÿÙŒîx²N1‹¢i|ÍF6'˜šû|=ozrµk -’¹ûÐ’ŸWª@ø2Y¯èµlæOH‚+ê[×öbW¹Úó>ŸØ[\xo*b}@«Ú9'x/v:Hbck¬Rc1¼.]OQûùÝÒ~Èrž ¦1ŸÝ"Xç½wÓõbi5¥R»¼P™S”Âjƒ‰¹k×K3)@ÜÙpüäF÷.ô9¸¿æÊc»‘‘›t§I)™ù“ªD·5Gi­j‰m„0 èëHR53ë·À`Fù¯8‹ª1ó'b"=cZÂW‘LT€›"Ñu OfyYš9uZ§·ä=*ˆ“(c,ÛU›¦ÏYÓ$ÒZ¨`ŒYØ ×±»C±:¶H ØA–CAw´½­9 ÉÚ˜}ßMe& !í'+ê[= ¨qÓ÷™8äߟ -Z.›º!|“höï€Ìô\έãŽ8; ©åzAŠÝÙl<´µñ®õàx ›šeÅ rþÛ6äÐÓgŒ9v+&û~Qô"«>ˆ×L×ï62YGuÁ -•¢à³IÑU©56…¿¡ñq˜YÌÂcåökßühþÓ³·gQîÕ«WýÛx׮ز n2-u–fq¨N쟞>x1½ýàÅ4Å-gÜQLHµëtÏœ ˆrên¶hÔŸeñRéÓÜÍÜš|±„KÁ‡ “×ëí¡FänÊÚ€kLýKa/¾°ù>/×ùꉘùë¾sÏ ’A5¼€ê£z¤Ï=1_k3™YåSËú*+CÍgˆSóÃ.Dºû[ýR`Þòì‹Ì˜FDv 9¬Íe>“=_àÌ#ç@K«I<[ÍA=>,"¥AàÚogPÉ®‹£uuL,yçC›pHE:ý iÜ·´ ˜ ½ Iòd!?G.bz$²ým…ôUu+×ë^¿´<¢œ¹oUbpo¾^”ÔcÃ}Å ù¸u?ˆÍ ƒ)Ñë§Å¸š3]gcËJùß#oÏ[î.:θ?œa'MR»•ZTcù ©ôsšÞ0ß1nF©fÑ–ÕÌÕÆt`Ê\ Üuÿvw÷(™ Ç²Ždêë™l¸*fN{–Ë"Ã*_Šq’¸“Û+y+)žÑO·|™» p¨:òt›1µ«–;Ÿ×Q|Ør :Su¶¦ù¶XÖºÖxÝØ%T0´p¼Ój²Æ*ÝÉ°¬ìAã‰:].…õõ²·äN"ü}aO…ËZþîŸ1n+v<€§û.°Û;'š!w$ç,R‰Ñÿó2Dendstream +xÚµZ]{£6¾Ï¯È¥ý<-’ KÇö¤É4™4v·Ûα›glH ÎLúë÷} 0’;Ûî“‹€tЋÏ{>%ðeø2a( <¼ŒyˆX€Ùåj\n`îæ+™+-teK]//þùŽÆ—ñˆD—ËÏÖZ +’_.×G“ÇÇùÃìößã+‚ѯXèÑé|1¾Š#.&¨˜Š‚Ñõíõ·nž&?ü*ú-`Áäa&o?ßÜÌ˹º}šOf·7 ‚ÇŸ–wó¥ymû§á€Šwþýâã§àr ¿ðî"@”'ìò+ÜsN.÷!£ˆ…”ê‘ÝÅââ'³ 5Û<:¤*FÄèŠàKŒgŒt”Å8Š(¡²uZ¬Óúrþ"ÊØ9š,) M†hÒRùãÓ»)()üÔGÆ,@ ‡w÷B©SlÊ-lÌJbʺà³rŸæ…$ô!Ýg•âX^MËb•½Ôjt$/Þ¥«|—×yÖè«÷3q Å ¼ Àø‡|äqŒ ¡Érì¾\}I_²úWJê¡|ÍöÏÙAÞažÄÈÉŽÀVÂsŒXRF´”Åó0⃶éc;±ÁÏ2r»Ùeû¬¨Ó:/‹/‹—l•ÿd%gOÉ!˜ýAmV[£÷Ä­wh0Õ3z·¤¶Cï6øü[•I0&9U½ìd”/úá9ܺë=é|0ŠÌÿœw<¦ààsXR +´”EñPàƒ¶(èc;(°ÁÊâJ]ÙaŸº"3— ¦‰Ù:—¼r††HÌè°LéWÁ(¬°Ö=wê>^ˆ|~ÝÛRnÝ)£û$ôÔÂ^èV÷'Øúï€/2U P6zŸ½É‹¶ +NWªþ¢h rBQç¦&Ié"p! ƒ á"ËÅíÃC¡(H¶8‚‡Zðp”ñH9 å£jêæ¸ÞCú®dQ@h2š©™yZÕW2ïˆNÞߥ_´ËÑŽ˜¾íZÊ/cNFÙn1¸–8M°Té‰P69í$ŠQ”€êývbIyìDK;á4ð؉Ú²“>¶ÃNlðŽ€ +¤ˆô]Õéó.¯¶¢™òÅÌåû¹ÚQ|zr…΄£G½M£™âDÐëdp‘½ÔÖŽ„Ÿ¡#FÈ9†,)CZÊbȓȼÐC}lC6¸QöSöû1Ó!ÍXö€? µå›"­’Úª%K:oÐä¸ÊåÆÔ”ðÿ7[#áslYR¶´”f‹AìaËm±ÕÇv°eƒƒ?)­ŸîµùN5T†à¸!C>¢Û5q#ÛµÁ`‹ãQ—$o˜ëîíù¹Á@r†KÊÖ2ÜDޜ胶¸éc;¸±Áo²êk¡Ø8–D嵈vqw‡×|•É©ÉnSÂÔv/çdØ“´±îe¬‰Ëôsª½–ôj¸ôß,2¿:¯ÉS_®e(da¯Z(úßM‹¡úôFvÝ—éá|'·hÞšß¡fÔ_åÏå«=s×±² +~ez’pu?øCºÛ©¹«º´Íïoòš§þþfÛ¨¶´5[KßµíIÃ<ŒýfmK¹ÍÚH³&ÄcÖ^èÖ¬O°‡Íº~[¬ÓmåSV•»W­èÅñå¥<Ô'çb>Êԃ؟°áØ?-‹ƒ¡z–­ºá;à …XÅ)=§wKÊ£w-eôžPêÑ»ÚÒ{Û¡w|¹•Ñ åÂK@žîÞª¼’wBÕâ¿ÜZƒ ³µ×jk ®t&×v&øT8I»×&VE +¼þ’ +Zî–ÁÅ“ž„N(ËEHq¤;#UO«E;õ4:É$£ÇgöHm)7™FJ“>2½Ð-™'ØÃdvÀ›ƒ¹0OÀ·j ™ÊõQEv1Ú(X‹’,oÏwn’:»˜ +’†ñüD> ]OÂ0&FïÕèéAuGìŽÄËܧU•éÈ-7Gd‡Óöé®*Þ-ú™›þ£8ÀgöKm)ýZÊ¢ßsîç…¶èïc;è·ÁEÌ”u›(ÀÃadUŠTÒÜ4i›BK*½™ªü-.Z{wf×iðà‹OB«?¦ŒK'¥=[h'ËÄè½7¶ gj[Ü t¨ïXHïLù/”¾L´ã~c°¤<Æ ¥,cð$T/´e }l‡1ØàêÀª.W¥Ø²‚z_®{»é QµœñbDV)"ª·U +ÜI£ã‘Ë.HŒ’ÛÅDz‚‚E»1ÂLØQ]ŒÞ+qm*¼«•;ö Óùßc'\ º§Âíî(é`>r€‚$Õ» +À´jP'Ïå±îí0ô¾ˆpØ!f +ã3­¤%ä¶B-dU™Ï}¸­ ö‡MÐFžŒ¯ -3wÊ,Ÿw¢^ [ÖŒ*…ÅÈ´<Øû©ÍØ/cŒ ­±ïÖÙN­>Ë^vå›~¾Ñó +åçú«d>C¶K¡`Œidå7ÆÁâU<2³û»I_å Cæœ:& ôÚäLcjKy¨ÖRמZ/´EvÛÁ¶ >-÷{¹ëŠõfëÀ·@09—¬–‡JÊH…‰Åq³N¬é„`ü]þmøèœÆ(æØ>F¢aóù XäýqŸêSW±ïÚôy°Úc +ïÔàT >d mâŒ^·Ãs§÷œ¥ÅùÆgîóÝÎœø~ŸIð‘0Šüa ¹ B µT$žƒnk}àak°‘Ù!×G%ǶÚ4[Y¯†ªLÆ,<=5G±Žö\×~ïGI ¶àÏÔÿ–[áZ¨Íø¾Ï¾|¸­ÂûÀà +·‘÷AŸWÏÙ6}ÍE5#P}m kkôÓÒ9áBŸÔ6"²€ÑÛÇ×H^MÖêD2ì #FEÐ|X|Ö~ѼJyÈ«m^§DRãKá%Jæ./öY®P¯ÙÙC²7Ü…¤jñ î€j“Ûÿò—¾ÖÎaŒh’8Ó(4Ÿ”r¬_Jü +LN>D6ߟ¾û#ïbendstream endobj -1590 0 obj << +2114 0 obj << /Type /Page -/Contents 1591 0 R -/Resources 1589 0 R +/Contents 2115 0 R +/Resources 2113 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1552 0 R -/Annots [ 1593 0 R ] +/Parent 2112 0 R >> endobj -1593 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [55.6967 389.5558 116.8967 400.9478] -/Subtype /Link -/A << /S /GoTo /D (statschannels) >> +2116 0 obj << +/D [2114 0 R /XYZ 85.0394 794.5015 null] +>> endobj +2117 0 obj << +/D [2114 0 R /XYZ 85.0394 752.3015 null] >> endobj -1592 0 obj << -/D [1590 0 R /XYZ 56.6929 794.5015 null] +2118 0 obj << +/D [2114 0 R /XYZ 85.0394 752.3015 null] >> endobj -542 0 obj << -/D [1590 0 R /XYZ 56.6929 374.4628 null] +2119 0 obj << +/D [2114 0 R /XYZ 85.0394 752.3015 null] >> endobj -1283 0 obj << -/D [1590 0 R /XYZ 56.6929 350.9179 null] +2120 0 obj << +/D [2114 0 R /XYZ 85.0394 746.3107 null] >> endobj -546 0 obj << -/D [1590 0 R /XYZ 56.6929 144.4344 null] +2121 0 obj << +/D [2114 0 R /XYZ 85.0394 731.5461 null] >> endobj -1594 0 obj << -/D [1590 0 R /XYZ 56.6929 119.2896 null] +2122 0 obj << +/D [2114 0 R /XYZ 85.0394 728.1497 null] >> endobj -1589 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F21 714 0 R /F48 953 0 R >> -/ProcSet [ /PDF /Text ] +2123 0 obj << +/D [2114 0 R /XYZ 85.0394 713.3851 null] >> endobj -1597 0 obj << -/Length 2948 -/Filter /FlateDecode ->> -stream -xÚÍ[[sâ8~ϯàÑT ZÝeí[º“ôfj&é&ôl×Î̃N·§Àf°I:ÿ~.6L ÓEñ`Y–ŽŽ>«$HÃôb0Ó¼§4GÑÏÎpï+|ûpF|›AÝh¶z7:û×S=´¤²7zhÅÇ1é&¿Gïÿsþqt9ì¨À‘Dý8zw}sáj´{¼¿½¹ºþðyxÞW<]ßÞ¸êáåÕåðòæýe uL¡?(ø¾w#ÓÉ÷¼]¿¿ëÿ9úùìrÔL œ$ÁÌpÿ÷ÙïâÞæúóFLÇ¢÷/­iovÆC‚3V×LÏîÎ>5ƒ¯¶kh‚ÅHÄTµ FijB#É(³¨ÍŠIöÆtœTY‘÷L°è¡X¸Â}ZU©//ú$ŽÒd’ÜgÓ¬zþ I¢£óÉ$3“©k™UZºâ,yv…dZ5M÷œ[‚Åc6I'®&óÃWß2ß}\L—³Ü Cqôßo©oØaîB‚º‰d“ÉhSª|?WN¿geUº2Ìç)Mí ä¥o_=aÇò'xc4Ê*Wû5{L˦SÝrá)çE>Éò¯uõ2·™—<™ùÖѨînå²e±“´²‚å(«llYŠìÁ=“ù|š“ûiŠLwXa¬0c â5Â1A¤? ãèÆqcä8]Yh1ƒ¼›«h±BŒ·ß÷y>IªÔI*¤I€.Ôt£{ñœ'³lì#]Kãð:ÖO:Žà¹*¥;â®bRÖîÌìš}E0,º;ÏË}ì€ëä,Ó¼Ú \ÈÔÉ¡jLyGÀc†8! #›‚-–ù819Tw Ð×FÚâ¨îˆß!€Ìž, «ÆRÓ@‚ˆDMŠ–¿· :°t|ž´{„&¼Ã½sa Âj%{&; \%Ü,‚@Y‹¸Ã£s®€é4¸ì›°î@p;cí@2àòXH”bŠÕ$ëíH2‹°¸K¯™@BcçÀ!μ[ŽÇi¹‡cùTG”LëÚ0.§ÖTrŒÝ|IÜ£td–S_—OE)!·};rÛ·Ðs–&αmnÕº.ÁV{¶,zú–íRÏäºyé¾%îqs{9ÞÝKhÁ=/оjÛÍŸ¦IY™³AÙ(Ð<÷P–Ñpˆ\åÈ-nžßùʪðO˜ÅöéÅ1ÂDPn¹sMË5lVgƒfKÀè¹cÐô1+–åÚfa¹Þ.8ÈÞ-ò¡8½M>ÿ¹¤²RHWY‡ùe±BJjU‹¼ÉP÷Š¥>m'QµÈ»MŽºñ†â¾à€ùSµÎLQD©ê°ÎL .j€oŠÄC< Ð º»IŽ‰w³•ðZàƒIêY)d3ˆÕ‘.0ÉP,tċ)¤ª‹dzˆ5ç|jSc­yóŵ5k††®Í ç[f°Í¤>­n7Š -ñÒvÇâb÷d˜D`À¥oøla°Ç:? s¬{ìBA(h—-dPÇu£©ß‹2­QMª6Uj2Afå{WÍš ª¼ó5÷Yü-ÈþÔ&*N®ˆÞ–+[i$É>[% GL4î5ß9MXa®Ù”$CÙHˆy®K’©1^ j`ÙƘÁR¯…¯µ`ß&ÿ WÀq-»¼æК5^áîrhÌÆoWfcþüú€"Æà®’lz4ß`ò0ˆ¹]wýË @“8U÷KãÒÒ±'G5E„Ƹºþ -jh‘ -ð½\,Ž†¯§½ÖåSu®Tr$éØRéDD1ÚØÊ/·¿ž_߀ °¸Âû!~–°M?K¼Ÿ…/5mä^½O%¬%µ ÖöíH—Z,¡D Dz1„“b–dy ãà⸹Éó£|j¸§êS)!s†Ô QIãUfbì X³q;¼zš|:PT|žkE Y–N^˜K‰M¡ô×.meážótñP,f¡¬ÕŒ´ˆ‹=¦Íy2´œXb;bPmîñæ_gG­+]$ˆ7"AU§ô¦Ý¶Ô:Ê-éö>R»ç±)¶ŒùÛ@$ŽåŸ…FJt ¢îÑ.¶DÆHkÜ -RjPÛ¸XÚëÀæ0†Q&¢!T"¶Têf{Šn÷ -µ¨šrRUéliS¸çJX}Ÿûeå -“¬´Iï¸ðA˜Û’ îi¯hÛ+ÔæÍìõIôìÞ\ôiJ–9S(íEfSºþè M&^vËŸÚÖÜʲwºy³/Eut}aë°½§í?WÏóÔ}MŒ&™¯ãiR–¾nZß‚vßîSwó›Õ[´Ï³÷!¥nö T›Ê)‡¯}¶+˜|)¥ò 9iÖ¿Eˤ¹@¦6µÌÐíqa°sÆ×¹=ªî…rý6EYép-ùA^ÈõØ[(HÏ°ŽC~¶þuÕ4ÚæbÍ -oÒ2\ w†Å÷l Ùò¦ÒÊž‡{{-Ü ã†äî4MÜÜY?.a,ëÛ,5¿²IÍö6$Bµ­ îu&óûþïnõOD®‹Ãºµ­(,AÓ´2ñ¢¡eÿÂ%¶áðÐó­Öÿ؆QÃendstream -endobj -1596 0 obj << -/Type /Page -/Contents 1597 0 R -/Resources 1595 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 1603 0 R -/Annots [ 1602 0 R ] +2124 0 obj << +/D [2114 0 R /XYZ 85.0394 709.9887 null] >> endobj -1602 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [333.4761 85.0848 413.3061 97.1444] -/Subtype /Link -/A << /S /GoTo /D (clients-per-query) >> +2125 0 obj << +/D [2114 0 R /XYZ 85.0394 651.9592 null] >> endobj -1598 0 obj << -/D [1596 0 R /XYZ 85.0394 794.5015 null] +1372 0 obj << +/D [2114 0 R /XYZ 85.0394 651.9592 null] >> endobj -550 0 obj << -/D [1596 0 R /XYZ 85.0394 717.7272 null] +2126 0 obj << +/D [2114 0 R /XYZ 85.0394 651.9592 null] >> endobj -1599 0 obj << -/D [1596 0 R /XYZ 85.0394 695.4159 null] +2127 0 obj << +/D [2114 0 R /XYZ 85.0394 648.8377 null] >> endobj -1600 0 obj << -/D [1596 0 R /XYZ 85.0394 695.4159 null] +2128 0 obj << +/D [2114 0 R /XYZ 85.0394 634.0731 null] >> endobj -1601 0 obj << -/D [1596 0 R /XYZ 85.0394 683.4608 null] +2129 0 obj << +/D [2114 0 R /XYZ 85.0394 630.6767 null] >> endobj -1595 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F21 714 0 R /F39 899 0 R >> -/ProcSet [ /PDF /Text ] +2130 0 obj << +/D [2114 0 R /XYZ 85.0394 615.9121 null] >> endobj -1607 0 obj << -/Length 2370 -/Filter /FlateDecode ->> -stream -xÚÍ›[s⸀ßó+x4U‹Žî—ó–I`[;ÉØSS{yð€™xàÄ6IeýiY6VÀ8ÉÖºRŒ­–ZŸZênY†?ÒICMOŽ&¢7_ŸáÞwxöã)Ë ªB¿Ô§ÙÙ¿FLõ 2’ÊÞléÕ¥Öšôf‹ß‰8êC 8ø4¾º4ý8˜ÎúŠçößl°`ªDYfÍÖ6 †À„RòyWòÛ0·«ƒ“íÊvIU–¸›K€äîÅ›¼¼WŒ~qµïB¨‚gŸøƒþƒ½%«¼FÛÃU­öª¶"¼ÓÊ^n’Ü]|‹Ü§µUû¹.˜3,ƒ¸O‚B¶˜iyysãŠÝ¥á|ïpæñ¡5’pyŸ0QaŒ‡ïS¸ø’Fitÿ†n½ü3šïœûb[ùöÄ}–Ñtå¥â,Þ- uÊsxüþ}Ô(Ôyec¢ -2\Òçyꛄ*5(,ŠÃ ¨A -k駷¯Ò\ªÀEkèý@Hx¥<RT9¸ \ºÞí Dû‚1~Ý]Ÿ!ýÈ£M¸™—7¦9$Jıå ^T9É‹1KBþÁàd°<‰ ƒ CaÅÚ!Ü/U)‚?p"í:5àÂ[Aê™ÄÌ³Ü ÈB>CnI¹™4}ZK Åì™—Q6Oã»Å—ä¸Pˆc¥ë6Þ§·%Ä0¸Çsj - %Ì!cÛ¡Ðü uÖ ~¼|ºÞæ|Ï‚b`6 ^e£ã/P¨05ÈÊb›*WëImrt˜ž§ÖÇÒûXCRŒrÒO1›|Ëðä)ðä›àÕZu™°»›B7À÷™5÷à7ï2<ç†æQü°'$¨zÚu"‡p“aÙ‘ƒ"Š>‡ø<¢ÓNu"÷©„h€ÈR’âþ´ 7¿Ç›ïÇ8º¨êGOÁ.s¤zRÌ8Bàù{éV¯ÏÛ:qvK=>qEô4ë2@‚•¢ÉŸ†´ ÊØf.¿  Ó¬ëþ$k‡ ÒF:w|þu4™D÷­ ÐʼÚ;6}k­ºŒNKÄopÇ ÒEà ¯ñµ‡çéÕe|Šƒ´ipÄL)d´tŽxüÛ·Æçôêº f’B6Ë\0“aFÈ3|m¬¯=>O¯.ã™Ï Óa%vou¦Ûù<ʲF~¿¾z‹sèuDfkŒG‰zªv™(Óü7¥vŒSD(VÑ•oÅy`ß²fé)ùQ,Oß1û;ö{ˆ4ˆ)ÊZí™QÐÃUǷ̨¶“ÆÛ3cåžÙ$Ê’ÕC5§n“U[³TH ûgöñß±ÙL¡EM(Ù¿EVm6S®lêõ™=¢Kšå}FùÑ­³ÝF°ßvwßQq¤hxD™Ý¥e.ؼ±g€¬'BÊ`:z\Ü4ïÈ×¾¿9\¯ Öºu÷}%ÐiL^QR -¦¯5÷ÊÖe{‚žrFˆ!žäR6 „jc´<¡áÞy[«âXª`2ic„{^›Ý ªzªvwR#1¤á%T…„*fî€Êv@å;úªv×B‰†˜“Ɇ—–D+$)užùêëåõçóñx ÆE0ïÍ@k¡=Ý:LPQ„5! !¶‘R•žx8±'zÿ;ê œîÛÍvLN{n¥A¤íÙb+Ý©§l‡g¹„‚´aÕ$’!eKY&£ëÉç!Ll»W &9¦i3ÈP ~µf¶Há ç ü”Š×'¡š=ÅË!Áä$‚åjË/r碓´Ý"é©Úa LÚ#/MÉ Ò˜:7>¼¼šâÓæ³-ú;Ã?RBO¯ŽfdG8zvx^SŽ¨ÄMÞ›*¤¹rÞûsœ­ÃÜž æF€ï¾ÜÞà¾k©÷¹pOß['¡6‹&NÒ†8>ë˜ãév3íq¡Fž³¾±ÌtPI¼“«§q‡¹b¸É±c† “αÿ®£þ@a»€×dDq\+ZEßÃÜý„£KOËî²Ôd¹9ŽÒ@%fµçv,PNaÒŸGÞÔ‹¦C—×Éä]”.“t} d¡bǧº’ˆƒðqŒ#L¥—ŸKÒü4~;`¡•9x’ð~›äauúu“;Ï¿:ÌÖÓû½pm'9µïb†lnßOÒp¯Ñuú¸ú'v'Mkï–Or·Ñi·“˜;\¬å+ö%-“»Ržêÿf3Šâendstream -endobj -1606 0 obj << -/Type /Page -/Contents 1607 0 R -/Resources 1605 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 1603 0 R +2131 0 obj << +/D [2114 0 R /XYZ 85.0394 612.5156 null] >> endobj -1608 0 obj << -/D [1606 0 R /XYZ 56.6929 794.5015 null] +2132 0 obj << +/D [2114 0 R /XYZ 85.0394 585.7959 null] >> endobj -554 0 obj << -/D [1606 0 R /XYZ 56.6929 543.3808 null] +2133 0 obj << +/D [2114 0 R /XYZ 85.0394 582.3994 null] >> endobj -1609 0 obj << -/D [1606 0 R /XYZ 56.6929 518.2602 null] +2134 0 obj << +/D [2114 0 R /XYZ 85.0394 567.6349 null] >> endobj -1610 0 obj << -/D [1606 0 R /XYZ 56.6929 518.2602 null] +2135 0 obj << +/D [2114 0 R /XYZ 85.0394 564.2384 null] >> endobj -1611 0 obj << -/D [1606 0 R /XYZ 56.6929 506.305 null] +2136 0 obj << +/D [2114 0 R /XYZ 85.0394 549.5337 null] >> endobj -558 0 obj << -/D [1606 0 R /XYZ 56.6929 293.2416 null] +2137 0 obj << +/D [2114 0 R /XYZ 85.0394 546.0774 null] >> endobj -1612 0 obj << -/D [1606 0 R /XYZ 56.6929 268.121 null] +2138 0 obj << +/D [2114 0 R /XYZ 85.0394 531.3128 null] >> endobj -1613 0 obj << -/D [1606 0 R /XYZ 56.6929 268.121 null] +2139 0 obj << +/D [2114 0 R /XYZ 85.0394 527.9163 null] >> endobj -1614 0 obj << -/D [1606 0 R /XYZ 56.6929 256.1658 null] +2140 0 obj << +/D [2114 0 R /XYZ 85.0394 513.1518 null] >> endobj -1605 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F39 899 0 R >> -/ProcSet [ /PDF /Text ] +2141 0 obj << +/D [2114 0 R /XYZ 85.0394 509.7553 null] >> endobj -1617 0 obj << -/Length 3227 -/Filter /FlateDecode ->> -stream -xÚÍ[Ýoã6Ï_áGW³üþÀØf³½hv7v8´}Ple#¬-§–tÿû›)‰JdËÙ8AàI9äÌü8_”ـ ¬"T890NE™Ì–'tðÞý|ÂBŸqÕi÷úizòãaŽ8Íõ`zѲ„ZËÓùïÃÓÿ¼û4=»¹¢CMFc¥éð§ó‹÷¾ÅùËéÇ‹ç?ÿvùndäpzþñÂ7_ž}8»<»8=³ÆˈB;™â 0r2=?Œþœþrr6­ˆ™dTàêÿ:ùýO:˜¯¿œP"œUƒ{x „9ÇË©QRˆªeq29ù\ŒÞ–C»„&¥Yq3kN„Ö|÷´~ - -Ó†[¡ˆÕJ=˜uì(È´ 8aB‰Z œEZp $¥ÙÀ(G´à¢ÔÂçmºþ6Y;~H²Šñh³ "¢ewìµ]˜¦™²a–ûëê6ͳü >Ðá_HÕ·@;Ý îäðcžúæÙj¹\…¡ž^RÀ3,f3FœR¼œòzµ™Ãb;»Á;>¼n­ße…“øǨƒo_]ûõ*£ÎyzïŸýR}ã|›v-f³òÐJüe‘-³M²ÉJN๺þA)_¤þ~ž³uv»Y­A𧄠L -5ˆ5÷<(H)Õ@2¬›=dÅétqèf)ïAÄhmtMGJ ³eºÚnúö9 ·ñcöI-ZÑóX|(5~<©QK8W=B–1]ŠàçÅ6ýnf7wr4FÈádò­øÜ/»óO8Ew1 0ÏÃ6)|Ã5ÒMÃC–ß­¾¦ó=òmÖþVÅ«A„\;»_¾Ú9b•–ä«Ÿ,_}TùÆ‹?®€·ëµ•D0izl q”‰‡>Ì« -Üp 4÷J5Zñ›…­ׯ\YÐF'5{Ûƒ¥ª(ÕhÅoVªšIeOü£µ ÎQW -é¿#ÆØ0Y¼ÛlÒåíêýÅdrvêev—,²yäþOd¯£%¾Ù-ª”®ÇÑkÅ!xV¶%Æ_Ÿ'Aˆñfi:ß+ÁhuÇ’ Ä,ŽQù’~„Ø%Aé°}^Iboª[¼H¿¯Å4a†Š–3®û@ÜkJ£ÅÍPC”ÓO2ÏÕn**‰³¦Ï -@/ΔwQŸ×ß.1ØŸNóü€\Òû"Èó†üum’«2mÂL-÷cÙiµÍ硤RáÒƒÂßþA½ žY rí©`Bš¥>•xˆ÷³| _mÌ! \jÈ’ýb»RDH­C—â6e˜ùᲬzs“âƒdwüîí*Ÿ—ù'¾¿n ч5 ¦†ç¹‡pÁcá+µ®Ù'å|~$Î! rú˜¥ eLµxˆ!)”$`)ÊN¨´‡@8 6gùc\Ç£G(CŒ0Ñĸ>Ö!bÄ «”ðC‹°ƒ­”»9´Œ@¥ÈbE±GCµ†¥µxäý6…þeRÕÂðá*ÝܧiÞeòÀ IköŒ=—€.mÁò9}áŠã˜d—p ¸TkÕ Wˆv?Wòcˆ?×–+]A‡å¦àúx¥ƒ’N>[l ˆ–‚ó΃Óé@ !¸±ÝÇhâ €õNÊç[œŠâ8&Ùaq Ü+Çš™w!P͸Oÿ~Äý2[,²"ÇÂê- zøK±ø®vLΈL[èEò¡¦©G*\È]šgÁ[AÃ}¸ÎSt˜yÚeê$(T½ÛÖaøLaN%ÁU‹}Á¡¶®¢8ŽIvØ: dœdÍ̸BÚiëTÑé«À<±”†Ó›Ð°HŠ—+Ó -c3Ööøi¾Á⨰bXܬ¶‹9ÞKOÚü&¿ ¡tNC‡¤è”/l½ÆïtÉ‚KˆÙ på`$;‚|ÅqL²K¾·€1lf.}É?º6²$¶Ž(Á™HfÀfXÕ@‘,Ó$–ð³BwXðoµåÊø¨Új‹ÁÀb{ÛÀâËÚÀâkˆË’…o÷çÀ®Ãõæx¬‹éc]pg1`ËKRf_îp .jŠã˜d‡Q¡Œ®e3ó.¿ ¼.Úæ£;Bvš$ã™iKÈ…€¡æì­÷0Æ@ßÑw ª)%ÀL µ&>|t(¨&–coÙU/¨N)%XD£™/\á‰'#r™¥ÃI8ºÂôóüÇáü¦ŠM6 Õ¾SH£6éºèÐò0iÞgLê“°@oŠˆ>Ï*råSÒ·5f}îoÓu ÑÝ|»M‹ðW;6¦ÓbÁ˜Vž÷·÷Ÿd' vHyXäÛ ãXaF×ÖS+ +œjÈê§Õ»È‚)‚ôPÛÞÛÓÓîe— ‘‰èCÇýˆˆHU>:ë§PÕQý-Ïþî¢ -HÑ6ösð4ïWË$Ë=ñ2ÙVnñÃûûdS§à­ÄH@¤\[œ)œ&ûÉð0!VÞo7E6OýC“7 ˆóµçz³¨ár5ß.ʨc®ËÜ›+]95¼^-«{´íe‰¢\+k¹S¶BÕqá¿:¸eH[Émú¿Ogd ‹’ZVNùßÝ¡+¶šç‘Ï/üª¿Ú˜UÜpÉ‹ÕÆ¿O ÿ²ÙÌåèÆAŸ»$[T\ƒ€<8ÑqJ_ÖÀ=EMöú?ý=„šé-Ë‚UŠæ¢Ã|U-þô,Œ½ypžÅ§ìéâq¡ C¤Üˆ¢Œƒy€+ü!5âi¾ {TµzÄ#Žš©±P ¡-\+ ·B•5É…/nN¾-¯V 7¾ù0æ_cð“”x’ç-E$(à~\UŸ]7ŽdvÙatRÉ¢½'kYHÜV–ïßšæ{¶æÎ þñ6íª‚\ã.tš4öŒEö,„Åõv±¨Kƒ’ -ȲÂ÷;Ö͉¼ÜØp“ÜÞ.²îò~¨±âÖZ5[¬ÃpH^8;ÄJC(Wqä­ÌNXEúz^V §šõÁŠ3¢”±¯ «Gmhµ?ÕÔ…ºm>‚ÂÆæû,˜#À ;ÕðÂNY P ߾UxEz;¼^À‚s'!U¡®^-zMx.0Ë=Ülzg8d¾[)1·Çr%/¡Ë £Êô)ØÒ.|=ùJJù)Ëçß±çË/¯ýõ* OMhVìQY$‹·¬2ˆ¹™¢ªOeF`Ä^u­òü™*›‰t¶y‚Ö¼8ô[×$ÜÌ©¾˜kLùk+­Wa§A-u“˜fÅM•¹tÄn;UÉâX*«> ~ö§Ä‘Ê8'ºõ:,éˆåúUã¡w3L'¿c«)!Ë­¦„&%‘r§as–ÏVËúiV+Ü?קöŦûƒ‚£3YQ#6ôa:LgÂÇQUÈ/Ê Ú»C&¦4qN˦TÕ]áZTâ鮿0ëÏ/úb/ü˜Ÿp%E»€R¦ó{@¡åy|QP3«i½vˆA„¨™x}P÷ú¼Æ©&Âi ¶¶C€Àҕꯙ4܃µ+Ž¯âi|ü×·x㟷åunÖÂÝ~ܶiý1M7n!ßÒ¢–Ò±qâX¸}ä”iÈœ”ìKN™±„:õªÆx’æó³õº¸gþ{¨Ö…e­OY× ±­Hñ›/¼ƒ|u]~^‡Yª¶´ÊRáU“¥Ù|fÕ™˜–ß^ufú˜¬qWÕ¾'Ý|€i“LURkj0>në jˆÐ¬äñïm‡ šÖª°{©þXùíKXVØËÚZ݇P% ³êUóÛËtv÷T„r*ÂßÜšÿˆa›Û,-?±Å—- âg‡!(ÇÏÛyžÒ†zR}`ÂÀ|C8PçáØÙ_‚åOCo´¯ž@]‚7hºýljóö”Þ2^…ÿ\%¡´~~úë§ÝVKõKp(É—=%˜X÷Ç2¢‡è¾DŸiG„Œ¬) Å±½Gº|”q°áðØZãºþJ½yÕ¡ÿ8mþƒ‹¦ÆÚèϼuŒNšAØ@ËkÝšÇó–(Ë›nÑâÿ±%Áßendstream -endobj -1616 0 obj << -/Type /Page -/Contents 1617 0 R -/Resources 1615 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 1603 0 R +2142 0 obj << +/D [2114 0 R /XYZ 85.0394 483.0356 null] >> endobj -1618 0 obj << -/D [1616 0 R /XYZ 85.0394 794.5015 null] +2143 0 obj << +/D [2114 0 R /XYZ 85.0394 479.6391 null] >> endobj -562 0 obj << -/D [1616 0 R /XYZ 85.0394 459.6946 null] +2144 0 obj << +/D [2114 0 R /XYZ 85.0394 464.8745 null] >> endobj -1619 0 obj << -/D [1616 0 R /XYZ 85.0394 434.574 null] +2145 0 obj << +/D [2114 0 R /XYZ 85.0394 461.4781 null] >> endobj -1620 0 obj << -/D [1616 0 R /XYZ 85.0394 378.1456 null] +2146 0 obj << +/D [2114 0 R /XYZ 85.0394 446.7135 null] >> endobj -1621 0 obj << -/D [1616 0 R /XYZ 85.0394 366.1904 null] +2147 0 obj << +/D [2114 0 R /XYZ 85.0394 443.3171 null] >> endobj -1615 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F11 1397 0 R /F39 899 0 R >> -/ProcSet [ /PDF /Text ] +2148 0 obj << +/D [2114 0 R /XYZ 85.0394 428.5525 null] >> endobj -1624 0 obj << -/Length 951 -/Filter /FlateDecode ->> -stream -xÚ­V]oÛ6}÷¯Ð£ L,¿E>¦™ÝºÀ’ÆÖ€]d‰i8–kÊ5öï{)Q -íÈΊ ’:¼çÞÃÃaø#‘Hjª£Ts$0Qñ<ÁÑ7øöaB<&éAIˆzŸMÞÍYi¤%•QöÄR+E¢¬üKÄÑ"àøýâîw=M¨Àñ*›¦<¾q?Ùb•-nWÓDkEãÛ7Ÿ³Ù²CÉ`b7â§ßÞßÍþ\ú÷wÝðr6Ÿ-gw·³é×ìÓd– „EÌ\öß'_¾â¨„Z?M0bZ‰èŒˆÖ4zžpÁàŒõ#›Éjò0 ¾¶SGE#Q&éˆj”Œ©&4’Œ²A5‚Ä4!C½õó.oªuµ©šºZUóäÊ|7—áš"!\.J+\ :a¤ - zòšÖ‡mcöÖãi€Oäˆ%¬uB9Òœðvâµm¦ £4¶ dg›ª°®Oâ¢Õ~mžr;šý”¨Øt¨üG^mòõÆt«íXª8ELJùº 0AËC=.\~Bµ±µOõ°ÛÕûÆ”WH ù9£¿@ª=©À>ÕÇíÀàU0.H”°”#ðY ÒBÐ6@¾®˜n%§‰ï3‚ãƒdîSv¶uc¬_ׇ¦kÖ@´ïš/ËІm—ÁµÊzà§ïv&÷“\¾Üس„ÎwA)!2÷"ÅSuat $D]ÞÊi²œËåo+÷{ÎM¨Déuæ2Â."aI†>!κÚ—¡•¡÷b*.:ùÜhè)è®M‘¬3×~ËX -Œ1ËÚø<«ˆó²Þùœ·úU½íÚõc›é0Næ\øèõ>é\ ›ÁZëSWó}Ym¿%)Îú3$·cÕ‚´Z’ëÅR8ô°:;‹Êª¼ì6h`ÌÓ7Ü ®¸­Gµn»ùkþÊg„éë¬=h„5,U ¤5{š=Uöd·ú]Øoì¢0ÖVí!y¶;»Æb[ÔÏn‰ÚÞÃÁì«þP°¦pn¸¬$%þ¿µoÔ%{T«äâáœ3u&×9{Ðg¨£rv[6äüu\šïc›)¤Pªôu!CÔe!T+äý®±ç¬ -T"T]gíA#¬'–Ä`INNYßr¸5‚cÏu¯{R#¡Hú+'î¯*sN[œ\‚ÁÍ·øìoÀ[-{a¡ÿƘ²Ûä…A—ž‹L ÷ÆÑGý)ùŸŸ’/kO¥èøJÑT!® ˆOª=-ÕkGú7çëÔ6&ÉÁendstream -endobj -1623 0 obj << -/Type /Page -/Contents 1624 0 R -/Resources 1622 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 1603 0 R +2149 0 obj << +/D [2114 0 R /XYZ 85.0394 425.156 null] >> endobj -1625 0 obj << -/D [1623 0 R /XYZ 56.6929 794.5015 null] +2150 0 obj << +/D [2114 0 R /XYZ 85.0394 355.0758 null] >> endobj -566 0 obj << -/D [1623 0 R /XYZ 56.6929 769.5949 null] +2151 0 obj << +/D [2114 0 R /XYZ 85.0394 355.0758 null] >> endobj -1629 0 obj << -/D [1623 0 R /XYZ 56.6929 749.9737 null] +2152 0 obj << +/D [2114 0 R /XYZ 85.0394 355.0758 null] >> endobj -1622 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F67 1628 0 R /F22 737 0 R /F39 899 0 R >> -/ProcSet [ /PDF /Text ] +2153 0 obj << +/D [2114 0 R /XYZ 85.0394 352.0499 null] >> endobj -1632 0 obj << -/Length 1321 -/Filter /FlateDecode ->> -stream -xÚ•WÝoÛ6Ï_aäÉ*Z$EJZžÚtÝ2ðfOëh™¶…È¢¦¦ÙÐÿ}<)[±à.0 Çßï‹]ÄöG™ 1Ï“Eš'DÄT,ŠÃU¼ØÙµŸ®¨—I'"áÜNfV#Á3"2–.¢SwW«Œ.XL¤dbñ°uÉ4%”³lñ°ùsy·WM¯Û›ˆ‰x™Þüõð nKHš¥¶ÅVEJDÎr·áÝý¯ïQ:Çá“.†¶ìŸqvgê®ÜèVõ¥¥F<šžHæñ¤ BrgM¹‰hÇË·E¡»nDé[SáäcÙõ‰-r’K&=§„3)RØϹÄý74[0Ã’bù9ñÛ»).*'ªýd³ÁiÀ:¨¾Ø#YQú½ê‘ùl$ -U#Ñi¿44(¬ê 2ê²x¬ÕÁ«ÚšÖC?œÚ0tÎ '¤”äB0w²ýyô‚ˆ9eVDTU™§¨6}¹}žq™$IÒÔ ¿™KH&äìïA·³X†”½*2õ Z–‰ü;p£âµz]9hS#£òUöxó6fÒf›Hþ'äºRÅãÞTz)±‚Œ¾..#¢*3µ5î3ƒ:‰¾Uu·µe|®Š ’PyTåJJ÷A¼°Ñœ¤<Áÿ£+ë•”¶*m¥ å¬ð´Ëy zƒã^}ÑH}ŽcV»†"é²°~¤Ëc)Ï|ÁÕxù´÷»]å8¡ /‡T§[Ø&î ’/ŸÊ~o†ÞÃTCo{Ø>S=PŒpvk)kX»Ã•ö p‘Ú;”¯~ ÍÇûßp¬Náo_U?O}é|³_2QæÁe:§||ÝÞEÞAÀ+Ü hòœ&XÀoEKo±Ñp6ŠŒ÷!L†ºÂ;vª ÒX{å×ÖZר*Ü¥}ªÑe-Ø›²‹fËnm ÝÿêLJñã2|2Â+Ñ~€Î}~‘è(ƒßž“Gh,mwÊÓ³ü¥¶ñKö\Ýö%á™endstream -endobj -1631 0 obj << -/Type /Page -/Contents 1632 0 R -/Resources 1630 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 1603 0 R +2154 0 obj << +/D [2114 0 R /XYZ 85.0394 337.3452 null] >> endobj -1633 0 obj << -/D [1631 0 R /XYZ 85.0394 794.5015 null] +2155 0 obj << +/D [2114 0 R /XYZ 85.0394 333.8889 null] >> endobj -570 0 obj << -/D [1631 0 R /XYZ 85.0394 769.5949 null] +2156 0 obj << +/D [2114 0 R /XYZ 85.0394 309.8192 null] >> endobj -1634 0 obj << -/D [1631 0 R /XYZ 85.0394 573.0962 null] +2157 0 obj << +/D [2114 0 R /XYZ 85.0394 303.7727 null] >> endobj -574 0 obj << -/D [1631 0 R /XYZ 85.0394 573.0962 null] +2158 0 obj << +/D [2114 0 R /XYZ 85.0394 278.3282 null] >> endobj -1635 0 obj << -/D [1631 0 R /XYZ 85.0394 542.127 null] +2159 0 obj << +/D [2114 0 R /XYZ 85.0394 273.6565 null] >> endobj -1630 0 obj << -/Font << /F21 714 0 R /F22 737 0 R /F39 899 0 R /F41 939 0 R >> -/ProcSet [ /PDF /Text ] +2160 0 obj << +/D [2114 0 R /XYZ 85.0394 246.9367 null] >> endobj -1638 0 obj << -/Length 3450 -/Filter /FlateDecode ->> -stream -xÚ¥ZëoãFÿž¿ÂßÎbYóÐcŠÃé>®é»½]wEÛ²¬Äº•%W’“ºý‘CÎX²•fb±Ñˆq8>~¤,f!ü³(b#Í,1:ˆBÍòÝU8{„gÿ¼¿[Ýß½`%¥Uì—¼ýqõîÓõBF!Èx { çßÞÁ -–bèòùÝ›ûOw«ŸèîÍÇŸïÞ¾ût{èùêîp«w+¯©¡6E¨PM¿]ýük8Û€R¿¿ -eÒhö 7a Œ‘³Ý•ŽTi¥¥ºú|õoÏpðÔ¾:y:" Ärâx¤œ:žÈ±å£Þ7-mn‘Î º+뇦Ýe}ÙÔDp×móLƒ¾¡ë¡ãWnßüÐí-Ǧ/òžÇæÀ«uEûT´¨ÇG`6ý¶àÓ3Ù•A’wz·÷ŸßÀáEÑœ­f´Q© ÏÍ6Oe×´GbŸõßÐbhC ƒN“Ì`&"J"ûêßÏÏ7ÖÖ"™%Z:Ñ =ý2s£Îƽ°¾aF×¿à‹«?ôûo–Kød‡./Ú>hÚG/÷‡õ’IK·»åí 0âpFd‚0ÔÁ¦îÎÅ× -Œ, åHþ× T&MÓió\xŽ¯lLÔjÆÜ4—F"Í…†Ï,ÞϺ\ut¬—ÜpٰɈ™ÐÒà8ÖÀw`ó)p‡—D»èu½aοm›†í8«7ŠþPn&L0œ-$ƒ!CúˆÞ“FóûwÿÅQÌСõ=/{¢–ÍÛ7]W®«‚¨ÖŸ€Ú^§óCM4U@-™w6á6R$žyB¾%‡œ’YÅAd7¹¨ŸJš^§5~ £ðЕõ# æ|Uµ.Â8Hµî¹U¾ ÿÅÔºi ãÐðô‡Ccر“í¢ë#¾„'dJ >*E”_º}‘—G+“Ò‰• éü)5­6²ÄDBúà°è'"öN–eÝì)"w[‡›ÆIÊoÖÙnZÑa`ŒÏD{âPÎW[<|dg5­·-ª=ÊÇÒ'Þ\wìúbG»"?´e¤»õ‘fì«,÷J!k±œXþŒt -¾€(‰Ó©ô[îÀÈ×Íï8äý¼-ó-˪¢QUîÊþ¹í`“í²G7nj—RØyF€qâÈ·Ï]Ù‹Е†1ù¶n`!|QÛäóp@I´˜?Yð9L‡äð€ä{pe1ï(»Á}ó@3Ø«€bEÒnS@ÈÖee•l© ]½G—ÙdÅÎ1ΘMÆ÷‡zß–OeU<’eØÝ 4b ÃL˜¯„ˆ¤@l¾š©¡ùb2‰œ?YŽ—6¨I{/@_3T"œÿçÚHºÃãcÑñéÒVkò}<ÆÎÅBÆÃ9dÐ:Ë)ܬÎ3˜2‰ ߈t<¦|H2‘õ Î>à`|”Jã±ñ|W8QÂØ3Æ«õ7¸¿g»}ÅÁw6ÎãMUÖLÆ“·”&ãgì[À¶d>ÙÔ¾ £ÕWìËDÆ/;áÍC­‚P†Žßò)k—/Å8\™&n*x³RñÜïÍíˆmy2¨EiªÎƒ$J)œš³àѽ”!ì%!ä`â3Àl%2”ŒÍt:ÂfüÞè$—‡®]VMžUËn]Ö¼wˆ¤!:…½?&ôt½P’ð¡žR¶Š |ƒQ¹ºEpî_¹È–@À;Lœ§@&*GÜih )ÄÚß·¬el³ˆ¥O™L 0V -ñªÅ€!(Ÿm/Ò6rG]ãrÏMû…(f÷E[éYY;IhBÖöe~¨2–tC\Ê[(S0Bù °ïÜL„,f’zbÁÙ -â(:Kè/Y1à©4MÌ d¡%'« -Êi”•pTh 8²Ö ³èipà”šq"¼P˜}k›ñ¨¬óê°)858Žý–ój:È«¸b7^’ʦw=Ïyvîö2rdö7ŒªÆ,­,`|67é©,ž18O©TGâk‚A,ƒ$J\à,y=BM!†yBˆDvkSnƒÁ/a(«‚ÐìLGéü' -Ÿó#:ûrC×ló¿Cן­÷”U‡¢ó«(‰1®ÄÑX=„¾:;¾ƒÑ¥ó$°M;€õ²åNT‹ -Òeì".†Å HkuRÚ¾Ü,HSîqŸ¹,Ï›CÍãÁ•Ü`H]àpÄhq–­îkÞ&‡ç²ß”(²¶* Y Ó±V4› -PÑ’nhhÃB–㾄hY?8¨‰‚AƒøF8ùëɈ#`Nâó 4" FEãÊê…S‰dô*>VP‰ù‚ ë³~(yÝ´ßÁ#Úð°Ó(>ËEÛŒÂJ˜`_·Y[ZƒK³ØHŒOÈÂS´Ûg¢8O@`dÒùwÍs1hY¤ Dñ}QoÏÀ| ùRßä@ -„Wª¥1û •Nt.@ÝeGšÍzL-ºACáò*g̽7Ÿú±;÷‚q±)D¸Œ»ÜOË?Š¶™‚*HŒo´M…°LYµà+ÐÎCL!Féט©!³ªy|¡“#Ãä„\\õ=Œ5á=æYô9Áƒ¾ÜM¹iªÐM¥¯Á&Ø” -D§D¸¦ÀýÎracñ¿çböÏqý±-›vèFrŒ¸¹À¸t) -ã¯q)ã*!7ð`½iþ TRžÚjÀ‰ä ‡.ˆz_+ Ü–òmV?Žn#¨¥C|,ºŽK&Û\â®Ù”8)wmHÔœfçú APa¢ôy¦hÿ´Â€ëCy¾mž§NGÉÀÈX]ì‡ 3×½OúÓ?ÁYg°Ÿ¥“è‘‚ŠóàrÃ]ŽAƒ•3츓:(½)p -s åÔ¶öóÛ²§Jhª;­@kÚÈè«ÚÓ4a£MöÿÀˆ!ÄD&Ž_æEï…À‹‡î³V¢ÿÈ mÿ -ØA{à–Âj’ÉXÒ‘œaC`°}¨ R¾Dü8LÌWðWÎß]ôue&2ªŒCB„¥g¿ÍDjcMŒí^O:°„åÝNÎÞ6°£Ù`SŽñbÈÙn*š›I­$°~ -ˤ2¥=5½IÚÁQa…(lÚñ°ò‡5¬f/bA|†P¶|†±€¹wtk‘=HÉìE¨î±Ú·“N%¿%£õƒýÝP3¡d©*ÔPØÁº`àBæQJ=8[_KHjèS j¼B·S *‡yÏtÓ]ÏBå}Á3÷¶@ÏèèÞv¡Ã–™[UD¯e4'4,¶,±ÎçNÔ¨O€P‡Æú×ì= èà§o=Í;Ç.…º>¹Ô¨ùíæÉÔ(ÎsŠ³ÜÛ#˜R™Sh¹ßo²¾píoî<¾Ú¿å¯„Ↄâ@ÈùÆñGêùãø!Ë9ðâ]·mÕ†Æk~N»â¶‰§µWµ57R=`ÆN€!`Æ+æT𬮎S-ºg ØŒâºFÏ7 ßo©š{·Í1 ­³Žª EñÝhWJ©ùÝDÈ6¨¿DE—r3õ|ÛPÙ¤“¿AÅÄ°r84wÃþÅBV¥Ÿª©W÷ÂÒˆ“²zYOAez-P ¨ø¯)‡ÿNtÛmÒ¿ €&Æá-€íÍó‚z²FMSÇþàrÊ% rqÃÉ»¢ß6ƒiP qúOšàèPÊ'í쮡)îÁø,pŇSŸ\ÅP¹ŒLù¤Þhq|ÿµa %ÿBø õbYWÚB&¢O°Ö£5XóÛªkXãMïEÍ‹‡‘ð âXè‚—±ú¥>lJ¦ðâÉ(£)=4|åd~úDmËØF’í˜Ð ƒ±f`­Ð¥«²'žê¿ `ÇŠv¤ÀÞŠ?KwD€á3•w\„ ¸ú‚7´û­M‰“H» ê±vÊðsjjS˜‘8-¶¶¹rÖ÷x¶z¸fjç«Áȹy¤¦¡ž9—‚Ýõ =ÆSþóŠî‘ÑÇ– V¼~ß6 "ü°ØMÅ0½`G²M…çŽ5}v˜¨uN‹ž°g¶|«²(·wÀM|C1 yâýQ‚ -­ùt%ú²b7†8LûM¬oûw6ø¹ØÁ/l—Ûr"å­nÖÌ=oû¾yl³ýÖõðqv jl?ô3Zó»"«§u‹& ³‡ú¸ËrvŒ?7=Öþ3EG“°˜X}¾û'Ái+òxxXZ“õK1ÕÄÖ¾4{=¦áÝÜ;,,ãò*.Žé‚¨6ý‘@ ѾGÔà‹à¸b¾C§$1#×-ÂÂÖ@´<ÿR;a[®ÎqõÑ Ó¸Ÿ6ÇŸº­Àà@åSò !\WÀÛ$6p&ª> h$V®!HjZ웪ÌÓ-Œ(ñŸh½¶¬#ð`}ªø6/—ZPi)5õ#†Ð×4ùGB'œ0O¥ƒ"ã¬FO -wf Éݯ‰.Eÿ?€ž¦ùendstream -endobj -1637 0 obj << -/Type /Page -/Contents 1638 0 R -/Resources 1636 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 1603 0 R -/Annots [ 1643 0 R ] +2161 0 obj << +/D [2114 0 R /XYZ 85.0394 243.5403 null] >> endobj -1643 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[0 1 1] -/Rect [63.4454 738.9144 452.088 749.0762] -/Subtype/Link/A<> +2162 0 obj << +/D [2114 0 R /XYZ 85.0394 173.5556 null] >> endobj -1639 0 obj << -/D [1637 0 R /XYZ 56.6929 794.5015 null] +2163 0 obj << +/D [2114 0 R /XYZ 85.0394 173.5556 null] >> endobj -578 0 obj << -/D [1637 0 R /XYZ 56.6929 723.0302 null] +2164 0 obj << +/D [2114 0 R /XYZ 85.0394 173.5556 null] >> endobj -1644 0 obj << -/D [1637 0 R /XYZ 56.6929 689.3491 null] +2165 0 obj << +/D [2114 0 R /XYZ 85.0394 170.4341 null] >> endobj -582 0 obj << -/D [1637 0 R /XYZ 56.6929 552.677 null] +2166 0 obj << +/D [2114 0 R /XYZ 85.0394 144.9896 null] >> endobj -1645 0 obj << -/D [1637 0 R /XYZ 56.6929 525.9649 null] +2167 0 obj << +/D [2114 0 R /XYZ 85.0394 140.3179 null] >> endobj -586 0 obj << -/D [1637 0 R /XYZ 56.6929 411.5673 null] +2168 0 obj << +/D [2114 0 R /XYZ 85.0394 113.5982 null] >> endobj -1646 0 obj << -/D [1637 0 R /XYZ 56.6929 383.9327 null] +2169 0 obj << +/D [2114 0 R /XYZ 85.0394 110.2017 null] >> endobj -590 0 obj << -/D [1637 0 R /XYZ 56.6929 225.6356 null] +2170 0 obj << +/D [2114 0 R /XYZ 85.0394 95.4372 null] >> endobj -1330 0 obj << -/D [1637 0 R /XYZ 56.6929 193.4614 null] +2171 0 obj << +/D [2114 0 R /XYZ 85.0394 92.0407 null] >> endobj -1636 0 obj << -/Font << /F37 802 0 R /F71 1642 0 R /F22 737 0 R /F39 899 0 R /F11 1397 0 R /F41 939 0 R /F21 714 0 R /F53 1029 0 R /F48 953 0 R /F62 1062 0 R /F63 1065 0 R >> -/XObject << /Im2 1051 0 R >> +2113 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F39 1151 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1649 0 obj << -/Length 533 +2174 0 obj << +/Length 2889 /Filter /FlateDecode >> stream -xÚ¥TM›0½ó+|©¸6Æ`³IÚ²RÓ4a«ÕxT‚Ó@6ÊþúšŒ“ -{ZEóÆo>Þx€"b~ Ž “!Šeˆ9¡å[‡ µ9ûîPËñ/$¿ÏºK¯ßXŒ$–Q¡ô¥—K`"Eiñ䎌æétáù'nŒ=ŸGĽKfðHx,§ã‡E’>ÿš-“Ét1òâÐMƒR$˜Ù­-LM¼tÝ$ž8ð‡'žüˆD“ r‘ç`o²ÝŸ9“oÐwu†¥Í¹2:7­.îÏþxOƒI„"Ÿø“û'c¬9aˆ'÷»/ÓQ4ƒœéÅòâfùéjß]ÿ5;'ž3ýÛñœx56WW‹ÍýB~\/âùru&xvø‘3ïî«ùòOÑóQÝz¹Ø̾Þ8[Üë¯mþ4ìPþ¿Ÿ}ùêLvð ?œ9ˆF¡7ù „£ˆLög®G‘çRªZ²³ÍÙ¿ô€Fo}kïTaê“ž¹"x‚1Š<´&Ë‹O ­'kÍÊâxØ29l[vâú~3ðöÊÊÁ_I1 +<ahX‰/Eú*+þ¾¬ß_bÒ¯]eLL‡Ø¥µÕ©6 mLä‘ ­½b?áçc:¯6âb½– ìoÇ!yZ¥E^ÏIç§`Ç…i¥>| >Ð;¸‹8ÓKô~‘)c,~°Ã ‡ÓçäPÕxz#»âú?™Þ&ûä¥(eïZö>dÙ>És9h’ïDóÝ “H ~[l_’WVR¸¾Ì„úJçbÿø´­ŠGø5eXt"ìG +}w„°i5LX[iÂã¶J7„O´{ ·´Xøé«M|§–=w¦í½˜A;ˆ‚ÈÀ öHü¿HiþM|˜øh²÷²ÈX–%òž.w˜Cú# + e¥9„ƒMÚàÐÕîç`jÇ|-Ó[–€;Á¥?}*¢mñ뵦ÁÊRL&tÞÛ„»ž°Xæ`¼× þ4•Õ3óbŸ¤²s•ìeë歬ؾ+u0òxm°R Þ+K~¤¥lk|:>ÏX’§,CˆX ·HÅoyk 5ìQY_K±>æLƒ†A{Ñ ¢#  + he¥AêX@Û¤ Ð]í~ЦöG&×øâ×ö9ɿɉ˜³Œ}SÛq'‘Û:\žÜzµé;Y…$2´}°RG§¸jí‘ݳ“…%Èuý1 +†•…‚²Ò`¯·P°IºÚýLíù&?ýã⯲s¬Ø,¯dSšwç]ù?ý +?â7?Òù1Щsàží’º( +ü6¡¹$´HÊ*K^˜l¦µ£ïÞ©s±ðûgM,&†af0 †•…˜²2ˆb6iƒXW»Ÿ˜©½ÞÄÜÎ=ØYEXž(E_q@ü¿Ø&ÁFQã‚Z}ƒ¤Æ¯G¨ù +\'4v¹@`ã£Ø\ÇÄÆ?5ØÄaFÔÊ'­0ÝÐA>Lº¦i5 S[0-»Uºy¢Ý ³¥½©ŠC½KáˆN/ÙAlapød%osk†¼¯fÈCÞ(ò+Å[Œ0$aH;†ü~Îßkºžã)†Â¦^aüâ“4¾:îöG8ÔÊùŴ‰´ÿÄs]8Ç4 #° + leeÀŽ,°mÒì®v?lS›ÃNÄ>ŠsÁÙô©>µœ_³º2#zas,E*[dè ÐéС7[‹8K¡7”¡7jñ÷[¡×Ç'>,ú. çøÐƨVªÊª¡êZÎ1ViƒjW»Ÿª©=gU²}f»ÿfcÙ»QèÁ³K©ëýŸ·J +id„ý4¦Õ0m¥Ñ¡¥`•nÐœh÷¢ii×G›@ÕéBQ€…yŽ §¥QàÒÉž’é3¨òÕ`ZÊ€h• E×fÍ+3Ÿ‡|Î ¼ 1…ZȨ4%!Ï( ÝHÃE™ªX«leÅÆX-’÷ìñ0 §M6Ig¸DK}9$Ä#+À°²¬e¥W@„=Ë +°I+ «Ý¿Lí{Ôu]î‹5e×¥ÓøX=ö[½‰®»"ååÑÇ¡®â»ûµðOÞ_3æ}í¬“wÉä¤?ÈúžÛð†hÁSÃú.•®‘Wä‘ÊïlEÕ {…ø¡Ó;G +ÛðÈ‘·±±06Š ÅØ^-¢¿¶j?½F•t7×ñ90d6BäQ—Â-D‹L^àJj±ªÞ£z‹uõ7®G¶Ëx8›c°ˆ¿¤uæåE\#þò‚tò&™ª1ZP"¦}Ä Ç‘…£4j@KÝΦkì÷£4„ã&]ÉøZ?$üÑ`'¿¿IËJ¦ž"ö:íbo¸ùáé+‡²w7Jcðì··T#ôB^UlŸOj4V`qÅ‘˜a4 Li`^d) Øt`]á^`¦°¨¡†p"üU±¼¬ŸTÂ숚*ü/¯¯Å¡FË;ÑøƒJQ6‡F¿¯2`äø‘±ºÄ›n¸ãþ¹Ø‹|·^ÊÖëc +¾šÈÖϺ`]Ë4OòJv‰šU N«µƒiqLË2í«ÿa:L˜o©3†Ø°²0VVdK5Á*mPîj÷c6µ¯aÒ2ýœQ9ÛCþ’?ó®Ó<Ül|Oº\˵ËÞòFnu<0–Îwu,«ä©l2ÇÓíªg0­÷ .XÁ”ðƒ< +ŒÛÏiueK×±ôƒƒæÏBŽãŒÄaÓj˜¹¶jÞLpð0s«tÃüD»—yK[ÏÇ"ß»ø+Vý,/MÓ­ ~‚é;üd'DÄñCK˜ýl~h½u Äë!ÍTò'/Ø‹PˆÇª¦•…’²j(ÙöK«´A©«ÝOÉÔ^³ïÇTìq{–«íPo‘Í#/þéºÐ湚»×,Ý…ô¦¬+#wŸ[<¹ÂùÅ!Ù±r¹ +…º#õ:ÓÊEYi(^ds›´¥«ÝÅÔOï7ÕḭD˜d™7žmôl‘‡ü€ºíÉÿ ãóa ±~ãcðÆÓÊ‚AYé´ŽbË®e•60tµû1˜Ú—YR–™> +.Wçñ|¾FñZD—øw¦~TЙìkUUIw9SAèJ6î$Í«z꾅щlÍ£ü~dÃÏu1dwGÛ›VdÊJ# ‰å4i•6uµû‘™ÚËøBm¼DÁ¶Ï9„§L½Î´ç1NîC݇MyúýȺ‡ лéz~ÐÛ–±DÇÊŽ§^I§‚ö;•“~f8ö–…a4LK5eb©TÛtV]á^T¦°Žqn¨bœñ7ƒ´ºsnÔ©b‚å2^Åâêr…tÇÉÐû¼¤é“ÖÓ?±N©áv3¥†f#¥æÒè¢.lå¹x òüßµ·eYšìÕ‹Z¤uö×ÎÚyÍnð i©³xˆ¿OÛ3ùŽ>“þϯíUñÑ08¼2ڮ嗪+ñ„œ|uõ‚ïéwÿq O,endstream endobj -1648 0 obj << +2173 0 obj << /Type /Page -/Contents 1649 0 R -/Resources 1647 0 R +/Contents 2174 0 R +/Resources 2172 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1651 0 R +/Parent 2112 0 R >> endobj -1650 0 obj << -/D [1648 0 R /XYZ 85.0394 794.5015 null] +2175 0 obj << +/D [2173 0 R /XYZ 56.6929 794.5015 null] >> endobj -1647 0 obj << -/Font << /F37 802 0 R /F22 737 0 R >> -/ProcSet [ /PDF /Text ] +2176 0 obj << +/D [2173 0 R /XYZ 56.6929 748.5056 null] >> endobj -1654 0 obj << -/Length 69 -/Filter /FlateDecode ->> -stream -xÚ3T0BCS3=3K#KsK=SCS…ä\.…t œ;—!T‰©±ž©‰±1ƒEV.­knj©g`fA‚!ÂVŒendstream -endobj -1653 0 obj << -/Type /Page -/Contents 1654 0 R -/Resources 1652 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 1651 0 R +2177 0 obj << +/D [2173 0 R /XYZ 56.6929 748.5056 null] >> endobj -1655 0 obj << -/D [1653 0 R /XYZ 56.6929 794.5015 null] +2178 0 obj << +/D [2173 0 R /XYZ 56.6929 748.5056 null] >> endobj -1652 0 obj << -/ProcSet [ /PDF ] +2179 0 obj << +/D [2173 0 R /XYZ 56.6929 743.7078 null] >> endobj -1658 0 obj << -/Length 1964 -/Filter /FlateDecode ->> -stream -xÚ¥X[ë¶~?¿ÂoѱV”D]Ò¢i³§I¶EÒ g¢íé-imõH¢#Rv7¿¾3œ¡,ÛJS »&çÎá7äˆbÁ¿Ø2Œ’2ÝäeÊHÈMÕ¿‹6{à}óN°L*“P¦I“îV&E(‹8ßl—F¾zy÷øu,6qfY,7/¯³¯,/Â2IËÍKýàé Ž¶¶±Œ‚âáŸ/"µ4Ì‹\ Z.d˜—Qá^„Á¨§]טƒÖ¶ö³šHÃ$ÍbVË’0Ï"òS„âa+¢( -žtßëþ0j0Ó›‹–Rz Ÿ‹Â˜M<ÛϤ ´¥ÁYŸ šßÐì Ï4¨{{¦ŸQ隣¡™ž¼öA]™=zØÉ‘Å›2,³8ãÀ =e*RJÈ,%©v±42º›l‹‹Ä™Õ3õ„Ér“va¨®SI5Ô4¨ôÀQ.¸­1ScüøÚ¶UŸ8Šãø Š 95ƒÝSûF™‰8¬¹{Ã¥ábæœÃbLc݆nã<¦#þfA§÷û™ˆquh9»æU“ÕÄ‚å2¢„°ÞNÎêS[³˜"ºÑ`ÅdýJôC;Xvçòƒ´v¿=ç96X´Û0Ø5× n“ijÚ_LÝn+à¤ÓÃÂ…ïÒS -i ·¥Ý3éÀ–yíˆùðŠ&Â8K<æcø¡›‚hïCû™<»úÐŒ­êhüýÔï Æס\@•‰ó÷w= vVXƃÓÆ-ÈÊ@͉ο&DüL|Œãœ¤!š7¢±Þð+Ôʲb@4@™ þ@ŒN³¬CX;6úØÍ2\ô<Ò스‡yÑ· g°È”}sɘ†€G€"6ù93À͵úFtür²e€h$Òßàï»ïÞ¿ÿñÇ©*e§^[ú¤ïÜvzW¿ ×}kì…{½^¬0‘p‘ÒyE?°)e™í0‹Óàu² |d ‡Æ‹o<ÐĪôHÒÕßO'2ŸëaÍžÑ_5±¹Á’FŠ ÈœŒðiÍZ W -ŠØmT¹,(¾ÊÞñ‰}q´€¨\Â&|&d¾vKÈTÝVŒÐhÆKI›S?s@Õ+6¸k0mHšŽµÇrRϯÄ'¨›CZÙN,HÉÀk™ôjY`:ujˆN^®5ôÛé³'A´é°²\¤A®xYöÊ`3§Áçs³‰uÿŒ`°¡¬mú£]­7>)34n-_³•>¾ñ±ûzs„ašÃÙ`M t9hðÃ|K>xÌ«,«DM¿Š~|ª`x‘â\,Íq.¼éÓlŽò{½$çF.ÝÁÌJö¢´VËlo>ͱýãÓh®o›ÿ+Ÿtc‹lѸÄ"'ÛCv0 -ýf3GÕ51b‘æi‘diNŒ‘Œâ±ˆ±0·"ð0àâÄßZÕ7’\sÂw"ó‡&0ÍåþF—?$cRÍZº”í(õåŠ:éH^04g¢°û(½À ÙWáÓ7˜¿S,[>°úŒ¹…;î3`ô¦'bÕÀ¤Ö^ ïöEy˜]¹œ­Þv‹íçÞa¯Úák@n@þzh|ÇütÓOÓ0J¿mºã—¿ÞeÚâš(°ÁiÇEðá êÍâÀz҃ѣm§žæˆ§çOŒ$ ¸aѯt ÇtéùL]%ŒFèŠâ¹Bˆ%Ç#¥ e/v­Î©­XKí)™®×âX°Åu’_=ÿ~-ÃÔ¶GYðþÛ§päÏH—@ -­è×ØÚ:‰óÎÐÃBYn?z·XdÌqâd¾©Üä¤ÚNí:ørðï»QÕaáƒL·CÕMucVìâªV.Wª4 Û8Hü»Uoy)”@»Zìo+B)ˆ×­©ôD9ƒ©;B.ÊõTyåvÂ)Î6™îZds§¡ÁÓÏMí­µ°r=¶öä&vÓž®é^/yr€¡¶¯ÓP;«y Â1{9B€FãŸà{ËוÂM>p\×-ž‘7>å èWˆÌ¨WKÐÆ 5m"û¿À¥–€ã6WUŸÔž9ZØוå,¶VHbžþ‹'¯´=Í\¦pÀŸ'8TÃ[WyÌ#‰6Éyè5µÒÇî:4 ßál 3,•ßbÏ[œ+ªë/WF".ƒ›ËÊ?@”€/jŒu“1Ô¢+l',{_¼2ãâ•sä®ÏñÛªÊ ¿&–Bú–åç !G˜ -¥Ìrcø-Š¼ûãËü -“¤%œ¡i±Iæ² —â~ÚøÑŸ/¯6³Âv¡ámÒ¥ß;»è½‡CÀê/aïoãã<,EQ^Çsór4 ÝÅpµö;[ÃïVÎy7G)JΑOü©5­¿|hW°hpk·IQ„"é5¶ÏÍŽûª‡]Ù)C™‹_Ú‘Âõ%KÄQXDñ¯oʬ±]ªÜïʽe×SX{üâññ|>‡¼+¾,}w¸ÉÀdñ:Æ›š¥îãºÊǽµÿ¶Uø]5èTíŠË°ç§ð6hÿ˜ÈŸ%×"ö"Û‹ ½H.ƒ€k(,â2÷†0”2¹õ6¿oÞ»ûq0Œâendstream -endobj -1657 0 obj << -/Type /Page -/Contents 1658 0 R -/Resources 1656 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 1651 0 R -/Annots [ 1665 0 R 1666 0 R ] +2180 0 obj << +/D [2173 0 R /XYZ 56.6929 719.6381 null] >> endobj -1665 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[0 1 1] -/Rect [348.3486 128.9523 463.9152 141.0119] -/Subtype/Link/A<> +2181 0 obj << +/D [2173 0 R /XYZ 56.6929 711.8197 null] >> endobj -1666 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[0 1 1] -/Rect [147.3629 116.9971 364.5484 129.0567] -/Subtype/Link/A<> +2182 0 obj << +/D [2173 0 R /XYZ 56.6929 697.0552 null] >> endobj -1659 0 obj << -/D [1657 0 R /XYZ 85.0394 794.5015 null] +2183 0 obj << +/D [2173 0 R /XYZ 56.6929 691.8868 null] >> endobj -594 0 obj << -/D [1657 0 R /XYZ 85.0394 769.5949 null] +2184 0 obj << +/D [2173 0 R /XYZ 56.6929 665.1671 null] >> endobj -1660 0 obj << -/D [1657 0 R /XYZ 85.0394 576.7004 null] +2185 0 obj << +/D [2173 0 R /XYZ 56.6929 659.9987 null] >> endobj -598 0 obj << -/D [1657 0 R /XYZ 85.0394 576.7004 null] +2186 0 obj << +/D [2173 0 R /XYZ 56.6929 635.929 null] >> endobj -1661 0 obj << -/D [1657 0 R /XYZ 85.0394 548.3785 null] +2187 0 obj << +/D [2173 0 R /XYZ 56.6929 628.1106 null] >> endobj -602 0 obj << -/D [1657 0 R /XYZ 85.0394 548.3785 null] +2188 0 obj << +/D [2173 0 R /XYZ 56.6929 601.3909 null] >> endobj -1662 0 obj << -/D [1657 0 R /XYZ 85.0394 518.5228 null] +2189 0 obj << +/D [2173 0 R /XYZ 56.6929 596.2225 null] >> endobj -606 0 obj << -/D [1657 0 R /XYZ 85.0394 460.6968 null] +2190 0 obj << +/D [2173 0 R /XYZ 56.6929 569.5028 null] >> endobj -1663 0 obj << -/D [1657 0 R /XYZ 85.0394 425.0333 null] +2191 0 obj << +/D [2173 0 R /XYZ 56.6929 564.3344 null] >> endobj -610 0 obj << -/D [1657 0 R /XYZ 85.0394 260.2468 null] +2192 0 obj << +/D [2173 0 R /XYZ 56.6929 549.6297 null] >> endobj -1664 0 obj << -/D [1657 0 R /XYZ 85.0394 224.698 null] +2193 0 obj << +/D [2173 0 R /XYZ 56.6929 544.4015 null] >> endobj -1656 0 obj << -/Font << /F21 714 0 R /F22 737 0 R /F11 1397 0 R /F41 939 0 R >> -/ProcSet [ /PDF /Text ] +2194 0 obj << +/D [2173 0 R /XYZ 56.6929 529.6968 null] >> endobj -1669 0 obj << -/Length 69 -/Filter /FlateDecode ->> -stream -xÚ3T0BCS3=3K#KsK=SCS…ä\.…t œ;—!T‰©±ž©‰±1ƒEV.­knj©g`fA‚!ÂVŒendstream -endobj -1668 0 obj << -/Type /Page -/Contents 1669 0 R -/Resources 1667 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 1651 0 R +2195 0 obj << +/D [2173 0 R /XYZ 56.6929 524.4686 null] >> endobj -1670 0 obj << -/D [1668 0 R /XYZ 56.6929 794.5015 null] +2196 0 obj << +/D [2173 0 R /XYZ 56.6929 500.3989 null] >> endobj -1667 0 obj << -/ProcSet [ /PDF ] +2197 0 obj << +/D [2173 0 R /XYZ 56.6929 492.5805 null] >> endobj -1673 0 obj << -/Length 2543 -/Filter /FlateDecode ->> -stream -xÚuYYsÛ8~ϯð[誑ÂûØ7[ÎádìrYÎNÕnö"! k’`ÒŠæ×O7ºyØéTJ@£hôñuƒö.\øç]¤ÑÚ ²ð"ÉÂuäzÑE^½s/°öùÇ•²8T²îf²Þ:‹¢A6Ö^yƒì$Mú]·JîiøE™N·gšh&vGIƒ›û- D]°èíý ê_dë,öc>Ӈ˹!ë[vGÝŽ d¼ ~ø~gx©óÃuý\‰)´¶»ôyPu­êQ¬6sñ] UÓø^TLÝžM'+Éó¾mñ‰ú©3ð{YÊT÷V¯¦ß•*Òõx4ÜoEv%K>~Ú B'óÝßhÄ– -\Ó±8 ØãràÔòD3h Ä“0D,¤É[µ³:Ýê dÐ9 QÔ€EÒÔ'{)Áúrø®óɪ¢«q—µÑ$”ÄêY_ÝÔ'ÿ=>\f¾sUË"' Á_‘k/ƒ“†® -¦6pkK­é·ç÷'‘s[w²…-@Ø£åÌ­ßp,XBšÎÞ'h7ü•¿Ù*Œpv -÷Ãa…|‘¥nl Ø-H±ÈZyá6µ¨€÷ƒ( -RÜŠ1ÏuL~”6`l ¿‚~ZѨ¢<ÓCƒÚ̓ý¬j¢$¸æI·ÏÌ]¿(òAw·øYìÜÛ€eö¢ç9'ÉQ³m§Vu´:Åìe/¡P5G*@'ëR¢tGÑ­Ò…Â<x)aA· -’ r”OœBç=Á 1j"«¢ºÑpQɧUäzý"GöÄÙ G,ØÝfS6ä ÐBdz˜€z²Ó„Q™DÏ B0q¶Ah3>£Œ7«®sÙØ£FfÁ'‘«RuJãÆÕùö‘]ôçÛ/¨N‡ÝVM)gQø|$¶Ì­} 8Épat*ÌÒ¹Ã^‰©€ck ˜Ö…/ ‘úf8ùtTù‘w)Ë¥áZ½RÜ0†Oå:»^•˜Ã&Ù:v3*LO„Y‰ÅèÖt4™\a¼°[`\ÃÈÈö®ž„Ž—ÌÉAM´Ěû«„Ä„ €É,Ö£ÄvFø[vAé÷Aô´QêÜéüY4²³Álˆ†±ˆC¶ýB=ù¸!‚nÌÊw‰P‰ü¨jiˆ¯ÔàbºHêØ슆 Â÷ZÁµêμûž¶ºž–Ï܈RvµïY×ÛæÕ¨äjµ¤½¬s«I˜ŒéT×wìDDåïÛÍêv{K‹<õ0Ø>Þá0(î9±Þs@ܘe·ž«„D±é Ønu»ÁƒÖÄqE?cÔq,¦…îÀ³ÆúE£ÁĘŽAÄ)ôkÙ>ËRži6”šQÑÇÑ í%"Û2R¡q¼µ2$Q†£5ÄÞÞ3Xßñ±bɾ¾Ûºù~­(z‚Hׇ î †FX³Á¿,0x,ã&þ,<^ NÖÀY_Ö# ÆÃkfÝOUÿÕ‰[¸‘{Y›åj_¼ˆ1î𥑈6Hy ÿ/óŽ#窀Š -ã”U#7Cã@Q²€.ÿ¾ô™Ñ„K ÷yIJ­¥¥tG6µí a)\§ë€Ö&tÅŒ‚þ[år Òéú@Øèªé)ŽL½"Ÿûæ¢@ù<ópBµÙ>~æÜpËBtG‰ãÉYxEìÅbè á¥…9`°8#Û–8Ϲ6aù/3!(¬ÝˆUÐâ£:J¼TœpŠq«ëÄLM³ÿ@ÏM •($Ñì]€B‰±c€2i ?P‡nþmD4“Ç v;)*¼Q¾Ý3,$¶×`(‡æJý× éz`ê„Þw§Y1J†|%\‹B¡kùüEÙi¸U³“eÉJ}“/Ë…ü¦¯KÑX%=›4øªQÕ‘¢®óñg¯,•Ä²áŽg k ¥TŸ%#.Q=( ‚ש©ö¦7F ŸgàÑ[¦Ã–è@±¸ˆ$ŸægH@Ä%²ZI(Ž":ž( 6SaUŸiQc¢õFêƆEiX*×5ÔÏ]OÕ-ãÖXXE p³Í‚¥¢o¹‡›MÔºõÁùˆ4òK®øbðج–S€¼V(Ø&ˆ0ð[P£ ÄNg[iÝÑÒF´åêNuЧ—%KÞ©gI«w}o }U¯K­yHÝ2Ž"ÛüÁ×ý ÆŠýô3À‹¬ÉC–Påú‘?{°GÉÏæ#Sð¹c"ˆ£oë¥yó–þ®‚¸åé·žøqsˆ™Ìy™Àfá:ã¤m,ßû¶¿š°f¬…´íº¥®ÙÀoçÁâgþe5ñÐ7þùçìÀשŸ%ÃF¨g½=mü‹Áßû R|¢Tendstream -endobj -1672 0 obj << -/Type /Page -/Contents 1673 0 R -/Resources 1671 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 1651 0 R +2198 0 obj << +/D [2173 0 R /XYZ 56.6929 467.136 null] >> endobj -1674 0 obj << -/D [1672 0 R /XYZ 85.0394 794.5015 null] +2199 0 obj << +/D [2173 0 R /XYZ 56.6929 460.6924 null] >> endobj -614 0 obj << -/D [1672 0 R /XYZ 85.0394 769.5949 null] +2200 0 obj << +/D [2173 0 R /XYZ 56.6929 436.6227 null] >> endobj -1675 0 obj << -/D [1672 0 R /XYZ 85.0394 573.5449 null] +2201 0 obj << +/D [2173 0 R /XYZ 56.6929 428.8043 null] >> endobj -618 0 obj << -/D [1672 0 R /XYZ 85.0394 573.5449 null] +2202 0 obj << +/D [2173 0 R /XYZ 56.6929 414.0996 null] >> endobj -1676 0 obj << -/D [1672 0 R /XYZ 85.0394 539.0037 null] +2203 0 obj << +/D [2173 0 R /XYZ 56.6929 408.8714 null] >> endobj -622 0 obj << -/D [1672 0 R /XYZ 85.0394 539.0037 null] +2204 0 obj << +/D [2173 0 R /XYZ 56.6929 382.1516 null] >> endobj -1677 0 obj << -/D [1672 0 R /XYZ 85.0394 510.2426 null] +2205 0 obj << +/D [2173 0 R /XYZ 56.6929 376.9833 null] +>> endobj +2206 0 obj << +/D [2173 0 R /XYZ 56.6929 350.2636 null] +>> endobj +2207 0 obj << +/D [2173 0 R /XYZ 56.6929 345.0952 null] +>> endobj +2208 0 obj << +/D [2173 0 R /XYZ 56.6929 321.0255 null] +>> endobj +2209 0 obj << +/D [2173 0 R /XYZ 56.6929 313.2071 null] +>> endobj +2210 0 obj << +/D [2173 0 R /XYZ 56.6929 298.5024 null] +>> endobj +2211 0 obj << +/D [2173 0 R /XYZ 56.6929 293.2742 null] +>> endobj +2212 0 obj << +/D [2173 0 R /XYZ 56.6929 267.8297 null] >> endobj -1671 0 obj << -/Font << /F21 714 0 R /F22 737 0 R >> -/ProcSet [ /PDF /Text ] +2213 0 obj << +/D [2173 0 R /XYZ 56.6929 261.3861 null] >> endobj -1680 0 obj << -/Length 2810 -/Filter /FlateDecode ->> -stream -xÚ­koã¸ñ{~…¿ÕbEõô²Ù$Í]/—&.Zàö€Òm«+K>QJ6÷ë;Ã!õ°•½ÚäƒÉáp8/΃b3þÙ,0ñ’Y”øNà²`–îÏÜÙÖîΘÁYX¤Åëãêìò–G³ÄIB/œ­6Z±ãÆ1›­²_æWŽçœw~wópótõ·ó…¸óOÏ4xº¹½yºy¸¾¡éýÃíÏO?]Gþ|uÿóÃù"Ž’`~õøxóðéþ_„s…]×B¯ožÏ]ýpv³ê8JÅ\Žìþvö˯î,á~8sžÄÁì&®Ã’Ä›íÏü€;Ϲ…gÏgïVõÖI-1×ñxèM¨Éó¦Ô$NÈ=®ÕôñþáHçÅóY«¼*q’Ì‚½ -EƒúœÅsYH¡dFyI+ÏòÐÈýZÖ4õ\×%QfÊ Að½øOU©¾Öy#i­ÚÐB)E]¼™mEaªƒLCÌb6;³µ-3©é-Ð( ™cNž³xËË-YÑH #¡ñÓŸ6-1ãØÝžë¸Q4Ôì0:R4óáÇ·‚Â<’•4>aòÙu½4IÞhK&„”ŠFfàVœ¹ó‡Êìϲ¼SDAóL¾È¢:ìeÙ@+©T¥=¥<–­·¦ftB%Úï¡ Θâþüµª¿Ð’f~÷"“´v¨”Ê×…$xSeâ†ë7B +@@»U­vùV´qΫµF`’Võ¡ª*I] (2F8"9!u“[WVÆŠ†qIm«MU7ª3žþ-Û=ùVÕš•¼Ìò—> endobj -1684 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[0 1 1] -/Rect [253.7995 149.3637 417.685 161.4234] -/Subtype/Link/A<> +2215 0 obj << +/D [2173 0 R /XYZ 56.6929 199.468 null] >> endobj -1685 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[0 1 1] -/Rect [63.4454 110.455 208.8999 120.6168] -/Subtype/Link/A<> +2216 0 obj << +/D [2173 0 R /XYZ 56.6929 199.468 null] >> endobj -1681 0 obj << -/D [1679 0 R /XYZ 56.6929 794.5015 null] +2217 0 obj << +/D [2173 0 R /XYZ 56.6929 191.7053 null] >> endobj -626 0 obj << -/D [1679 0 R /XYZ 56.6929 662.0717 null] +2218 0 obj << +/D [2173 0 R /XYZ 56.6929 176.9408 null] >> endobj -1682 0 obj << -/D [1679 0 R /XYZ 56.6929 624.1661 null] +2219 0 obj << +/D [2173 0 R /XYZ 56.6929 171.7724 null] >> endobj -630 0 obj << -/D [1679 0 R /XYZ 56.6929 624.1661 null] +2220 0 obj << +/D [2173 0 R /XYZ 56.6929 157.0677 null] >> endobj -1140 0 obj << -/D [1679 0 R /XYZ 56.6929 593.0972 null] +2221 0 obj << +/D [2173 0 R /XYZ 56.6929 151.8395 null] >> endobj -634 0 obj << -/D [1679 0 R /XYZ 56.6929 294.2701 null] +2222 0 obj << +/D [2173 0 R /XYZ 56.6929 137.1348 null] >> endobj -1683 0 obj << -/D [1679 0 R /XYZ 56.6929 255.4568 null] +2223 0 obj << +/D [2173 0 R /XYZ 56.6929 131.9066 null] >> endobj -638 0 obj << -/D [1679 0 R /XYZ 56.6929 255.4568 null] +2224 0 obj << +/D [2173 0 R /XYZ 56.6929 117.2018 null] >> endobj -967 0 obj << -/D [1679 0 R /XYZ 56.6929 226.1045 null] +2225 0 obj << +/D [2173 0 R /XYZ 56.6929 111.9736 null] >> endobj -1686 0 obj << -/D [1679 0 R /XYZ 56.6929 53.5688 null] +2226 0 obj << +/D [2173 0 R /XYZ 56.6929 97.2091 null] >> endobj -1687 0 obj << -/D [1679 0 R /XYZ 56.6929 53.5688 null] +2227 0 obj << +/D [2173 0 R /XYZ 56.6929 92.0407 null] >> endobj -1678 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F21 714 0 R /F39 899 0 R /F53 1029 0 R /F11 1397 0 R /F41 939 0 R >> +2172 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F39 1151 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1690 0 obj << -/Length 2825 +2230 0 obj << +/Length 2542 /Filter /FlateDecode >> stream -xÚµZ]{£6¾Ï¯È¥ý<-’ KÇö¤É4™4v·Ûα›glH ÎLúë÷} 0’;Ûî“‹€tЋÏ{>%ðeø2a( <¼ŒyˆX€Ùåj\n`îæ+™+-teK]//þùŽÆ—ñˆD—ËÏÖZ -’_.×G“ÇÇùÃìößã+‚ѯXèÑé|1¾Š#.&¨˜Š‚Ñõíõ·nž&?ü*ú-`Áäa&o?ßÜÌ˹º}šOf·7 ‚ÇŸ–wó¥ymû§á€Šwþýâã§àr ¿ðî"@”'ìò+ÜsN.÷!£ˆ…”ê‘ÝÅââ'³ 5Û<:¤*FÄèŠàKŒgŒt”Å8Š(¡²uZ¬Óúrþ"ÊØ9š,) M†hÒRùãÓ»)()üÔGÆ,@ ‡w÷B©SlÊ-lÌJbʺà³rŸæ…$ô!Ýg•âX^MËb•½Ôjt$/Þ¥«|—×yÖè«÷3q Å ¼ Àø‡|äqŒ ¡Érì¾\}I_²úWJê¡|ÍöÏÙAÞažÄÈÉŽÀVÂsŒXRF´”Åó0⃶éc;±ÁÏ2r»Ùeû¬¨Ó:/‹/‹—l•ÿd%gOÉ!˜ýAmV[£÷Ä­wh0Õ3z·¤¶Cï6øü[•I0&9U½ìd”/úá9ܺë=é|0ŠÌÿœw<¦ààsXR -´”EñPàƒ¶(èc;(°ÁÊâJ]ÙaŸº"3— ¦‰Ù:—¼r††HÌè°LéWÁ(¬°Ö=wê>^ˆ|~ÝÛRnÝ)£û$ôÔÂ^èV÷'Øúï€/2U P6zŸ½É‹¶ -NWªþ¢h rBQç¦&Ié"p! ƒ á"ËÅíÃC¡(H¶8‚‡Zðp”ñH9 å£jêæ¸ÞCú®dQ@h2š©™yZÕW2ïˆNÞߥ_´ËÑŽ˜¾íZÊ/cNFÙn1¸–8M°Té‰P69í$ŠQ”€êývbIyìDK;á4ð؉Ú²“>¶ÃNlðŽ€ -¤ˆô]Õéó.¯¶¢™òÅÌåû¹ÚQ|zr…΄£G½M£™âDÐëdp‘½ÔÖŽ„Ÿ¡#FÈ9†,)CZÊbȓȼÐC}lC6¸QöSöû1Ó!ÍXö€? µå›"­’Úª%K:oÐä¸ÊåÆÔ”ðÿ7[#áslYR¶´”f‹AìaËm±ÕÇv°eƒƒ?)­ŸîµùN5T†à¸!C>¢Û5q#ÛµÁ`‹ãQ—$o˜ëîíù¹Á@r†KÊÖ2ÜDޜ胶¸éc;¸±Áo²êk¡Ø8–D嵈vqw‡×|•É©ÉnSÂÔv/çdØ“´±îe¬‰Ëôsª½–ôj¸ôß,2¿:¯ÉS_®e(da¯Z(úßM‹¡úôFvÝ—éá|'·hÞšß¡fÔ_åÏå«=s×±² -~ez’pu?øCºÛ©¹«º´Íïoòš§þþfÛ¨¶´5[KßµíIÃ<ŒýfmK¹ÍÚH³&ÄcÖ^èÖ¬O°‡Íº~[¬ÓmåSV•»W­èÅñå¥<Ô'çb>Êԃ؟°áØ?-‹ƒ¡z–­ºá;à …XÅ)=§wKÊ£w-eôžPêÑ»ÚÒ{Û¡w|¹•Ñ åÂK@žîÞª¼’wBÕâ¿ÜZƒ ³µ×jk ®t&×v&øT8I»×&VE -¼þ’ -Zî–ÁÅ“ž„N(ËEHq¤;#UO«E;õ4:É$£ÇgöHm)7™FJ“>2½Ð-™'ØÃdvÀ›ƒ¹0OÀ·j ™ÊõQEv1Ú(X‹’,oÏwn’:»˜ -’†ñüD> ]OÂ0&FïÕèéAuGìŽÄËܧU•éÈ-7Gd‡Óöé®*Þ-ú™›þ£8ÀgöKm)ýZÊ¢ßsîç…¶èïc;è·ÁEÌ”u›(ÀÃadUŠTÒÜ4i›BK*½™ªü-.Z{wf×iðà‹OB«?¦ŒK'¥=[h'ËÄè½7¶ gj[Ü t¨ïXHïLù/”¾L´ã~c°¤<Æ ¥,cð$T/´e }l‡1ØàêÀª.W¥Ø²‚z_®{»é QµœñbDV)"ª·U -ÜI£ã‘Ë.HŒ’ÛÅDz‚‚E»1ÂLØQ]ŒÞ+qm*¼«•;ö Óùßc'\ º§Âíî(é`>r€‚$Õ» -À´jP'Ïå±îí0ô¾ˆpØ!f -ã3­¤%ä¶B-dU™Ï}¸­ ö‡MÐFžŒ¯ -3wÊ,Ÿw¢^ [ÖŒ*…ÅÈ´<Øû©ÍØ/cŒ ­±ïÖÙN­>Ë^vå›~¾Ñó -åçú«d>C¶K¡`Œidå7ÆÁâU<2³û»I_å Cæœ:& ôÚäLcjKy¨ÖRמZ/´EvÛÁ¶ >-÷{¹ëŠõfëÀ·@09—¬–‡JÊH…‰Åq³N¬é„`ü]þmøèœÆ(æØ>F¢aóù XäýqŸêSW±ïÚôy°Úc +ïÔàT >d mâŒ^·Ãs§÷œ¥ÅùÆgîóÝÎœø~ŸIð‘0Šüa ¹ B µT$žƒnk}àak°‘Ù!×G%ǶÚ4[Y¯†ªLÆ,<=5G±Žö\×~ïGI ¶àÏÔÿ–[áZ¨Íø¾Ï¾|¸­ÂûÀà -·‘÷AŸWÏÙ6}ÍE5#P}m kkôÓÒ9áBŸÔ6"²€ÑÛÇ×H^MÖêD2ì #FEÐ|X|Ö~ѼJyÈ«m^§DRãKá%Jæ./öY®P¯ÙÙC²7Ü…¤jñ î€j“Ûÿò—¾ÖÎaŒh’8Óh¡„ðX¿”ø<ù$øôÕÿ Æ¡bxendstream -endobj -1689 0 obj << +xÚ¥Z[w£º~ϯð£½Ö˜Jqé›'Og’ÔÎô´kÎy ¶â°ŠÁœ9s~}·Ð‘<=]yH>Øß¾cEÓ…7›S„ÔêÍíf6„o¾¢éõêúóêñ~½xúø/qѯˆ¢ÅÃRœl¾Þßßnžoåéúv±\=܃žýöüéêöY?¶ùjþÌÿ¹úöšìà ?]!$1|‡äá$ñ'‡«€„¨•üjsõw}Cc·½tLU”ÄýhDW>ž`ì%”ú=eÑÄ ‰OZe-6⵬J›¬,jë[ Oq.-#À#KÈpôoë»Pùmˆ‰)òâžßªe†¨pØ¡bJ½8"Ô„]–‡4+Ä{§»CVdu/_VµX+;]´çûS¶cÆÁ+ázAÆð@ü¾„øOüÿ\6pÏY¨‡ò^X%ÎpGžUÙ@œ/mÈ¡nCÊ¡p%¥UNIäP¹ ÚPúÛ¢vü¦<J©xmyË´IÅÑ]–3qtS¿"äïO‚±x[U3O9M#T€2ƒ0 }*žfØO¦’kƪ†R¹÷¸mJƒŒ„XÉ èB¨2¥ìdh)MF‚};N莌3ìq2zà£dè0æÒ?ŠÝŸ¥ÄÇÔ ãØïS²Tl¤•éw쥚ÅÓSZýÐŒ„vF"xsŠâ ŒRF””bÄG9qAŒ ±-Œ˜àgÊ¿©²†U™t×Rëº,QÒƒô˜ «ÞYUF©(ŒÃ>×’‡/iQdÅ~ÀvÏqþ1£tšýž1‹ç8x}„¾@S'ä`I +i’|œ8Hrà €-È_k©îòuà8‹¦‡,o”Ói’ÖrûîGU¶k,E +²WÌ}’x”B]1|DX᪛+¤f0 f&MnvÖ:F‰#|¡R0¥ì¬k)M{ìS;íNèŽ÷3ìqâ{à xó0œ>Ï0ÆÀÀ>oõF |MÙË_gsøÓU]ŸZ+€ÖFàšŽ>ˆC­DØn•È×#E)4oLì>ÂQ%¯o a8;ŠˆÛ”Û2‹ºÄO<„3Àjq-î«‘Ö­MLæZ~.LCú2Íà•¦2&û!«¯Ó òÂ0º@{'ä`] +)ÒI8² ×à|l¡Ü@øˆ‘„v’@:B»,–ètq<æÙV—°Â»‰Õòa¡Z†aš$€™PluNîÒ¼µ%þÐ +D}`k°ùzH‹v;–<óç‘Ķn‚sF…‹±#ø4¥ w}vÓT`j¯K‚^ñÒ•‹µ±ŸïÄQ¾¯Ì‡‹è8:4‰8Œmúp€ÂŽq~ƒqq¯–p¾óE®nÒ#ü:O‹íkþáAL ƒº”ÍM);áZÊ ÜQ;¡;ÂÏ°Ç ï?ŠÛrÇx§Qç#2½†«n ççÁ” #ψˆì°úµÈø¥bQ$}XK °¯ãFÔÅ XVK2nÌ[òP?½è…`¯ˆB?ê— O•ð?åìguöAq ”²NQe(QÍ+–§*€Pk}@¡‘¡>0¥f¤¤t7= ÃŒ\І ±-fd‚­[ë (9º¬ÎÕQ +u¾ºù,Ī('J¹Á§<¸ˆ½Eõ’5UÛ‰ÝJ#,8y95–àyÈìºÜ“—Šü.ë²fÅKz:ÈužÚe´Wõ‚…³+&P²äB fÙYTBšÄ;FB.ÜŽÃ!ð8…&²ä‚WUý"¾›T°—Ó~ÏY)à¼L<,à•ç­ÁJË( ì* s£ÀŠ[dž”CÉJªÓrâp'´¡æ!¶EÏ&¸Öçæt<–U3P÷ç2Ý©OV}“À c2˜÷<óNH ª¬Þ*¥/ŽU–kS»ÆýØCQ|aÔcJ94®¤ºž5pÔ±NhCãCl‹ÆMð…Ô,Û«ÉÂuZggv>èðTc›—¢œ-8¦}õØ ñ§éiÿ&ŠÒ1Ó·@ Šà…ã í„)å BIi"Hàè"ÐCl &¸Î¡®ø¡¨Ýàà¦<ÓâG' ŽÖ â={òF(H|/ˆÍéIÈô“'®ü[Î +ÈLíª¯ÝƒïüÂÙ)óWy~„{¹ÿý_ýò£ Šòr,4æ0[ÄV>ýˆzQx)]˜Rv>µTÇ'uNèŽÏ3ìq>{à =}gE7½S.%«‚ó©êÏrjÇtå¬Q„Gõ1þYoÓm»›x1xé„´H!]Ò£ÈÑùp RÀN ä5ƒnŒ°­Q3+ZÄpEdôºP•:¢ þ0yCA»/ÁóêÁЯ%k”"J¼8 õ÷'IQ猣o(À±&B½JSÊA”’ÒLAnv0å‚6¨b[¸2Á—ü˯d[7 H8]œš7Pyç‰%ù‘ró“húÎçâíê›hdxóÁÏyW–Ö¼ßn'6ëzÔ©è3Rt‡:Pò;|wßµão¾)j 1ÈJGá÷æ1ÿC ‡/¡ÜÝ”rP¬¤tÝFŽFÙ mP<ĶPl‚_g…N[ŸÓ¦zæì,ÓŽörbé'’ ÿ vS¥ß_ÅŒd§‚ÁiªÍCbåB "Ý4Bv”P÷I*rôÑ.ÜŽƒ!ð8&²p²CÀixU!Š8oJþßl®aQFe82ò¡\ØïÅÂ^}וWÀ]Ö¬8qKo ØŠ"sè'‚®¸OWw[™7å…=·ºQŸ;O™ñ;O§üg>?ñ²‚ŒÚ:ÒþÿþA–1ŸŒ<Ûf.² ! VÕvG>>ºþéÖù³ÿa¤÷Éendstream +endobj +2229 0 obj << /Type /Page -/Contents 1690 0 R -/Resources 1688 0 R +/Contents 2230 0 R +/Resources 2228 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1747 0 R ->> endobj -1691 0 obj << -/D [1689 0 R /XYZ 85.0394 794.5015 null] ->> endobj -1692 0 obj << -/D [1689 0 R /XYZ 85.0394 752.3015 null] ->> endobj -1693 0 obj << -/D [1689 0 R /XYZ 85.0394 752.3015 null] ->> endobj -1694 0 obj << -/D [1689 0 R /XYZ 85.0394 752.3015 null] ->> endobj -1695 0 obj << -/D [1689 0 R /XYZ 85.0394 746.3107 null] ->> endobj -1696 0 obj << -/D [1689 0 R /XYZ 85.0394 731.5461 null] +/Parent 2112 0 R >> endobj -1697 0 obj << -/D [1689 0 R /XYZ 85.0394 728.1497 null] +2231 0 obj << +/D [2229 0 R /XYZ 85.0394 794.5015 null] >> endobj -1698 0 obj << -/D [1689 0 R /XYZ 85.0394 713.3851 null] +2232 0 obj << +/D [2229 0 R /XYZ 85.0394 748.4854 null] >> endobj -1699 0 obj << -/D [1689 0 R /XYZ 85.0394 709.9887 null] +2233 0 obj << +/D [2229 0 R /XYZ 85.0394 748.4854 null] >> endobj -1700 0 obj << -/D [1689 0 R /XYZ 85.0394 651.9592 null] +2234 0 obj << +/D [2229 0 R /XYZ 85.0394 748.4854 null] >> endobj -1083 0 obj << -/D [1689 0 R /XYZ 85.0394 651.9592 null] +2235 0 obj << +/D [2229 0 R /XYZ 85.0394 743.3452 null] >> endobj -1701 0 obj << -/D [1689 0 R /XYZ 85.0394 651.9592 null] +2236 0 obj << +/D [2229 0 R /XYZ 85.0394 728.6405 null] >> endobj -1702 0 obj << -/D [1689 0 R /XYZ 85.0394 648.8377 null] +2237 0 obj << +/D [2229 0 R /XYZ 85.0394 723.1655 null] >> endobj -1703 0 obj << -/D [1689 0 R /XYZ 85.0394 634.0731 null] +2238 0 obj << +/D [2229 0 R /XYZ 85.0394 708.4607 null] >> endobj -1704 0 obj << -/D [1689 0 R /XYZ 85.0394 630.6767 null] +2239 0 obj << +/D [2229 0 R /XYZ 85.0394 702.9857 null] >> endobj -1705 0 obj << -/D [1689 0 R /XYZ 85.0394 615.9121 null] +2240 0 obj << +/D [2229 0 R /XYZ 85.0394 688.2211 null] >> endobj -1706 0 obj << -/D [1689 0 R /XYZ 85.0394 612.5156 null] +2241 0 obj << +/D [2229 0 R /XYZ 85.0394 682.8059 null] >> endobj -1707 0 obj << -/D [1689 0 R /XYZ 85.0394 585.7959 null] +2242 0 obj << +/D [2229 0 R /XYZ 85.0394 668.0414 null] >> endobj -1708 0 obj << -/D [1689 0 R /XYZ 85.0394 582.3994 null] +2243 0 obj << +/D [2229 0 R /XYZ 85.0394 662.6262 null] >> endobj -1709 0 obj << -/D [1689 0 R /XYZ 85.0394 567.6349 null] +2244 0 obj << +/D [2229 0 R /XYZ 85.0394 599.7666 null] >> endobj -1710 0 obj << -/D [1689 0 R /XYZ 85.0394 564.2384 null] +2245 0 obj << +/D [2229 0 R /XYZ 85.0394 599.7666 null] >> endobj -1711 0 obj << -/D [1689 0 R /XYZ 85.0394 549.5337 null] +2246 0 obj << +/D [2229 0 R /XYZ 85.0394 599.7666 null] >> endobj -1712 0 obj << -/D [1689 0 R /XYZ 85.0394 546.0774 null] +2247 0 obj << +/D [2229 0 R /XYZ 85.0394 591.7571 null] >> endobj -1713 0 obj << -/D [1689 0 R /XYZ 85.0394 531.3128 null] +2248 0 obj << +/D [2229 0 R /XYZ 85.0394 565.0374 null] >> endobj -1714 0 obj << -/D [1689 0 R /XYZ 85.0394 527.9163 null] +2249 0 obj << +/D [2229 0 R /XYZ 85.0394 559.6222 null] >> endobj -1715 0 obj << -/D [1689 0 R /XYZ 85.0394 513.1518 null] +2250 0 obj << +/D [2229 0 R /XYZ 85.0394 534.1777 null] >> endobj -1716 0 obj << -/D [1689 0 R /XYZ 85.0394 509.7553 null] +2251 0 obj << +/D [2229 0 R /XYZ 85.0394 527.4872 null] >> endobj -1717 0 obj << -/D [1689 0 R /XYZ 85.0394 483.0356 null] +2252 0 obj << +/D [2229 0 R /XYZ 85.0394 502.0427 null] >> endobj -1718 0 obj << -/D [1689 0 R /XYZ 85.0394 479.6391 null] +2253 0 obj << +/D [2229 0 R /XYZ 85.0394 495.3523 null] >> endobj -1719 0 obj << -/D [1689 0 R /XYZ 85.0394 464.8745 null] +2254 0 obj << +/D [2229 0 R /XYZ 85.0394 420.5376 null] >> endobj -1720 0 obj << -/D [1689 0 R /XYZ 85.0394 461.4781 null] +2255 0 obj << +/D [2229 0 R /XYZ 85.0394 420.5376 null] >> endobj -1721 0 obj << -/D [1689 0 R /XYZ 85.0394 446.7135 null] +2256 0 obj << +/D [2229 0 R /XYZ 85.0394 420.5376 null] >> endobj -1722 0 obj << -/D [1689 0 R /XYZ 85.0394 443.3171 null] +2257 0 obj << +/D [2229 0 R /XYZ 85.0394 412.5281 null] >> endobj -1723 0 obj << -/D [1689 0 R /XYZ 85.0394 428.5525 null] +2258 0 obj << +/D [2229 0 R /XYZ 85.0394 388.4584 null] >> endobj -1724 0 obj << -/D [1689 0 R /XYZ 85.0394 425.156 null] +2259 0 obj << +/D [2229 0 R /XYZ 85.0394 380.3932 null] >> endobj -1725 0 obj << -/D [1689 0 R /XYZ 85.0394 355.0758 null] +2260 0 obj << +/D [2229 0 R /XYZ 85.0394 365.6884 null] >> endobj -1726 0 obj << -/D [1689 0 R /XYZ 85.0394 355.0758 null] +2261 0 obj << +/D [2229 0 R /XYZ 85.0394 360.2134 null] >> endobj -1727 0 obj << -/D [1689 0 R /XYZ 85.0394 355.0758 null] +2262 0 obj << +/D [2229 0 R /XYZ 85.0394 345.4488 null] >> endobj -1728 0 obj << -/D [1689 0 R /XYZ 85.0394 352.0499 null] +2263 0 obj << +/D [2229 0 R /XYZ 85.0394 340.0336 null] >> endobj -1729 0 obj << -/D [1689 0 R /XYZ 85.0394 337.3452 null] +2264 0 obj << +/D [2229 0 R /XYZ 85.0394 325.269 null] >> endobj -1730 0 obj << -/D [1689 0 R /XYZ 85.0394 333.8889 null] +2265 0 obj << +/D [2229 0 R /XYZ 85.0394 319.8539 null] >> endobj -1731 0 obj << -/D [1689 0 R /XYZ 85.0394 309.8192 null] +2266 0 obj << +/D [2229 0 R /XYZ 85.0394 295.7842 null] >> endobj -1732 0 obj << -/D [1689 0 R /XYZ 85.0394 303.7727 null] +2267 0 obj << +/D [2229 0 R /XYZ 85.0394 287.7189 null] >> endobj -1733 0 obj << -/D [1689 0 R /XYZ 85.0394 278.3282 null] +2268 0 obj << +/D [2229 0 R /XYZ 85.0394 272.9543 null] >> endobj -1734 0 obj << -/D [1689 0 R /XYZ 85.0394 273.6565 null] +2269 0 obj << +/D [2229 0 R /XYZ 85.0394 267.5392 null] >> endobj -1735 0 obj << -/D [1689 0 R /XYZ 85.0394 246.9367 null] +2270 0 obj << +/D [2229 0 R /XYZ 85.0394 252.7746 null] >> endobj -1736 0 obj << -/D [1689 0 R /XYZ 85.0394 243.5403 null] +2271 0 obj << +/D [2229 0 R /XYZ 85.0394 247.3594 null] >> endobj -1737 0 obj << -/D [1689 0 R /XYZ 85.0394 173.5556 null] +2272 0 obj << +/D [2229 0 R /XYZ 85.0394 223.2897 null] >> endobj -1738 0 obj << -/D [1689 0 R /XYZ 85.0394 173.5556 null] +2273 0 obj << +/D [2229 0 R /XYZ 85.0394 215.2245 null] >> endobj -1739 0 obj << -/D [1689 0 R /XYZ 85.0394 173.5556 null] +2274 0 obj << +/D [2229 0 R /XYZ 85.0394 149.4956 null] >> endobj -1740 0 obj << -/D [1689 0 R /XYZ 85.0394 170.4341 null] +2275 0 obj << +/D [2229 0 R /XYZ 85.0394 149.4956 null] >> endobj -1741 0 obj << -/D [1689 0 R /XYZ 85.0394 144.9896 null] +2276 0 obj << +/D [2229 0 R /XYZ 85.0394 149.4956 null] >> endobj -1742 0 obj << -/D [1689 0 R /XYZ 85.0394 140.3179 null] +2277 0 obj << +/D [2229 0 R /XYZ 85.0394 144.3554 null] >> endobj -1743 0 obj << -/D [1689 0 R /XYZ 85.0394 113.5982 null] +2278 0 obj << +/D [2229 0 R /XYZ 85.0394 120.2857 null] >> endobj -1744 0 obj << -/D [1689 0 R /XYZ 85.0394 110.2017 null] +2279 0 obj << +/D [2229 0 R /XYZ 85.0394 112.2205 null] >> endobj -1745 0 obj << -/D [1689 0 R /XYZ 85.0394 95.4372 null] +2280 0 obj << +/D [2229 0 R /XYZ 85.0394 97.4559 null] >> endobj -1746 0 obj << -/D [1689 0 R /XYZ 85.0394 92.0407 null] +2281 0 obj << +/D [2229 0 R /XYZ 85.0394 92.0407 null] >> endobj -1688 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F39 899 0 R >> +2228 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F39 1151 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1750 0 obj << -/Length 2889 +2284 0 obj << +/Length 2928 /Filter /FlateDecode >> stream -xÚµšMsÛ8†ïþ:JU1†øy¤-ÅVb+^ÉÎÎT&Z‚c–)Ò©$þ÷Û >R$˜Ù­-LM¼tÝ$ž8ð‡'žüˆD“ r‘ç`o²ÝŸ9“oÐwu†¥Í¹2:7­.îÏþxOƒI„"Ÿø“û'c¬9aˆ'÷»/ÓQ4ƒœéÅòâfùéjß]ÿ5;'ž3ýÛñœx56WW‹ÍýB~\/âùru&xvø‘3ïî«ùòOÑóQÝz¹Ø̾Þ8[Üë¯mþ4ìPþ¿Ÿ}ùêLvð ?œ9ˆF¡7ù „£ˆLög®G‘çRªZ²³ÍÙ¿ô€Fo}kïTaê“ž¹"x‚1Š<´&Ë‹O ­'kÍÊâxØ29l[vâú~3ðöÊÊÁ_I1 -<ahX‰/Eú*+þ¾¬ß_bÒ¯]eLL‡Ø¥µÕ©6 mLä‘ ­½b?áçc:¯6âb½– ìoÇ!yZ¥E^ÏIç§`Ç…i¥>| >Ð;¸‹8ÓKô~‘)c,~°Ã ‡ÓçäPÕxz#»âú?™Þ&ûä¥(eïZö>dÙ>És9h’ïDóÝ “H ~[l_’WVR¸¾Ì„úJçbÿø´­ŠGø5eXt"ìG -}w„°i5LX[iÂã¶J7„O´{ ·´Xøé«M|§–=w¦í½˜A;ˆ‚ÈÀ öHü¿HiþM|˜øh²÷²ÈX–%òž.w˜Cú# + e¥9„ƒMÚàÐÕîç`jÇ|-Ó[–€;Á¥?}*¢mñ뵦ÁÊRL&tÞÛ„»ž°Xæ`¼× þ4•Õ3óbŸ¤²s•ìeë歬ؾ+u0òxm°R Þ+K~¤¥lk|:>ÏX’§,CˆX ·HÅoyk 5ìQY_K±>æLƒ†A{Ñ ¢#  + he¥AêX@Û¤ Ð]í~ЦöG&×øâ×ö9ɿɉ˜³Œ}SÛq'‘Û:\žÜzµé;Y…$2´}°RG§¸jí‘ݳ“…%Èuý1 -†•…‚²Ò`¯·P°IºÚýLíù&?ýã⯲s¬Ø,¯dSšwç]ù?ý -?â7?Òù1Щsàží’º( -ü6¡¹$´HÊ*K^˜l¦µ£ïÞ©s±ðûgM,&†af0 †•…˜²2ˆb6iƒXW»Ÿ˜©½ÞÄÜÎ=ØYEXž(E_q@ü¿Ø&ÁFQã‚Z}ƒ¤Æ¯G¨ù -\'4v¹@`ã£Ø\ÇÄÆ?5ØÄaFÔÊ'­0ÝÐA>Lº¦i5 S[0-»Uºy¢Ý ³¥½©ŠC½KáˆN/ÙAlapød%osk†¼¯fÈCÞ(ò+Å[Œ0$aH;†ü~Îßkºžã)†Â¦^aüâ“4¾:îöG8ÔÊùŴ‰´ÿÄs]8Ç4 #° + leeÀŽ,°mÒì®v?lS›ÃNÄ>ŠsÁÙô©>µœ_³º2#zas,E*[dè ÐéС7[‹8K¡7”¡7jñ÷[¡×Ç'>,ú. çøÐƨVªÊª¡êZÎ1ViƒjW»Ÿª©=gU²}f»ÿfcÙ»QèÁ³K©ëýŸ·J -id„ý4¦Õ0m¥Ñ¡¥`•nÐœh÷¢ii×G›@ÕéBQ€…yŽ §¥QàÒÉž’é3¨òÕ`ZÊ€h• E×fÍ+3Ÿ‡|Î ¼ 1…ZȨ4%!Ï( ÝHÃE™ªX«leÅÆX-’÷ìñ0 §M6Ig¸DK}9$Ä#+À°²¬e¥W@„=Ë -°I+ «Ý¿Lí{Ôu]î‹5e×¥ÓøX=ö[½‰®»"ååÑÇ¡®â»ûµðOÞ_3æ}í¬“wÉä¤?ÈúžÛð†hÁSÃú.•®‘Wä‘ÊïlEÕ {…ø¡Ó;G -ÛðÈ‘·±±06Š ÅØ^-¢¿¶j?½F•t7×ñ90d6BäQ—Â-D‹L^àJj±ªÞ£z‹uõ7®G¶Ëx8›c°ˆ¿¤uæåE\#þò‚tò&™ª1ZP"¦}Ä Ç‘…£4j@KÝΦkì÷£4„ã&]ÉøZ?$üÑ`'¿¿IËJ¦ž"ö:íbo¸ùáé+‡²w7Jcðì··T#ôB^UlŸOj4V`qÅ‘˜a4 Li`^d) Øt`]á^`¦°¨¡†p"üU±¼¬ŸTÂ숚*ü/¯¯Å¡FË;ÑøƒJQ6‡F¿¯2`äø‘±ºÄ›n¸ãþ¹Ø‹|·^ÊÖëc -¾šÈÖϺ`]Ë4OòJv‰šU N«µƒiqLË2í«ÿa:L˜o©3†Ø°²0VVdK5Á*mPîj÷c6µ¯aÒ2ýœQ9ÛCþ’?ó®Ó<Ül|Oº\˵ËÞòFnu<0–Îwu,«ä©l2ÇÓíªg0­÷ .XÁ”ðƒ< -ŒÛÏiueK×±ôƒƒæÏBŽãŒÄaÓj˜¹¶jÞLpð0s«tÃüD»—yK[ÏÇ"ß»ø+Vý,/MÓ­ ~‚é;üd'DÄñCK˜ýl~h½u Äë!ÍTò'/Ø‹PˆÇª¦•…’²j(ÙöK«´A©«ÝOÉÔ^³ïÇTìq{–«íPo‘Í#/þéºÐ湚»×,Ý…ô¦¬+#wŸ[<¹ÂùÅ!Ù±r¹ -…º#õ:ÓÊEYi(^ds›´¥«ÝÅÔOï7ÕḭD˜d™7žmôl‘‡ü€ºíÉÿ ãóa ±~ãcðÆÓÊ‚AYé´ŽbË®e•60tµû1˜Ú—YR–™> -.Wçñ|¾FñZD—øw¦~TЙìkUUIw9SAèJ6î$Í«z꾅щlÍ£ü~dÃÏu1dwGÛ›VdÊJ# ‰å4i•6uµû‘™ÚËøBm¼DÁ¶Ï9„§L½Î´ç1NîC݇MyúýȺ‡ лéz~ÐÛ–±DÇÊŽ§^I§‚ö;•“~f8ö–…a4LK5eb©TÛtV]á^T¦°Žqn¨bœñ7ƒ´ºsnÔ©b‚å2^Åâêr…tÇÉÐû¼¤é“ÖÓ?±N©áv3¥†f#¥æÒè¢.lå¹x òüßµ·eYšìÕ‹Z¤uö×ÎÚyÍnð i©³xˆ¿OÛ3ùŽ>“þϯíUñÑ08¼ DnƒÈ/Åjž|sõ~ïéWÿ#.Oendstream -endobj -1749 0 obj << +xÚ¥ZKs㸾ûWèºjÅŸ{ÓØž-ÏÌÚŽä­d33˜¢%Æ©%){´¿>Ýh€eŠÚJÊF7€¯_€Ì' þø$Ý0ñ’I”ønÀx0I7l²‚±_.¸æ™¦©ÍõáñâïE4IÜ$ôÂÉã³%+vYóÉãò«3s}÷$0çÃíÝõåÔ ˜“ÐçúnA/·æ³ù¥ˆœß‰°øíáá^/§ÜÏ™=<ÜÜ]ßþ‹f(“1C½ºY\~ütqóØ-ÚÞgWüÇÅ×ïl²„ý}º`®Hâ`òæò$ñ&› ?nà a(ÅÅââ@kTM<(Î\O„ÞÀIy|¹›×;ª qCá uT÷OMUdm¶<:žE–îê¼ÝSoþñª9¹Y!\á%ü Š­ÍBÑpáÒ¾‚V…Á÷cÍÜóàT‚h\uÇõ^·H,ÝÜ‹ÜÀ‹úº¯«ÌËË©ï1çNn2lqg±oÚlCÔÃáÈÍ6+›¼*Õ1íŽÇÌâ(„u¡ìŸ`J(œkWO•M[È—ì’Óˆïˆú’ÇÎ’ôÈR7®4ÿg¹{ÞÈRKù$ˬ÷¨¶lM vÚ ØUäžDÁ)qß;ƒžÅ5‚žáêÐã"AoLµ…Þ±îaôlÝ +<ÃL[µFÛ„¦2q¦âØ—r“§Ôùm»”m6dÂ]ßK, Õ\—¾HMÖ(êÞl[ç5Gñcᆰñq¸4ñŸ—^³¢Im¥b™'œ»ê5Û‘‘;¡îU!ëüc^*ÛŽh¾ÿ®Jãr­lwCNåñÈe‘÷½êF{Õ—ì-o†á§áË=v¦4°¹F1\ ¾?ÌÆT[€ëÄÖý%ßä-yäêv^‰x‘VÛŒhÕ3‘ô˜ï|¾ù(ó¬©(3¥zhž¥U½¤6ºÛ|®\m!Ü ò¬¸‡S0î¡à_eÓd{¢©ŠA-ÉÕ:ª¢—»ÎRÛÅŒÌiW&’y'! bß,8S/Ø\§!í¸:HÃ`ÒQÕHßé„´§{ž-3tž2'ç'á«üODLź¬lsð0¬–Õ˜l%µºÙµŽ’ÐÊÛ! YìF,ò§˜sú1‘h„%4î5Ó/»åfW.›£&h„ö@ìb©ñRqR¸dø ]WF µ¸F 5\¤#©nTµé±îaHmÝ×Y‘­¬XˆiËœ†Jk KÝnz^IòJÃ}Ò+yº¾ó~ܼ×q³Õ)Æÿþ,‡k;S Ú\#°®–hÔÓÆT[°ë†ÅÖý@I÷‡c/^ÍY\U›-àõ”]Ž{®jsj ̇ÃLê'}tò·¼I‘ïtémßaãŸÆB±3•†Í5‚á²°¹5ª¶°9Ö=Œ­»«Ò}Sb««Ò¡­ò6ta}íE@;ò"EÑ^¤gh/"±ö ú7e[ï©ùPåe{˜µ¸y8LûXÈÕÎ.¾øb´ŠŒµs~®ŠºGc.Òu±o{&¡bð©rȺ×ZŒù–pÆbl®ÓÓqu•B£ªóN÷ ÅôtŸ¨M¯ êÚ—ýhл–#ß]k~=» ç=sF¤U½‘ƒÉ4„•Çžßwîg»Õ®i°:~$› +>4°îëEáz—S×綹e¦%]×ò¹*©^a ÆT6Z³âÀÌ‚6•}·×>”Ý!AGµ«Ýj=]â"¾Uõ‹*Aqþ²Jw¨LÿªúÄñ¾æ›r•—YVëéú°eóBÌpÜäÂøÚÄatÑãë{‘^£*abG]*£ÈÉ  +-S¢&ôjô°§Š[š^@-]âó•"6­\e µ©ü +eöšÕ÷+ +îÜn¶E†ýªÖÒ»ó‰©Üa¢ -rʪժ«þ6š¹’æÅÍs,¨!ÕW8æÆ“¿Êm)61!Rõÿž¸šuµ+4UiÅÆSFß?v½±£Êj@KsMòÕù(¥öŒV_Ñƺ»²€cÖüiZm¦Cøle™+éœ9O{ú’E@c™7i!óÊ¡j@¶‹f>!t¾yž6×PW-¾„bµ"Ö¦q‘†è¡±–¯Zˆ¤O‘?g ,zÊZáÛä?¨±©Êv­ç‚½›%¾­s¸rlT¯8°W ef½jwG†mõ¸§žôT’ëzBª'f08°÷AAè p"Lµbá…aç©ÚéX¡~èäÂÄ;¹ž véëÈsV£|s÷"Ïeqäg›ë}6᜹À&ÂT:á§ɨÖC"y§v0‘ô´R"aö+ÚGe/:„ì +äÃœ¹+hÒ¬€{ןG’®À,œ<}Qú_òNä>”œÛ}¯Ö*»LxÃükaú‘Òïæž… ìÓâûÆx0t;€-²Ø”Ÿ@ベ†ú)væúÚbG~ËŸj”U"Ým·UÝ'8Á\æs +¥ë,ž'šž^¦°ƒŽ_R‡­„>+²(»¡°Ä¼Õ2r•´0b¯P+Ê3=ØTô¥¸E-ŒØJ¥VŒ¡—'/ôvEÙæœâýt+ëVåv[äôzÖ Å™MÕ…À)“M^à 1ÊßošžÊ¢ *¬hC´ÃFuxZ‘ƒQv{BŠŠ© ÓvÞ÷±0Àª& •kã^.õS…RUiªÑ½‘ÿQIhêTçZö€8{¸m†²á;“Èu ƒêŽ„”m¡íb×@ñS>©AÛ¤¶…vu®xÍ—ÙѤçª(ª7ªG°›ÉV—‰Íϧ ›N‚ðÌåØæR‘¨çȇ{ihÉÒž+@½q¥†é½ÒžÓÄÜ ð׋žÒGuIâ”Ù›:_h¦t4  ñ‹âh‘£e=AS-w…ªÙ‚H{"’ÍWÒg ÁNe)hXXQ̺€–…–Qj‘è˜Ï2Õ+.«Jº> +® ,¸è«ª íEšN¡hKÂsÚZ–LµYÃÈ[Þ®©%éƒÞš§»BÖÔo²úõPá óAÖ²û9Ø(ããûÃ÷VSì¡Á ø9-]@ öné>ÃEƒ …ņzrù*!_ƒO/‰`±™€OæŠYQ<‡®HDƒÊ2_Jóú(Ì»ŸêÎr…µo”²ƒÁ á'ÿ9¬LU8U«_ê›}™® Ö²Ú5Gw[98 r³“WÚ8qáxÏ<ZL§=Ð0sÀ1ÿkt?[£ò>!"ô>j _ÝÎä^Š€W´Rå# γÂÛ+æ(ìÒC‰~†~¡³(çÜÁÿ‰àêÒÒPß»"µLË»°‹‘]MucHfµà/ƒ•?eµª89ñ+-$­ÊgÁo´‘h3@â!ËaO›õRý>ç«\Òl³”~h"‡½Õ®6's$Z=â!‘~XRK=uÑKå½P²•é \ /Mvœ@àÓ:ßÞ»‡ÃKÙè­“ZŸr¸^¾QŠ=aç"pñ_pŒŽu—ƒÿû?}¬7 Èq|â§/ +\˜šE©º¬ôxéæ‚Þ¯ý¿Ô! Jendstream +endobj +2283 0 obj << /Type /Page -/Contents 1750 0 R -/Resources 1748 0 R +/Contents 2284 0 R +/Resources 2282 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1747 0 R +/Parent 2112 0 R >> endobj -1751 0 obj << -/D [1749 0 R /XYZ 56.6929 794.5015 null] +2285 0 obj << +/D [2283 0 R /XYZ 56.6929 794.5015 null] >> endobj -1752 0 obj << -/D [1749 0 R /XYZ 56.6929 748.5056 null] +2286 0 obj << +/D [2283 0 R /XYZ 56.6929 749.0089 null] >> endobj -1753 0 obj << -/D [1749 0 R /XYZ 56.6929 748.5056 null] +2287 0 obj << +/D [2283 0 R /XYZ 56.6929 749.0089 null] >> endobj -1754 0 obj << -/D [1749 0 R /XYZ 56.6929 748.5056 null] +2288 0 obj << +/D [2283 0 R /XYZ 56.6929 749.0089 null] >> endobj -1755 0 obj << -/D [1749 0 R /XYZ 56.6929 743.7078 null] +2289 0 obj << +/D [2283 0 R /XYZ 56.6929 745.2843 null] >> endobj -1756 0 obj << -/D [1749 0 R /XYZ 56.6929 719.6381 null] +2290 0 obj << +/D [2283 0 R /XYZ 56.6929 721.2146 null] >> endobj -1757 0 obj << -/D [1749 0 R /XYZ 56.6929 711.8197 null] +2291 0 obj << +/D [2283 0 R /XYZ 56.6929 714.4694 null] >> endobj -1758 0 obj << -/D [1749 0 R /XYZ 56.6929 697.0552 null] +2292 0 obj << +/D [2283 0 R /XYZ 56.6929 699.7048 null] >> endobj -1759 0 obj << -/D [1749 0 R /XYZ 56.6929 691.8868 null] +2293 0 obj << +/D [2283 0 R /XYZ 56.6929 695.6096 null] >> endobj -1760 0 obj << -/D [1749 0 R /XYZ 56.6929 665.1671 null] +2294 0 obj << +/D [2283 0 R /XYZ 56.6929 680.9049 null] >> endobj -1761 0 obj << -/D [1749 0 R /XYZ 56.6929 659.9987 null] +2295 0 obj << +/D [2283 0 R /XYZ 56.6929 676.7499 null] >> endobj -1762 0 obj << -/D [1749 0 R /XYZ 56.6929 635.929 null] +2296 0 obj << +/D [2283 0 R /XYZ 56.6929 652.6802 null] >> endobj -1763 0 obj << -/D [1749 0 R /XYZ 56.6929 628.1106 null] +2297 0 obj << +/D [2283 0 R /XYZ 56.6929 645.935 null] >> endobj -1764 0 obj << -/D [1749 0 R /XYZ 56.6929 601.3909 null] +2298 0 obj << +/D [2283 0 R /XYZ 56.6929 631.2303 null] >> endobj -1765 0 obj << -/D [1749 0 R /XYZ 56.6929 596.2225 null] +2299 0 obj << +/D [2283 0 R /XYZ 56.6929 627.0752 null] >> endobj -1766 0 obj << -/D [1749 0 R /XYZ 56.6929 569.5028 null] +2300 0 obj << +/D [2283 0 R /XYZ 56.6929 603.0055 null] >> endobj -1767 0 obj << -/D [1749 0 R /XYZ 56.6929 564.3344 null] +2301 0 obj << +/D [2283 0 R /XYZ 56.6929 596.2603 null] >> endobj -1768 0 obj << -/D [1749 0 R /XYZ 56.6929 549.6297 null] +2302 0 obj << +/D [2283 0 R /XYZ 56.6929 572.1906 null] >> endobj -1769 0 obj << -/D [1749 0 R /XYZ 56.6929 544.4015 null] +2303 0 obj << +/D [2283 0 R /XYZ 56.6929 565.4454 null] >> endobj -1770 0 obj << -/D [1749 0 R /XYZ 56.6929 529.6968 null] +2304 0 obj << +/D [2283 0 R /XYZ 56.6929 550.7407 null] >> endobj -1771 0 obj << -/D [1749 0 R /XYZ 56.6929 524.4686 null] +2305 0 obj << +/D [2283 0 R /XYZ 56.6929 546.5857 null] >> endobj -1772 0 obj << -/D [1749 0 R /XYZ 56.6929 500.3989 null] +2306 0 obj << +/D [2283 0 R /XYZ 56.6929 531.8211 null] >> endobj -1773 0 obj << -/D [1749 0 R /XYZ 56.6929 492.5805 null] +2307 0 obj << +/D [2283 0 R /XYZ 56.6929 527.7259 null] >> endobj -1774 0 obj << -/D [1749 0 R /XYZ 56.6929 467.136 null] +2308 0 obj << +/D [2283 0 R /XYZ 56.6929 501.0062 null] >> endobj -1775 0 obj << -/D [1749 0 R /XYZ 56.6929 460.6924 null] +2309 0 obj << +/D [2283 0 R /XYZ 56.6929 496.911 null] >> endobj -1776 0 obj << -/D [1749 0 R /XYZ 56.6929 436.6227 null] +770 0 obj << +/D [2283 0 R /XYZ 56.6929 464.7873 null] >> endobj -1777 0 obj << -/D [1749 0 R /XYZ 56.6929 428.8043 null] +2310 0 obj << +/D [2283 0 R /XYZ 56.6929 439.0859 null] >> endobj -1778 0 obj << -/D [1749 0 R /XYZ 56.6929 414.0996 null] +774 0 obj << +/D [2283 0 R /XYZ 56.6929 352.4521 null] >> endobj -1779 0 obj << -/D [1749 0 R /XYZ 56.6929 408.8714 null] +2311 0 obj << +/D [2283 0 R /XYZ 56.6929 326.7507 null] >> endobj -1780 0 obj << -/D [1749 0 R /XYZ 56.6929 382.1516 null] +2312 0 obj << +/D [2283 0 R /XYZ 56.6929 290.6891 null] >> endobj -1781 0 obj << -/D [1749 0 R /XYZ 56.6929 376.9833 null] +2313 0 obj << +/D [2283 0 R /XYZ 56.6929 290.6891 null] >> endobj -1782 0 obj << -/D [1749 0 R /XYZ 56.6929 350.2636 null] +2314 0 obj << +/D [2283 0 R /XYZ 56.6929 290.6891 null] >> endobj -1783 0 obj << -/D [1749 0 R /XYZ 56.6929 345.0952 null] +2315 0 obj << +/D [2283 0 R /XYZ 56.6929 290.6891 null] >> endobj -1784 0 obj << -/D [1749 0 R /XYZ 56.6929 321.0255 null] +778 0 obj << +/D [2283 0 R /XYZ 56.6929 241.4457 null] >> endobj -1785 0 obj << -/D [1749 0 R /XYZ 56.6929 313.2071 null] +2316 0 obj << +/D [2283 0 R /XYZ 56.6929 201.7704 null] >> endobj -1786 0 obj << -/D [1749 0 R /XYZ 56.6929 298.5024 null] +2282 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F39 1151 0 R /F14 956 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1787 0 obj << -/D [1749 0 R /XYZ 56.6929 293.2742 null] +2319 0 obj << +/Length 2294 +/Filter /FlateDecode +>> +stream +xÚ¥]sã6î=¿Â9yf­"õÕ·ìn¶“¶—Ë9éLov÷A–¨˜]Yrõa×ÿþ‚’e[Iö®Éd @€øTøŒÁ/ŸE¾ËD,ga,]Ÿq–n®ØìÖ~ºâ–fÑ-ÆT®?‰p»q೧|Ä+rYñÙSöÙ¹yx¸½ÿx÷û|áù̹qç Ÿ±ûáöq¾à2Œ=X‘¸0çýÝýG¢Žéññþ‘€_ïÞ/o–s:ÿ!Äãoÿ2ˆ§ùקŸ¯nŸ†CãLà‰ÿ¼úü•Í2Ðïç+æŠ8òg{xa.co¶¹’¾p})D)®¯þ=0­š­S†hBºQ<^7§»ðÄ`N.G挌hÐS¡9¿0ž«Ê™„M2œù]H¨.ÅzÞH,gËàTìMƒœmR·ÅN•¦]+î–zU'õaÎ9wÞ*àN©öÅVõf[¨*[•¢i“2Kê9œŒX'Yf^UÓ,Êdcùo’íV—Ïô’weÚêªl¬€gÕ&Ù Ê.8wcß÷ÌɳZ—yõ…ù þ8P‡¡ˆp +S ÃH:t Eô[óRít¦2pRîú´VZìKE–®à¯·Éþ„É.)t–´¤¼[«b§jÚ·JÒo“:¨2ƒc Áèä‚K'­ºÂ€‚€¸ +NP˜d»¤L•%ÎUÒvVž%Íi¯93"(èŠéA·¨û M—®iKb1i’®AÐÆ„žº >y¨OøÆ&™sgg$rjñÍØ°r?„Z.ÒªL»šø”-úbQæ~­Jz#aÿÈÏìi’î÷h+¾+'¯¤ÙªTaÌSjã¾”~‚X¸’ þz"S½œª7Á«R‰àBìd"8{ƒF |GýµUµÆ8N +Âä5DÒ¾ª¿ákà´¡›n»­0iàKï¡È`{ »î\'VˆuJ€â4hHuÙ˘À®¤ù6åuÍ¡iÕÆÜè6ê/1Ÿ-<0 ÈÖÓ†PˆÀ;9ƒ2õP«ZýÙéF·Êr[Dy¾x>íüéþ78‹' U}Có<ò"ÀŸ'2ÂÁsÕiÌ°œp``2Àc ºsoIX¥œŒ‰jxZ»iLˆÔX€¦ÕEAK+un÷ïµ 5ädØOø}{Øâ1¼(  +OÔ–b`!yèÜ•„¦t©¼ÑefÝhg»Ö†—ïdUÚ¡3aö}ç‹çIÞVˆJJ+ט¹l…ÞW­êy&-AÚ¤©6vm[$ídjÊ«zƒÜc檉cà~ L©L©ï —t¹«ð†—Ð#Ó9ª™+›{ ƒµ´’V› äEå x—#îLÙ˜ò•r1µJ/6ëÏ=-bÈ "b°«N“ÖG·)÷FFƒ–‰Œ6 ¬9„gÃàCµÙj°&j³SòÓ(¡ëG,4˜/Øã^C.ÎõsW+B,ªLV…ZgƒOþ³ue„ó"yn¾Nßr5‘5ˆÚ2_†øÉøsì»#”ÒÅCqkcô„¡hªBÜÞ2>»¦Kìf +(„bzØŽàr^CWbøà5sr +|4 +bsب–t|ŽÂÚÈ£1GX«äÚf‚©ÞƦ“´­l¿…Õ:‰OæCI°ßz7qmœEPVxL‘×QÒuV6×ð +7™06— z[_ÚT(c›¹$³­4;E+X& ›%‡"óÀÐ 5Ô H²RÏu‡l»‘ ù© èj$5.’û4-È¡ƒì1á<k´“Žˆôã;%Lטn ©Íyåi_„xr0\HŠ¦"he%ØÌj8ÑÝöœ&RÐÈþ9eCñzzÇ…®Û(E/+UTû¡ùŽ 6¨ïJ輋ÿ1ªÓŒž¯ûå8X ¤IÖ÷F®çÖ°õ›ÍK©æ¥Zýv!˜œÌlö{s#žÊç†Ô¨‰#Äêp¶ Rn€UÑ&­†…¶œ!¿áÞçnèòñHÛÉv‘¼ Û~¼¼LåIW´?Rsû°¼ýt÷;†Üõ +²y<ChR µJH%âWÇ«jØb€;WP§ªbu8›ZÎURC—iÑÁ„&L^š‘ÕÖÆóÏ´ €È*k9† Cá,«ª%6ÛZït¡ž-Wô |–PªÁÄÿ¼¯r§BËÖ>8Ž®'1ý ›ÅÈW1 ^öU?p¹Û ¶ZÃÓoø¬Ÿ„±€l_Œ]ëÖ¸Xmƒ°§Ê 9w!Ë +P#¢ &6æ0wV}-±b]íO«–í%9µ2¶žTû¾Ò“žAäíEÑѣ̀~ãÊ»Ì^¹¾'åe ±)ìúŸ`ÖnqaSx¿áÄ«¶´¥$ÓÕå„á#áQàY1Ó½|Os‘ï¤Íw¿”Æ +惒ÊáNšë¥jÚZÓ‡„—8@Ääܘêån zs€{Uêq€»;9Àˆýp2ßh0á–ÂCP˜XÃg‰±ˆ€âLî€×Û Èwƒã´‚ðYÝ26iàÞ.‘ØO|)Úˆ8ñKD˜‰••@Åt"'%M_ñX¨Ù«9÷}WúL¾qŸ#ªWzû>_“:ºÏs±Ó÷9K^"áÐtÀ¼¿TF¹ ‘Ë¥é:$ã˜b¯¦m‹ì›ýpG'ßNìWšèäúÍÖ’žm/zèᢋÛYìÜå´dF+ö‰™Ú¡¾™ 8¢oX/dîpŠ³:áØ8Ò WÐBi:–Ž™ .Ó>÷7ŠCßfœÈ²‰œ#„‰¸§Ú¯ua‡H;B£x“kéƒÞqàõÁûxÁÏD‚…¶êÚ³IÙªJ¹’Ì Exêìc…±dÐż³@©ß•%±3Hqøñ….oÔ~½9»åη¨ks“ÓÛ;‚W%0þ5=ÿ}Ï ÷Âòÿ?]¾}¾‘Ž_§œòÕVx*åW1ùQž %ìoÿ{☻dèŠ(ò¦sˆ€\Sï… +qÏ??º/ PG^8qöÿIì»äendstream +endobj +2318 0 obj << +/Type /Page +/Contents 2319 0 R +/Resources 2317 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 2112 0 R >> endobj -1788 0 obj << -/D [1749 0 R /XYZ 56.6929 267.8297 null] +2320 0 obj << +/D [2318 0 R /XYZ 85.0394 794.5015 null] >> endobj -1789 0 obj << -/D [1749 0 R /XYZ 56.6929 261.3861 null] +782 0 obj << +/D [2318 0 R /XYZ 85.0394 662.3711 null] >> endobj -1790 0 obj << -/D [1749 0 R /XYZ 56.6929 199.468 null] +2321 0 obj << +/D [2318 0 R /XYZ 85.0394 634.4781 null] >> endobj -1791 0 obj << -/D [1749 0 R /XYZ 56.6929 199.468 null] +786 0 obj << +/D [2318 0 R /XYZ 85.0394 566.8617 null] >> endobj -1792 0 obj << -/D [1749 0 R /XYZ 56.6929 199.468 null] +2322 0 obj << +/D [2318 0 R /XYZ 85.0394 536.3186 null] >> endobj -1793 0 obj << -/D [1749 0 R /XYZ 56.6929 191.7053 null] +790 0 obj << +/D [2318 0 R /XYZ 85.0394 411.7882 null] >> endobj -1794 0 obj << -/D [1749 0 R /XYZ 56.6929 176.9408 null] +2323 0 obj << +/D [2318 0 R /XYZ 85.0394 386.7645 null] >> endobj -1795 0 obj << -/D [1749 0 R /XYZ 56.6929 171.7724 null] +794 0 obj << +/D [2318 0 R /XYZ 85.0394 230.2565 null] >> endobj -1796 0 obj << -/D [1749 0 R /XYZ 56.6929 157.0677 null] +2324 0 obj << +/D [2318 0 R /XYZ 85.0394 203.9874 null] >> endobj -1797 0 obj << -/D [1749 0 R /XYZ 56.6929 151.8395 null] +2317 0 obj << +/Font << /F37 1018 0 R /F14 956 0 R /F22 953 0 R /F21 930 0 R /F41 1208 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1798 0 obj << -/D [1749 0 R /XYZ 56.6929 137.1348 null] +2327 0 obj << +/Length 2527 +/Filter /FlateDecode +>> +stream +xÚ¥koÛ8ò{~…±8àd bùгßÒ6=d»Èöììí.Ú~-Ù*K^INâýõ7Ã!eÉ–®*r8œçI‹ ‡?1ñÄ2ž„±Ç|.üÉr{Ã'kXû×08®ErûXïoÞ~Rá$fq ƒÉãªG+b<ŠÄä1ýêÜ2MwÞß?|œºÒçNLŸsürÿ~v;›ªÐù“óß¾|ùU§®ðÂX:·_¾Ü=|¼ÿƒn‘&çúán>ýþøóÍÝc'tÿ`‚+”ø¯›¯ßù$…óý|ÙŠ#ò ÎDËÉöÆóó=¥,¤¸™ßü»#Ø[Õ[G%8“*#šòDOS‘`~û“ÐY ¤ÒšúÇÔ àHÛäGvñ02b^½rIG$ÍYx=Ρ†Á‘2þÆExÊ1j"’W9Zœ3ŽRŽµÇñq“M]åùβȳ²Å±çl«t_xR¦4h Ósîgs‚ù¢NêA—ûºžŠÈ"ÅÖÓŠ¾eeè6ûÝ®ª[‚‚ÍÍï>ÐÂSRäiÒæUIkû&/×í—)ØÜP+pVWû¾4Úò¹– +íp_¦Y]ô>œÓš,“’8Naväí,ö- €Á ˜Ýee–÷e²èv—mV¯’¥™¶'ë¡t²­²¤ÝeY°KFÄ!SxòU«êc]6«ë5»ºÊ´3¬3¦£–5`:û·+Eà€÷ ù¤Q€h‹@€±ˆ,%x^˜4kúVaÞ´û¡:›ªx‚;ÓkÕêdsöBÖ†@k«B"–ŒcçÞ0ƒKÔ– ˜Ä¨œxG–ÔC¤ ú¼É´Õ¸RIÚ®”Ólª}‘¾æÂiëim–’r¹©ê†ðŸ†‹Ì¬Ó´94m¶uŸóÔÀ—Uùs¹Þ×ÆMôþM¾ÜÐú©mR&kÐìˆç,xÞØÑn!#'I·y™7-¯êiè9o ÕM®PI«00W£î +¦Â¡[às^4Z˜ ûF_/°±l+½3ÍK=´ »]‘/õÑÂÕZ+ %‹EŸ²ª·I1v.`¥Å¿ìažd2‚ŒrÝÃzXW<Ìb½êaט=ì”鸇õ™>hó”ÒIHçh&Û-Xr’çB…€ïOÜø6k—okí= ,kE Á“#?°ª]w5À­ ’À±ïÁ°¦=¾Æ\e „œx ºÆ#!I§*‹ƒ¡ý”ä…¡x½®9‹= ¯ù(Ä6ÚÚx ¶ØÀ$éGôoRzi¶Ø¯q`Ö1¿Ùµ2­ÚÌhDL:¾«‰ ð˜ÁÄU1SBuU•¥‡‚áÑü´lH¯zö)§ãœhlW,ŒÀ”ºL,£Ðh, +Žù¡FÏ -iÇ(Êš¤OU²Ôœ Vσ¢D;3 NŠ„® uú‚…Ö +A! zBΪª zÊaÄwIl3H’ ²R7IK#«pˆ1‚¾‡JʤM.“]²È‹¼=Ð ýèh\JpÝ̳³ž Ú«`âsy~¤3,­Õë f½ŒlÑÝ>þyF>£Š‚̳eÛ¥ž€A®§ÒxÜgÂSþ@œ³² ÃzE +‡P€bPœÆD”µO†mÇhJS¾N°ò,§&§Í“íÎ64·ý*íÕ„6¯Ð +×–¡ià¸WéÀDÆ5·† ¶ûã]ÈÒï ÷†€u½Þf «)AôÑq@h+ÓÑA‚Ę$M˜EQ=w¬ˆ‘À"§‹:ÏVcy-ÍšeïŽ×lm¡±¾ÑSñt © S’Ü?ê› £qÒÖ;2éÄøO~¼S€Ã¨>ö?Ø·”+_½˜{ôBJ7È^ ‘ ôáí)DŸÊ®(g?e%!ï úÛ%‚C ´¿®'…€vu T§!’hl+(ú­“-fû/pݾ[Ë]Ô6ÖP@=w]Û=¬+Ú¶XxÖ¯®‰ÅI±®ê¼ÝlÕu33rÐ*¶c ä~î€M[c,8‘\‚T^Ìãë¢wX#²÷/ + +H¨ã4¾»(%(à nÀKtÓ‡•Ô¾pÉ õH©lž{/.د{, +e0ì>Ùr${ÑÁãÍðÍtÜŠzéÙüDñùîÏ¡9rP#nßÔ“±ÏOè(µ”GµMo£g~ÿÑèþ¾–Ž¥4úøôyyyI´î KyÅK¶˜¦C7c§±¯ë)ÆãØ£‘8hyøíÎ,|¦ïO ðOcŸõ;²2ˆm–h CnÚwš‡i3ÁE HèówUfÿ4ûðU‚ð`¡É×%Ý(í6O!•î‰%[VÏ¥!Ø£Ò``Û.X»+ÛÚÐÝUù‡ž×]DÎïa38îÈË­-Õ6oé+ª&i6‰ ‰yÊÄ_ì E\áê⃣òþR5âѼ«ÃÿïÄŽ/—T•Ñ¥^A†Ð±Ä06B¡„ Î#©ùéì\öÿ=- endstream +endobj +2326 0 obj << +/Type /Page +/Contents 2327 0 R +/Resources 2325 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 2333 0 R +/Annots [ 2330 0 R ] >> endobj -1799 0 obj << -/D [1749 0 R /XYZ 56.6929 131.9066 null] +2330 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [344.9397 501.3201 406.1397 512.7122] +/Subtype /Link +/A << /S /GoTo /D (trusted-keys) >> >> endobj -1800 0 obj << -/D [1749 0 R /XYZ 56.6929 117.2018 null] +2328 0 obj << +/D [2326 0 R /XYZ 56.6929 794.5015 null] >> endobj -1801 0 obj << -/D [1749 0 R /XYZ 56.6929 111.9736 null] +798 0 obj << +/D [2326 0 R /XYZ 56.6929 609.3932 null] >> endobj -1802 0 obj << -/D [1749 0 R /XYZ 56.6929 97.2091 null] +2329 0 obj << +/D [2326 0 R /XYZ 56.6929 583.208 null] >> endobj -1803 0 obj << -/D [1749 0 R /XYZ 56.6929 92.0407 null] +802 0 obj << +/D [2326 0 R /XYZ 56.6929 484.1849 null] >> endobj -1748 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F39 899 0 R >> +2331 0 obj << +/D [2326 0 R /XYZ 56.6929 454.463 null] +>> endobj +806 0 obj << +/D [2326 0 R /XYZ 56.6929 405.4622 null] +>> endobj +2332 0 obj << +/D [2326 0 R /XYZ 56.6929 378.8348 null] +>> endobj +2325 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F14 956 0 R /F22 953 0 R /F21 930 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1806 0 obj << -/Length 2545 +2336 0 obj << +/Length 2458 /Filter /FlateDecode >> stream -xÚ¥ZKs㸾ûWè(U€ øÈM¶l&3¶#y²IÍî–`™ŠTHʳ³¿> âA" É¦|0 4ñýu7º›ÂxS‘$˜DIàQ„éd{¸B“=ÌÝ_a)3WBsSêúùê/w$š$^úáäùÕX+öPãÉóîÛtñôtû°\ýs6÷)š.¼Ùœ"¤Fon7³y&|‚ð©M¯WןW÷ëÅÓlj‡~E-–âfóõþþvó|+o×·‹åêáDðì·çOW·ÏúµÍ­aDø;ÿçêÛoh²ƒ~ºBIb:ù7ÈÃIâOW% Q#ùÕæêïzAc¶}tLU”ÄýhDW>ž`ì%”ú=eÑÄ ‰OZe-6b[GV¥MVµuWÃ[\ KˈðÇÈ2ýÛúîE~bbŠ¼8÷w€j™!*\v¨˜R/Ž5a—å!Í -±ïtwÈŠ¬n`óeU‹±²ÓE{¿?e;æñwl ‡Ô â0†âë~â_<ñÿsÙÀš³(På;;¼°JÜá$Ž<«²8_ÚC݆”CáJJ«œ’È¡r´¡ô!¶Eí&øMy8”RñÚò–i“Š«»,gâê¦,~EÈߟbð¶ªf8žršF¨ea@úT<Í°ŸL%׌U ;¤rîqÛ” ±’&.Ð…PeJÙÉÐRšŒûv2œÐgØãdôÀGÉÐa Í¥»?K‰©Ʊߧd©ØH+Ó7îØK5‹§§´ú¡ íŒD°sŠâ ŒRF””bÄG9qAŒ ±-Œ˜àgÊ¿©²†U™t×Rëº,QÒƒô˜ «ÞYUF©(ŒÃ>×’‡/iQdÅ~ÀvÏqþ1£tšýž1‹ç8x}„¾@S'ä`I -i’|œ8Hrà €-È_k©îòuà8‹š²—¿Îæ$𧫺>µV3­À3+?|—Z‰0Ý*‘GŠRhÞ˜˜}„«J>ßÂqw·)·e>u‰Ÿx%æA«ÅµXW#­[›˜Ìµü\˜†0ôešÁ•¦2&û!«¯Ó òÂ0º@{'ä`] -)ÒI8² ×à|l¡Ü@øˆ‘„v’@:B;,†ètq<æÙV§0«‰Õòa¡J†á1I3¡Ø ê0ÜÜ¥y)jKü¡ˆúÁÖ`òõít,yæï#yÖ0sÚ$ nXž—šédû¦ù¶gEŽwJü ÁÝ”r0®¤ ʱƒr´ÁùÛBº Î.ÆŽàÓ”&Üõ ØMS ¨9>, NxbÄSW.ÖÆ~>7Gù¼2.¢ãèÐ$âNlÓ‡vŒóe ÆÅZ-á|æ‹"\-Ò#ü:O‹íkþáAL ‚ºtš›Rvµ”A¸# vBw„ŸaÞ:?¶åŽñN£6ÎGdz )VÝÎïƒ)+@FÞÙaôk‘ñGÅ 8ôatì…y7¢.nÀ°’qcÞ’‡úÑبE/Ø" -ý¨ŸF,<•Âÿ”³Ÿå ØÅ%È _á^Î?BýW¿ühƒ¢|\sxZÄV>ýˆzQxé¸0¥ì|j©ŽOêHПgØã|öÀº7úΊ®-z§\JfçSÙïåÔŽîÊY¡¯êcü³Þ¦Ëv71°1xé„´H!Ò£ÈQùp RÀN ä5ƒjŒ°­‘3+ZDsEœèt¢*uDüaØò†„v_‚çÕƒ¦_KÖ(E”xq òïO’¢ÎG;Þ€c;M„z -.¤¦”ƒ(%¥™‚³ÙÁ” Ú jˆmáÊ_ò/o<“mÝ$ átqjÞ@å œ8ïL ‰8ȯd“›ßDÓwÞoGßD!Ë~Ï«²´näz»˜¬ëQ§" s Ì8 :Ô’¯ðQ¬¾kÛß|Rä¢y¦žîB Ò· U”P¾ì™R"•”&2A.—sAD±-Dšà:§[=½‡*ãGG•u—ä}á¸çŸVó¬`ãßô—ð£s4§^ž*í©úB¹ÚêM°®œmÃŽ‘zC¥'N±CòÔï‰?¾ÔeÎ6@K;sv€Ø¯*ßÛßa‹Q[ä!Æb ˜À9 -Æâ¶SÊn Zʨ¢‡¢º³…3ìq[è [ðÃém×4»6zÂÿ{Vî«ôøNš‹‘ÏŽ3ô½˜ÒÄlŽâé'¼KÅ÷G–çr¦ýbâCµ¼};å09º‘òO9Ëš‚éïŽK.an)e èØ•EöAf: -¿×ùJ8Œx ½àƒb%¥óž0rÊNhƒâ!¶…bü:+ô±õ9}aªfÎÎNÚÑšB¶@,õD$ãŸÁnªôû«è‘ìT08íOu£yH¬<@(A@¤›CÈ΂ê>IEŽ:Ú…Ûq0§ÀDNc8 Ï*D²÷MÉÿ›Å5 ʨ WÆy(ö{1°Wßõcå°Êš'néãE8›@Qd6=âDÐ÷éê–•ç¦|°çV7êsç)3~§ñé”ÿÌç'žVQ[G:Àÿß?È2ú“‘Gb[Ï… 2õ$R/Å7—$Ã7׿Ü:õÿo÷±endstream +xÚÍZ[oÛ:~ϯðÛq€c–w‰yKÛì"»9Ù&vÑöA±åD¨,¹’œË¿ß!‡TD[¶Hv±(ZÓähøif8ó k6¡ð‡MRE¨0r’Iej2_ÐÉ=¬ýõ„y™Yš ¥>Þž|ø‹H&†Íõäv9Еš¦lr»ø6=¿¾¾¸ú|ùÏÓWtzNNgŠÒ0ûéâætÆdb8¬H»¦éôãåÕg”6øñùê»üøåüË©H¦ÿ‰›¯×׺‰ÛÓ·œ\Üö ‡/ƨ°ˆ|ûA' x¿?N(&U“'øB 3†OV'R ¢¤a¦<¹9ùG¯p°ê3”T)Q\êÉ „ÁNlÜœ”Pæ™%’™jÙ›“³1s)kÎY‹o¾¨WYQee·ýâLJ’JÀ0Ô~ìÕ91išŽ¿ø¬×x08’¤B¨q›7y³ƒ2Ñà–„½#Ê ñÊÄj”‰Qf‹E“·í6LÎ1JšæŽC{©‘­ù`kÎRb„[Zçóbù~fšÁ‡¤`´uÖd]Ž“Í)K§ù|Ó´Å£ŸòVu»“h[\\Ö º‡Üë³{|§”Ïqá;çCÈŽàà šL/žgöýÁ”p843ÆàÅG­Öe~¢Œöa˜?»Y2¯WgœRv¶¸KÏÎrç<ú ×Æ)ð@î?C©ý'£—:gàÁD´íÛÂÌ+<‘1MeiŒqO”A¢ LÓô°qz©‘­‡QÆ SñÖzìòú;UôQ~xÔ0`8GLÔKüÄ‚Áv*ú‚V®Æϧ‡bþ€Ã_›¼)r¯/ÃçÃUGöƇ6Dp°ûáøHˆ e ðP·]•­òãsƒrhã 4²qdz! 7rkçÞˆxâpì ¸žÖ¡±­é^,έ÷šIC¸R“™h!\…© ‡:J¡°¶î<βö¥šû³šy«vÅ»Í÷kÞÖ¥u£RÓß½ëægQÝ{ÇYEM]Õ›¶ ˜†¯L!ý)@%1™Ý«¢Ìì q…QÁµË6ÌŽì6‚Nï6Jeóy¾îZÍp®,Z¿ê"ÑꀨuvñQ K½9aÙš³õúÂ'® R)LÚXúqV-PÄǾ5„]ÑëµY‘neC4Œ}2‡16%½l +‡P¡‹¾¶Ù}ÈœC¡‰¿…d:žÁ8gD =QüL¾=}³Â‘RU˜Œé· é˧‰{‡ƒ/_vpJ©Ìû + 7‚$B¦òîe{ÈEµÞì&!ç“wÛ+< VHM4$ì¬QWŠ¹o%š‡€2NâÏuWÔUÈ­.Œ-¹vι߬ ¿¶gû¬Œ¤F¡¦C©ý ¶—RÓ=…˜[ú,U´ÿÛ*qÐx,ãˆ{„v_){ Ãåa3õR#[Gõ@ H IŠ·¶9Kj(ÅGqý• f=XðNïÔ_©0ÁL s¡þÂðµþÚ úúë´õ(ŸqY`è¹tÁÄBò$‰aUûÐnÖëºéòE8g¡ª>0\²Á™Ùèuy|OŒÊÔ@3æpŒ¥öÇh/åbtoºbÔÀù‚`j}[|G€2Æ ‰Ž‘ÚŒµƒQpB5OÛ§—Ù7&+ ¡R²xß×ndÈHÀ^8aQ3DoËÜmÏyòe¶)½ÙC$ôõ{ù ¤]7E…þcá\³àý5x7G±§¢{ÀµUQ«¬Ä/kdÐs(9àlçTÕ#^Ôy[ýæ¿À«{ˆã|ÜòuŽ­v7ðm„]3s£§E‡ËmW¯[zÂÏ·á\]Íýjxò>džE€^¢½Â+ÃÌU­¶vˆMÉ(Ú9,6¨¯83þ”U/ó¦³$^÷P$LU® ‚)[à?]ÿý¿¢$ƒ¨‚)ßI ›³GOõ¦\  îúkSôÜÖ—›ÆcÃ_ø‚I0MPšã +¤px—í¾¾ã bzéQ×Nñˆk¡!µíïÛŒbÓeÑùbq¥‘Gåþ`…¸Þ=·,M‰N(vßEq?rº˜$FŠÔËOÓ)Ð}&¶}Á¦yȪƒjУìéµm ›p¨{:]ÞÜR³¡Ê‘žJ¢)tƒ½ØV;ˆ°‡W,ÖÐBj{]ñ^­ ‡J%ù1.0”ÚÏz©˜ŽÒ.ži{°ƒû÷R#âr+ˆT‰Šü¿Ñ.N9<9fêÔS©ã×´C…ïsM{bMa> endobj -1807 0 obj << -/D [1805 0 R /XYZ 85.0394 794.5015 null] +2337 0 obj << +/D [2335 0 R /XYZ 85.0394 794.5015 null] >> endobj -1808 0 obj << -/D [1805 0 R /XYZ 85.0394 748.4854 null] +810 0 obj << +/D [2335 0 R /XYZ 85.0394 650.8348 null] >> endobj -1809 0 obj << -/D [1805 0 R /XYZ 85.0394 748.4854 null] +2338 0 obj << +/D [2335 0 R /XYZ 85.0394 625.7398 null] >> endobj -1810 0 obj << -/D [1805 0 R /XYZ 85.0394 748.4854 null] +814 0 obj << +/D [2335 0 R /XYZ 85.0394 378.0874 null] >> endobj -1811 0 obj << -/D [1805 0 R /XYZ 85.0394 743.3452 null] +2339 0 obj << +/D [2335 0 R /XYZ 85.0394 350.2627 null] >> endobj -1812 0 obj << -/D [1805 0 R /XYZ 85.0394 728.6405 null] +818 0 obj << +/D [2335 0 R /XYZ 85.0394 153.7325 null] >> endobj -1813 0 obj << -/D [1805 0 R /XYZ 85.0394 723.1655 null] +2340 0 obj << +/D [2335 0 R /XYZ 85.0394 128.6375 null] >> endobj -1814 0 obj << -/D [1805 0 R /XYZ 85.0394 708.4607 null] +2334 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1815 0 obj << -/D [1805 0 R /XYZ 85.0394 702.9857 null] +2343 0 obj << +/Length 2393 +/Filter /FlateDecode +>> +stream +xÚÅY_sÛ8ϧðtîAž]sùWsOé5·“Ý6—xgî¦ÛÅV]m˵”¦î§?€ eÊ–Îv(Aø€ÅˆÃ12)K­´£Ìjf¸0£ÙòŒ`îç3áy&is½žžýôw•,³©LGÓûHVÎxž‹Ñtþ>¹`šAO^_½}3žHÃK7ooiðÛÕ뛋›±Ê’áö÷ëëwŽ0O„άL.®¯/ß¾¹ú'1\ LÎõo—·ãÓ_Î.§ÒñÆW¨ñ§³÷øhûûåŒ3es3z†΄µr´<ÓF1£• +”ÅÙíÙ?:ѬûtÐP‚3©R9`))‡,e,K•TÎR¿7ÅCy>ž(Á“¦X®å䡨h¿uÓ®Še‰»Y"’ÅG¥™ÍyÚÙ;eÌÆy'çi=/Ú » ‘M…S4žoAx5£b¦ñlQ•«–ÆëMý°)–^ÙWA›¡\á©NŠÙ¬\· ¾(·*КjõàV…q·ŒgõrY¬æž·ñzs“EµòÜÅf,òäái Êýˆ¤,iÊÕ<|¶"1±|÷Aùé©l¼r˲A{ÓK[ã®pB0kŒtûhaZ©4)žÚÇzSµE[}ö¤¦Ü|.7ãL'°¾2Yâ”w3õsCÃN­Þ¬ëUã)÷ŽT/÷wb]ÐäÉÕŠ&j`ÙÐð¹vßηrW~½ð,¼0<áêÎe9vœx·«ÆÛëð|µdÜ…;Fæl5 ĉșέ9æñ;½¯×mFø@¯p˹×MèhE‘jÆ•~É(%Y–fÚ3ÌËEÙ– OxÉRêxaH#ÕEš²œst§ÈyGºÑ䋈4‘«5ç(#X&D:JyÆŒÉåT ¦IÌE  @¡ãB¥&>ZÑ÷Ïsà@ŠÅ¾„q"χn¾ ¨„@é)ê=wOE!,“"?mŸÀ4°l|àBjÔZõ×½À`·"¹ºÆ'j>÷ÑÖÐD}OÏv, 3ï4’¼þNFûX´D},šþ[ⸯ7^*‰äÉ×zå%ÍêU[T+ºKˆcmÞ»à¥*ç "<Ä}jódJA DÀ“§bKf“U½Y‹Å–fîJ¢zäˆÐÕ²Øl‰ºZ(ÊïÇ´GÇ`Éá&€CÒ´A`ʵy¥a·ˆ¶JˤX45‘œ^ð,h¢)Á"sÒKï c¯ŒÜnX°žèçžÏK³?öω½³LFßÄŸÉîº QjÒ™Ë]‡ò r£“:?ãÓñL.Â?’Ë-î|Qî/o-3¹°'—<‡Ë÷"ˆCRùFoý BëéíÕÏ0â!’WÇ)aÓ§?úAwÀÔnŠUSÌNÁ[`Á=Ûn—îõº¥¯œ Ä"LxÜTÑM9fú‚J¢¥†ÞÜhÔîR£Ì¦­ÂBˆã§¬!{Í5d¯'9æ:~Η;èuÈ£Ê ¸iÕTíÁY ©˜•®žÔ¢ãP£˜9³<Þ“?pi,¨áŽ1D ©ÙP7ã);#Zwi×+Ä œ!Ô;)Î!²ÜyB³.g>-Á›a¶’“‹àô $ÐŒ).Eÿ¬ƒ ¡i+{wçO.ä.ÐnjŸ™ð¯ô÷ýÝvOÄŸq!8­_Êb®.¸œ mH‹ Faƒ¸¾ï?š,=¾+'è$¾ /„é4ÝSøHV ,Zæ§ Õq ¬Üór yÔ¢¿²Ë ŒÏ ŒÜË ŒÏ p‚^i2˜Õ‘º”ÀÈÎm„O·‘|Á‘Ÿ«Å‚FO ^âJŠ´E/‹-¹w +ùÔi߽3¬XÂu…xìœxyiu¿ï´û Îî‚£é¾1vâž«Ù㞬ØýûeTDP~µÇãA@6¯sõBÒó×/_¾°V«ÕKøÇ\ÿé˜Ø¸Á«ûºf{{¦ ã¬âô¼zKÏ z+™Hs_ ÿæ7¾a­®sìÇáê ç}H!Žê┆":Nc …_u=¢]åyÌ¢ùÏ¢”úü)£~ƒ ɇ–õç2˜’JªÈ–ÍÿÚ˜Ùÿט¯Žæò5Ø⣫ßý›çÊ°õ’«ÀefeÚi…62?Ì}ýÏ£ÚÿÊy}nendstream +endobj +2342 0 obj << +/Type /Page +/Contents 2343 0 R +/Resources 2341 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 2333 0 R >> endobj -1816 0 obj << -/D [1805 0 R /XYZ 85.0394 688.2211 null] +2344 0 obj << +/D [2342 0 R /XYZ 56.6929 794.5015 null] +>> endobj +822 0 obj << +/D [2342 0 R /XYZ 56.6929 740.3318 null] +>> endobj +2345 0 obj << +/D [2342 0 R /XYZ 56.6929 714.7319 null] +>> endobj +2341 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F14 956 0 R /F62 1352 0 R /F41 1208 0 R >> +/XObject << /Im2 1341 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +2348 0 obj << +/Length 1890 +/Filter /FlateDecode +>> +stream +xÚ­ÉrÛ6ô®¯Ð‘š‰l\Оœ&í¸ÓI\Çi'ñ"!‹.*Iyé×÷ H‰¶;“Ú>o߶¤ðÏ–IH¨Pr+IBÊÂeV-èòö~Y0‡³öHë1Ö»›ÅÛŸE¼TDE|^­™Œ‡iö"¼»üø±~ÞüŒÀo—ï®/®W"þÂ…Ï\]}² 7«Û›_n¡ÇŠ1*ŒÄ/¾ÜÒeúýº D¨$\>ÀJ˜R|Y-d(H(…ð+åâóâ÷àh×3T(&<ž±çs– +‰ÖRíŠ%®š{Ý¡viY"p}íV¶Më†äOuZÑiµ/5Éš +7]Qß!Øï4wŽ®ü¦ŸVŒ±€“`l$]®… ŒyçS"(8­îöm³Ñ?¬Ö‚Ñ oª´¨ß‚ ŽE§Û{íäËv:ûæŽq¯ÛÊ)Òlf?ÿ„€¤±tòð©<\%™´ò\öÀ; +‘|‡pj>¸»=CÚ|Q>‡Ô7K»…P~¡ü"z*Þ„ÜFïÒ{·‘5-z.ëË'áF–Öl4îºS¹Ò9ý …×h¥2íÍ ßû}Ydi_45ÅD H sè.½óÑfbÏj²qÑöeßzèþØÀ&äö}Yg. Sˆ™ÓÁÈP‰eysÿ—*Á‰J’d¾F¬Šë1ÉóÀa—Š9…Óõ äaÏ–2 EAùJKc=ŸOÖ•™ŽÌ%¡Ñ„í÷呧øŠŒŒAؤ2ëeQ; l9‘ +&ô¼ÅxŽI‡›)~ÌÅ®tG½‰ ì/a€qð\SwÔŒ抸žæ6Iwo48Vl\Z’jH­[ì…r˜I䈫¸Jès]kíOh\H÷ú—Žèht_qW|Gã’qû¡.‹oî·ëÍ3ÅÂH¿k¬Šap¸KQoØ°¯Ù{xxX)ŒïÎfÙ„˜‰ÁO.s ÜÑ"¨C¹®û£‡`Àj¢èPÍÞÛÇXxŸ«|>ò9ºõ €2rÅÖ:]ç¶ĶóÑ–«Å°ó÷A·…MX¶)ÂmÐu÷W]XÇbmH7•Û·&í…–ÛÈÎѤfÓo&šuî'©aì5ýñd<ÊÒ²Ä7ˆ7î&˜çÓ…sÏqJ¶úùm¿?îÍΘ¹Id<>p Þâ{ ®Š@‘‡‡ŽØ=süæ/¼vŽÖ[Ýê:C…_~¸0ÞXÄÌ×e€"Ô=(h´•6pd@´Â«üný +®UZÒÒi=!ïà üíèëÇLï{$àe0%5;Tµi§St–ðźó?Bj#aÆÁ~dÖî­É%É=ËxA÷~ÊÎ5TüÒÄúq_¦µ½òw&ÙÞœ¸Ø?]œ<LxÙ· òÜ{xÕ<ÒÍ46:„Áw¿_DeLD’<3k +*¡1*æ…2&d\Š>¼žËþ/+bHÐendstream +endobj +2347 0 obj << +/Type /Page +/Contents 2348 0 R +/Resources 2346 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 2333 0 R +>> endobj +2349 0 obj << +/D [2347 0 R /XYZ 85.0394 794.5015 null] +>> endobj +826 0 obj << +/D [2347 0 R /XYZ 85.0394 741.6375 null] +>> endobj +2350 0 obj << +/D [2347 0 R /XYZ 85.0394 716.9352 null] +>> endobj +830 0 obj << +/D [2347 0 R /XYZ 85.0394 420.5643 null] >> endobj -1817 0 obj << -/D [1805 0 R /XYZ 85.0394 682.8059 null] +2351 0 obj << +/D [2347 0 R /XYZ 85.0394 393.2598 null] >> endobj -1818 0 obj << -/D [1805 0 R /XYZ 85.0394 668.0414 null] +2346 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1819 0 obj << -/D [1805 0 R /XYZ 85.0394 662.6262 null] +2354 0 obj << +/Length 69 +/Filter /FlateDecode +>> +stream +xÚ3T0BCS3=3K#KsK=SCS…ä\.…t œ;—!T‰©±ž©‰±1ƒEV.­knj©g`fA‚!ÂVŒendstream +endobj +2353 0 obj << +/Type /Page +/Contents 2354 0 R +/Resources 2352 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 2333 0 R >> endobj -1820 0 obj << -/D [1805 0 R /XYZ 85.0394 599.7666 null] +2355 0 obj << +/D [2353 0 R /XYZ 56.6929 794.5015 null] >> endobj -1821 0 obj << -/D [1805 0 R /XYZ 85.0394 599.7666 null] +2352 0 obj << +/ProcSet [ /PDF ] >> endobj -1822 0 obj << -/D [1805 0 R /XYZ 85.0394 599.7666 null] +2358 0 obj << +/Length 1945 +/Filter /FlateDecode +>> +stream +xÚµX[Ûº~ϯ0Ð>x#†wI穹µÙdS4[ô!Ù­MÛBdI±äÝEÿ{g8¤lyåcÅ+r8ü83œ-fþÄ,3Œ«\ÏÒ\3Ã…™-¶¯øl k{%6Š­L&V£2f2™Î’S·÷¯^ÿUŠ™äÌZif÷«á,›¦Œç³ûå×ù›¶uõ²üy“HÃçooî£]š¥Y*p‡Rf•±~ǧ¢Þñ·ÅÚuá™ÒV†=Ö0ËMæ÷¼eâ&œóù²\#?2¨”)kIŒ»b뎜å,·Ò%˜Ê@fäÂÍþÜoR¦4z÷…UÓ|ß·4Þ÷eUö‡£`‚åÆDÁ´`2¤Ì—CÝ´]éuxõá~°©åL(°¨– “«)» S}áR2Î@{Ç!ühq¢a¼’kÐÓ‚µ¾þ¥s»'·{Óä‘t2êBð”™Ü87ËåÎuáVFgâ™V"𠘋 LeXfM„\TÅ$ ÌY–¥ù9àê*બ\=\ùXÈ”e’§ç˜ßÿ˜ÛaÔN ' +½ÞdÙ,üv·Í®ÿÓ%[dçGü¸*ö‘¥b¹à꯿Š×ÚÿïçU_ïnD6oZ·V˜:Z+húså~–•#rß4­V„íÝŽÖ^¯‰“j¬û˜ö$Jß»IOç·=Qáx”«#nÜæ:ê2ògªkÀªˆX/a ±ŒvmU¹ß8"u÷ ÇEjчm^ÖÀCã~¿«Ý’–W¤Êö Œ´@iÆíÈl¸|„‡##>ÌÐJ·• Ì>5] þ©ZÞVÊ +È/Û².oļëwEßxá¼ïÜ„K€°ùPq.¸tCÊÆlß7Ø“’{¸×nÓ4(ºåG1ZZ†ÕmGKnQ ~¹YÑ·ìÃjôj4@®ù/°Šó=„ûÛ£‹VœIh•¢ID¬²;ó- nöß}ßî{ôÁçŸánv/ÛôÐ. zé»)ž\Ø‚]­öõc¢¨†óà6ë ƒ+Ì&Ƥ¿opÍr­bíc1;k–å¹s–¦)Eü›ªß4ûõfâ(m ãTêÚÕJÈ”W)9¯1Æ«ê€3oî%ÑŸË~C´E³Ý‚õ“ª¬­QH¬÷[W÷^‘p¹Ä]T]C\›¢ $š?ý"@n›e€ò÷Œ_kJ5ÞVC +åzìöC +¡ˆ)–”<ôÉ…B~ E¤®9â¢8;f*Y9Ÿ[ìü Ñ!öV4ìö ôî@“&½ãc“xÔS“’÷&ÜÞ¢bÝ0'"ºÝaZD~«çÏWÓÓÉË"ŸæL«ÃE&›i¯2™} @>aÃw]>¹Õ7jþϺ*¿;¢»bW•>P`‚éEÿ§)e7iÍüííÝ{âÈ궅àÝ‹ãIÍj2&à5&†>úb]2©‰Þ ÞÙ<“ÕO«\èqðo÷U_¶•;înÉa±ìº½ Q~â>ˆK¸Ü7̆; F°¥E¾/• +ÅP¡Ւ(þx øÂN¤‚(]ë%:á‚æ±ì©P0nR Yñ¥%ϼCä5Jx՞粪‚`QW`(Ê€^R¯> +FU—¨UÙ‘[¢–õ„/ +c˜"v¨¯]¿x /¨¦zŠ©,ƒ‡“jì^MÈ=n´B$ŽÌÿ/Š™AÃozrm@ £óÀ’O#°ã—_ØäƒcÒú:ƒÄl²«Ö2[PCçB‡A|ßöÀ7z WQ@x©k†ÿˆŽ=]LÈw›{Šh( Ï`žÙ±¥|ßd³ø)¼Áº.4h@õ +Ôζ–ú‘*ÁŽ––nU@€u´ŽÂMô©…2&ô5»XžG»<•Å”? +iô¦?ÿûãçOþóšÞn1˜)f3+NAÍï7QUÊñ§êgCí r õ(G§ÀM¡É\3-äY=òaoø‰ëà¤m!.cÖAs/ç˜S¤à¬“içÞ7˜P²nïèK]- Þ}¤/ýÞà[fÌ)Qˆéªhij;Œú«p}ÓXåž\E4z%d˜^§ÙüCIMÒ©s gLü¬o“e±ÄÇùèz“ÀtöJ ­à¹ç@^ÌUìn“Å¥ª(Õ¨*†rHq (-¯ÇòKü]À¯‡ÑdæP½ª—ëµÈ!i˜A²%‹á3œ{":R‡GŒÑúAŠ&í òéãö.&Xzhè¡ +§g=42¾ûùÁC#j*u[ø a;xs»icŸì½‡ÁKØù;üø> endobj -1823 0 obj << -/D [1805 0 R /XYZ 85.0394 591.7571 null] +2359 0 obj << +/D [2357 0 R /XYZ 85.0394 794.5015 null] >> endobj -1824 0 obj << -/D [1805 0 R /XYZ 85.0394 565.0374 null] +834 0 obj << +/D [2357 0 R /XYZ 85.0394 769.5949 null] >> endobj -1825 0 obj << -/D [1805 0 R /XYZ 85.0394 559.6222 null] +2360 0 obj << +/D [2357 0 R /XYZ 85.0394 573.0107 null] >> endobj -1826 0 obj << -/D [1805 0 R /XYZ 85.0394 534.1777 null] +838 0 obj << +/D [2357 0 R /XYZ 85.0394 573.0107 null] >> endobj -1827 0 obj << -/D [1805 0 R /XYZ 85.0394 527.4872 null] +2361 0 obj << +/D [2357 0 R /XYZ 85.0394 538.4209 null] >> endobj -1828 0 obj << -/D [1805 0 R /XYZ 85.0394 502.0427 null] +2362 0 obj << +/D [2357 0 R /XYZ 85.0394 504.6118 null] >> endobj -1829 0 obj << -/D [1805 0 R /XYZ 85.0394 495.3523 null] +2363 0 obj << +/D [2357 0 R /XYZ 85.0394 432.7569 null] >> endobj -1830 0 obj << -/D [1805 0 R /XYZ 85.0394 420.5376 null] +2364 0 obj << +/D [2357 0 R /XYZ 85.0394 303.3232 null] >> endobj -1831 0 obj << -/D [1805 0 R /XYZ 85.0394 420.5376 null] +2356 0 obj << +/Font << /F21 930 0 R /F22 953 0 R /F41 1208 0 R /F53 1303 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1832 0 obj << -/D [1805 0 R /XYZ 85.0394 420.5376 null] +2367 0 obj << +/Length 3825 +/Filter /FlateDecode +>> +stream +xÚÍZÝoã6Ï_ õk•)‘ê}à²ÝMÑM÷6)®EÛÙVbamÉkÉ›¦ýÍp†´$KÉ÷rÑCŠçã7CÉsòßžéDE‰VÊS6g×gÿvzÝ«£"ŠUH –çRFY’Ä=$Y”ªX9\_¾{ÿÃkÚ×O×°)ܼwd'Ρ;2Æ¦î• Ý>ìÊe¾¡eõ¹^æmYWô»¾åydgI$,,Ü<«ònd1i"­tÂc6uý±¡)7åÇâ[zAwgK©#€ìæÒÂþcfŸ§prÿjŠýçbO?ª|[P Ø/F–Ÿ'QfLêç¢߯á}ig´~ïÄed¤LÏÓ4…S'DƒæÝQQÑ0 +—fæËfq”$V?¾¬tºloÇ™‰•™þ²% +Ý‚”Ö ®Ød,8$Õ{z^¾§ž|µ"á4üœýÔ»þ(ÚÖDût(öϤ”305•e³›µ_}™W4vÁï»ßníÏzbõ’‡¬ê¶-Vs”&œª¨!ÞPCŠe¹u +lÕ¬ª[¯¾ð‹ö¨x=…ë¥L鯧x=5[Ö›ºš¯ŠM¹-aáþ¬°3-²ÙÖ&Ù@£9ìv›Æ;ULTç`”1‘ÍŒdS8jÂà•R«3–;öxßZ¦QbþÉëݶEղݲqåôX×M‹§õ|ÔzAÌž¶^åYfI՛ϯӮs^™•Zp¸rv[Ó`"9(«»é—XF;­‘ ·<¤e .OÄÀéÓ¢T åÓ¢Œû¢Ô–D Ï{«þ\®ŠÕ˜3ÙDÇOŠQ¦)YÖUsش͈ó† ú~øMÑ.¿Ù;GðÒíÈÌþÀ_úÊ«1/ Þ)§† $’÷oʆ4œÆÒÁE$¦X§‘Œ¥ìËéfÍÇFcw›úyK²Úús.&Žy ¬W»ºZ5}=^•Ín“?«hÊS'%?î¨;ƒ¦ý´„tV´"JÄîÇVôcNVìšM@õtÚ[±l&…Vߺ¼\cÙ£.ÉðVC‡ùë`¥†!"<ú°›sb¢Õüq9wF="h? +÷íãö¨¤[ô(êá¢ã²î.ZV+À:­3LpR‚–ãƵœÐáIáÌ5KN‚þt(©±"êoql°PòêÿžSÇ?ßýÌëË7ÜûŽÆÜ[F'…wÐ&N#+…öNÅÅ6˜sÁÈ+fûs¾)WÝÍ8ÃVð: ƒ´oظԗ8` ¨[fêIµ=ç;«|Èu®6²ÚÊ¿€0ïË cØ]±‡(´íDÔöÃŽUÍŽ(g{1fGQઽç1 Td =e@Q|sùãÕõcˆ; îóÔ÷Ë p?LEû˜/ƶŠ AæãH½ó=ÇÚ:qï%€Ôó†Ðûä_:oz‡f;~¥ŠlšxVqBœì”_ ±Qø€Š< nMKË,xåœ:¼Êžrkf~ÇuUpˆ²ä b¢pSJ%´)¥R‡…¾nˆXí}½ÿHeÕ‚¦äË‚;Q-­Eäþ°ÙíL\ç·ßâ—qšÙEÅÜ¡ Å9võ¾%ú6 Æ‚ùiv€Wƒü ˆëx Ž|·+À?UN×QuºÛ¿"IËž¡`ËÈßGŽÂDF[?À±u: äH Ôþó©YœTLéH˜~ŽEÁ@/ns@;˜ŽgA³€¾ÜäîH¡ù›HÄåµÉ*a¨;8(è”ÔUòð ľ\­ø†ß(8|£5+e2ö»š/Çí*Õq߮ƳÒQf…Ç“´ƒÔ ‰šI¼cö\“?6½r{`,0 ¸Áåš]s¢ÀýKÓ?ùœÝåÛëûz[4e½ó]ü†øòíàÍ—ë¼n@Ä£ïFAý:Yø¤çÊŒöÑ`>†SÁ_ÆIìÞsAj†ñ±hF\ªTdO¸~Ú0k±‡ NÓ–<ý"oA®´R½âN25ÉsglŽãC8DLr#2Žã[ ÊMÛA>9WX:g…„ˆ)m…P%mªúùçÕz†Î`SŒ©] jçµó¶ÜžÝ-$˜±0wkµ7Ä0½S6È&Ú¼„<­jˆÓ£:l]ú¶§Ÿ.2ÀöŠDÈ(PY­tÎ×õì(ý× ²ªà_ç(q$B¬'sO(¯ï6é°£gͺ>lVD_°[|gE:0Rλ¼*ÿt¸+ŽibxÒÄÐh8Çjv>—û¸uÏ AsÁãw_€Y?§³5˜à˜Fá$õˆ–ÆQ˜z2ý“‰ñáÐP&ÜåyYo·¼ÍQŠ~[•8SB‘‰ô íQ¦&x¼í¸ÇÓ:±'HBÀ™å‹Ïï·Å¶Þsrwhò;NVÅâpwÛðÌ©(•j@*áTK 8²š7-l2÷ +vr€Ä~T½=QÑgâÓÙô¹˜)>@Š€P픿W2J”õ[›ïÆwŸešoVÖ°Ùb5 ˜(Ñ £_€,Žm'¸Í8$sû='=kJÕNl®t™Ä aRÑb;„Â-@·WÔ*LTIGµ‘Z5-¸AúáŒÞ#§XuöN »^]]Sƒ¶‚-¿lCü¢ý1Ô °ˆÚÞ áÅÍ«ÖüïÊ^“7Õ†_VYXû¨¹( +Öop}èzîÇì­“»ZH5ˆ“GYa4­zÅ©Z»Üƒä‚ý$WØêÔôq6Y8ǹ¨ÂÄÉP…¥ò¥·åxT0dB,™Œª"•Þ:œ ´u…UlÁaQƒÊ¶Øb\§$ø´}^5¸,’ºòïèMŒ±*ø¨ôÿw‹)û8 H*³}= ©’ènü¯ 'e¤çuÞNaÓӜϟó郪8âëPÊ0b<‡DÔyªÆAo¾Žˆf¾li.çs-Éø’Ä•]Ääè~]DcdWðk%Oýâòê» ~ =¢bO™ãÉx”wÒ £Ž‹Çañ˜WT.}¹À€ÛÙ¡ÚP’iâ‰Ð"³$ÒꨴLWjOë¸n¸" •jîå’ɉH. ++µÌ;ÁPÞóýó˜ KÈU³là*^Þº0ƒHM¶q15Ž»hÖe¢Øõ@].E½¥Â=Òs"“(‘àÐ1P.~þîCD$ºA¢_¨¬–´–~\b Ži×ÝgÏ¥‚0e}îõf,Öàž©•Ä"yBÃA«Ž%•’q{S´ÙTé 0nNÊ?n÷ÿ¸ƒ VI’ŽñÀ„7ë  ÅD‹Š»b:…rlrçä¦õ“-×yuW4>£òyå%AA„½‰IúFD«º( +\ƒj3DÖÒß ‡(ŸðÍ\w Nó5GÉë/¦«Ò÷y3q©‰º?Š1‰òe®()} +bÎDü…îR +ïóæŸÆíWéd !ËôîVû룻UÇ»•)w ˜‘GŽ Ü©»ƃ(˜ùð 5óö°¡Ÿ«šŸ€YÀFe³>ò7Æ‚…Œ:ã)Rà3°Ð¹Ðykw;äšÝrnã³€Ä)—î#œÞa8%ÿ…z*5WÌ‘¼Íw;ò2²w%ë4H µã™IÇ—sÓˆ#šr Î5”Õ$;3©&\:XI÷&qÜ¥#I“§«C)Õ¸[÷7âXå-y7ÎWûQQIMd‘–jPÕìWC _WÓ¯Çwà,ümõsºZwhÈ9½qzÁmÂÅ¸é‚ 7Ößv¥ecñ ±0¶ÉŦ¡6âIØ HJóEóŽSšcO5È+ªúžËa€Ñ”£Ñu!ؼû‰ 8[¦‚#ÞîZ.¤á<€çò®êfÆ…›uJ¿Öpw¦@^<Œ}Éã¬F<é¬ w;´ëN¥d•:~…ÁJ{o¹ŠÂãQÚ7×—oPÔÏy“AÐبR©ÁÍ3¾†ƒÒÙGW«Õb NÒ©ÜLpË’›}W$+‚®EÒ2›ýâÎå@+Pb‹v¼ij"u¶á/J:ÂtÙ6Åæ–ˆ$ªôh¬\æ%*×zÃæøŠ ƒ|DǧWc5ü*5T‰&®]º$¸ã¿M]l%>r¬·ùrºÈA¦$| +"BV˜ñI§ë†¾xÀfHÏqàÛw/çï^%cÁ8`–Y(bOud)ú O¨&y¢álD ×Tˆc÷Âà)†Ì‰HÉ´ õ0QÉÓÁù âþ“I‘r5Æ|Äï4K‹0ANEÞóTS_Q-ëÁ'ï Ñþ´ôŸõnx’»¢ÂK2œvE”'0« +‚ÕrœÀ4d‹VM}­°¢Æ¾ÌáK‰ÿù{éã×àÚDÊÚ‰o|b‰amfÊ¡Ÿ~ËÄ_VŸòþ_dúÈnendstream +endobj +2366 0 obj << +/Type /Page +/Contents 2367 0 R +/Resources 2365 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 2371 0 R >> endobj -1833 0 obj << -/D [1805 0 R /XYZ 85.0394 412.5281 null] +2368 0 obj << +/D [2366 0 R /XYZ 56.6929 794.5015 null] >> endobj -1834 0 obj << -/D [1805 0 R /XYZ 85.0394 388.4584 null] +2369 0 obj << +/D [2366 0 R /XYZ 56.6929 752.1413 null] >> endobj -1835 0 obj << -/D [1805 0 R /XYZ 85.0394 380.3932 null] +2370 0 obj << +/D [2366 0 R /XYZ 56.6929 501.191 null] >> endobj -1836 0 obj << -/D [1805 0 R /XYZ 85.0394 365.6884 null] +2365 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R /F48 1228 0 R /F53 1303 0 R /F11 1442 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1837 0 obj << -/D [1805 0 R /XYZ 85.0394 360.2134 null] +2374 0 obj << +/Length 3111 +/Filter /FlateDecode +>> +stream +xÚ­Zßoã6~Ï_‘·sÐZKŠúÅúÝl‹-ÚÝ´ñâzØæA±•Xˆ-¹–œœÿû›á )J–œÃÝa5E9ÃáÇo†d䥀ò2‹¡tt™ê(ˆ…Œ/—Û qùm?]H–™[¡¹/õ~qñîG•^ê@'ar¹xôÆÊ‘eòr±ú6»¾½ýøùæÓWó0³÷ÁÕ<böëõç¯×¿PÝí•g×?}¼ƒÏ$!IKÄìæÓOW÷‹Ÿ/>.œ1¾ÁR(´ä¯‹o÷ârvÿ|!¥³øò>D µ/·Q¬‚8RÊÖl.î.~sz­¦ë˜b•q¦#Ã1Ä:HT¨Œ>䇶¬««¹é¬Yׇ͊Êý¶ùsÁͯk[:4eõÄíë½ðîÇHzºdY&b°µÌ$Ó³G‚=RI©wöw{Ø´åüÐ{¶ïشŶ¡¼é 0…ç∅d¶Ì«þ^ʦ|ØðGY¡-—sðvi•@I:ŽCc†-LÕ¬>´»C‹åhö¸¿’Ù¬ÞRË®ùS€—á?É¢{ƒ‘Í·£Y›ÍßúX—M[ï$ú§ᦠ©LÌþaüŠ2ìW,.î^FVÚr™“‡°õµl×ìRßíJ‡A¤²}º*ŸÆü„Xæ{Pw6Wù¶ E" p¬ž`-^p9Âûäè 8›• Õüu(öe±¢ª(V µ·5U=Wõ«í[P“Y5¬É+î—ožê=ÌoË}Y‹vZ +ò46VèE•Ì>UÔúþÓç›ï­’²é¸ª«‚1'ðôˆv´Ò/åŠUˆY¾ãÊݾÌÛbÄëRˆ@gZ³GqF#^×ЙbœìÈ@:PqjeØÕ§C) Š$I¬X Vm ÙKøìÇ,Ô"â.¸Æ«`YW#£;¤@,83 +/ç¡>J3 ]a›eûúñ÷«8žý“ ùr»øôåóÝÈ<Áé!€PËs(MÊ”ÍèÖ¥ÀiJ@ þd³ê°}0x„ªú‘ê…G®2¬Â]^×å•œ-×<À#ùX,[ú&DBÕkÎÍ~ÆŠui;mêúù°³&£¸×6_\m€,3;¢ž‘\lÖ0÷ðäz[kU6»M~$@ÝÕ[ì¯2š˜2T×pUS´Ü¶§6Öa«`TþDå‡Ò`C¥4#e-S« m]À öW@8¸{"1kœþUÑûmYñ§õtjÀ}ì`ggfcB·¹B}óJÜ!fOÆP(À®ªÚbõ=o6"1«aŒ=#ÚWŸLP(·E}h=É­™|6íöÇSY4³)”%±±écNK›v¨É\,ÂjÃPÈFÞ6ü-,Ó'lû×Ú(çå'ÌËb5Ñc·9ðàMùÄê0´Œì_ÀC%™%íïÆöm ÓÔ’'€Q¨µ…‘Ì| ÒFp‘Œ"ÙGʱRÉ0È¢$ê¯'¹É¨‰g Ʀˆ`+àTM‰ ,®±wÇFs"¢›Ô°Î_†ëýv <2 ÒLÛ¬à;šÇêcÛˆ;3$Yº`“^Ú'œ!ˆ JãQXðÞeŽüûI¦,CÇ1$ŠPMíYhîK™Ä6ÊF['efù­ªïÛån¨X*€r"ÞÐì¤NU—ÂÆÝ_q'(˜ý·.y¹PÝR $,÷TZ|¸¥6N«¡Ê¸–2k샙˜©§LlžÍ+«â1‡˜B2¢Ä}Œ_ÈZ(b Gj©ðõæ–¡ †ëáÒªMÑØ•«è÷úgNfîþäj,g²ÆŽ~¡¡éX½ä¡là€â2o˜Åsú1î0-uUQTéL©ÞŒ ©R†oÀÈ“:#+å`ô²Šb8t,Ö„X€ 0Le¨Òˆ«6ÿ•[fÛXùtep.pù§¿Ñ†!I¡Ðö„W2iF¡ b©â©Ì»à@þhñö/Ÿ_ó.plwpz(7e{¼’R"M))hs ÄŸa½,ñ›@†Ð F6Bå¾=ä·4j–‡²Å¶I¼EiHEçñæKMãÍI9oBô¨÷Å æb¤:ÌÎ+wR§Ú§ïòüHöÕBÍ6«€ý²*{ô„33mfALb*8gØç›ä\à†‡ÝŸ¯¨¢¬—˜qütŠ52cj\Elx¤jf8¤i) ’:†o˜ÉAºé&‚if±Çèx†B"8V…q¿±¤žÔ™%µRfIWõ6/«0Ÿ¶§ëÞºÂàI&Òó8©Súë +6$¼{&ÜaB§›*@¡)È=ÈÇ*Á4¤±"5ý·9.v¿,Þ†Ë4¯†%$£:²gHâk#ˆB¡H»»¥ÝìÀøå#ÙÖ슥˼M[•œ-çJé †”§O/¾­ýÃtD‰NÜ §ªmi²«DŽŸ§ã(PÙ“ú»¢]¾ÛM½y™:UkX̺‰f|Rĉ€{è~ +ôõWFz+ù„Mô­}_Éî:®· Rgœ¬½ß¡ŽåzÄL0 rÅ“[1w  ^øûê üTMî)•&AÆoì)_jzO9)G“Ý,Fiò¬òŽ&O´ÓdO½ ÍHI&4CŒ£ÐŒ5š±ÄgÝ[Ql Å–U°®è|(ø|8Ú“ûHÎÂà—Mãôa‹Í£°…˜åØ^Ë2dùŒ7ºòp†Ä&²;l +ÄeG>{ö¢qϱs—Þ‘9Ï㸴ç¦Q¦¢ Ž²ä ”yRgPf¥:”­ë× ¤¥Q +õ†NêÔ‚Á…—‚â¾ ··È„6ßYÖî{©ôÐÙ8wiΓK:»ŒÝÜNM»XDA¦ox¸:ã`rþ…ÕŠ1À1ÑYÕNèDwßµ‰ ÒX¦=å7…½–È»“JKUXÃ.mú®=VuuÜviä×&ô‡¡öÓãqüXÇ…!±:ï]_jÚ½NÊéÎóºÚ'Yò¬òŽ%O´³dO=dÍàÊ“ê<ï²rwMé0.)¹Ÿr]ú2õÆÖ÷¥Î¸ÎJy®{ÜäOÓ®;§ÜsÝPû„ë|õ×ÿ1Ü “t7ûƒèJ@U¬bÿjÔ©p +Í©ßpª'uÆ©Vª³nuÞ©ç”{NjŸpª¯ÞdÁRÇÄ£X0<Š…¦hï©dЇ…ëúÅèæžà¨j•·9=ÿá×CɃ”Õ`ÀóP‡|èÆ&ô²Ol¦²öÅÛþ:sày]|Y¦pªÇ#mÈ—ò!¿“š{ oÊ+’Ââ«Û‘ê½{}ø¢«F#F£âÓªy³„ÒK¾)WL˜!=Ë¢$Œpp‰"Ö/—|wJ¡-ªIôä¹@òûŒÀe³]½¹‚d|yôg•u³b¯¥‘¹  +ÖïIMeµÂÇÓ¢±]Ìm¯ï#ÞåxoÖ“ÍüÉ‚qÞ|³Î³o=†hI9üRX‡‚÷à¬)ö@å—Û¾®Í¿|]PÅ>¯žð 9Rf¶‚ãÙÒOV»ç¨Ûå{Öc¼¨%{ +¾U¯ycGôsd*ö6Åe%ÎK“ƒ÷¦€}žb|©iŠqRŽb–ç)æ¬òŽbN´SLO½¡ؘœªevM3Ƀ%ò6>ÜÐ/RÌr],Ÿik@ͪlðD¸â?2€Ã2X0aÒ¥Ç2 ŸX›ú,fa×Ë=äãPõVæšôqóùîîã‡Þr»býØK,ébh +p2£·RKOhV¨ÃÁfòÞöœÖîÚv¨vüÖÖ×{C¸Sù:¿ñÞ2¿\ßÝÙ;ò¢ò^F]Þîdû\5éVˆõ*|ãY¥“™v*Ët7½-,ö‰[!wÉ$æŒV'3T;øã Û/‰}½ÿO‹_þOµ'—8À¿Ä™›pñ?ÿÁW÷çlþõM6ñb€¥´´F¡›¤RCÓÝŸ†ÚþoÒë¯>endstream +endobj +2373 0 obj << +/Type /Page +/Contents 2374 0 R +/Resources 2372 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 2371 0 R >> endobj -1838 0 obj << -/D [1805 0 R /XYZ 85.0394 345.4488 null] +2375 0 obj << +/D [2373 0 R /XYZ 85.0394 794.5015 null] >> endobj -1839 0 obj << -/D [1805 0 R /XYZ 85.0394 340.0336 null] +2376 0 obj << +/D [2373 0 R /XYZ 85.0394 679.319 null] >> endobj -1840 0 obj << -/D [1805 0 R /XYZ 85.0394 325.269 null] +2372 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F41 1208 0 R /F21 930 0 R /F48 1228 0 R /F53 1303 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1841 0 obj << -/D [1805 0 R /XYZ 85.0394 319.8539 null] +2379 0 obj << +/Length 2837 +/Filter /FlateDecode +>> +stream +xÚ¥Z[oܺ~÷¯ØGITÞ%èC‚¤9hOÝ-øA^Ѷ­´Yic8¿¾Ã«HÝö´Å>ˆ"GœáÌ7’‹w~xÇE* +R첂¥a¾Û®ÐîÆ~¹Â–æ#zR½»½úÓ_i¶+ÒB±»}æÊS”çxw[}IÞ¥8½†Pòþã/×oˆàˆ$oon>üöþã¿á# „’¿¿ýíóÛ¿™¾›ëÈ~ùðéúîö׫·^˜P`Œ¨’äûÕ—;´«@î_¯PJ‹œïžá¥¸(ÈîpÅ8M9£Ôõ4WŸ®þé' Fõ§K +`6òú Íq2<éIz9 ×8©ÛGóÞ=D8ùý½y~E®qžèEÔ]kè+Ùצ» +lhïëÁ4êvÂîûYž^®1Æ €"C,¹}ªûéG¶D3Ý¿(•iäˆg  œ–¨VVɇòÜ ¯“äù©Þ?ÄŠ"9ȲíÕ‡  (Ð+2Î@«úóúÑÒDJÌÒ‚ˆÂÒ´ÝéP6Í‹™·—m¥$Dúø!ͨZ`-{X€*ù=PЫ•)¢òcÝ{ÿb{M¦ÑïÎy ‹` +Ùê–<™¢,rÙ“}:”ߤuÀz'惡Ë7vé„CÀq¼víù„Z÷è»FK˜Õ#ŒX=BËz¢õ*ƒn£2Š’ƒ|®¡hhóòÐ5M÷2y§SÙôvx´9x¦ÍÈZZ¥q©ÿ©{ö‚¸HãÓTžÝŸïŽ,O‡Vèßc$x.û1ÙÁ. !VG‘×+u(5¬ø="ÍH.¶ý>¤Z÷{Oåý~¨f^ VÇôgO5gà ² +Ø„÷èõJaÂ"†šOu;˜  Ý*à ê¾zP)ó¾ïÙnp2YwŽg7X]ýðâçöT +:¢XŽ Ž²S¤JýíÒŽgØѨԢ]‡´²Iiém¿VÖŒz*`î¥+ÒÊ㱩U©ŽŠl¡«úGep[ÂS+Ô¡ñÞ2óg t +’]H6!Õè•8áiXM6›¼Çd3c¾œl"î7Æ›¬&­º¥Ú=™ãüK¼ze¤³X»Î½µ–'ŽÆ‘ºäî;ÇÒÏaÕLmWó o["¤Z·„§ò–pN±Z¶n²ËÖÿå²5àÓ“íà€_tþç«:ÓÑêà *\ß™>Þ¡ññÆŒ•Ueƒjot5§FŽ +^f¢óá^žÜ¥›õl(š˜9{™a–f9]Ü&QÎÖ¶I<åLø‡ùtgÚ(0v{$W©Ã´:ÇÃÓæx@  8ùø`zÍ|º© cZFhûß ©Ó†Óª\€ ¯Å&åtsÈÖ¨]-¯3ZÈYZÐŒÇé±×v‹ÞwgÍmïšÆ¸‚ @Æ4ªåL£cßÃtÂÅôzÝ·Zö5í¶kžz/rz!‘†Tžä¨ÆDjbo¿îI[ìOšò_ñ¤P€°†Ž´2nk%GY¢©[ÙÇ!Êm²çÿBÖí•(¿`€jÃŽjÌ1°åìWsÌ&ï1Ç̘/瘈»MÇ4÷ÉšÎÉU{ðuzÑj…FP÷(úóT«¨û¡Þ÷V§9L… ¨~ÚÉÇ'S‚BãPVòµÚŒâ‘®¯JÏ`}Oã`œøؼL¼¸·æîÚMtÜK¨^j·Íý#)3¨‡Æ¥¯"ˆŠ,eŒ\È!Õ:‚<•GÐ÷Ó”o‘§œ^`kiæ\'U1…ê¶ÀÛ›Q#_*«%“½ºîÖõå¶õÄ5{pBk¥wqõ÷z}2÷qÌ}ãtÒ,ÅPåo[b$Ú0„%í 2˜òžµÈºÅ{ ¬SæËq5äîÌ¡*mW™ø}Š2‡ ãN‹ªßz¹_ÌN†êÐPj]CÓ¾Â<¥¥õ…#´µ%„ÛþçSk +Vh§[/Vþër5^Ãf?¾8l•Qh_2¯@èB¦ ©Öáà©<Æ2-¾ë àH‚n3÷Tsî“ÐnI`Û±¦Ó¹‡Úl{·± ˆ´êr9 ¶öã§Ý(Ï׆,(»rCª Ã8ªÑ0ö¬w¾›`(¥Y·ù{ª¹±m Ì¦±X‚Ñ6ÌÙ†9Û°È6ÌŸ£dY¿Žæ¡…13æaKæA™5 Íìy˜5‹N—·ÍÁŠbva×Rm˜ÇQ橪Z­®læöê®%ÛÀSÍ%ˆí’RšÇæÎ<™GDæÉœyDˆ¬ßGû0aí#Œ}Ä’} +gÚGXûkŸÌÛGSQ¤Í'цÑpAR$.ĺ€hÝdŽh´XÓ¬Îm±Ïæ¦|—æBÆŸ¤1®lÛ7²´M%Ï<Þ|Eˆ–ëUêŒ\¸x ©6Tä¨ÌÕa}¹]©Ò6Ùº*mÆu¹J‹Ø‚†4~\ÞW ÊòNŸ5»¹ÚFi.Û+ÒnéJ\%ã™;¸¿]84È¡>ñ·¡à][õq"!ÈLV lOnñ÷o[+¬¹ÖórZÒaA`PÈ`»É²à°—r§¢.a5þdv÷6b{†^;”Ù#„1ëÅghA¹:®5H«Ø§ÜÎí[‚ë@†º†Z\¨n\H•!Õj•½ð®e?‡íèÙ[œמ²^ñí·…®»éR  c¯Ûô ¨ÓÑuö©U ÏïoLÃÝEdþÜÆôÍC8M Œù&Ò ÂsKP·ý Ëj"Ÿ>ø‹à˜ªÿF°\—-¸lÖs~‘¯»«íÅlͼ¾ƒK¿øºx)¿ŸË&.Ï~Jsp5Ýp-Y¥†;¸ºjÛmÂÍTçÖŸéËì€^Åt–¥$¶ËÑÆ_,‘ôI:6½ÅvÄó”ï2œCÆÍÔpàQ£Ð6g(Ø£Y5;ó´›)sf‚-¦¡1b: ö˜6}K˜†:4cÅ&¶HVÌ  +éVìÍ)OHjŽ}>«CŸ¦þ¶tê ž€Òœ4>¦5qféø™«ÿß8Oð˜th«:9Ýü×í¾9WÓÃE}ç þýjåwÀWý[nhçœëÿþSÞø—C–AÆÌÉ2žHÆSøX8¡”& Ï¥„BÚËþ'ƒþ‡endstream +endobj +2378 0 obj << +/Type /Page +/Contents 2379 0 R +/Resources 2377 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 2371 0 R >> endobj -1842 0 obj << -/D [1805 0 R /XYZ 85.0394 295.7842 null] +2380 0 obj << +/D [2378 0 R /XYZ 56.6929 794.5015 null] >> endobj -1843 0 obj << -/D [1805 0 R /XYZ 85.0394 287.7189 null] +2377 0 obj << +/Font << /F37 1018 0 R /F48 1228 0 R /F22 953 0 R /F21 930 0 R /F53 1303 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1844 0 obj << -/D [1805 0 R /XYZ 85.0394 272.9543 null] +2383 0 obj << +/Length 3255 +/Filter /FlateDecode +>> +stream +xÚ­Z[sÛ6~÷¯Ð̾ÐÓ +!®òàÔNÖmš¤±ÓíNÛJ¢,N)RI»î¯ßsp)Rr§Ýx2ÀCœà;WˆÎbø£3-IÌS1KRAdLål¹½ˆgðîÝu4sO4ïS½¹¿xõ–'³”¤Š©Ùýº7—&±Ötv¿ú9ºúôéæÃõíO—s&ãè ¹œË8Ž¾¿úðåê½ût™²èêÝÍt•ŒQ$Sqt}ûîò×ûo/nîƒ0}iÌQ’ß/~þ5ž­@îo/bÂS-gOЉ MS6Û^ɉœû‘òâîâ‡0aï­ùtj„ÔD2¡fs ¦\&ÓÛ“X²牠„+©Ã6 =µMž +·é«jU·ÍëëãåRΈV1õçqTcÖŒõXSž-èﻼ½œsžDí&·ªÛ.ò=¶UT¯íÊçÉ2÷Á&{t_´µ}f»]~I£lo»E… zõVòž,N‰Ò‚ìȾʶ¹¥ÈÊ”¢ŽæOD‰w×s¤„s&ÁºöBµ}™U´pkXÖUS¬`ÝTGùÊ­gÑÔe×ægŸÍ™V„1Š[NI*%33ß›}“°Gù:ëÊÖv³²sãEcŸnç å/qÌ*ú]SÀ®UžÌ}W¹M‡fÓfm¾Í+÷½ßXAû[¦a€-·àWy»|µÏaÖ¶žÚ I” ~ ¿†¹µˆÌ>êX!¤ŠªÚîOR,}°NT–J#*¬ÆI‹#…{³ƒaØÞ$BŒ4ðô\}8’§¢Ý`KDëü 1ˆƒ~nÀÂÓqÓVm¾ßÙ‘·ÒP¸‰ìp™µÅcnßT.Y娟Š²´C BØ ·,k¾šÜr\nÌü`® Œ°G`žæ´°±ª·YQ5¶SMë?éSŽO&šhšx˜"Çåf⬸&p ^k@Š‰©(˜ég²òœœÉ«Öª°[µt;eO.¡Š«¿ .2²äÎ\ªD–huÞ¦ö©NÛÔ@elê¢[7ÅŸùë7#«*l9 ÷,ï@5f>´ª"%Iªä»±ªÌk36¾\² €a“=¸Q·m°ŽŠcKEÙê1ß·EcadŒZlÞ\¸‹ÝôS–‘©]°Ë›‰ÓÆO°xnó† É£Öš1³?Šm·µÔ«þT‘Èt¨þÛ¢r´Ij–ÐØ&z|¶›Â Ö ýƒFCGIÉ¥7* +Ø>,Y³³8-Ÿ/)¥Šœ&ÑB ¹õ\»-ù€µŽ£}ûG /è ›vÝU«|5eºU ¯û«úÉé48<ûín_€…îÉEã¡\ø9`aïmAæføÓzœÚöœA‚Ö2맙}à©ÛÖï]¾v¹ŽÖšÕSºÆ(¡B½¤k=ª3ºæ©Œ®å«ªyý¯‘¢1E†ò<ã@5æ|¾ }ãzÈú Q¬Ính¯l:ì•Ž@‰š¢®ÜûÚ>Ãjãq ô…?¯bå¾ G§{hN<œŒIé&¥o’ž•Å00þCEúÿÿ±o)‘2õÁÁWUG6aÀêq›lé–%ø£æÈÓÙ½Øæ&JtÑÒP@·Ð“@”àôR•¾H÷©N1P™uý\Õ¿n!+Ê¢ÊGxTš$`[ÏóTc†xL8Ib•%ø´/0îL»}ZÖæ¹jì`Yü–Û–ÙOlÜ}¼ÂF2ý†øÌì¶vQ7îK³Ò¹YªéCt²ÍwJakÓm³jnQ§@f§Cûfùf«lQâD1…`x‹ñ:…DIëp<„¸ØAÃ* cC bç–Cy¶ÜØÁášìª#Re¶‹ŽÍ2f®QÁÓ0í:[ÂiblI¶0·;܃¡¶ê³°:Œ­óéÇ]¬¯°‚B.룠‡ ]  \xp+»î´q… ‘hž¼„éÕL{ª€éº‚`+ZÆ{0}žy s. Y¹á½4“xn¥1; OÐzRhÿË‚þ=š>hSKk@cà'O›¼²owùAë RG7~õÓÛÏÄ»ˆ¤>ì¯Ok™ŸÁ¸D3M‡_Ô&³èÛ1/´³²•3cyµ +ƒnñ±jžDÐŒ(T°³(èSFA  +(XgE9®h<,užu ó>Šf9D½é÷5¦ÊÒºµÝΆ™Wùî]“ïMõ@¸äžÏugéÝ6æ&×À7™}ÜÝ|¾”2úñíe"¢«Û÷Äßûé©5Lbòiá2ø ±| + ¤F,¸Âº>4^TymŠ¥H1íðЩåCÓR¡½-=šºEŸs#?ù"ßd€Vw:"&B‹s :Gp³È!]ƒ¢µ#ô$œ?Ï=Ø™KSÙ‘þWm›ow¨´Êz +¦@“‹fWfÏnÐl34 ‘lÑéX³Ç0êÒ¥Æöü1)Ú‹É*+ÑŽä+ƒç±ðÅÁh@§hœ„”k9´>”2p2a~:·Íàáäaò²ì2¬³§Ù§:}œ*œ'„nM¾<é Î2?xƒ÷io0`ÿ9‡à³Á3¢©Œ à»»ùƶGÁ µeólL1ÈŒ<û+cÇ@àxÂß¹/ +÷):šëÖÅPS§:|ýñÓý”,“^Á.gTÅÉV«¢…Ð5h5&œu5Ž(z¸MùNA*Byü‚Z÷©ÎÁS 4ÅÃr“5‘.# Ìq–»'sA%§|ÈþÃvÎ ¾ô‡ÆÖ/ª¬í‚j2,ža] õ‚7Ä«85ö5†^¦aR†…Øí®(¢…0[óë‰ ôS"åb°Ò—®IµÖÓó0ã Û"àT€– ·åîöÝ7ÿ¾º»9&IëÂÄ>ÕîMGÑú"/a¦CB£ñºCš‰oMÑL:?”¨¨ ›ºúz"“I(ÀO©—2¥C½ÏU€GY׿Y&ëÉ’²L¡¤lª¾=˜ø?ÅŒ1ÂRŸ6µëO#\ˆ^œ4­ŒGnÌvâüJ¿´Ç%¹\ã=POXœ»¯{×}~|GöÊ|ø0<âž½’±·WК´W,Ac*ÒS`>°ZÿOíU˜qÞŸr¬° ŒKByràü—ìã À_°W}ªÓö*PÿÕÖ;SLE2 +bXœç¨Æì%‰¤Éÿljnw2W5 éÁ™Á‹cgF½3³m—»ÚNf?‡Í]y˜šb±ÊZS +“à >pú +¹9%:–G˜ý{£XëÓfœ0moµÿÆüŒóþ”­–‚Éç¿„1šr+¥Ïc¬Ouc*` ¯uO&ÍgY’æïɤyÀû¶Z–Ýʇ•Õq‰ÔÜ{»ó…Þ^÷SHjûô4¯B…÷PŸÈ&ãP㠌ր- Š¾zÎñÛâÿû/ï1½¿ýôþÆÎòכϷ7wÆŒ"xyÁir¸ñf^¿¹ý€‹4Jí@±Ý•ææ7sQ³0—@c§…[+£/Ößhê½VÓívÁ6–Scëþv'€‹)…îJ'nHaT ¨ì õ0€ÕM[î:²ÕSla~Q8¡1pÞ¡TS~”-šõñ˜Û2D,¼|F"3>}ßSÀsì]ê|êê” +’&©ß›EÖbT‚,0¸¤®»õ¥À„oÒêâdn~·$íÆ‹q(ì Ž/3'ý"?H_æ 0j- Ž›ÀÅÌøT9JóƒËÃnU$F‡?0] +Ïš¯]ØcDmŽJm½‹ G0á¡pîïò µ„ gæÊ–šÇw ‰$2öA‘å3qJ¬ýFÛ‚ÂCç~¹l¬ºß4a8sò ‰Åª3É"ga9æ•9w[̹b=Ž4Ï &Øö*o–ûbá®ç4ŸNÅQ²š-êÇnÃ4‹íïVLFŽ=sîïOŸ{Ìå¬ØhZ#óQ+Ò†³Á×æl°q8¿Ãƒ˜·[fÆÚ~¾p}Œ%s÷q·sߘ1¼Y9u½Ú¿ÎzÞåGY–YsŒ³ºi…ûUg8›MÝ•«aÄ–y¨÷oПœËêC&NðGcN#†÷ÿ6íðË;‘Ž÷ù“Þt’pžR/n)åòXt‰WƒñËþ?QªÆÃendstream +endobj +2382 0 obj << +/Type /Page +/Contents 2383 0 R +/Resources 2381 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 2371 0 R >> endobj -1845 0 obj << -/D [1805 0 R /XYZ 85.0394 267.5392 null] +2384 0 obj << +/D [2382 0 R /XYZ 85.0394 794.5015 null] >> endobj -1846 0 obj << -/D [1805 0 R /XYZ 85.0394 252.7746 null] +2385 0 obj << +/D [2382 0 R /XYZ 85.0394 147.4749 null] >> endobj -1847 0 obj << -/D [1805 0 R /XYZ 85.0394 247.3594 null] +2381 0 obj << +/Font << /F37 1018 0 R /F48 1228 0 R /F22 953 0 R /F53 1303 0 R /F41 1208 0 R /F21 930 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1848 0 obj << -/D [1805 0 R /XYZ 85.0394 223.2897 null] +2388 0 obj << +/Length 2054 +/Filter /FlateDecode +>> +stream +xÚ¥XKsÛ8¾ûWè°UK×D0^|ÍMŽíŒ§2Ž7rjwËñ&!‹ŠTDÊŠvkþût£Z²¨r¶¶x Ðh6ýøºA1âðˆQ±(•é(N5 ¹Gùâ„ž`íÉpÜý~ry×k³«±à +Uù~rÿÀG(þû g*MÂÑ&œ‰4•£Å‰ µRžRLOþÑ ÜYµŸZ@p&U$L å ”EJ*k‚ œHEÁSÕ ¡qwÀ‘: új6à”” ù6ž«$õ.§hÓЈ +ÞÚMÖeÕQÉݔݜˆ¤¦+þà6³ª3 ¬*ÿCÝFÍ"+]±ÆÞÇ×pêÌšU÷ŽfÖƒðî+{–ûf" +úî¤(Ûe•m‰Z7õØù8bÐdžû.žLß__cŠ©^ ߀µlÀR‚\@ä¼e«4â>ƨÀAÔf©¶´]ÞÔ€ÿkÉòy¶Êr0-š:oŠ²~¢µ…‡õÑÌ( ݼ5µý”ÀBrDÞxÿÔˆQêÂr[Q$ØÚ%Á… x ´fõŒ:á¸qog^PDODÚ“·Äât§®£l›L ÜÉ„ú˨&^ÏhaÛ¬ÿ^sUÚâÞ«ïõª&6°ˆíIM]˜¡Ê1ûý-‚^) $XãAq •³¶©±ZÀ-¡0wMKœÃª€N€Ç}‡Š{¿º¦I)›†)´¨ÓØØýÄEM²4ntðš6î%ŽwEÚ;Ø~瀞‰Ž_vF/®§“ó—C2®µ*S?—ä¶zacÑÏDîc…-(}…ãY›[{:›Û‰­Â° +q‚Ž:#ª3(8& ¡›z…¸~'¶²}Õl[,¨)З ù&~i¥½ÇV§I°®Û#p ä:öpKš]]¤Ëøaë¾ ¯g¦ËÏV¦mªg>ëÿ Wüí¿¿}úãòÏ3Š®ò! øÞÎÓËK:ýäãôÓÛ?oÚ¡V ˆ¾£/, +$&;Ä¢n[“¿™í“©wí lÇv4bº7Þç«÷‚«p¨/HXö|ÃÖ•€ :M÷ŽxþåÃôí“AÜyœ³÷³Ý‰ƒØGw 뚆 {W:vGëUÔLé¨7?D€Gs&O!&àþ„¦õUp¿Q©¶7ˆÅÇ®UQ$’Þ1´ùW)c]øÎÂ÷ÿ8^weUvÛŸˆŒmÝ,[È’Wà»Æ D[œ@o¼¿t0eˆ%jø‹…€ÜÜ‘pˆ4ýßÇôrH¼lÞ³÷EU¯Ú»Íóƒ'åC-§ÂËö%Õþð¼Ÿ0 Ž–©x3 P…,‰B…uÑtGåÅékŸß¸^<šÁ‹cĤÔâµÄîM‰ø_gHCwr®_Ëûç›ò6YÙ•§zyt5KÁÑë¶è~¼Øe_¡Y•= í¢™Ž“+è~¹u0–F-Áñp:üA9©¼OŽÿû?èËo^­n"‡qÊ8dðqä•ÂC +¨îÿ˜êþŽâšendstream +endobj +2387 0 obj << +/Type /Page +/Contents 2388 0 R +/Resources 2386 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 2371 0 R >> endobj -1849 0 obj << -/D [1805 0 R /XYZ 85.0394 215.2245 null] +2389 0 obj << +/D [2387 0 R /XYZ 56.6929 794.5015 null] >> endobj -1850 0 obj << -/D [1805 0 R /XYZ 85.0394 149.4956 null] +2390 0 obj << +/D [2387 0 R /XYZ 56.6929 562.0317 null] >> endobj -1851 0 obj << -/D [1805 0 R /XYZ 85.0394 149.4956 null] +2391 0 obj << +/D [2387 0 R /XYZ 56.6929 444.3852 null] >> endobj -1852 0 obj << -/D [1805 0 R /XYZ 85.0394 149.4956 null] +2392 0 obj << +/D [2387 0 R /XYZ 56.6929 354.5963 null] >> endobj -1853 0 obj << -/D [1805 0 R /XYZ 85.0394 144.3554 null] +2393 0 obj << +/D [2387 0 R /XYZ 56.6929 284.7704 null] >> endobj -1854 0 obj << -/D [1805 0 R /XYZ 85.0394 120.2857 null] +842 0 obj << +/D [2387 0 R /XYZ 56.6929 241.0985 null] >> endobj -1855 0 obj << -/D [1805 0 R /XYZ 85.0394 112.2205 null] +2394 0 obj << +/D [2387 0 R /XYZ 56.6929 206.0104 null] >> endobj -1856 0 obj << -/D [1805 0 R /XYZ 85.0394 97.4559 null] +2395 0 obj << +/D [2387 0 R /XYZ 56.6929 168.371 null] >> endobj -1857 0 obj << -/D [1805 0 R /XYZ 85.0394 92.0407 null] +2396 0 obj << +/D [2387 0 R /XYZ 56.6929 95.6233 null] >> endobj -1804 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F39 899 0 R >> +2386 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F41 1208 0 R /F21 930 0 R /F53 1303 0 R /F39 1151 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1860 0 obj << -/Length 2121 +2399 0 obj << +/Length 4190 /Filter /FlateDecode >> stream -xÚ¥YIs㸾ûWèª*B°pÍM¶ÔŽ»=¶cy*™t÷¦`‰eŠÔˆ”»5¿>x J$5•”Äòà}x 6¢ðc#Ï'~Ä£Q¹Ä£Ì%›+:ZÁÜí34“šhbS]¿\ýí“F‰|î^Þ,Y!¡aÈF/˯Δ2 Ô¹¾»¾¿{¼}ž>ýã·ñ„{ÔùF=:}˜agñëíí|ñ27Ýçùtv÷p $l< üˆ:Ó§§ùÃìîß8?URi3z3_Œ¿¿|¾š¿4˶·Æ¨Pkþýêëw:ZÂ?_Q"¢Ðý€%,Šøhsåz‚x®õHvµ¸úg#Кլ¦b”páó[q6bŒDžÇ[Æò"â .´±_Ë"“•\âg c™ìwiu0¦ùtSönV¸Ð Ñ-*\ﱦRKû -Z9õ½ï§šç`/VÝPë‘¥›ñ€xÇù>Þ”VØr­hÒÀúà\¤=ê’êxG¢ì QÁtz-äNwg)Ö¨(ëIsž Žª8êÃmpÔ‡<Þ¤ v~Ý.ãJvA1âòÈ‚PóüÖšaƒŸéM·»4Ãæ ~è“0 | -›ª‹†ªÃ~4¨úˆÆ™îN8Zº/Û¿h†ý($Š¼ÿƒ_bÝMÖ Q?~H"\ÈK6Õ5Uƒ 4ÀaHµ…éînlÝ5" ªUã Û " tž„\°˜ß`:Ôé*Oóv¦ûj]húsœ¸Ï ]EV¸ãܹ&Èø¯qÄ™e ©*tãÂy(>äæUî0ŒÕü­(Æ)¥ý˜‰ˆP7º„™E5€YMuÄ,¢˜ ©¶0;ÕÝ™­»'7.‚Ý›,Þ¥ß(åI\5ƒõ÷?E^»\Wû.§â, 4àaÛ«æÆ«îå´ìv"„õÂaÌ/bQ RS5€¸îP0Rmrª»[÷}ºI+ôÈÒÕZy¤àERl%Žo8dæ\çËü7y–e™)1SÏ2)vKl+w{~Ö®Ö¬! -¸÷‹Š{Jð/qYÊŽéZA/‰E©¢—›ÉÄv±Zæ©ñ^H=Hœ‡ê<›ªÒ†ªÔ÷ T}„ôLw'¤-ÝÏr)•óä):‚_í" :ÖɼJÁÃT¬çâ*Æ–¾QÌL”„þkZuaHC°ÈcL¤ c"ð´c"Ž!–Ðx4D·ûåfŸ/ËREM±Ú±‰¥µ—Š~HU uÙDD€" Ï<7¤×‚óDq7š–â™ÌäÊŠ‚*aÕvÐ m0éMËqý±¦îõGŽë†¬1MÄlÁ„JíyW—†j@›j’šªÁ$ô±!Õ(§º»Q±uß(Éáhö죶ÅM±Ù^¯iÖd··bW[íOÙájªD7j£³0è §¥H -\§Il‡·îLx‹j›šÊÂfà²4¨ÚÂæTw76¶î¦>wëºPµšúÚ:ƒ©†) ¡o¼ÆN¼H/2Æ‹P¬}9ƒþ<¯vl>i^¹ó§#Û§,^uà,à²ËÁ uLlF[1±vÎ/EöŽwgÕûlFÉ:;T­#¡£o_!dÝèO rÄ /Ý$lªþÓP5'&*‚UOÌ™îÎÓÒÝS•ž^ô…Oþ¬` u!Wt-ªçÙtìy΋òÌ)}*v›¸3ú°ò»mçÀqº_íËê«Ó‡±‰€á2ª!áA¹Gýæ‘' .Î]rsi$Ívñ[ÕULSHÊ.Dæj WèÕ\ÐÆ‚ïnV+ÀdÜ :º]ìWëÉRñààb÷®‹OÅ¿,’ýj’çTÉ¢¾ºîTómÍó|•æRî »1v\¾#1˜]X½01˜]K|P¢m/2kÔÅKèèëd8êÏ<ÁÑ_ -aÜo汆ÆÙ3¨¢sõd¥Ë*^ÉÛXxùÎR~ȬتýÁŠüˆ9w›m&U¿Øé½cïU¢Àâ,pò¢2ª‹ö6°L@ÎU\¿²q8.€6býN}×I?âL¥°Ž ®üHU®‹}fFµVÕx•øý}_à»*ê¬cIj†\m­17ÂÞÔ©ÏpÐƺû<3ú$)6“.|¶qžjéŒ:¯ü≀Æ2-“,N7:‡ê‰¸jH ññBçç®:s%võrá‹(+$-K¢èp -uüa„ÄøÉÒ7YÂò°§O+|Ëô'66E^­ /œ÷z‰?Ö)\6;6jVìÙ+†ÎRZ/ÙÉT[?뙉Wà -BRSOÄú1£ì ô<(AD]­Xx©°óZìM¬¸¾{˜åºP¬ú\J"VßCÞäN¹Qï3;¡Ô»pý²©Î“ ì‚™8 -ÓÙ„õç‘A­Çâ@¢m”Xe&X ä¥”Q–$jÀƒ$‹R­´ãÁ›·w¯ßß¼»¿ùñWã¾éØ&.çÊDJã:¯ë¦å^ª×KÉHÇ:cŸ²¹šÃJf95M¹Ým +„íìЖ›²}¡«zOÀ®Ø¼-«Gz~s{GÀ¦®?v ð[ezvÓÒ ~ü +¾É7íÐK‚ÚšÚE]={þ¨Ê·E3|óŽé\.÷WÒΊ¦.°8X2­gxËÊ+_¥vöT. +†Š}“u:Õ³Ÿ×EEت¦6w£>¶EÕ6„»v×–uÕôû¹!Íì±|*ªWÒ‰8‰™É§6BÁ'~'vû2LSÓ¬kd‰Ûm¾¡yë!KßQÃ[X2ñàÒHå9BÚ³)«‚´d¼TD9vÀkˆÚD…KfQlX¸p¦Ö IO¸”³v]°¬·y‰œ—’à×yKPø ¦>Üe %áÃΉ˜q"†ˆE^ošÑw¹Ÿ¶m‹å|Y,JBÂݼ{Š©sO¤è•ÛøîëE½©«9ó––7µe±)·e‹ôi™âÀ)BIàW€Ñz†kÇ7Ïër±¦î‹¼)&$HÅ*;+@‰TžÛÏåfCc>¼Ð4Ëb•6-!Yqé!§DjFAxRb‚Ê#@û3ZÑ”ˆ€€ÄQ˃šbSLЯ³HJ#{Ò¢ІLR†e÷Ëa{RKÏDèê?-Jµ=áœÐ!’ ¡š_¡1qcöwÞuXü–Á¯óvbÏt&;9³góXƒ·1©ª'¨úaÃJøñP8M°¬š¶È½r®¨%uÀÓä^îû8ÖëMÙ8¹¤¡ˆšx`¨t ŽŒhþªh_틦Þå'ŽGµgGÛ:_å7AP +V„%ÍŸÎRÔ' ˜Î¼ù€‹…U‘ÔRQeÙÄø <õÛüƒ7ÚG¢¤áeÇ}®oÿ{%Á ùM1Ó8³C»M®OK}‚q +; á 3ãõ3@ÌŒGÌÀ!B‹þ}Ê/§…Òê¬U‹m,GVMÏr0âÛ]ËÄ×تٲlv›ü¥[‘î~¼&€Ô{Q»vÉÔ±aÓ³?몘0c +"îypÊÓX‹ñkY¹ê-“êifƒÖ Ö>´Œ^?µŠgù¡w_¶y Q¡¼õI:­F4Ñf€p%邹_ó×88}Mf­/ŽGÖÝÅoB¨Ê伈›…?ÂHû™Š CsÆ.=D,¡«úàÕeå V°f´?ØçØ‘,øŽùbZNUœÅTKgU÷Wá.0Қ̾!…CLNÞ"€šw%g/ôä8 +íb“7Í”IÜnš¼×m(CYdm°…¸‰‚å–L•‹lpš‡‚ZŠ›û‡ ¸ïŠ¦¬—LàÞƒId¥ƒ¯×yÝToQç@v‡õÁ‹¢ ŽA4ÄE÷~ãB˜1ÌÛæ›[jÑßTm±‡™Ñš6›ìÓœ +öuㆇ8àÐî-Á4$DÞEUìsömEu"„‚ð"I‚ˆœ6¼™²ÁÚPb˜SÖQG)ø /uËiW‘ÈÔKÝ~JraJ¤gü "üMÇ…ˆöš7h~®™e!e‡žšžŸd/¡Àà‹4åO0$º™ØÌÖ9Z#[BÇÀíÈØ=•K·€!mÆNùâÃsÌ-¾ƒädFí²IrPs- § W<•õ¡¡QÐ6• m°†W„™ÞÄà­R}f?b"œÀJ˜·y.ÛÅš–Ë©Øm¦6‚Pæ(È8<>v‘Ä>_½ä阴̀¤„þ3‚Š¢Ê6>X{ê@°ð~I YcbÍPk¾w¶^Alº­—ANR mŠM± UQNU\{"ç ºíSŠùfšl%Óa,ävÔ›.GÒf*J!øÍâ³:™*ëy7§ÆynZÇ>¯š•‹‚•—CßáØ.KT`%Ò3®]G™qg–ÝÚ®2°„<ùt›¦éPRÈŸZ2¹ÔždM³3f„ž·w(å`ÁßÝ¿' E•zœœâ(¢A$ZÖ믮áìªCÞ¬¨ý{(WÇ'ùõ”&F•ž ËUò㜤ȅm¤OÖF)VÃèeÛ±-Ù„+8á÷a¸¤S¬rŠPØ?-ÆÑ:V–š]±(1Ê õ%¨à«A.Œ.hÑ:|ªCav˜a%ŠFç$ŽK\„t»ŒÀÍ»4º¹½§_ q5-þ¼‹¿8~«ÍPºJN;ÞóZZP¦O¹bï}6qð)¹~OÕÒ/༑ȂZÎo§C.m’£˜+Ö˜ˆaTûxPÕaûàRj@º€ +p˺ëæ‚[À‘ r8ô >ð >­EðI‡<ãt¯CŠ©q¼–§ªéù§†t¸G[¾¤wùdʇÖEÞ™ô\Ÿ +"¯@îÇ.Äï ð|ðw>sÛ(Ž™êâØáÐíp} +*b‚ ¤ •EÜp“y~b`wC©è‹óüWdu…)%5劦tEÔ ¢¸h¦IˆÆ†ì`Š•eGe}иàæÓ³[*ãKg·´*žÉÜ[–„º Ä “GcÇGZ†/ ½á4 1U7 Ù]73oÊ’¥‚¶)hŽzïç£)|¶7J†HקK2ã‚ŽŸcXÔ uS„K6¸¼€“¥Ð‹G±´ƒÉp¬Žíh€B¾ÂôdO¤ÅjöÓ¬°ÅÞ7´û²hÁz¦\~Í5šSx¤ŒR;p^ë¼z$}S,ˆžŽ^T¿ì*9ïOX¨ä(z96!ÚDR…œMÕd S¥!}(«e¹ÁçÅ®ëgfb&¡Û8ûßæÕ –´åv2Z‚ðÖZ«ÏÖK”Õé ^‚ƒïw…·*9¡} §e‹ƒf·`Å­jF= @Èóìíèe¬-ûü®oÓ¼=Ç®:ˆ`@„·v’‡ºYM’ pßÈ‘Å8½ ÷´_GF­¨ŠÇ¼Ó¯JÒRêW#Õ Ä÷JkCâÁÌ;Zï`¥×¦g 3·u5gÍ=@vóÄþëãá +Ó]Ví5À;R²ä®O%+͉Ø=K#c¬íùþ„ô‡î‰µ³;_(¥ J&§sá œ0OŒo½xÿ†¿AÔM˜Þ"}N¥ i‘qzä›2øS%$¡„˜= F”³zÂï“A|¤€‰Ä‚|cÏ\u’/—®¸s¥Ø'10i(ÊÃdÛ"¤äL%üY BI^„À¸(ŸÈ/ƒ2º4æ;t\÷†4® +.>ÖWl6O“ù,SÅ:þœ|§3üóØÊS1 ‰„ 锌‰®zh¥wÊÐ¥ ]|þ¼4†@¦W#ÇA·å¶\0OœPðP@ÌX:W#è¸ÔñùIUPazSX(ƒ)KF"êj &Cù å0x”}¬È€Æ%-†Gh+fÅ;ôÔþ[G4´hþ4²Í°W»v5€£Ñ94¶½ê*¢ÍÁ±BZuƒÌuŸoFYAMGfÎ’w§H“ÉÁ×/¤'l§êüƒêLÉó~+ uþCC"¦à.ÆÓðìG,s¥4>%¥x¤£UWºŸÎf­•c1ŨváÀ’} ¥N€ÈÙF¼f!”ªpƒk¦ÔÑL!·Íb5ܧ÷$þ`Ka,“2œé™˜ô0£©°? ä“Z [9ÜÍ +úÜ{°Ÿtˆžø„óv|ObññP1ÂCøöèZ¸Ø[_U9*÷wE®ó^ÿòÍûîÄÎÏS4mó%©>ì¢ )Ú<žÞÅ4‘GÕ=C‘¦«aOÚIžP‘†é¾¬I"¯•ñù4 ø.éÎçéx²«÷.—1ê’*T(ˆÍÓÿã5¦>ºQx]*ìPõ+ÿ’­NbŽÛ +«Ò£3XË $´t<¢,YPÄ:L¾O*â^vÅTô/M ê îŒuò²‹±ÒW;èŠåŒÑb2ùBÔø +ÙcUþIñw´çföúöú‡·¯UA²$‹@d4Š†ï~¼vÕìîæ[†þõ–N€Ý£œ¡òÈþОˆÄß}²ŠÒvh)Ê&[®J¦«˜Mžè‚h@öaÓ³R&MìÍñÈl¹YÜ>54uÎôå;>hØíKHª˜™ŽâTeÓÒg o)¤\Š<•±§‚aÙ¦CG¬ï5Ô2yÀ9–b ¯è•÷Ã/ÔŽê<ꃫêBW1§ +ì`WAŠõÉóõ82ÒþÀ˜Ï9Ì7ÏÜÌÞ¶óMŒŒ® N“:å“ÄÔgÚ_ó€Íu2±@0°_¹šT‡ÉÙ’›ê’o:æ¤ËHÐŒoi!Ž,«ë4¸«Tz²ézVÿ–N{ÖJf†Nb‡÷ûW³¦nòD&3çMg,Âù²×/‹op…}ŽRcpõ7+z›@ +‰PÍ}n@© rüƒva¢ ±}qM›ï9îîþ@™3}]}9O!£…ìX"B¾gøzPТZ†C1ÿ8ú|ãOù7›úyü]Wï +DrÐYúûé8ÆEôȵî9'ÝȇH¥ã$5öäq2U*tìJ, ÕÔ>çÎh¾P@N WNœq‚Gbˆ¦š³CÔUK–iC'vbÂ×<Ítþ”¨È¤q8`ûùÄ9‹íÎY&ñUfÂ0ϧ†!»³{i' k’fŸAÛ‘ÖñÉ¿T‚“L?óVÜHi‹ðæäÊŸ¤‹t˜™„Ã{ì=mtÀNr§”¯rŠ—$Ùtõ)Ñ’u×*?gT2ez¶aóäjkA3;ê•Pݺ\©ú‰ÌÃ4¿¦kn ÿÉgêù.—Ö'ë¡I¤cm?%%˜EE‰µ£"]x•r(`Nß겑LSs>ÛSbxW/V¨6+*gS8`¼jÚÔG¸UáúäôÜé*ß,ˆeÆZXë¡E„ã¡Óv;ÐþÆSi8¤KÝÆ8Ù‰ⵑ¸ú”ú“EE@zp~ü„q\ó5 +¾NQü­ñ—ÿ(·‡-_às¤þ*o‡Q¶ýô`“«¶»€qâ§ÏÍôÔDømÂ_þ™D÷+Ø­ê~1¨êŠ8‚pFz¢ÃR›1éáÇ´ÿ2à +Éendstream endobj -1859 0 obj << +2398 0 obj << /Type /Page -/Contents 1860 0 R -/Resources 1858 0 R +/Contents 2399 0 R +/Resources 2397 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1747 0 R +/Parent 2371 0 R >> endobj -1861 0 obj << -/D [1859 0 R /XYZ 56.6929 794.5015 null] +2400 0 obj << +/D [2398 0 R /XYZ 85.0394 794.5015 null] >> endobj -1862 0 obj << -/D [1859 0 R /XYZ 56.6929 749.4437 null] +2401 0 obj << +/D [2398 0 R /XYZ 85.0394 751.6872 null] >> endobj -1863 0 obj << -/D [1859 0 R /XYZ 56.6929 749.4437 null] +2397 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F53 1303 0 R /F41 1208 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1864 0 obj << -/D [1859 0 R /XYZ 56.6929 749.4437 null] +2404 0 obj << +/Length 2028 +/Filter /FlateDecode +>> +stream +xÚµËrÛ8ò®¯Ðm¥ª!‚A‚G%–³šÉØ^SÙÚ­L´I¬¡H I9ãýúmâ˜ðéæ0ÁÓœ}œ‹ãµH^ëýzòî–…ÓE ¦ëm–@X2]§_fïCs €g7wq¼üàÝÄ·÷¿þ²ü÷Ü#¡ÀÑlñð°¼»YýkîQŽ°1žýº¸û¼ød`óˆÎ—ñüëúçÉrÝIÖ—ž`¦Äúcòå+ž¦p‰Ÿ'±Hðé7Ø`D¢ˆNŸ3Ä}ÆZH>‰'ÿèöNõ§NmŒ( ¨C”ºÔÁ#0Ê´:Ö{©.ñîÖ'=T +}?ú +Ç« Ê€áˆS*,Jyl²²˜{Œ‹Y#ó¼ý¢O® Ø/öeÝ$õ9S1¿%[”‹u€„†§) ÛZ©î¤œdõbaåà,šòÏÆ€Šä kY=ËÊì³­ùOŠ—–òù°š1“õ±,ÒÚ@¾eÍÞ~ dz„Fˆ3!`EPÄ9ÕbÆËÇ9ç³ÞÎC¶XYO:“«åOômŸmöf™Õæ_ }Faj (·æ¿(«C’›uÝœžÔË\‹¯ OrŸ´ŽQÉMY¥QG"àÜ¢ýä äƒ§fŒ(2±°óç¤H„@qŒ‡-¥¦J6.Jà0B´ªC]ètî³z,b( Â.é3l¢wusg”~x¸×¶vÐS;lRàjëˆN1…ÅEpå$àØŒ´H‰rO‚¥²6øÚÓ)Ë4a¡€FHý†9ΊFVE¢²E’gÿÑNGiyH2KDÅ# sRŸŽÇ²jTpP–YêÆ¿9ÙläÑ• µ¬>æÉ‹%Wž LI4„l3ˆËEüaµÌœ…€µN +È¡'‚1Š|ö–¦(ÂA—¢’ãQ‡by¬²Òã‹á±) ̦¶»}îÑèH…­,6ejœv:Î"šÕ“Ü–&ÖÍ^¥Bõ©MG aEÁ^Ûø@˜Ad3äɺ1PÅÑÚä§Ö¥ý·úAÈlg@zG}CØn͵–¶ô K¨:y,•Gꃗòô·Ô çÙï²/üŸªÂ 6€ìv@5²~¦D6.Ó¥·žµ•žÆܼÓBÖ³qgDˆYÒ6‰(Þ£^€bшGÓP¡2GßÓ PU"…»ð:Š^Ÿ¤.ô£ê" +òÌY‰x³Šï?-Îês„}ŸÚ«Èâ93f+²hŒžðܧ\ªfÂp½·ÊÓ:×ú´:×›¬6§à'ê£ÔB·j +†‰84"ÁÐ1[Nà +Ø‹o{È5Žì- ¡o§/Á»*VÍÅìTÔît ™ù!‡éövõÉô|#…òë;ÙlÞUºî"ˆñ­‹RŽ—Ks¿Å§øþí žf;•L‰J“¶mPÙ U@¡€½[ùˆùAËÓ§ˆ ÆÛNZ^ ½mZÔµÜxi½­ÊÃïò¥(”AÈ}§²[0Ð}$Œ\gB&ð1Sµ) ÍÊ´Ýv›ÿÇGó¿“…¬ÓJš^¡Ì¿G{/Ey¬³z‚Œ (Ð þ!ˆ{˜€£ˆrU¡Ý½µú\´Oâ2âÚÖºÃ)Ã*"]ñž]}UítÔ6 +9ôx¹«/WBçÁ_[Š¤[Ñn•8¸¨xó»¾&Éw®Ä&`„ÀÁ˜Eî 7ì£liº¤8D³AÛ,—¯Z ÙÀØÁb=W,Öb½n1~PÏ3˜È:;ý¢y[Ñt¶ê”/‰rZyNþßÖûâÕÝjã ­&,„9ó‡¹}“'uýýn½}SêÖ…Æô`ÒTã÷ˆÞâëµ 8 +9ãÿK‚ßçô8¬$TMç„Œ*ÉÍ2þð¸zX¯îïÕlœíéy”†G&$ô0~jŽ'ÝVRnÛ#Ìnd.wmn…ƒ8Ûº±ƒµª7±mº·Oz±‘Ë@7¦ÕLÏ_>>¶u>M,߶‹²xºi…ãÇÛÀ.ÌÊNNSÏ^bа|(>Ç‘-uº‰LŽ»ìYÚ’úQ2Õ£*øjí¸×F¸|ɱi„0¸"ºžkúXæáÅ•k:,=D“1˦Έˆë,[$˾?° aR°üܾÄ_xÄ,“ñ´fP‡ù®¬`Ž;´“7Çg<¹MNy3z¨(»iߎÿe³¿äY¤gåAg*§ ™…®¿a€Ö´XÚôU\cy6ÀK§ú,€‹ÿˆ ^UPÍ~ëúé!½®žIk§­k|0ûBuŽø¹¬YïIF Ñ¦šçk¢uH—² ž•h€ÔÛT_¶2Ù¦1ÚyÏc¢Sšö”æñ0°ã + ='ùIœrë¬É! +ê¼áø55D$¤m¥=œZÞO–UYœéêLlmû®s… ÆB2,˜?±_Ù€±ï6~¼×vžV[¸pëjúÊÖÃ’î‘6›¤EÉŠZuÖ@E¯½hCÝUÏÐKâ.¹þå×îóþ"&uû ¡8F°¶B)MA¢» û.~)ûˆ/ãendstream +endobj +2403 0 obj << +/Type /Page +/Contents 2404 0 R +/Resources 2402 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 2414 0 R >> endobj -1865 0 obj << -/D [1859 0 R /XYZ 56.6929 746.6461 null] +2405 0 obj << +/D [2403 0 R /XYZ 56.6929 794.5015 null] >> endobj -1866 0 obj << -/D [1859 0 R /XYZ 56.6929 722.5763 null] +2406 0 obj << +/D [2403 0 R /XYZ 56.6929 684.0716 null] >> endobj -1867 0 obj << -/D [1859 0 R /XYZ 56.6929 716.7581 null] +2407 0 obj << +/D [2403 0 R /XYZ 56.6929 572.8605 null] >> endobj -1868 0 obj << -/D [1859 0 R /XYZ 56.6929 701.9936 null] +2408 0 obj << +/D [2403 0 R /XYZ 56.6929 509.4701 null] >> endobj -1869 0 obj << -/D [1859 0 R /XYZ 56.6929 698.8254 null] +846 0 obj << +/D [2403 0 R /XYZ 56.6929 470.2699 null] >> endobj -1870 0 obj << -/D [1859 0 R /XYZ 56.6929 684.1207 null] +2409 0 obj << +/D [2403 0 R /XYZ 56.6929 433.5878 null] >> endobj -1871 0 obj << -/D [1859 0 R /XYZ 56.6929 680.8926 null] +2410 0 obj << +/D [2403 0 R /XYZ 56.6929 401.47 null] >> endobj -1872 0 obj << -/D [1859 0 R /XYZ 56.6929 656.8229 null] +2411 0 obj << +/D [2403 0 R /XYZ 56.6929 335.1577 null] >> endobj -1873 0 obj << -/D [1859 0 R /XYZ 56.6929 651.0047 null] +2412 0 obj << +/D [2403 0 R /XYZ 56.6929 244.1508 null] >> endobj -1874 0 obj << -/D [1859 0 R /XYZ 56.6929 636.3 null] +2413 0 obj << +/D [2403 0 R /XYZ 56.6929 168.8052 null] >> endobj -1875 0 obj << -/D [1859 0 R /XYZ 56.6929 633.072 null] +2402 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F41 1208 0 R /F21 930 0 R /F39 1151 0 R /F53 1303 0 R /F55 1311 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1876 0 obj << -/D [1859 0 R /XYZ 56.6929 609.0023 null] +2417 0 obj << +/Length 2162 +/Filter /FlateDecode +>> +stream +xÚ¥Y]{›8¾Ï¯ðÝâ§c„$$z‡§“Išvã´;;ÄÈ O1d N&ûë÷è &Nf·½@Wç¼çC™`øO&’#Lc61C>YmNðäÞ}-BxÈ£hÒU{®•Avur¨}t—UõÝzn]míà»z¶ƒß1 Uû Ç !Xðƒ]ÈËV¼VoªLý`˺†!‘@‚€ƒìí'3+ØÃÈ¢”J'ç€jÒê<Üœ2pïˆ1»ƒ‹ÎÔI¢:/ t¢ô5*t¤ŽPÁK*¬G¨£HR~ê€D¢¬rW+5¬Ç‚xN€ð=d¿V¥GÜÙÜŽµ;ßOg”ëmXz(Ò•{[­í³¹7 ‘vk÷ë2Ý(Í•(ö"ó¬›1€¾¶ºÌ±õÀÄ(´gÕkÚ6z¥ªÝ«0Hë1< Ƙˆ¿ƒÇ؃iÎ +ycumÒçÖ,ÆÀReÄHè-lKBµÉ›Fe/SÄ9bq$SWêå`j¥L0%C•quCˆã*½ÐˆÊ^˜`e/î«ãéÑ*Õ6mòòÎÎO—öi)µªÌ3«‘¶¬þ5åÍ}µk¬XsŸ»-«‡&¯J>|UY<Ûe9½NC`=¼O•ÿ^.–vHOÓ;ã@‰$ýðh÷S^v¤ƒ@?WUù¨¶àY;m*û4‚çà@v1-ôÃ6/ )€[8øZ«õÎmïŽÒ©–øûz³¯$/sŠ„Hö§:RG8å¥ §ŠÑMBîcÊ%¥aŠ¦ ”BI=Š¬•Öãl„Ä}l-µ´}¤4駗ºßú¦'ÂyVó²žÎ_zb¦ÿBX„u* +ipsïö¬Ô*×N§&`¢9°Ã<•HPZ1Cg­üáA•™r ™Kã5»ô#Ý…Ølƒ)"<æ}ªÔþ€€}JÙ}a`©9xã—ljǺùIësz£äE2s¡ëpøJ·Ñ•z™Ì­”!s} C=yx\¥QÙõs ]D¢¾Ê‹A/øÞßÄ7:¬®ê60õÍCWdÐð%ä$ˆ)#k¥F õSx‘aÒǶl‹v¶ØÚPÉÔ:Ýïœ_éÐAvr¼t=âï#ÿCàZÓW¼Õ‘:â-/e¼õ8æ-‚(¾¡*Ô£*½¡P@×}Y+5­ï-‚Bõ¡-U3ôR¦nwww¶©A†\ÎÖ÷ +—W×p ÅD_!©€æ0²wÃÅ/ɧ/—‹‘$'Ð|#"¨¼ÑùÑ4$¸Ýå…Ƀ¡ÇA‚åO <#»j;â’h§¿6«ú[{d¯Ñ†æ3_U.Ô_éæ¢uUmÐ;èpÞ…ŠðPtŽeï/ž{‘}’i±œª(ª'g3¸T›™/HPÙbƇ ßóðE‚ç1#7î³úìür±<Æiѱ%=ÎPw[ ©½-ê(þù]ij?ÌnŸí³é|nÐf”ɦ+Û_ŒµXztæóþE ÿл4Mßåúßh¨Â1kãÂdÌ®rÈ´…EkŽ0%²SSH¤¢§ß²Ÿ©FÈþåo ésâ“Ú¢‘ÿ='u ÊÝ’|¿t늀‹Ø t5‘¶n~§q‚Vòaé÷ÅHç''ØÍ<¸“yúW|Žø¾ûóKÃÞ¥n¶:¶À•…ì?Œym,ƒ†ûCyR€U÷Þîï lc½_Ãê1Šà£^}H¦$Œƒo‹Dçý›×c)mñÔÖÚß•yXšù£êµi¿‡!ë9µò¬ve¦ßº •Û"v—=½åuS£7¤Šåba?I.—Ÿ_/ƒãüÕL Ì¿Ô¹B74×f_÷H§«õœŸ_êMpÛG’mò1dCîj­ì•¨\¹àÿ”–;ˆø´«‹‘@LDaËÖC IÈNÀ^e@¸§f‚ýííôÍèÕíÐÈv•¤·ÍR”!AXØ/ŒãxÌ0 ùqþ{™-’¯7?}¾~öçe£¶¥OKËg¸”o\úP•uµmòÝ楿‚@ ë?]Œ´‰¸Eøÿ…dÿÇ &•2ï7)ÖÙ'&”>tVCèîþ\†bûXendstream +endobj +2416 0 obj << +/Type /Page +/Contents 2417 0 R +/Resources 2415 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 2414 0 R >> endobj -1877 0 obj << -/D [1859 0 R /XYZ 56.6929 603.184 null] +2418 0 obj << +/D [2416 0 R /XYZ 85.0394 794.5015 null] >> endobj -1878 0 obj << -/D [1859 0 R /XYZ 56.6929 579.1143 null] +2419 0 obj << +/D [2416 0 R /XYZ 85.0394 463.2352 null] >> endobj -1879 0 obj << -/D [1859 0 R /XYZ 56.6929 573.2961 null] +2420 0 obj << +/D [2416 0 R /XYZ 85.0394 318.8302 null] >> endobj -1880 0 obj << -/D [1859 0 R /XYZ 56.6929 558.5914 null] +2421 0 obj << +/D [2416 0 R /XYZ 85.0394 224.0131 null] >> endobj -1881 0 obj << -/D [1859 0 R /XYZ 56.6929 555.3634 null] +2422 0 obj << +/D [2416 0 R /XYZ 85.0394 159.9229 null] >> endobj -1882 0 obj << -/D [1859 0 R /XYZ 56.6929 540.5988 null] +2423 0 obj << +/D [2416 0 R /XYZ 85.0394 83.8775 null] >> endobj -1883 0 obj << -/D [1859 0 R /XYZ 56.6929 537.4306 null] +2415 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F55 1311 0 R /F22 953 0 R /F41 1208 0 R /F48 1228 0 R /F39 1151 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1884 0 obj << -/D [1859 0 R /XYZ 56.6929 510.7109 null] +2426 0 obj << +/Length 2546 +/Filter /FlateDecode +>> +stream +xÚµßs›ÌñÝ…fúPy&û \Þ[Iü%±]K™6Mò€²#P²ëþõÝ»½C€”Nç=°ÜííîíïEtDàGG2ðÅÔ(T—„ÊÑbuFF°÷ñŒZÏ!ym¬÷ó³·x8R¾ +X0š/[´"ŸDÍ“ã÷¾ðÏ_^ÏfÓ ïóôû‡»›¯_&ï§_Î=*£(Ono§×—Wÿ8÷˜$p2þ:¹þ6ù‚k·çŠ'§³ó_ó?ΦóF¸ö(áZ²ýøEF Üã3âsÉÑ ¼Ÿ*ÅF«3!¹/çn%?›ý­!ØÚ5GB‰ÏxÀ4Âèˆ +Ÿ Øl«D*ŸE!s*‹¸aRTUºðžÒ×å¦\åñ}šëûK_­W8p¯R½ÔYK߀Ŕ/‰šn;§ÑØ4úûÉXˆšaÀEà!-ÒM\geïuYæ–#܇úJJfYòÀ”Š ËÙkQ®«¬ê…S?Œ> +4 AÚ%R¸“ æöCJƒ‘×&a,è€Ë5X}E4J@Ýž½pÝ‘ <ôE$ðÕ‡#ô8=¢@J‹õÃã¿æ/ +>QÀ-vœ?”›¬~\ ÐL%ÂÀb6D'D»"$q¾-—Ë*­ÈôÁEŸìb€,¸ZèGâÕk, gy\U”Áå¢(ê¾üsäž$›Y‘ž4XCqy’â2†î-|F¬Oïc] Pî^ëSNWRçRѵÍï©aûù¤û%Ù&]ÔåæuÈý„0Iû·*Nj©€œT¿®‡4/À û4oÿYŸ$»Þ”u¹(óßõn0LBHT„Îô·eÞsÂú¤ÌTË [è*×£÷|’^ž>¦µáh~µP±+<2à1ø4R•eÎ_NgwW·ó«›ëæT·\:XHféý­Dgô‡´®Î!_Q]¹,ô‰¡ú1Eà!{N 2›Îͪ«Šøãc±y]×%±ÁH^ði‰ÅE‚Àý6Ë“{~Âò´BfËrƒQë¤îm»ðþ$’ÌÒÅÖ1²…–é|‹+|&©fQ¤ ¾f¶@ß}°” „J{¢Hz{‚ph¾lCA#hB¬óÇ!ç‚ŠL¹ˆZ>`øŒÆE©Ÿª¥P³l¢–M|ŸcL»"€¢Ù«#îK–ç¸lT ÏmeÒìÝ¿âJ’.ãm^[BÛrk…;õ`ÎâBù!¡®‚{|ÀÞ0…¬)råÚŽ9½[xÖ¾ôyœÈ®B³æ~‚& óPÚdb@T¬†Ú&·hæÞº·8xo–3Ôi ‰Ä "iÊÂÕ wG!4ôè-%¤‚¦5Ð7ks’¶ŽÀ>wÕ¯8Ňɓòn›ÓÊã¶@Õqm=¬åðjÍlR¦õºÇtñä*¦b½Z®Ö0rÞgyV¿º£º–kÈhÑ×õ°ëœ!Äe¢åè;>PNXAú`½5žDºŽèÌãC—ŸØôǵ¶Ÿ­ÖyºJ‹º†bhË­æ3›´È 8¸ž7›@1±•£söZºªëkQè >YoëŠ_¶ˆóÜêª2½Zžòž\wAxüà*9,$à*0S­:m¬Ã…§ÁÚùe›%“R4:ÎÒ! °l;x`Èi—å7ÌgÌx5ôBè8Þ"^Ç÷9ä¥W;.ÊÐÄðt…Ü’@Ü]ŸÆL@)5 —†˜õyìMj² tk6«¡,`²hGm~p ¸[?ÕX«¦ÿ^çÙ"«[öF ùFã̾ë àEwPoZ1´süÁÐt²ÌÀ¦á4ø°÷°È猜òžÖïqXÆ{¦C …NJò½a¿Ó¶HÙ’GÇEk°dëäQ¢ @Úë7kò˜‡*«} `ÿ©!Ý/t¶Üp¡áýáB¯ê„³N‹Ùì .à uÞóuõ'ã¿›Zj¨A¾Ìrm.ý†©RC·Ÿ/f¡˜'!„üˆËžKUÛõºÜX÷ÉêŽ])›ï„bý´¨(ÕÐA' ‘ô•`'œ uØ ,ãù€À\ÂdØÿ@×–KÁ`I ’ŽÊåäê:ä—(ì ÖqšqÚÀ˜0³hèìáœÀ:Î6™æ¡ÁCÍJ÷½œ@(‚]°Æu¼u[Ò÷–×ÚÖ41%ŸbHëg\ sÀ€G¢ˆw3XlóBãŒ&a¸X»ù—‰Ö±º‰#vÙ(/‹Þë¦Öw½͘Ëw3Á}ˆSnÖÂ:âf˸Yq2×´?pu² 5‚Dê¸p Ö€tÝQ‰ú\Ö¯ãl,ˆl® |Š¥A…ŸˆpqÙÁRã']ùv•+vŽ‚-7Gá±á9Š†’ ~æëŽQÄŠóîdSÈL(£môë?o®§¸¢3¶hð»–3„Ô¬X·ålê°bn’WöË‹^Ò„>O¿¿4xèŒé¾žÖ'=(4à +žÓëùÕü;îîdPXõÛtãª*™uox·=©¢ˆÉÆ¥¹éN„ïvïÛlz§/ËÚ7G®³\ƒ× áP‡ …zÓ㇎âÍüS›ÓN->.â°hÀf<ÔŒ›ñ^ìxû×ÖÌ8²aè³0 Ç#¶…t8`’‰×‹½Îv Gù9œ}~m?™O#uø]tg]fWe’¾Ãßµ¶ˆm.óÄ«ê×ÜÖv×;j—$hÑr[»#ŽjZÇ0|Ķڿ·Ëͼÿ•´È]€þÞgTý­Ògj÷?^ÓN¦¦¿b‘o“_lù2ŸóþZáÚýÄþG¨WÓ8ãáÞ9w+\®`¶2‡|·_lw$Ô®ìÙ’ ÚŠãÜ}€¤óŠFIŒöü¬ÿ:僟¯Hóîÿþ›x÷§¸}ElعX=„Ø +¥µNÙû‡ò¾ìÿ‚Ê¿Áendstream +endobj +2425 0 obj << +/Type /Page +/Contents 2426 0 R +/Resources 2424 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 2414 0 R >> endobj -1885 0 obj << -/D [1859 0 R /XYZ 56.6929 507.5427 null] +2427 0 obj << +/D [2425 0 R /XYZ 56.6929 794.5015 null] >> endobj -642 0 obj << -/D [1859 0 R /XYZ 56.6929 477.5928 null] +850 0 obj << +/D [2425 0 R /XYZ 56.6929 769.5949 null] >> endobj -1886 0 obj << -/D [1859 0 R /XYZ 56.6929 453.2532 null] +2428 0 obj << +/D [2425 0 R /XYZ 56.6929 744.4739 null] >> endobj -646 0 obj << -/D [1859 0 R /XYZ 56.6929 369.7201 null] +2429 0 obj << +/D [2425 0 R /XYZ 56.6929 712.5891 null] >> endobj -1887 0 obj << -/D [1859 0 R /XYZ 56.6929 345.3805 null] +2430 0 obj << +/D [2425 0 R /XYZ 56.6929 647.0402 null] >> endobj -1888 0 obj << -/D [1859 0 R /XYZ 56.6929 310.6805 null] +2431 0 obj << +/D [2425 0 R /XYZ 56.6929 551.5126 null] >> endobj -1889 0 obj << -/D [1859 0 R /XYZ 56.6929 310.6805 null] +2432 0 obj << +/D [2425 0 R /XYZ 56.6929 446.5077 null] >> endobj -1890 0 obj << -/D [1859 0 R /XYZ 56.6929 310.6805 null] +2424 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R /F53 1303 0 R /F55 1311 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1891 0 obj << -/D [1859 0 R /XYZ 56.6929 310.6805 null] +2435 0 obj << +/Length 2973 +/Filter /FlateDecode +>> +stream +xÚ¥ZKsÛ8¾ûWèfºÖb€à£öäÄvâqüØس»S“9Pe±B‘‘²ãùõÛ(€¢è­Ýähî¯_ Ù$€ÿl’H?i8‰ÓЗ““ùú(˜<ÁÜç#¦i¦†hjS}|<úp)âIê§&Kk¯Ä’„M¿{g÷÷·çWÿ>™rxý“© ïæìö׳¯4v’rïìóÅÃÉ”É$‰€(D²(ðÎo.>M¯/~»üvwóõìãÅד?9ºx옳/ÀœýyôûÁd÷øå(ðEšÈÉ+ü|–¦|²> +¥ðe(„)ŽþÑmhͪ¥C‘"ñeÂã‰pnI„УI,S?\(‰¬³7¸¸H¼YNm“·Ø‰½v•oNXâéñ¬¡ö5/Kê}dð¼•Å÷L#?’`½£G¢#Ý`Å4±{äç¼Ê7à´¨A{fŒyÚ´fÛ–:‹šZ2Qè¨XÕèPèÁZ‚ÝE‹ÖÎи±NÛ›±±P3½ïikzvPS2}11®)›ê°¦:*¥©Õž¦06…ïiˆŽ´5•¦~ÈeïÈûMQµ£'p·›ÖÀõ:Û¼¹A—o'ã¦'82–§í:ï6nkvЦ>çr[‹ +bì| + Ynêu™Íòr V§¨ȈhÍa EÒ‡ì)}GCÕˆ† •ÒÐõP†ÔO¦æÅ&Ÿ·5­ïƒ%‡Ô0ŠÆ™ë¨¸sÌN‚ãÄå\pÓÓ°C.O±¤Í@ƒUÌW=òÆŸ¡.MÎãø¿V›ëÌØЦhÛ¼:¬ br½£ ‹jD†JéâÇAk;rg-{GZ‹}¤ë×TôÁŽ}´Ð€ne²Wȉ´ÐMÐXvX‚„Y¿“LØT#4TJ‚ÏChf˜1{ÞÔm=¯Ë=4‡!àN†ãÌuTܹ)xêÇ"Š]öÎÂäzr=JÇ5Kjê%+·9u—#J“‹.ä`a˜$:!€ñþ6\Ŝɨ©¶ëY®w›åíkžW4h2ôvØáRZ›«BÀ]Ò vSˆE¾Ì¶%fH@ªKROÐOL$¨f5µÌÝzpþ¹nŠY8¡.ÜÐ Ý©ðÂ!ÛýÒ\g½8 µU‰L¨ ƾ]~¢.…Ô»T†¦mܪêóf;ŸCQTo£6 c?¥G­Muµ•Bm;˜CcbIûöœ¥ÀP²„ã|uTŒõSà@`ÎìJˆ¯Ê– +4¢Bèn&°º_»2¡ “Þ¥zœðÈgÉý×Û¦¥gúèºê}öëã—Ow·—ø|rJC·w{ƒLj +€eÇ${ç`ûöάõ‘<";ÃN‡zü¡Ò0híÃüÝö¤ö‰K¨öiFElÍ–Ù¬(‹öÍͶ0_µJøúä¬ÍyÁtfcêÐ0wÑo··çòj¾y{6¹*l{ñ"e¾"G¼Muñ•BüË°ŸPåhÍ—ùK¾ï¤<†Bm”³Žj€5·úg>—‘ËÚPʑ϶OO]1¤8;,3 ¾#3‹jDf†JÉl/K¶è# ÑÀ‘NvøI÷Ž<+ËúÝp ô$ö9%U8Ø%U8ŠøÂÁYNí“Î-4 R«h¢Xê+MÙíwuN3¯ô>‚CÐÊb‘ëqUÞà0=Êà•ÒÁ¨ÍBD@e¡a¦‚½êש۸N™Ñ7Sœ¶Ô¥˜/LîÃLJÉà¢L[ùKýŸP r U 4Õ×Ó…;öšl©#»äÚ©Â@±¤ö­ÞÒŒ•®Â­ýKÓ0YuÜyÿ]’œÂ¶é¬â#vdÀtQßnNœ­ª}æ+SŸ®3(¨ò +†öjÌTŠ©ô¶ªòó—º|ɨ7S8uYN¦<ôÓk„0ð“ÃW7W·Ÿi‹»ûÇ«»Û‡p·ä±Ê„ {®£U,½¹JQãB ä?wŸ šRº‡)â:€¬ÕsLþÿnnÎÏiFÉÃýòåææáÁ§Iõ*‡»}ܬGf9¸fèÅX WQsü·cìDúL˜#XF¯±Ž=0ƒºÙèkµt+I/æØêÛn`~Iì°xIÙâºww#Žå¶Xç*{‹¼KÃʼ®À< +"êI=áW˜j5~n1xýenFñÎ"o†öÁbça@‹ÅšMh¶j[ô=?•®aò,ÚS2â¡w¼®©+¼ã×®·èz+ÓSwÂÕë aØ¥côy±{ ¦E-¾½lIæ,&$Áè[žm4Sè9òYÕ€I’žOD’:<œ®êí†~,²·F‰´üTÕ2_˜(óì™zê0´*M·®«v¥7uOWCÝyÁ㬭 BøaŽ·8AzÓ×ITO뢩4§vIˆ§ma³«^ðqë_'®Ö–­û^c)ø´ÿDc+Ãz +³”a½4PŒV#…(KŸ§é;)½Mu8XwT*Xß¿[ˆâG©õR]¥ŸæDÜ’÷øë¨tÒœ(ö£fuž“ÙBi´ d†ÔCcº{QÁ¢‹F(øaeV×ÔÎô&ú­Sišîù Ÿ³yê-[=Ô´rºš‰SŒäf>T¥ë2öc.¤kE¯…ú.síè¹ù„·0¿¨Õ~Ž+ô…¼XX{У­µÙ¶1©»@«_lqkõN žü¿µ´zª®2|,{|L?SÛ=íBE6Jßw¬k¦ +wó¹æt/S5å‰eßÁ'Võ+6‡ Ap?Nâw2}›jÄ •2„³wßÇì ô…dÉ8{Õ®¤¾‚¹ ê7©ã vÈ°‡Z24vàPQÒŠ̬¯©iýZe„„% wÚDe¯ú,„{Âv&Tê=Éà +IÌ\ØÁ]‚;¶´î8D Â`ZQÕÔ¦‘\aZJÂ4N)Lã aZÈn#Êï#Lck0}…ig'B±áDm*Ìï>âÿgLÇ1TPùŒºÞ|¹ÖD +Ð߆Œÿ7ˆ~lí8Œg¢ÙçÍEsâÇ1D›9 æD»ìh0'äÔ±5`¶©rI _òÈo#(gøÕ’ºnƒƒ6ˆNŒ7‚FCÆ÷¶gÑI°C4ž<.¢é æ“ çYc'»*+ð®ZS“(ÿm½â[1ÀJ:O©c€ýgíú­·“ÝÇ:4“ƒ#¤83 Û «zþï¿ÏÙý5RƒOH> endobj -1858 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F39 899 0 R /F14 740 0 R >> +2436 0 obj << +/D [2434 0 R /XYZ 85.0394 794.5015 null] +>> endobj +2437 0 obj << +/D [2434 0 R /XYZ 85.0394 287.1527 null] +>> endobj +2433 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F41 1208 0 R /F21 930 0 R /F55 1311 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1894 0 obj << -/Length 1945 +2440 0 obj << +/Length 2099 /Filter /FlateDecode >> stream -xÚµX[Ûº~ϯ0Ð>x#†wI穹µÙdS4[ô!Ù­MÛBdI±äÝEÿ{g8¤lyåcÅ+r8ü83œ-fþÄ,3Œ«\ÏÒ\3Ã…™-¶¯øl k{%6Š­L&V£2f2™Î’S·÷¯^ÿUŠ™äÌZif÷«á,›¦Œç³ûå×ù›¶uõ²üy“HÃçooî£]š¥Y*p‡Rf•±~ǧ¢Þñ·ÅÚuá™ÒV†=Ö0ËMæ÷¼eâ&œóù²\#?2¨”)kIŒ»b뎜å,·Ò%˜Ê@fäÂÍþÜoR¦4z÷…UÓ|ß·4Þ÷eUö‡£`‚åÆDÁ´`2¤Ì—CÝ´]éuxõá~°©åL(°¨– “«)» S}áR2Î@{Ç!ühq¢a¼’kÐÓ‚µ¾þ¥s»'·{Óä‘t2êBð”™Ü87ËåÎuáVFgâ™V"𠘋 LeXfM„\TÅ$ ÌY–¥ù9àê*બ\=\ùXÈ”e’§ç˜ßÿ˜ÛaÔN ' -½ÞdÙ,üv·Í®ÿÓ%[dçGü¸*ö‘¥b¹à꯿Š×ÚÿïçU_ïnD6oZ·V˜:Z+húså~–•#rß4­V„íÝŽÖ^¯‰“j¬û˜ö$Jß»IOç·=Qáx”«#nÜæ:ê2ògªkÀªˆX/a ±ŒvmU¹ß8"u÷ ÇEjчm^ÖÀCã~¿«Ý’–W¤Êö Œ´@iÆíÈl¸|„‡##>ÌÐJ·• Ì>5] þ©ZÞVÊ -È/Û².oļëwEßxá¼ïÜ„K€°ùPq.¸tCÊÆlß7Ø“’{¸×nÓ4(ºåG1ZZ†ÕmGKnQ ~¹YÑ·ìÃjôj4@®ù/°Šó=„ûÛ£‹VœIh•¢ID¬²;ó- nöß}ßî{ôÁçŸánv/ÛôÐ. zé»)ž\Ø‚]­öõc¢¨†óà6ë ƒ+Ì&Ƥ¿opÍr­bíc1;k–å¹s–¦)Eü›ªß4ûõfâ(m ãTêÚÕJÈ”W)9¯1Æ«ê€3oî%ÑŸË~C´E³Ý‚õ“ª¬­QH¬÷[W÷^‘p¹Ä]T]C\›¢ $š?ý"@n›e€ò÷Œ_kJ5ÞVC -åzìöC -¡ˆ)–”<ôÉ…B~ E¤®9â¢8;f*Y9Ÿ[ìü Ñ!öV4ìö ôî@“&½ãc“xÔS“’÷&ÜÞ¢bÝ0'"ºÝaZD~«çÏWÓÓÉË"ŸæL«ÃE&›i¯2™} @>aÃw]>¹Õ7jþϺ*¿;¢»bW•>P`‚éEÿ§)e7iÍüííÝ{âÈ궅àÝ‹ãIÍj2&à5&†>úb]2©‰Þ ÞÙ<“ÕO«\èqðo÷U_¶•;înÉa±ìº½ Q~â>ˆK¸Ü7̆; F°¥E¾/• -ÅP¡Ւ(þx øÂN¤‚(]ë%:á‚æ±ì©P0nR Yñ¥%ϼCä5Jx՞粪‚`QW`(Ê€^R¯> -FU—¨UÙ‘[¢–õ„/ -c˜"v¨¯]¿x /¨¦zŠ©,ƒ‡“jì^MÈ=n´B$ŽÌÿ/Š™AÃozrm@ £óÀ’O#°ã—_ØäƒcÒú:ƒÄl²«Ö2[PCçB‡A|ßöÀ7z WQ@x©k†ÿˆŽ=]LÈw›{Šh( Ï`žÙ±¥|ßd³ø)¼Áº.4h@õ -Ôζ–ú‘*ÁŽ––nU@€u´ŽÂMô©…2&ô5»XžG»<•Å”? -iô¦?ÿûãçOþóšÞn1˜)f3+NAÍï7QUÊñ§êgCí r õ(G§ÀM¡É\3-äY=òaoø‰ëà¤m!.cÖAs/ç˜S¤à¬“içÞ7˜P²nïèK]- Þ}¤/ýÞà[fÌ)Qˆéªhij;Œú«p}ÓXåž\E4z%d˜^§ÙüCIMÒ©s gLü¬o“e±ÄÇùèz“ÀtöJ ­à¹ç@^ÌUìn“Å¥ª(Õ¨*†rHq (-¯ÇòKü]À¯‡ÑdæP½ª—ëµÈ!i˜A²%‹á3œ{":R‡GŒÑúAŠ&í òéãö.&Xzhè¡ -§g=42¾ûùÁC#j*u[ø a;xs»icŸì½‡ÁKØù;üøãGøîÃñ:Ó 4ík½¿?{wÅäH#Ðdt¿ìÙR+EF÷‹¯ã÷H  XÀãË›»»ÙÅôãì_f7“)ÑJèñùçϳ›Ëëß'S*0(ƒ*Æã_Îo¾œrï>O4Ÿ˜ÝM¾ßÿ|6»ïÂê‡N0³1ýyöõ;-`?ŸaÄÀÃè>`D´¦£õ ÎXx“ŸÝý³3Øû¶]ƒ‚ …å €"Æò`IB@I2¸æ^”ÄðòJ®éµÝæ»+!zŠ%Š%`Új,ÒƼ+—ËÚ4CD£ˆP½³‹­S: Žö|&!„îEwgšz2eŒŒ›•q‚ ÇJx\îÍó*›¯Z˜'da}é=x…jBÔØ4™{.,Ÿ/Sù2^¥ÍÎéßA1ÏYž;©n:üXmÖD›B‚¶ÛÊŠy¾]˜…#\V¸gkÙ +?ÊÂz³âöñJþéœY©(ý«¿l[‹v³öYgEXŽèì9“h8üubõµŽ3«Ój©u¡±µ#ßB­AFøëáuZ‘øöÈÅ 5¹ c¥ÌC‚c—•,»(¥]{Zmê­…õ¥{¶©€E “›¦eÃ$°Ê™°” +žl’©ŠØõY©ð–ó²x#ŽS°1 â>§ ÞÀ-ÁãoXàkÏ¡uúâWë4,<0àbì47e5eõ2Ú{Ò®ÊgóÁJ>Fà„8aºx—£)åHãDB‡£ˆ+ÕîúôìöÜößûÙ¥³ÝÛ Wן\K¤ƒ)…ˆ"¬5ñÛÊ¿Õ@;Ê6ó)leY•ë<}0yIJ–-~ͼ\olRmÆ¥×ÛùÜÔõr›ç»½+áê¾ßTYѲKêqê—4ðîÑÉåÒ=¬ ,Ëjíbà{q3ŒO¨âcÿÐOišþ”Ù‘¨¡IAܘv¸S1t„.u“‹´Í¡§J¹m6ÛÆsã~ÕRÛÀ?Ó@ˆ…)šìÆtž6YYs~o ÃVŽqÆ.ËM½ßÒV©ñh +S¥mÝ9z…ÂHRybjèkµ½€ð@’ „%=[Ÿo˜È¡S öˆ¢¯; J‡N÷ò¨ ÿh-öÚdF2HÄ1ñðbY¤ks¨#¡4;TOë ‚ÖI ^sºjè4Tß)ð=†FœvõyT±]›*›ï5+÷¨Á=Ø_™æe•5«õqx9ø†ÒzÝÒ+àz¥“ؾâqíÀcÙžÇcMF6&Ur’ƒ»f`ªPá‡ú_–eÓöA{ HWžB«‚¦ ‘C. Sì¯ugÉ’0IÌ]fSןE2nžÛŽ'CËi&k³r +¶|j§òÖ¦½…ûäh‘„ÝJ×ÊÝšøF‡b­ZÀh£¤<Òª‘;»áÜFšr¾x[@œw°6+†¹ØlòÀrk¦wC‡ÄIìÉKŽE ›}²3Ða4„ ˜Êáøõ{ñø½SM Ý év{¿_™X”ÚöÉà (k¯ä2mG®¤ý”Ú‡´B÷¹*¬àX3/Ã9hß¹­5bÏ<+´—0MÕRÁ¾V”=ûI;[9©Š­ˆ…¿gÌ›üÅ™²5b¿u„ìùÛõÍÔÁÅ¡¬•\.>}¹œuGxcÖ¦W^í0tZÐÀ’„Yè•ŒƒUJ¸ÂËI^Þë—Ózcæn6pzmgȵ½^):¾jw ïˇ§¬ÜúåPì[Xþâ¾ò…\—…­Y–Ø™¹½Äys!„Eiüz{j“^}ÀVé“éyÿ@Hýì³1Õ:«k8PlXÅ{SêÝÌ'àüÓݯ§'Ò];ƒ,”Í—/Qÿ¥½¨Yöô¾ní2Ý/ ‰Ü£CM¼¿¾ñ3²öá,ÖY‘AƒJ›ÐoÍÒ¸sÂ/i±Mc •$ +Ñ$ M?4EB?º½ºp9fÿ Ùœ„dS•M9/ÿ$vÒíÿ8h7b‚`ûuZE|Q蟇õ\ ÊõÂ<Áâ÷–Nã®w}ÒŒ1Pø0¿íæ¤Í#]ÛÆöžNÚËÍ“ÉuP5´÷ÃK…Ÿ!b¿+€}û÷ È‘Œ»1à¿þ³Óî +@’)Eã¿™S ÷= ²Ên†pzøg˜J V‡±ÿÑÉkendstream +endobj +2439 0 obj << /Type /Page -/Contents 1894 0 R -/Resources 1892 0 R +/Contents 2440 0 R +/Resources 2438 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1747 0 R +/Parent 2414 0 R >> endobj -1895 0 obj << -/D [1893 0 R /XYZ 85.0394 794.5015 null] +2441 0 obj << +/D [2439 0 R /XYZ 56.6929 794.5015 null] >> endobj -650 0 obj << -/D [1893 0 R /XYZ 85.0394 769.5949 null] +2442 0 obj << +/D [2439 0 R /XYZ 56.6929 632.7441 null] >> endobj -1896 0 obj << -/D [1893 0 R /XYZ 85.0394 573.0107 null] +2443 0 obj << +/D [2439 0 R /XYZ 56.6929 393.4246 null] >> endobj -654 0 obj << -/D [1893 0 R /XYZ 85.0394 573.0107 null] +2444 0 obj << +/D [2439 0 R /XYZ 56.6929 322.7553 null] >> endobj -1897 0 obj << -/D [1893 0 R /XYZ 85.0394 538.4209 null] +854 0 obj << +/D [2439 0 R /XYZ 56.6929 278.4974 null] >> endobj -1898 0 obj << -/D [1893 0 R /XYZ 85.0394 504.6118 null] +1446 0 obj << +/D [2439 0 R /XYZ 56.6929 239.5941 null] >> endobj -1899 0 obj << -/D [1893 0 R /XYZ 85.0394 432.7569 null] +2445 0 obj << +/D [2439 0 R /XYZ 56.6929 205.2551 null] >> endobj -1900 0 obj << -/D [1893 0 R /XYZ 85.0394 303.3232 null] +2446 0 obj << +/D [2439 0 R /XYZ 56.6929 131.664 null] >> endobj -1892 0 obj << -/Font << /F21 714 0 R /F22 737 0 R /F41 939 0 R /F53 1029 0 R >> +2438 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F55 1311 0 R /F22 953 0 R /F41 1208 0 R /F14 956 0 R /F39 1151 0 R /F53 1303 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1903 0 obj << -/Length 3825 +2449 0 obj << +/Length 3022 /Filter /FlateDecode >> stream -xÚÍZÝoã6Ï_ õk•)‘ê}à²ÝMÑM÷6)®EÛÙVbamÉkÉ›¦ýÍp†´$KÉ÷rÑCŠçã7CÉsòßžéDE‰VÊS6g×gÿvzÝ«£"ŠUH –çRFY’Ä=$Y”ªX9\_¾{ÿÃkÚ×O×°)ܼwd'Ρ;2Æ¦î• Ý>ìÊe¾¡eõ¹^æmYWô»¾åydgI$,,Ü<«ònd1i"­tÂc6uý±¡)7åÇâ[zAwgK©#€ìæÒÂþcfŸ§prÿjŠýçbO?ª|[P Ø/F–Ÿ'QfLêç¢߯á}ig´~ïÄed¤LÏÓ4…S'DƒæÝQQÑ0 -—fæËfq”$V?¾¬tºloÇ™‰•™þ²% -Ý‚”Ö ®Ød,8$Õ{z^¾§ž|µ"á4üœýÔ»þ(ÚÖDût(öϤ”305•e³›µ_}™W4vÁï»ßníÏzbõ’‡¬ê¶-Vs”&œª¨!ÞPCŠe¹u -lÕ¬ª[¯¾ð‹ö¨x=…ë¥L鯧x=5[Ö›ºš¯ŠM¹-aáþ¬°3-²ÙÖ&Ù@£9ìv›Æ;ULTç`”1‘ÍŒdS8jÂà•R«3–;öxßZ¦QbþÉëݶEղݲqåôX×M‹§õ|ÔzAÌž¶^åYfI՛ϯӮs^™•Zp¸rv[Ó`"9(«»é—XF;­‘ ·<¤e .OÄÀéÓ¢T åÓ¢Œû¢Ô–D Ï{«þ\®ŠÕ˜3ÙDÇOŠQ¦)YÖUsش͈ó† ú~øMÑ.¿Ù;GðÒíÈÌþÀ_úÊ«1/ Þ)§† $’÷oʆ4œÆÒÁE$¦X§‘Œ¥ìËéfÍÇFcw›úyK²Úús.&Žy ¬W»ºZ5}=^•Ín“?«hÊS'%?î¨;ƒ¦ý´„tV´"JÄîÇVôcNVìšM@õtÚ[±l&…Vߺ¼\cÙ£.ÉðVC‡ùë`¥†!"<ú°›sb¢Õüq9wF="h? -÷íãö¨¤[ô(êá¢ã²î.ZV+À:­3LpR‚–ãƵœÐáIáÌ5KN‚þt(©±"êoql°PòêÿžSÇ?ßýÌëË7ÜûŽÆÜ[F'…wÐ&N#+…öNÅÅ6˜sÁÈ+fûs¾)WÝÍ8ÃVð: ƒ´oظԗ8` ¨[fêIµ=ç;«|Èu®6²ÚÊ¿€0ïË cØ]±‡(´íDÔöÃŽUÍŽ(g{1fGQઽç1 Td =e@Q|sùãÕõcˆ; îóÔ÷Ë p?LEû˜/ƶŠ AæãH½ó=ÇÚ:qï%€Ôó†Ðûä_:oz‡f;~¥ŠlšxVqBœì”_ ±Qø€Š< nMKË,xåœ:¼Êžrkf~ÇuUpˆ²ä b¢pSJ%´)¥R‡…¾nˆXí}½ÿHeÕ‚¦äË‚;Q-­Eäþ°ÙíL\ç·ßâ—qšÙEÅÜ¡ Å9võ¾%ú6 Æ‚ùiv€Wƒü ˆëx Ž|·+À?UN×QuºÛ¿"IËž¡`ËÈßGŽÂDF[?À±u: äH Ôþó©YœTLéH˜~ŽEÁ@/ns@;˜ŽgA³€¾ÜäîH¡ù›HÄåµÉ*a¨;8(è”ÔUòð ľ\­ø†ß(8|£5+e2ö»š/Çí*Õq߮ƳÒQf…Ç“´ƒÔ ‰šI¼cö\“?6½r{`,0 ¸Áåš]s¢ÀýKÓ?ùœÝåÛëûz[4e½ó]ü†øòíàÍ—ë¼n@Ä£ïFAý:Yø¤çÊŒöÑ`>†SÁ_ÆIìÞsAj†ñ±hF\ªTdO¸~Ú0k±‡ NÓ–<ý"oA®´R½âN25ÉsglŽãC8DLr#2Žã[ ÊMÛA>9WX:g…„ˆ)m…P%mªúùçÕz†Î`SŒ©] jçµó¶ÜžÝ-$˜±0wkµ7Ä0½S6È&Ú¼„<­jˆÓ£:l]ú¶§Ÿ.2ÀöŠDÈ(PY­tÎ×õì(ý× ²ªà_ç(q$B¬'sO(¯ï6é°£gͺ>lVD_°[|gE:0Rλ¼*ÿt¸+ŽibxÒÄÐh8Çjv>—û¸uÏ AsÁãw_€Y?§³5˜à˜Fá$õˆ–ÆQ˜z2ý“‰ñáÐP&ÜåyYo·¼ÍQŠ~[•8SB‘‰ô íQ¦&x¼í¸ÇÓ:±'HBÀ™å‹Ïï·Å¶Þsrwhò;NVÅâpwÛðÌ©(•j@*áTK 8²š7-l2÷ -vr€Ä~T½=QÑgâÓÙô¹˜)>@Š€P픿W2J”õ[›ïÆwŸešoVÖ°Ùb5 ˜(Ñ £_€,Žm'¸Í8$sû='=kJÕNl®t™Ä aRÑb;„Â-@·WÔ*LTIGµ‘Z5-¸AúáŒÞ#§XuöN »^]]Sƒ¶‚-¿lCü¢ý1Ô °ˆÚÞ áÅÍ«ÖüïÊ^“7Õ†_VYXû¨¹( -Öop}èzîÇì­“»ZH5ˆ“GYa4­zÅ©Z»Üƒä‚ý$WØêÔôq6Y8ǹ¨ÂÄÉP…¥ò¥·åxT0dB,™Œª"•Þ:œ ´u…UlÁaQƒÊ¶Øb\§$ø´}^5¸,’ºòïèMŒ±*ø¨ôÿw‹)û8 H*³}= ©’ènü¯ 'e¤çuÞNaÓӜϟó郪8âëPÊ0b<‡DÔyªÆAo¾Žˆf¾li.çs-Éø’Ä•]Ääè~]DcdWðk%Oýâòê» ~ =¢bO™ãÉx”wÒ £Ž‹Çañ˜WT.}¹À€ÛÙ¡ÚP’iâ‰Ð"³$ÒꨴLWjOë¸n¸" •jîå’ɉH. -+µÌ;ÁPÞóýó˜ KÈU³là*^Þº0ƒHM¶q15Ž»hÖe¢Øõ@].E½¥Â=Òs"“(‘àÐ1P.~þîCD$ºA¢_¨¬–´–~\b Ži×ÝgÏ¥‚0e}îõf,Öàž©•Ä"yBÃA«Ž%•’q{S´ÙTé 0nNÊ?n÷ÿ¸ƒ VI’ŽñÀ„7ë  ÅD‹Š»b:…rlrçä¦õ“-×yuW4>£òyå%AA„½‰IúFD«º( -\ƒj3DÖÒß ‡(ŸðÍ\w Nó5GÉë/¦«Ò÷y3q©‰º?Š1‰òe®()} -bÎDü…îR -ïóæŸÆíWéd !ËôîVû룻UÇ»•)w ˜‘GŽ Ü©»ƃ(˜ùð 5óö°¡Ÿ«šŸ€YÀFe³>ò7Æ‚…Œ:ã)Rà3°Ð¹Ðykw;äšÝrnã³€Ä)—î#œÞa8%ÿ…z*5WÌ‘¼Íw;ò2²w%ë4H µã™IÇ—sÓˆ#šr Î5”Õ$;3©&\:XI÷&qÜ¥#I“§«C)Õ¸[÷7âXå-y7ÎWûQQIMd‘–jPÕìWC _WÓ¯Çwà,ümõsºZwhÈ9½qzÁmÂÅ¸é‚ 7Ößv¥ecñ ±0¶ÉŦ¡6âIØ HJóEóŽSšcO5È+ªúžËa€Ñ”£Ñu!ؼû‰ 8[¦‚#ÞîZ.¤á<€çò®êfÆ…›uJ¿Öpw¦@^<Œ}Éã¬F<é¬ w;´ëN¥d•:~…ÁJ{o¹ŠÂãQÚ7×—oPÔÏy“AÐبR©ÁÍ3¾†ƒÒÙGW«Õb NÒ©ÜLpË’›}W$+‚®EÒ2›ýâÎå@+Pb‹v¼ij"u¶á/J:ÂtÙ6Åæ–ˆ$ªôh¬\æ%*×zÃæøŠ ƒ|DǧWc5ü*5T‰&®]º$¸ã¿M]l%>r¬·ùrºÈA¦$| -"BV˜ñI§ë†¾xÀfHÏqàÛw/çï^%cÁ8`–Y(bOud)ú O¨&y¢álD ×Tˆc÷Âà)†Ì‰HÉ´ õ0QÉÓÁù âþ“I‘r5Æ|Äï4K‹0ANEÞóTS_Q-ëÁ'ï Ñþ´ôŸõnx’»¢ÂK2œvE”'0« -‚ÕrœÀ4d‹VM}­°¢Æ¾ÌáK‰ÿù{éã×àÚDÊÚ‰o|b‰amfÊ¡Ÿ~ËÄ_VŸòþ_dsÈkendstream -endobj -1902 0 obj << +xÚ¥Évã6òî¯Ð-ô{ƒ[æäØN·ÓwOKyo²( +¶ù"KŠIµã|ýÔŠ”hõaì +@U(Ô +JOüëIžÄÊn’.N”N&ÕÓ™š<ÀÜ»3-8Ó€4íc}??ûö›MŠ¸HM:™ß÷öÊc•çz2_þ]~útsw}ûßó©ITô}|>M”Š~º¼ûùòß<öé¼0Ñå»›ÙùTyRR‚h©Š®ïf³›«é‡›_ÞÝÜÿ1ÿñìfÞ±Õg]+‹<ýuöÛj²„üx¦b »M^ £b]fòtæ'ÎÚ0²:›ý§Û°7KKÇD‘Ø»}Çžn~^¨è¹\7eÕÖ!0«Öe{®#9xƒÚ ·ýóB·–•|&Lî‘Six™ƒzÒéT8kþ(¨ðü+ÆƶG»µàaLaUÈÐ_ø#2óGÏÊáúº¤‹Ødy!Ú±.Ÿüˆ™4N´Ñ‚´¹J©ŽZØ;5ò˜š¨ÙúªF6=ÈpÉct¨þªjóôDº€U½ö ÖÙè”®Š($š lÀdtô´kZʶz<ØŸÎB0LJå’8+ôP©äöÏf-)/5í +`‡ÆgEÁË},|½~`0hã2gèp΀ÃÈø:>’uÏŽœ•ŠU.1)l¬ŒÊÆý¬ MûXÁ·ûÙ éNKf.IúZ bP‚à#ÊÕÃæìåé9íÀG™ì+ÜuX#ìõµJ'.NøÏ3¿òU‹ÂÍ­ˆ=wQõüºm7Ïåî„ç:.AoœV¢7€ÛéMn;½È!{ÙèK¹Úɶ¬&aÈ-Kõ˜4Ž¤pR¬‡ô‘5M¥±MÕ[ /Ò@uM€%KÂϳ˟®Ñ]XS`göþ’ü«…È6»¼`ä;8”NÒЃ'M’Ê4÷ÁrǼ»û"º¹ºz÷q6?¯‰˜‰ q +=å·äµÀ‡Du‡\³åð¦ÈÏkÜáIÀi7bó€ÃJ’ã ø&š¡ +‹.²!ÍÈøt ã–þFø©ÊÆGÜøuS·õ?ê~oÑkfy´Þ`[ôÔŠ†ÉÀ0¹NàŒ¤µD¦óe¾f4¹Æ}©W+F±c ánÉs‹WYúûr·je£Ýz囆gÚÑx`Áx3¥sQé©Ñzíâ dÂÁV"ÖÁ)øþà¾]ììÞXuw>Œ!zŠÃE‹P_ïC,Çs#´ð]˜_rä‡kh}¹Ät"ç;fãÀ~œ%úä)“8-””ºRJ$! ¤%ÝRJЈ”æjÅÙ‡Hºd +1e+¡¾§†øš)Öp[=úêÏtá +ê¶lëE½ªÛ×°´•FRŒ)QλMëùæôwÁ̉áý`¿Jš¤†Š®½äÃzÙnž_µ¯Ÿ¶+ÿä×í\°Åq.€tf—½ma6?8Þ¨K€—rÁ† çEß%‚ ¾e·÷L¢s‹ß–Šµ&2 wzýþ‚zþÊ&!§µ¶s8šÑÚGâ}³{xì­§L Ê]»ì¥®ÊÕê•q߆՞‘¦ó±ƒ£c¦£°Æo¥N¹¸€Zët*ÑÇz;•è°Èlc©„Ž!“°b6ëüQ"ÕQ–eùiÞ:¬æ†þÈ‚1zÈݬ³°†uƒÅ Àz÷´ðÏ sÓª[A#g¤1‘7ìƬÕdê QŸ‡ªÇM]ùáN”!"@'hé· ¤²ÿ¦Û_f ø çÚ¤©èvPÅ% pí6ÔnI"l]´`ž ô틧¸¤o°•`”Ë£ËÞÃP“ªß¢hÙ'QÛ#§MÎL ¹‘äé"E×qpÝb÷:ÉL ƒx>´ tøT€'¾CGZ·ß˜!™4ä¨qÀÿ UƒOkpKÜ£ÊSG,±9óñ4æ}˜ÃžsÞsP¼­ÅY3lj’s¿Q¦MÉ¥Ò€õȘ,Zn(%1˜E´xŠ‘›¤…¬ïE¨ï¹Ý5\±Xʾœ$ÈX/¯†Ø:À:âN‚?´t#¢ +&&!Å‚¢ý#©0d Pr[Ø‘Bž41Q¿Î>|*p˜d_ k0bí\+ÌOmü7&‡žîk7F¤Àyœ68 ®C¡4 …e(9l?–VdqaMȯðX1š +„©Í‹ÿn ,ႇ.ÌjÖ[;Ì ¬D2hýßÛU]Õ-Æì/ÖK`Õ9ŸIllUÑå|åÛr0F%/åÃR ¬Q²kUOul(¡‹T "”f±.²l¨4弑®B’–&¡ é0[u.Ôh{e×úFì4¹†Z’·“±³õvìì°ˆÕõWc'>`´¯Ûãàé ÿNwš¹k„»¡x á·i6do[6¾éè<½é#ò"†lÜžv=¤·=D@"®«ñïL€ʧjyÇQvk’X'y~’­阯,ÖNéc·ë%ê‰ÆÙ .|lrô…Ó=> endobj -1904 0 obj << -/D [1902 0 R /XYZ 56.6929 794.5015 null] +2450 0 obj << +/D [2448 0 R /XYZ 85.0394 794.5015 null] >> endobj -1905 0 obj << -/D [1902 0 R /XYZ 56.6929 752.1413 null] +2451 0 obj << +/D [2448 0 R /XYZ 85.0394 751.3869 null] >> endobj -1906 0 obj << -/D [1902 0 R /XYZ 56.6929 501.191 null] +2452 0 obj << +/D [2448 0 R /XYZ 85.0394 624.8718 null] >> endobj -1901 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R /F48 953 0 R /F53 1029 0 R /F11 1397 0 R >> +2447 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R /F55 1311 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1909 0 obj << -/Length 3111 +2455 0 obj << +/Length 3191 /Filter /FlateDecode >> stream -xÚ­Zßoã6~Ï_‘·sÐZKŠúÅúÝl‹-ÚÝ´ñâzØæA±•Xˆ-¹–œœÿû›á )J–œÃÝa5E9ÃáÇo†d䥀ò2‹¡tt™ê(ˆ…Œ/—Û qùm?]H–™[¡¹/õ~qñîG•^ê@'ar¹xôÆÊ‘eòr±ú6»¾½ýøùæÓWó0³÷ÁÕ<böëõç¯×¿PÝí•g×?}¼ƒÏ$!IKÄìæÓOW÷‹Ÿ/>.œ1¾ÁR(´ä¯‹o÷ârvÿ|!¥³øò>D µ/·Q¬‚8RÊÖl.î.~sz­¦ë˜b•q¦#Ã1Ä:HT¨Œ>䇶¬««¹é¬Yׇ͊Êý¶ùsÁͯk[:4eõÄíë½ðîÇHzºdY&b°µÌ$Ó³G‚=RI©wöw{Ø´åüÐ{¶ïشŶ¡¼é 0…ç∅d¶Ì«þ^ʦ|ØðGY¡-—sðvi•@I:ŽCc†-LÕ¬>´»C‹åhö¸¿’Ù¬ÞRË®ùS€—á?É¢{ƒ‘Í·£Y›ÍßúX—M[ï$ú§ᦠ©LÌþaüŠ2ìW,.î^FVÚr™“‡°õµl×ìRßíJ‡A¤²}º*ŸÆü„Xæ{Pw6Wù¶ E" p¬ž`-^p9Âûäè 8›• Õüu(öe±¢ª(V µ·5U=Wõ«í[P“Y5¬É+î—ožê=ÌoË}Y‹vZ -ò46VèE•Ì>UÔúþÓç›ï­’²é¸ª«‚1'ðôˆv´Ò/åŠUˆY¾ãÊݾÌÛbÄëRˆ@gZ³GqF#^×ЙbœìÈ@:PqjeØÕ§C) Š$I¬X Vm ÙKøìÇ,Ô"â.¸Æ«`YW#£;¤@,83 -/ç¡>J3 ]a›eûúñ÷«8žý“ ùr»øôåóÝÈ<Áé!€PËs(MÊ”ÍèÖ¥ÀiJ@ þd³ê°}0x„ªú‘ê…G®2¬Â]^×å•œ-×<À#ùX,[ú&DBÕkÎÍ~ÆŠui;mêúù°³&£¸×6_\m€,3;¢ž‘\lÖ0÷ðäz[kU6»M~$@ÝÕ[ì¯2š˜2T×pUS´Ü¶§6Öa«`TþDå‡Ò`C¥4#e-S« m]À öW@8¸{"1kœþUÑûmYñ§õtjÀ}ì`ggfcB·¹B}óJÜ!fOÆP(À®ªÚbõ=o6"1«aŒ=#ÚWŸLP(·E}h=É­™|6íöÇSY4³)”%±±écNK›v¨É\,ÂjÃPÈFÞ6ü-,Ó'lû×Ú(çå'ÌËb5Ñc·9ðàMùÄê0´Œì_ÀC%™%íïÆöm ÓÔ’'€Q¨µ…‘Ì| ÒFp‘Œ"ÙGʱRÉ0È¢$ê¯'¹É¨‰g Ʀˆ`+àTM‰ ,®±wÇFs"¢›Ô°Î_†ëýv <2 ÒLÛ¬à;šÇêcÛˆ;3$Yº`“^Ú'œ!ˆ JãQXðÞeŽüûI¦,CÇ1$ŠPMíYhîK™Ä6ÊF['efù­ªïÛån¨X*€r"ÞÐì¤NU—ÂÆÝ_q'(˜ý·.y¹PÝR $,÷TZ|¸¥6N«¡Ê¸–2k샙˜©§LlžÍ+«â1‡˜B2¢Ä}Œ_ÈZ(b Gj©ðõæ–¡ †ëáÒªMÑØ•«è÷úgNfîþäj,g²ÆŽ~¡¡éX½ä¡là€â2o˜Åsú1î0-uUQTéL©ÞŒ ©R†oÀÈ“:#+å`ô²Šb8t,Ö„X€ 0Le¨Òˆ«6ÿ•[fÛXùtep.pù§¿Ñ†!I¡Ðö„W2iF¡ b©â©Ì»à@þhñö/Ÿ_ó.plwpz(7e{¼’R"M))hs ÄŸa½,ñ›@†Ð F6Bå¾=ä·4j–‡²Å¶I¼EiHEçñæKMãÍI9oBô¨÷Å æb¤:ÌÎ+wR§Ú§ïòüHöÕBÍ6«€ý²*{ô„33mfALb*8gØç›ä\à†‡ÝŸ¯¨¢¬—˜qütŠ52cj\Elx¤jf8¤i) ’:†o˜ÉAºé&‚if±Çèx†B"8V…q¿±¤žÔ™%µRfIWõ6/«0Ÿ¶§ëÞºÂàI&Òó8©Súë -6$¼{&ÜaB§›*@¡)È=ÈÇ*Á4¤±"5ý·9.v¿,Þ†Ë4¯†%$£:²gHâk#ˆB¡H»»¥ÝìÀøå#ÙÖ슥˼M[•œ-çJé †”§O/¾­ýÃtD‰NÜ §ªmi²«DŽŸ§ã(PÙ“ú»¢]¾ÛM½y™:UkX̺‰f|Rĉ€{è~ -ôõWFz+ù„Mô­}_Éî:®· Rgœ¬½ß¡ŽåzÄL0 rÅ“[1w  ^øûê üTMî)•&AÆoì)_jzO9)G“Ý,Fiò¬òŽ&O´ÓdO½ ÍHI&4CŒ£ÐŒ5š±ÄgÝ[Ql Å–U°®è|(ø|8Ú“ûHÎÂà—Mãôa‹Í£°…˜åØ^Ë2dùŒ7ºòp†Ä&²;l -ÄeG>{ö¢qϱs—Þ‘9Ï㸴ç¦Q¦¢ Ž²ä ”yRgPf¥:”­ë× ¤¥Q -õ†NêÔ‚Á…—‚â¾ ··È„6ßYÖî{©ôÐÙ8wiΓK:»ŒÝÜNM»XDA¦ox¸:ã`rþ…ÕŠ1À1ÑYÕNèDwßµ‰ ÒX¦=å7…½–È»“JKUXÃ.mú®=VuuÜviä×&ô‡¡öÓãqüXÇ…!±:ï]_jÚ½NÊéÎóºÚ'Yò¬òŽ%O´³dO=dÍàÊ“ê<ï²rwMé0.)¹Ÿr]ú2õÆÖ÷¥Î¸ÎJy®{ÜäOÓ®;§ÜsÝPû„ë|õ×ÿ1Ü “t7ûƒèJ@U¬bÿjÔ©p -Í©ßpª'uÆ©Vª³nuÞ©ç”{NjŸpª¯ÞdÁRÇÄ£X0<Š…¦hï©dЇ…ëúÅèæžà¨j•·9=ÿá×CɃ”Õ`ÀóP‡|èÆ&ô²Ol¦²öÅÛþ:sày]|Y¦pªÇ#mÈ—ò!¿“š{ oÊ+’Ââ«Û‘ê½{}ø¢«F#F£âÓªy³„ÒK¾)WL˜!=Ë¢$Œpp‰"Ö/—|wJ¡-ªIôä¹@òûŒÀe³]½¹‚d|yôg•u³b¯¥‘¹  -ÖïIMeµÂÇÓ¢±]Ìm¯ï#ÞåxoÖ“ÍüÉ‚qÞ|³Î³o=†hI9üRX‡‚÷à¬)ö@å—Û¾®Í¿|]PÅ>¯žð 9Rf¶‚ãÙÒOV»ç¨Ûå{Öc¼¨%{ -¾U¯ycGôsd*ö6Åe%ÎK“ƒ÷¦€}žb|©iŠqRŽb–ç)æ¬òŽbN´SLO½¡ؘœªevM3Ƀ%ò6>ÜÐ/RÌr],Ÿik@ͪlðD¸â?2€Ã2X0aÒ¥Ç2 ŸX›ú,fa×Ë=äãPõVæšôqóùîîã‡Þr»býØK,ébh -p2£·RKOhV¨ÃÁfòÞöœÖîÚv¨vüÖÖ×{C¸Sù:¿ñÞ2¿\ßÝÙ;ò¢ò^F]Þîdû\5éVˆõ*|ãY¥“™v*Ët7½-,ö‰[!wÉ$æŒV'3T;øã Û/‰}½ÿO‹_þOµ'—8À¿Ä™›pñ?ÿÁW÷çlþõM6ñb€¥´´F¡›¤PCÓÝŸ†ÚþoÒd¯;endstream +xڥ˒Û6ò>_¡ª=X³kÁxð…ÍiÖžØÎÄŽcM6»•äÀ‘ Ë©ˆ¤'“¯ßºA%¥jKÐhô?1‰–h©'©ŽXÌEØGUXÔh@@I£TMï=v]•ÏC¼ÇªøsHUƒê/K’,ªPoìÅßÍï°a ÓyÆμ€%½”ÍŠÜ’dîöß?ÜÝž–™±4‹.ˆË錴’–·GŠ—1°`êì~çx¿P RŤæÉ`¿·¨pCÕ9Ь‡®ÅƲ7MØveѬ±SКwûm€ÅØ"+ëp¬Aîºh}kí4 ¬¨¬™;ðPšÃ%fŸîivsòŽb2!Õ±NßRå®éqÜi«(H©É”7ý¶ç® Þ8K]5BÞÀoË„e[ é³öTÉh`Om?ÇÏ›be5Äé:BÞ™²ÜXkk;Áý«H¢eµðÖ]Z°..¦6ˆS³•eý䔾æegy@G¬"Ęf¿_¡BG`«$Dw…¶¾P)lëºH —%Ù"|©ê§ +›Û]aý°m®=6ò°“?ûÁ2V[OEYbë¦ –ˆ^¬h½ºi¬x‚çW)H1˜ºÝSѾ5|ߎ×B!ÄPØåiñƒ©ú‚øXgÄ×c9ñ]Y™„q^ØÒ#l9°3‚ñ4;ØòÓ®¨Úf`fš5ÆX¶Ùm6ùŽlsMÁFS½‰hôžü{·1ýÂ;9µp@FDJ¦¤—˪iÌb2ÒDèƒð$û½CìÓwñr¦/Y–=Ò™›!$w1wcvÒ”X{ò‹Y€<›§b.ÏRÖ#“64*šqy_HÛÜôlöÄ ƒv‘é&ƒ½.ëô/ÞûZ]-MÞ£éo}Ž·û»¢mMuò¢4c'2Ÿþö8§/pÜ|9¥g6ëUãp³1Å6{c¶ÄBpÂË! WùWïK½JÌî)b@ÊZèÓ|‰'—ä3Ä:Ã帳½˜®nwu[/êòHBEág¦Ï×cP7”Qp·Dy@ +©šbOi-¿3÷H’rÎ 1 ÑÉÇ8{pï ­›‚eîO¯ŠÞ}2Zi¥¹}2.•…Nh`ÇœÇSš¥š§C'ã˜aæëv”RÎ:ÎyÀWÙƶXo±,ñ¬O¦÷VØóÎYzX :wÛ + k¡ÙåµÝ¥ÕRRá×ùQÛ?Ó4:â,¼iºÅÂ4M½kNÊ1Ü0ä”éb–ãËÉñ林üì–½žo9¦éƒ-ì +—sÅétS/Í?A¢¤šÎ»-™€‹-0ÜU•±œq.QÅÉ´îÚm×Úà&³©Ø¢ì–ÓÁIâ£_—(ªe±ð%B’Ÿ¯ãX¿®;¢¢9h¡}éîJpK~P¹:̈gM‰ø«ŽU3•öᱶHA†—Áq± ¨Þ¢-¾+dÏÅJ‹ê{9Íù<¿± ‰iÞ @‘·Æ6/\œjÓ™(¢zŽ¢(Ï!Àf6<¡•ñÓ´;Ëb§¢LRªŠLh“!ú|Þ<ÔeƒD!Ÿ0RyÞ´K³Û0He,Š2Ϻ?ÌQµw¢zäºeÂ{bz4òµú ¦²é Â_°Ø Œ?Á:oqÍT¦Ãt›s&Sé +íMŒÄt»‹µ6KnLLçb¶ht›7 –á]¦õ|E[ä%›Â|5ØâZ¸£oð_üã‚7&¯h·!£” vòkW¥+¿!wÁa%¾è ñ¤Æ8¤ÙçüÁUEj³‹¼,lÍÏa½61ˆ2ô1¤(ù‚V ªqUËëÁú½Û€¶;[žN`Û¹ËMD²ŸbwkÆÎÒ‡ÊÅAà âЬò jÛ{¹vXj NV\ˆ'B¬Óv¸Çrvxw©:†ò·4_#^ÎD¥ç‰ë±F¨Æ1q2¤nÞg–® .|EKN›ºsRàn°ä%ˆÚ +ÓVµ’SñýLÀÜîSr»Ð3øÒ -k¿+±ØaR÷¯Å’¦ç#FA´ ´ôØ+`Ö+\d,²ì@È{•>4A6îO}ª„±X™ß»bØ–/Æz#ÕK®ÞÇ'vÊ€=ö+DÚ³áEÓ‡Y5½'ÐHVÅ,ã<ƒã@jQ%´WÍðVû:¥¢b½«AR 3ÇÏb[Ï„OŠ8@˜»¾ *K‚-êªÍ‹Š.YõOvl™·´(>¤DXe,ª2¸j+E¾’rTTaQ¡/¬Qæäél)t0â=æ¥1‹,„¼¤[XŽ°2æL ¡†ÞÉô aÞö†$¸GÌf¶¾~ W.‡ ž=ói«£$È#èîy«`±:ËYùÅ,†^˜B²2H4`í³TÎQƒŠ¼`…«!Q¯Ñ¥»Gqt ó„}çÒ-„¼¨…9ý+ÝAßü±-‹EÑ"´°qå-D†8ždtéDYì«ñ™Ó‰—Tµ+kHÈ×ׇ©øÓ¼¤‰A.–ù òñ¼5ØrqJæãíkÚÝlë†-;䛼uуæûùû3øÕü¤&e¸ *s*4C‰q$¬í +tì>¦l$qtFšèŒˆÎÈ.²¡Õ`chãˆ6‘ƒ“Øaûæh´}j´ÕöE¿˜ó±¬þ D$Y“þ1`STÝaÁ‡2•!%NÉÁ4‚‘yyTü ^MƒòŽâ4š?ŸÎýDbÿ}]¨î„X§µ¿ÇrÚߌi?D¶¶äåƒô©Ûõq # +p–¸k„ºAÌ! ÷—I4$ï èàÞ=qK•ã¿£ÌA|)ƒsrv¨ ÷ +=¶J±ä·Ÿð1~_º€ïè±!b÷¯‚bFÆ„LôP¦ÝŽvlK +818ž¹—Æž¸ò5°m·ÛÖþE×Ä°ÂqZ^ ÒË´¼ð댼x,'/÷cò"íÿ*¼çÜíœ;ú‹FÌøEÒz¬Úÿ¢¡ˆJ‹ì+YÚÿß ŒÄz¨zµ°Œì³›\ã—Þ|4ÈÂe¹ÂA<Y.p%JŽ¸rgŠÈónÓ5-.ý@[˜KW¶Ý?ø˜RƦ3} fû¢(˜må¿ + +gÐq©|ý²RGô7 ír%X@<9…îÏÆm_”¾‹œÖy ­ë¯êË¥_=™{ó(+_ïíÿÌ°÷œ¿k«| |~2Øgô_ào¤f÷0‹@žöýcø»7¯g>Ú¾y· _Õ$8½{³õ&ýtIÚ—ßbfÿl5¢|â¯ñÿþO×þ¿kQÊT–P%™ÆV•O”埈¢cËbB"Ghÿîÿ“Îendstream endobj -1908 0 obj << +2454 0 obj << /Type /Page -/Contents 1909 0 R -/Resources 1907 0 R +/Contents 2455 0 R +/Resources 2453 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1912 0 R ->> endobj -1910 0 obj << -/D [1908 0 R /XYZ 85.0394 794.5015 null] +/Parent 2457 0 R >> endobj -1911 0 obj << -/D [1908 0 R /XYZ 85.0394 679.319 null] +2456 0 obj << +/D [2454 0 R /XYZ 56.6929 794.5015 null] >> endobj -1907 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F41 939 0 R /F21 714 0 R /F48 953 0 R /F53 1029 0 R >> +2453 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F55 1311 0 R /F22 953 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1915 0 obj << -/Length 2837 +2460 0 obj << +/Length 2936 /Filter /FlateDecode >> stream -xÚ¥Z[oܺ~÷¯ØGITÞ%èC‚¤9hOÝ-øA^Ѷ­´Yic8¿¾Ã«HÝö´Å>ˆ"GœáÌ7’‹w~xÇE* -R첂¥a¾Û®ÐîÆ~¹Â–æ#zR½»½úÓ_i¶+ÒB±»}æÊS”çxw[}IÞ¥8½†Pòþã/×oˆàˆ$oon>üöþã¿á# „’¿¿ýíóÛ¿™¾›ëÈ~ùðéúîö׫·^˜P`Œ¨’äûÕ—;´«@î_¯PJ‹œïžá¥¸(ÈîpÅ8M9£Ôõ4WŸ®þé' Fõ§K -`6òú Íq2<éIz9 ×8©ÛGóÞ=D8ùý½y~E®qžèEÔ]kè+Ùצ» -lhïëÁ4êvÂîûYž^®1Æ €"C,¹}ªûéG¶D3Ý¿(•iäˆg  œ–¨VVɇòÜ ¯“äù©Þ?ÄŠ"9ȲíÕ‡  (Ð+2Î@«úóúÑÒDJÌÒ‚ˆÂÒ´ÝéP6Í‹™·—m¥$Dúø!ͨZ`-{X€*ù=PЫ•)¢òcÝ{ÿb{M¦ÑïÎy ‹` -Ùê–<™¢,rÙ“}:”ߤuÀz'惡Ë7vé„CÀq¼víù„Z÷è»FK˜Õ#ŒX=BËz¢õ*ƒn£2Š’ƒ|®¡hhóòÐ5M÷2y§SÙôvx´9x¦ÍÈZZ¥q©ÿ©{ö‚¸HãÓTžÝŸïŽ,O‡Vèßc$x.û1ÙÁ. !VG‘×+u(5¬ø="ÍH.¶ý>¤Z÷{Oåý~¨f^ VÇôgO5gà ² +Ø„÷èõJaÂ"†šOu;˜  Ý*à ê¾zP)ó¾ïÙnp2YwŽg7X]ýðâçöT -:¢XŽ Ž²S¤JýíÒŽgØѨԢ]‡´²Iiém¿VÖŒz*`î¥+ÒÊ㱩U©ŽŠl¡«úGep[ÂS+Ô¡ñÞ2óg t -’]H6!Õè•8áiXM6›¼Çd3c¾œl"î7Æ›¬&­º¥Ú=™ãüK¼ze¤³X»Î½µ–'ŽÆ‘ºäî;ÇÒÏaÕLmWó o["¤Z·„§ò–pN±Z¶n²ËÖÿå²5àÓ“íà€_tþç«:ÓÑêà *\ß™>Þ¡ññÆŒ•Ueƒjot5§FŽ -^f¢óá^žÜ¥›õl(š˜9{™a–f9]Ü&QÎÖ¶I<åLø‡ùtgÚ(0v{$W©Ã´:ÇÃÓæx@  8ùø`zÍ|º© cZFhûß ©Ó†Óª\€ ¯Å&åtsÈÖ¨]-¯3ZÈYZÐŒÇé±×v‹ÞwgÍmïšÆ¸‚ @Æ4ªåL£cßÃtÂÅôzÝ·Zö5í¶kžz/rz!‘†Tžä¨ÆDjbo¿îI[ìOšò_ñ¤P€°†Ž´2nk%GY¢©[ÙÇ!Êm²çÿBÖí•(¿`€jÃŽjÌ1°åìWsÌ&ï1Ç̘/瘈»MÇ4÷ÉšÎÉU{ðuzÑj…FP÷(úóT«¨û¡Þ÷V§9L… ¨~ÚÉÇ'S‚BãPVòµÚŒâ‘®¯JÏ`}Oã`œøؼL¼¸·æîÚMtÜK¨^j·Íý#)3¨‡Æ¥¯"ˆŠ,eŒ\È!Õ:‚<•GÐ÷Ó”o‘§œ^`kiæ\'U1…ê¶ÀÛ›Q#_*«%“½ºîÖõå¶õÄ5{pBk¥wqõ÷z}2÷qÌ}ãtÒ,ÅPåo[b$Ú0„%í 2˜òžµÈºÅ{ ¬SæËq5äîÌ¡*mW™ø}Š2‡ ãN‹ªßz¹_ÌN†êÐPj]CÓ¾Â<¥¥õ…#´µ%„ÛþçSk -Vh§[/Vþër5^Ãf?¾8l•Qh_2¯@èB¦ ©Öáà©<Æ2-¾ë àH‚n3÷Tsî“ÐnI`Û±¦Ó¹‡Úl{·± ˆ´êr9 ¶öã§Ý(Ï׆,(»rCª Ã8ªÑ0ö¬w¾›`(¥Y·ù{ª¹±m Ì¦±X‚Ñ6ÌÙ†9Û°È6ÌŸ£dY¿Žæ¡…13æaKæA™5 Íìy˜5‹N—·ÍÁŠbva×Rm˜ÇQ橪Z­®læöê®%ÛÀSÍ%ˆí’RšÇæÎ<™GDæÉœyDˆ¬ßGû0aí#Œ}Ä’} -gÚGXûkŸÌÛGSQ¤Í'цÑpAR$.ĺ€hÝdŽh´XÓ¬Îm±Ïæ¦|—æBÆŸ¤1®lÛ7²´M%Ï<Þ|Eˆ–ëUêŒ\¸x ©6Tä¨ÌÕa}¹]©Ò6Ùº*mÆu¹J‹Ø‚†4~\ÞW ÊòNŸ5»¹ÚFi.Û+ÒnéJ\%ã™;¸¿]84È¡>ñ·¡à][õq"!ÈLV lOnñ÷o[+¬¹ÖórZÒaA`PÈ`»É²à°—r§¢.a5þdv÷6b{†^;”Ù#„1ëÅghA¹:®5H«Ø§ÜÎí[‚ë@†º†Z\¨n\H•!Õj•½ð®e?‡íèÙ[œמ²^ñí·…®»éR  c¯Ûô ¨ÓÑuö©U ÏïoLÃÝEdþÜÆôÍC8M Œù&Ò ÂsKP·ý Ëj"Ÿ>ø‹à˜ªÿF°\—-¸lÖs~‘¯»«íÅlͼ¾ƒK¿øºx)¿ŸË&.Ï~Jsp5Ýp-Y¥†;¸ºjÛmÂÍTçÖŸéËì€^Åt–¥$¶ËÑÆ_,‘ôI:6½ÅvÄó”ï2œCÆÍÔpàQ£Ð6g(Ø£Y5;ó´›)sf‚-¦¡1b: ö˜6}K˜†:4cÅ&¶HVÌ  -éVìÍ)OHjŽ}>«CŸ¦þ¶tê ž€Òœ4>¦5qféø™«ÿß8Oð˜th«:9Ýü×í¾9WÓÃE}ç þýjåwÀWý[nhçœëÿþSÞø—C–AÆÌÉ2žHÆSøX8¡”&ŠsÇA)¡vç²ÿ&üþ„endstream -endobj -1914 0 obj << +xÚ¥Z_wÛ¶ϧð[”ÓZERΞ²%í²Þ¤½Kvv{Ö=ȶœèÔ–œ¦[¢±OõãÝÉ»÷2åažÄÉènîñÊÂ(ËÄènöGpþùóåÍÅÕÿÎƱŽ‚󱎢àúüæ·óÿÐØç³<Î?\ÞžEžéˆ4’%Qpqs{{ùÓøãå——7gÞýrryçÔòU‘Dþ:ùãÏh4ƒür…¸žàGŠùEùX.ö0àˆSðÅ£š9ªÕz˜—"ŒuÒWí¶ìZ¶—µâ¬œlîï«úž~Íß1ú!~±‹CE¡BÑiÜ]]_Ý| µŸ>ß]}º¹€=!¨­³<3‹.ØëRL‹;Š\Êï+BUÛ–3šªjš"¡3oÖË¢£É/ðïúúâ‚fú½ÑŸ¾¾¾½ iòjN“ŽOa$Ýo–€F™”`ŠvvOU÷À«¨9}sŠ„eÂÀø1œ‰ êh¦âMVuW®y[í +ØðdÁ»—‡ùy[ò⹡o–;{·Öq*wÕ²„ Ê, Þ[U¦MýXÖ8CiTŠƒjN3ífúp\nµ³}º÷æÍbÑ<ÝELÐëDÊñ +L¼‚RÚaû5Šâïæ¬aò¢g`l«àtÙPW§O®7s½Û3{ÂÕËÊaø 1,/íïB°é¡6ËÕ†lT/{.‹5+õ5ÒѬD=k 8x:§,‰¦N¬ÆÍfM?fÅskL §|_7kr$˜X”ÅŠzFˆL·lêî™ö¥›!'/: ÎcõT–߬xO¤·}¾ v6µ¬j°Š¡ÇeH­ÊiWûÛKn,Eü~¦ak°ä ZPãðÛ˜Ò; ø]qÐñGkæT\gíÁ@ ™S¨âô…Ôħ:¨• ÔŸ‡u–k¨á)ß5s³•ÝpÄa’½¤Ÿ£P°®“4L’\÷5äx[Ûf¹Ñˆ†ššÚ§‡Êø4L4‚yŠù]ÙÕ µf²ÚLUû`N›vBþdžóWqœÏ!vÙitY 8tÙ5,Ô¤: ÓXêÝð¹X „cô‘êéb3#ÔÇãcçb£/0ÈK¥Ç£nº>³Mk™½@Û‚;2ë¡ ‘â¿·Nõ-;]mõ˜ïè1þ@m³êª†9>JÃi XNÊ’±z½Ý»qmšå¹ÆWˆ‰uó„ÍaGˆ4äðzÐùkü@…R‹ì¸zŽj@¿¾ä¡”Rô$?šïAì`OEjeý Ge<;•]ßP;a‚C°šF¸–îÄáne!ÜájßçL¨džä°…,}ØÂ]J‚;¶ÄNJ†;(b‡0m¨j ÓHn0­5a§ ¦q†0-µc$ ¦=a„il-¦±o0ÝãD(¶š¦æêBü?Æ´Òä…‰:ŽiŸê0¦•Áô¯Ã˜Ž"¿Ô2L}–Ø&¢õúÎÂ4…+¥§C:ãÀ€†tF¡[ iŸŠ€—‘™ÍLCÐœ@vUR—.ôÇæ›Áu +aÚâ:³aÜ +„sU"Þc/,®³h‹kÈûã\öq €,îïí¥^´~Ja5ÀDâŠÑÁQ\ómdwxi‹—| ózvˆ_ÞK/ä؆_×n,^È-|ª#ð³T~Wƒe$“ú5èƒ MäqõÕ€~}üéPé4í+Èø“6¤A‡ñ'0bñçS@ SÙõ -š0¿s*jg&PI@éÈM`âÏ„^Û¹®Ã"ÜB¤‡bìA ñe<±Ùlµ‡JÊþ=´$Üx Þ G¡åS†–£2кŠlX4L_w[g9¼Ãªç¨ôÛ½­!¹}9k¥‡u8kÅçZ.Ž]ÖêSQÞ +Ê®o¨¥úX ×Ì¢¤»ZFÂ¥¦†…IMY’y&f|ù”cÌܨ]4õ}¹v÷vPÜÍå^¤8Ðá›Î»eñìÇÃeaî1 åªi«®YÓSŒAûðGP6UAˆÀƒÈ‹E˜ä€†ãÈó¨Ž ÏRäU/ÕrM¥ã±Ø¯m)0idGusTÊõ`§觢¯Ã.±UÄKÌsgZpNMC57%.è÷¶Ì ‘)¥g Û×Bdë‰-ËÀÒ=tW%.Ãt3Sü2€“iÅb'Q䪰¢5V ^ë‚ÞÍ8üLmÁd‹² ¸qã90¸¤:ÚÖ‡¢œv¢¬ÖjG7e“jädù`Q ÂG¾“¾ézLú[J ‰g‚^]Ÿ&©3¡­ÆÁôŽ •·’ýÇ\¢™px0,Œº0ÂÛÆ1Ø6MJ<`į"jçd(tü€',°€6ª›€ûµ¶@‚W¬)»6Aƒqܤbn+8ÆW«à¬ ÚžaqÀ;¾ZøÛ®΀(– 8DÏ÷¦àe•1ƒ VÔmÆÎæøDæä‹£,t½ +£≢Àoð•YhdÊ"èù…“’ +d04¥3a\ÃœI3.LÂïòû +¤™ :3…ËiÙ¶ÆUaÒ½!n@Úz+ÎÆËÜ• }…¶ðÉ£Ã~½Xá½mLuÎ|bxnàª*òTµe?³°+þ.© ;h¹s“Ki®2K©\2æhÛ·ü˜Ó çLj§S”œ)¯n‹£“gåǦám˜“Þ«Ûâäéó©œØ¢­é>²6T´5c¶7\u´%Ü$Û÷Ý ÊŠÌí¢Û†SIKG3¦®Ê쨦Ê?\U4ÙÖg¡ëª¢~(âk¿ +ê ;ù'UÑa íìï@]tïc <©óhû1† úáòæò×süRwwyAL>^~yÅ™ßñ4¬ïk%ÜíB'6«¬[Pi Nvï¨}ž ¦ÊN±Ô‹¹š)”åÖ{ç›Å6xÆYJNOÌլô µ-¦çôyÁ>‚q¿ |„eý\°kø¾)ŠâM…ÿ”γPÅ®ÌEÅÃÜU9Æ*ÎÂXˤúm·;ùŸà`µé8¼sñÔ¶…ÍúføÝÑáî9ííú”‹ &†6 <Ø76C¹¦ÚÕ¿%‘ •Œ²ãáS™dK(ßBÐͤNj^ý"ÝËñ"Àd¢ÒãRÕ¾Øþ÷ôú*é‹Åóþª®"{èU{È€u™ÐSe*”é¡×šµ”GtØP–èE;¹5Ó®ÌA+ù2îC6ÂÏ + Ý#Õpw¬«iï ²ýÒèÕ¸¢¿²XÜ7k…˃¦Mt‰úqËni–i^´ëy[³î´ª'ðPü1>K^ÄÞÖóm2…ÏDëìó¦éLÄgÝA;JâŸó ì+rwÿþ«¡í‘¨4”Yv ¨$ÁRB¤e¥p÷Bé]Õ5\O:‹ÓÝÿ×LDòendstream +endobj +2459 0 obj << /Type /Page -/Contents 1915 0 R -/Resources 1913 0 R +/Contents 2460 0 R +/Resources 2458 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1912 0 R +/Parent 2457 0 R >> endobj -1916 0 obj << -/D [1914 0 R /XYZ 56.6929 794.5015 null] +2461 0 obj << +/D [2459 0 R /XYZ 85.0394 794.5015 null] >> endobj -1913 0 obj << -/Font << /F37 802 0 R /F48 953 0 R /F22 737 0 R /F21 714 0 R /F53 1029 0 R >> +2462 0 obj << +/D [2459 0 R /XYZ 85.0394 658.0977 null] +>> endobj +2463 0 obj << +/D [2459 0 R /XYZ 85.0394 153.2806 null] +>> endobj +2458 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F55 1311 0 R /F22 953 0 R /F41 1208 0 R /F14 956 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1919 0 obj << -/Length 3266 -/Filter /FlateDecode ->> -stream -xÚ­]sÛ6òÝ¿B3}¡§‚O~<äÁ©ÝœÛ4Ik§w7m(‰²9¥HU¤œº¿þv±DŠ”Üi/™„¸Ø],ö›3Å,5Œ«LÏ’L3Ã…™-7|öïÞ^3÷@ó>Ô›û‹Wߨd–±,–ñì~ÝÕ2ž¦bv¿ú9ºúøñæýõí.çÒðè »œΣï¯ÞºzGk/3]½½¹ƒil¸ `1®oß^þzÿíÅÍ}`¦Ï°à -9ùýâç_ùl|{Á™ÊR3û ÎD–ÉÙæBÅŒVʯTw?„½·vë”´I™‘:žÍ8Q™˜gÜÀ±ç‰æ,‰¥bÒ锘<ŠéËzÕtíëëãã -%Ys1ëãQPcÒRöH •°T‹#ÚwEw9W*‰ºÇ‚õ~³(v8Ž£fMkÈŸË݆ÇüÉíèzæÛmq)¢|GӲƽúƨ’g,NµÞ‘|o -‚ð*&ãX8 À?F$$ãZ9ˆë S -IëÆ3ÕõyŽ£…;ò©ÛrçiT¬ÜymSí»‚!öÙ\¦1“R ÈËŒ‘󽕛ë|_u4yÊ«½[/[z:ÉYÈ_8—µ%Ó}[‚ÔêæöÕNè0l»¼+6Eíö{ÁjÑYª™Ýr~UtËW»ðÄàlë)káEøàNudå4„#… -`â¨nH*É@‰àèNdçŽU™Ë*œÆq‹+¥{³…eo¡Ž´ðì\k½p ŸËîG:ZŸQqÑãÖ¨Xx;mÝ»-­t(J áÑr•wåSAoꕼvП˪¢¥…UBÄàjÛ‚(.-~pWVpW`Ÿö¶p°j6yY·4©Ê¶ó[úã[IÊR‘x5EŠËlj»R)ƒkðV\L àŒÇDüœÄäMkU’¨–NRÄð¹‘LÄ*þ»ÊÅFžÜ¹Ë8ÑŒ'";ïSûP§}j€²>u±_·åŸÅë7#¯ª5ˆ®ø,í5&>ôª:cI›!uëU¥·f|ºþHPÃ6p«À$Šmu 8ÆQ嫧bו-©‘uè!pxsýþŽ;ôSžQÆ †`¯,o&n"šJ<Àâ¹+Z†.O7³læ”›ý†&h1dþÂ0˜lh'›²v°IfÐÒ£>»ÇÒ­ Î óƒEÃ$6F·nMœÖnIO«çK!D„,gIô¦èn=Õ}‡ž|@:åÑ.ù K fÂvÜìëU±šrû-†·ýUóÙÙ4<ڻݕà¡{| >ä ·ƒ.ì¼/Ȇ?)â44s FË|ß:{Ìé·N£ß÷ÅîÙ!r–Üê)[có‚­õ ÎØš‡²¶V¬êöõ#C“154ç ¨1å£ôý›J‡¤ï@%ʵ•Fê- ²J#0¢¶lj÷¾¡g`j#ŽU}íï«\¹áêÒž¶À„‘Ic0úÎéY^(™ç?Ô´ÿßýÇ“1c2Ÿ|Y7xeŽ¼žR d‚[VÚ£HG²Ø6KtÙÒAwГŠh’¸‰ÕyEìCVÄeÏõsÝüº$¬¬Êºécœ²|ëyújÌÀP¨xœ 9ø¸+1ïÑ2urZ6ö¹ji±*+hd剃»W8H¦7`ú€Ïœ ÚEÓºö¤s{T;‡ìd“;ê”Jáèq¿Éë9i] <ÇüÈ}Ý|•/*DÄ$ÃÌß0($±¡ €ë!ÅÅ :V ê ηîè°TäËGZž‰ÖÐ*§)6",#< $¢Zeí:_ÂmbL Àí.÷ØQoAYr ->ý¼Kö ¡Ô²> z˜°‘0­´‡°²ÝŸv® :…âæîAÑitz—Õ¸:„ÔQ%ñyÒjLû(QïdCÚ×X$i(EšŽ:¥öÚWÅî][ìžlݨ]ÙÏçfOðN -›e⛜w7?^ýôÍe¢£«ÛwŒ–ï=úCQHl%¥]í6Á–/žÔ²E) œ+Qlj=±jcîc‰Êj3ßiW‡î¬*U–æ\uÛí}pÌŠ=òEUr Ú§;©:j*®yr^uúP§U'@ÕYP‹¬Á5t#‚Œ5áêÔ˜ƒ#k±…½²pÕAáºÅd8&O!cp#e»­òg·h… ($:t:c% «.]niæ/+½˜ŒPy…ίXYýq _ýÁIÙ:/)»JÍP'|(µJeÓ¼À%L“ëêÓöô•ª˜É˜¿jõ¡Î\©‡ -W -¡»-–£ë4*™ž' ÆÔ‡× iM’h1$ÿcÉG‹w$ j†€wó5GÁKPYmŸ­mØ•g¿âr%œX8Føá;·£t[á†_€ÿÍ12Š,>ìþðñ~ŠºsmÀ­¥G½›QŸ¯Ve©K°m,8šzQz‰¥ü'AehR.Ï+Bê´"¨ mù°|ÌÛ‰LG²pœ¥îÆÔ‡ŠÕd"35$ÿµ%;—_øK“ëׇ:ïöÁ4%6O°/‚v ÁõÇuZz¡×l -+±·Ù–•5´Æàh~=ÑÖ©d:SzpÒ—ZÂ’eišN7„çã bÑp++‡b¹»}ûõ¿®înNë=Fõ;¯=¨3ú࡬>t»=6æ¿ϯ¿€?#Hc€NÕyÔ˜‡¡Vd‚Å*‹‡LØj {›…u¶vÁ.UÑ̓F8ãkÚ]¦Ñžúe8þÝfôÈø\¸ûÖÃX­˜h*ÍLši_öÍãˆlågé¡=5—€öƦ­Htú»›ÿú–'\Kš©©¤ùØÚ ÇÖcÞu”oøÖfº,$±£ÅYjßÚ¦‰qq(‰£6uõÕD&›&T¿”ÉÆiè÷¸*hTMóYO¶M¤-EÛõ멃SĤd2ói38ËÉnµdÊ€^DšUBJÁn;qq¹_’ÇqEŽJˆ '.¬ÁÝ÷=›¾ ?\Fâ]Ï_ÙÃ+îù+ý¿‚Ѥ¿’ :SÍŒC(ûÇþ*`œ÷QŽ V‚sI„J”ÿ’¿’ ü"å/|óêCöW*į®ÙÚfÚ(“‰!÷àú<õ5&ÀKŒH†ôÿz9—¶»Ÿ»ªQd‡`/Žƒ™ðÁŒÆÛb‡)!MrÚš»ö °-¤r•w¶&;V'Øàìª3(»¸9ÒÙ¿§c{=pÓÒ¤L¢jücóç}”:Vm´4ÊMÇde/”Î}¨3:æ¡‚Žág½“¥óYÒ‡ÒyD{²tо­—Õ~åÓÊú¸Ef¿{ºóP‹Þ^÷ I›jû"µ¨C‡ozùdjDP£5èV -†±<#úsêT}ÿéV¥÷·ßÝš>Ýüx{s7á}Á+ʘ)‘¾xJ(²ßܾG†ue´Pn¶•ýò—»¬YÛã …¢5±/ö_Dæ£V»ßn¡ˆm‰RK}_’P±­°måC”ÖÄš)ZÀv·èƒN#êžáë‹Ò1u€‹&Xe©8 -ÿt>Å5#¸öüYŽìúô÷>ô¾†û:Ÿút&4Ë’ÌËf‘w˜• L.E„§Äi³E.° Â/©‰pù ·ßí¤{´ÍB\ -2Áõeî¸_î«Ò~‘†Uò0¸n‹ñsí íˆ HÄŒcÀxUùCû•K{,«­·†Õ¨‘í¦3"¼¥ü·-!©CÌ*¦VãøXb˜á>)":ŸB!Qá©45öîË5!3tߘ۰œ;~J°Ä§rµ·Å¢’á8ö•g¹p“ιf-®´Ï`&ÐxU´Ë]¹pŸŸæ‚CLú¨XÍÍS¿°ánZrúÝ‚­Èqfï]à÷³çÞ‚t5+ÚØÈ}ÖŠ°ánðµ½îïðãéý–ÅØÐö…›c.Y¸Íû­ÛgÕLúëÍ«©®mÿsÆó¶8Ò‘e•·ÇzcO7­@áûšsœíc³¯VÃŒ-÷ªÞÿ‚rØräMµñŠôî¡jtñ ™„t?—ÁgЄØóeµ5 ý+Üä9s?BÁç3÷ »h³u‡,Ø¡Z’âû¶¡7f[tÛf˜­ÕÂq}úöçƒB`»ÝÖ4Êö÷]wUÐ+R -xƒ~iG`°ºßVn¼´Jƒ -!4]§ãmÛ¡éI _ôtf¤’\ždŽ;?õK1UºšüÐÃCˆüÇ¿";üFNC€_Þ'óðžLáïÇS(vÁÍ1ëcc*“ Þÿ:ÇÀTendstream -endobj -1918 0 obj << +2466 0 obj << +/Length 1723 +/Filter /FlateDecode +>> +stream +xÚ¥XM{ÚF¾ó+8ôO¢í~Kê Û$qmc×>i“d´=ÉAÂ.ýõÕ¬„°×vÚÂA»«ÙÙù|gV¬OáÏúJó¸Æ’(ÊT¾îÑþ-¼{ßcŽ&hˆ‚.ÕѬ÷ó;öck®û³E‡WDh±þ,ý<8"š œL¦Óñqp=þýòl< XK9]]''§Ÿ†Wˆ”ÒÁÅhòqtŽkWØFïÇÓá×Ù¯½ñ¬«+:£ÂÊô½÷ù+í§ Á¯=JD©þL(ÃxÝ“J%…hVV½iï·–açm½Õk +F š{lÁ™Ï*&ZpQÛ"ÍËÒ̃ofwkr«lâM!ðŽb 'YêùfÈ¢I*S!ä z(ì@ ¾PÊW¦| 3¥YµD‚B›A8?ÿ ‘yQ?S\«–Iå˜$9n 2†fƒ~‡U¢Ã_þ.rw|W”/TÑ4s'U«²‚#ë·.úöL~:h. 9Eú0 +ŽÏ?žŒÑºe†^›¼‚š˜þˆi‚†L4¦}ÞãÀ•3=6¯d]óJˆ³Õm±=ÖAygæ™%œ#šUZZ\Šøà]­5¬7÷Y±uÛ!§·°}‡¯\Ö–E^'¨à¬Ü³kDH ãöçE… AÞH³Cƒ-“{f“¬pâŽI]ÔšÍ:+ˬȽv<*ÀICJ" ØË1-+‘ÈŸ’p–¦JÿG”jÎáX!Tƒ5²íTÅH…w‹Úî0(w뵸šãÔäóÍî®Êjˆƒm­#Ïr;_:înåÃÅèØ…§ÅÆU|hî‹åÐÇÜH;p(¶·ËpËZÅøºQ­fû} 4+{‡¸¯­ ë9)ˆTè¸ñ§ÑÅÕùØcIëᬮ±´Ìl•„læ‚¡ñì!!Yú×|„: +n²ÊN (OG¸ŠÂÂJmk»‚šÂJZ¬!WœÛ£·3›‰Ò¹Óü•¬ïV†Ì‹µG`­H¨DCkmlKÚÒɶ(V«âÊ ,ÖhTx÷PlW)®ß8rˆõ­IñÈp­IÄaÍe@è)½†&#HðY› ^¸Á'È-8Ê?/'c½¬¢½j—ïµI£ FK^¹i qƒ6€q±xqà™µOåGÇžu„$o(o¸fš¾$/Úè´®ªÁ+*u߶ÚéU$‘T4eøµÎFÃ0ޗރΦ>Ñà "<…ÀFÊâ«žÑñc„…ÎêE ƒ‚Ó¶· VˆʹTìqGspø ­‡Ü£º©DÞÄZ"&K;»j9:Ÿ^¾ŽÎev›ÛjnkwdË«s¡ˆ;[£ˆD±j„::œàI±;0]gy™T5$ÀÒµYô]>wAy‘ä[¨I>£GrQ· ÿTè㢶Ž_¿;FŽ\‰ØÃOBq´ø×ì"©þ;;ù˜½|•ßÁ"V$’¶-î üèãìÃåõëŽ=…~}“Ó] ­“ë]¡Õ(6U¶]ï…Ê.u[P,Ÿ˜7÷1( °Ì…ÊÆÜßLÓ5ˆˆ΢št× ¿`‚{yq5«Z¨/œ‡NÖFèÈð +è¢ K‘Å»ü +ñº¸¯¤¯ÖÊé./îʬ||O„´ +#°"“1"’¾{M~ˆ;û/}$dÌ6²õOúî|-U×<Î4¶ˆ|–›¯Íðƒ³»7ÐJ7-× +‘•¯éŠI5ÙÛò;óðwZ5Ø ½<ôñÅfçá©$Ѽ ã–éøU¦&¿Ír_³~HÖr\¸xv‘­Œ?_`¯ +­Ý;^>O¯O¯f§—OUò£á>Ä—¥Õ¶£MKmÓJcj¶CÝtt0À:e›èïKS¹-áºáÀ#\»ï’9~¬nOíBj,çÜö½vš¹ ˆ>@§(cõ©¼©bý Qâ°4uKl'«róàz$Ûöm»Ú¶åØ»Ô7¥¶+i“8/:IŸz.̾5àRû…Å“e´õýÿþ³ÿ`%Á6QÄ÷ßho6Êv%ºÊÚIýDôæ“ÏSÙÿ2®Çìendstream +endobj +2465 0 obj << /Type /Page -/Contents 1919 0 R -/Resources 1917 0 R +/Contents 2466 0 R +/Resources 2464 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1912 0 R +/Parent 2457 0 R >> endobj -1920 0 obj << -/D [1918 0 R /XYZ 85.0394 794.5015 null] +2467 0 obj << +/D [2465 0 R /XYZ 56.6929 794.5015 null] >> endobj -1921 0 obj << -/D [1918 0 R /XYZ 85.0394 179.5067 null] +2468 0 obj << +/D [2465 0 R /XYZ 56.6929 598.7685 null] >> endobj -1917 0 obj << -/Font << /F37 802 0 R /F48 953 0 R /F22 737 0 R /F53 1029 0 R /F41 939 0 R /F21 714 0 R >> +2469 0 obj << +/D [2465 0 R /XYZ 56.6929 432.9509 null] +>> endobj +2470 0 obj << +/D [2465 0 R /XYZ 56.6929 360.8886 null] +>> endobj +858 0 obj << +/D [2465 0 R /XYZ 56.6929 315.6627 null] +>> endobj +2471 0 obj << +/D [2465 0 R /XYZ 56.6929 279.8921 null] +>> endobj +2472 0 obj << +/D [2465 0 R /XYZ 56.6929 241.5703 null] +>> endobj +2473 0 obj << +/D [2465 0 R /XYZ 56.6929 166.5861 null] +>> endobj +2474 0 obj << +/D [2465 0 R /XYZ 56.6929 97.4887 null] +>> endobj +2464 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R /F48 1228 0 R /F39 1151 0 R /F53 1303 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1924 0 obj << -/Length 1913 +2477 0 obj << +/Length 2079 /Filter /FlateDecode >> stream -xÚ¥X[sÛº~ׯÐCgJ͉`Üx;oJlçøLŽãFÊ´Ç4 YœP„BRVÔNÿ{X¦$jt:=X@‹Ýodc -?6öÄ<‡±$>eþ8]èøæ>Ž˜[3mMû«Þ/FW·"Ç$x0^,{º"B£ˆÙ£÷žp2 Ôûíó|1™r?àÔ›=<ÜÜ_ßýÃŒ)¬”zÌî¿Î>¡ìasoöñf>yZü>ºYtÖô-fTS~ŒŸè8ÃQ"âÈï`@ ‹c>^¤/ˆ/…h%Åh>ú[§°7kÿ:ˆ£„‹€@Àù~LÁ……`Sä*¯¤ôtiZßkV -©^¯“2Ci‘— - 4òfå¼ú9)pþÇVUN¬7M®ËåߨOÕÏTmœ4Úµ«[Éz¶ñ(&”q<2VýòXê§táÊC/ÀY?n!n{0grâœxv>èWUUy–©ÒèO…ˆ ¢h*ü9…ãûñØç>àO”þœÄT¢ƒ…ÿ´Ó8í«´UýáN9#¾ílL¼¾›ÏÞº"ŸP)[’RåkŽa+×Êð«á5Ì}.L¹ïóövð,æO‡¹Øf!OÌŸ2']¢Ô -‰}¨¤ŽØ¶Ý y-¯ -mËã÷ ÔdŒ_ä/)d±jyÛ²>Cµ€ •!R-ãØþåöî¾ïNëö½^©&½ªT­‹W'|Ù¦!à ²+þòïß>ÿqóŸ+vVéôpãùÍ z?û4ÿ|‘ßWºn Ó2áïð†+2#Œz¬¬k•N¿«ý‹*{“v÷¡  “v_n?ÀSÖ* "úݺap9¨ÏÞ®±÷_?Î/º9×rœ}—õŽ^Ÿ!qÜë«Ñ;kûF:÷6ëìSdÐaxew&ðn2¸¶Á?ááìÛ÷†‡Ï=§B&ã.*¸ù7ÎCì]·E[÷›þ¶É‹¼ÙŸO Äl¾/õ¦†óqD;‚‘0‚ÇpAE•ÇÀçFrß\NÃßÀh§²§á”cº/nÑ›‹æ‰ù8M>dEYÕ‹ÝëS+J‡ -Maž²½LÓ"©ëÁW ±´hu -ï -ŸDß&`™é款0>Vøå²ÂíúY >¹dÇ›‹›ýfðë‡ 1£òXßß/êÛ%ysVŸèôáƒ,‚·‚Ãø8]ìrhвH^†v‘D†Ñ -²ë®‡µ‹•a1ðtî»xg>v d*íŽÆÿýMíí“¡4Enć?—ñÐ'ðç 5Ê8ÉhpbzûõíÔöÿB"endstream -endobj -1923 0 obj << +xÚµYÛrÛ8}×W¨j_äÊÁ… ‰Ý'ÅV²ÊÅöXJíVeò@KÄ +/‘²ÇóõÓ Š  yk§âTE Ôènžnœn@dˆáÆa&‚a$Ä1áÃe>Àà |÷a@ŒÌØ +»RïY4H„4.Ö]1ÂqL†‹Õ·Ñäþ~z{3ûïÕ˜rŸ^çÓÅböezõ}ñq0]´~u}'˜)§~|ûŽ‡+x…Œ˜ˆùð0"BÐa>8C<`ÌÎdƒùà×VaçÛf© ÎbÄcyÀ dHœS .PÈ(kи»_Ìînç'o‚æXD ŠÂüQ0Bã®”5쉂•RvÇÛ¾Ip>‚WLZ!IÚ1) +(æi­|¨’ÔÃ\VLJ¤Xéü#­Ñ9LBA ‚ð2&]©ó˜´R &Ÿ”É·ï9ïHÈ.@¹’X¥{¹¬ËýKß7Â)dH^v®•òx×…ð±(v½›ËºÒèÔ[ƒ¸sEâ‘q©™J ýù¼M—Ûžøi„~ØfÒhK´#[êO=W¥+y> !†ØFâ•0t¤.„ÁJ5aØŸ¤&ETm˜‹&­Ç¤“š¢„…®Éɺ–{Ü>­ÓbÓƒ®Ï-†•¬=0jÄòòIö––ût“Ivvýy„Ð'ä„;R¶R ÂO¾DW¹1“é™|’ÙI–ÓÑòñ¢g­”Ç5'ËA”‡®k¾,—‡Í¦IãÙYÌ8PÕà2f]©ó˜µR fS?f±à3Y€—ò4FQ ‘¾ìZ+åñÍ-BQ 5Æqîk%U­ 5hDD£Mú$ =w·“Å|þY?h¡šRÁFÿÙZ™e™ïÒL®ôÓsZoµšûO×󢧫ÃnWîkýÖZb%×É!SAkì—zv÷cYò/…ÅpL#3ÀmÜCp¹ ¯Ìwµá¥"É¥Ã?m2ØÊaù©0ŸöuÎei€ékÙБº VªÉ†õ9Žºh²å¨S“>ŽrL¾/P– +!LF@4{ÅUòŸð‡£ëäP59êøO0(‰CjKXQUr9Þ˧ò‡4â]Ûaˆ"N#Ýà ÖKz¨‡©áD˜Ñu»$Ýë‘l²OÒµ–Nô£æ<=N2ædeÖCÙ¯šˆÃ8OêåVmú&…HH µ‚Ô19DÜJ² Ðl½Í{}D[ñf7†Œ×=rÑ(,:K!#ÔBÙiáÆ4@«Û‘Nåùtª×N>Ïïò™²‘˜5ÕN.S¥Z/Ge§ðŽí»8io7´[ÐL¸œz沂#ulìîý[:Î꠯鈬ŽÙÿ cÌ(i‚àÉmµ„M@» { +ˆð6GË]B¹TWj4-š‚öN¸ài™j@UX +=õh¡Ñ\éï_| §ˆéìy“¬é¦ø³,¼ÙAS…í¾WeOY)Áð^›QkÛVAWGaì&DU®ëgïUÆJBÓ«½k.FdáÔÕ¶§•»ðѬس´ÚÊÕ/­íZ÷`RmËC¶rjœœZnߤë€BŨ–õÙ&„ĈDßýÌ m…îŽ=ê5˜jÿÍ xRÙ)V=ŸšÏ没ù¶hè 8òåzWÃl–6>0Ât¼O£ +'u8¥³°Õ³Â›Ušï²m Ȧ¨+í„ñÆD¡™Ñ¢C­nbN\&vÛ$÷¡ ®õAÉbooĜޫíðûHë#1¥ÂäíÒ˜šn˜+S\ªžŽËmRltš06z,Õ!Z)8ÞPsQ+{VÌÙ©±À±o›Cý0±øTÀz“$É›Tý¡cOèì|uË°]åghöHÀ]Í:‰PE½ÍÖ±j+‡Ç2œ;¹m¨3DXt0Sz ! §¹NŠx4úr¤"Ñ…œ‰Ø]Þ ¶zVÁVŸ:¯`p¬lFQ&‰žÛ`ŒÍ)Óºìä›Í¯ä1ko¤ªå>m¶Û™c¥›£–Y’¬2ܲ˒e?AÕ†”E{ãQ\¾½Eç~ü€~DýbáiÛq[Uþö#Ç_€‚±8¦þ‹ †á ƱN)8¡åé»Þþ„rêû_·Ïj¤endstream +endobj +2476 0 obj << /Type /Page -/Contents 1924 0 R -/Resources 1922 0 R +/Contents 2477 0 R +/Resources 2475 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1912 0 R +/Parent 2457 0 R >> endobj -1925 0 obj << -/D [1923 0 R /XYZ 56.6929 794.5015 null] +2478 0 obj << +/D [2476 0 R /XYZ 85.0394 794.5015 null] >> endobj -1926 0 obj << -/D [1923 0 R /XYZ 56.6929 581.7741 null] +2479 0 obj << +/D [2476 0 R /XYZ 85.0394 752.123 null] >> endobj -1927 0 obj << -/D [1923 0 R /XYZ 56.6929 460.6765 null] +2480 0 obj << +/D [2476 0 R /XYZ 85.0394 500.7908 null] >> endobj -1928 0 obj << -/D [1923 0 R /XYZ 56.6929 366.7195 null] +2481 0 obj << +/D [2476 0 R /XYZ 85.0394 437.8079 null] >> endobj -1929 0 obj << -/D [1923 0 R /XYZ 56.6929 293.4426 null] +862 0 obj << +/D [2476 0 R /XYZ 85.0394 398.8908 null] >> endobj -658 0 obj << -/D [1923 0 R /XYZ 56.6929 247.3727 null] +1447 0 obj << +/D [2476 0 R /XYZ 85.0394 365.8909 null] >> endobj -1930 0 obj << -/D [1923 0 R /XYZ 56.6929 211.2315 null] +2482 0 obj << +/D [2476 0 R /XYZ 85.0394 330.3396 null] >> endobj -1931 0 obj << -/D [1923 0 R /XYZ 56.6929 172.539 null] +2483 0 obj << +/D [2476 0 R /XYZ 85.0394 264.4348 null] >> endobj -1932 0 obj << -/D [1923 0 R /XYZ 56.6929 96.3402 null] +2484 0 obj << +/D [2476 0 R /XYZ 85.0394 180.5065 null] >> endobj -1922 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F41 939 0 R /F21 714 0 R /F53 1029 0 R /F39 899 0 R >> +2475 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F55 1311 0 R /F39 1151 0 R /F41 1208 0 R /F53 1303 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1935 0 obj << -/Length 4190 +2487 0 obj << +/Length 2923 /Filter /FlateDecode >> stream -xÚÍËrã6òî¯ðm媃I€[µgf’x7qfÇÎ&[I´DY¬‘HHÙq¾~»Ñ ð!j4S¹¬}@³ F¿ÉKÿòÒ&‘ÐY|i²8J„L.Û qùï¾½Ügî;Íû½¾¾¿øêm.³(KUzy¿êe#a­¼¼_þ:»~÷îíí››_®æ*³¯£«y"Äì‡ëÛŸ®¿'Ü»«LÍ®¿}{‡©ÂN -»¥böÝw÷W¿ßÿóâí} ¦O±Iùxñëïâr „ÿóBD:³Éå3<ˆHf™ºÜ^ĉŽ’XkÙ\Ü]ü; Ø{ë>â@¢m”Xe&X ä¥”Q–$jÀƒ$‹R­´ãÁ›·w¯ßß¼»¿ùñWã¾éØ&.çÊDJã:¯ë¦å^ª×KÉHÇ:cŸ²¹šÃJf95M¹Ým -„íìЖ›²}¡«zOÀ®Ø¼-«Gz~s{GÀ¦®?v ð[ezvÓÒ ~ü -¾É7íÐK‚ÚšÚE]={þ¨Ê·E3|óŽé\.÷WÒΊ¦.°8X2­gxËÊ+_¥vöT. -†Š}“u:Õ³Ÿ×EEت¦6w£>¶EÕ6„»v×–uÕôû¹!Íì±|*ªWÒ‰8‰™É§6BÁ'~'vû2LSÓ¬kd‰Ûm¾¡yë!KßQÃ[X2ñàÒHå9BÚ³)«‚´d¼TD9vÀkˆÚD…KfQlX¸p¦Ö IO¸”³v]°¬·y‰œ—’à×yKPø ¦>Üe %áÃΉ˜q"†ˆE^ošÑw¹Ÿ¶m‹å|Y,JBÂݼ{Š©sO¤è•ÛøîëE½©«9ó––7µe±)·e‹ôi™âÀ)BIàW€Ñz†kÇ7Ïër±¦î‹¼)&$HÅ*;+@‰TžÛÏåfCc>¼Ð4Ëb•6-!Yqé!§DjFAxRb‚Ê#@û3ZÑ”ˆ€€ÄQ˃šbSLЯ³HJ#{Ò¢ІLR†e÷Ëa{RKÏDèê?-Jµ=áœÐ!’ ¡š_¡1qcöwÞuXü–Á¯óvbÏt&;9³góXƒ·1©ª'¨úaÃJøñP8M°¬š¶È½r®¨%uÀÓä^îû8ÖëMÙ8¹¤¡ˆšx`¨t ŽŒhþªh_틦Þå'ŽGµgGÛ:_å7AP -V„%ÍŸÎRÔ' ˜Î¼ù€‹…U‘ÔRQeÙÄø <õÛüƒ7ÚG¢¤áeÇ}®oÿ{%Á ùM1Ó8³C»M®OK}‚q -; á 3ãõ3@ÌŒGÌÀ!B‹þ}Ê/§…Òê¬U‹m,GVMÏr0âÛ]ËÄ×تٲlv›ü¥[‘î~¼&€Ô{Q»vÉÔ±aÓ³?몘0c -"îypÊÓX‹ñkY¹ê-“êifƒÖ Ö>´Œ^?µŠgù¡w_¶y Q¡¼õI:­F4Ñf€p%邹_ó×88}Mf­/ŽGÖÝÅoB¨Ê伈›…?ÂHû™Š CsÆ.=D,¡«úàÕeå V°f´?ØçØ‘,øŽùbZNUœÅTKgU÷Wá.0Қ̾!…CLNÞ"€šw%g/ôä8 -íb“7Í”IÜnš¼×m(CYdm°…¸‰‚å–L•‹lpš‡‚ZŠ›û‡ ¸ïŠ¦¬—LàÞƒId¥ƒ¯×yÝToQç@v‡õÁ‹¢ ŽA4ÄE÷~ãB˜1ÌÛæ›[jÑßTm±‡™Ñš6›ìÓœ +öuㆇ8àÐî-Á4$DÞEUìsömEu"„‚ð"I‚ˆœ6¼™²ÁÚPb˜SÖQG)ø /uËiW‘ÈÔKÝ~JraJ¤gü "üMÇ…ˆöš7h~®™e!e‡žšžŸd/¡Àà‹4åO0$º™ØÌÖ9Z#[BÇÀíÈØ=•K·€!mÆNùâÃsÌ-¾ƒädFí²IrPs- § W<•õ¡¡QÐ6• m°†W„™ÞÄà­R}f?b"œÀJ˜·y.ÛÅš–Ë©Øm¦6‚Pæ(È8<>v‘Ä>_½ä阴̀¤„þ3‚Š¢Ê6>X{ê@°ð~I YcbÍPk¾w¶^Alº­—ANR mŠM± UQNU\{"ç ºíSŠùfšl%Óa,ävÔ›.GÒf*J!øÍâ³:™*ëy7§ÆynZÇ>¯š•‹‚•—CßáØ.KT`%Ò3®]G™qg–ÝÚ®2°„<ùt›¦éPRÈŸZ2¹ÔždM³3f„ž·w(å`ÁßÝ¿' E•zœœâ(¢A$ZÖ믮áìªCÞ¬¨ý{(WÇ'ùõ”&F•ž ËUò㜤ȅm¤OÖF)VÃèeÛ±-Ù„+8á÷a¸¤S¬rŠPØ?-ÆÑ:V–š]±(1Ê õ%¨à«A.Œ.hÑ:|ªCav˜a%ŠFç$ŽK\„t»ŒÀÍ»4º¹½§_ q5-þ¼‹¿8~«ÍPºJN;ÞóZZP¦O¹bï}6qð)¹~OÕÒ/༑ȂZÎo§C.m’£˜+Ö˜ˆaTûxPÕaûàRj@º€ -p˺ëæ‚[À‘ r8ô >ð >­EðI‡<ãt¯CŠ©q¼–§ªéù§†t¸G[¾¤wùdʇÖEÞ™ô\Ÿ -"¯@îÇ.Äï ð|ðw>sÛ(Ž™êâØáÐíp} -*b‚ ¤ •EÜp“y~b`wC©è‹óüWdu…)%5劦tEÔ ¢¸h¦IˆÆ†ì`Š•eGe}иàæÓ³[*ãKg·´*žÉÜ[–„º Ä “GcÇGZ†/ ½á4 1U7 Ù]73oÊ’¥‚¶)hŽzïç£)|¶7J†HקK2ã‚ŽŸcXÔ uS„K6¸¼€“¥Ð‹G±´ƒÉp¬Žíh€B¾ÂôdO¤ÅjöÓ¬°ÅÞ7´û²hÁz¦\~Í5šSx¤ŒR;p^ë¼z$}S,ˆžŽ^T¿ì*9ïOX¨ä(z96!ÚDR…œMÕd S¥!}(«e¹ÁçÅ®ëgfb&¡Û8ûßæÕ –´åv2Z‚ðÖZ«ÏÖK”Õé ^‚ƒïw…·*9¡} §e‹ƒf·`Å­jF= @Èóìíèe¬-ûü®oÓ¼=Ç®:ˆ`@„·v’‡ºYM’ pßÈ‘Å8½ ÷´_GF­¨ŠÇ¼Ó¯JÒRêW#Õ Ä÷JkCâÁÌ;Zï`¥×¦g 3·u5gÍ=@vóÄþëãá -Ó]Ví5À;R²ä®O%+͉Ø=K#c¬íùþ„ô‡î‰µ³;_(¥ J&§sá œ0OŒo½xÿ†¿AÔM˜Þ"}N¥ i‘qzä›2øS%$¡„˜= F”³zÂï“A|¤€‰Ä‚|cÏ\u’/—®¸s¥Ø'10i(ÊÃdÛ"¤äL%üY BI^„À¸(ŸÈ/ƒ2º4æ;t\÷†4® -.>ÖWl6O“ù,SÅ:þœ|§3üóØÊS1 ‰„ 锌‰®zh¥wÊÐ¥ ]|þ¼4†@¦W#ÇA·å¶\0OœPðP@ÌX:W#è¸ÔñùIUPazSX(ƒ)KF"êj &Cù å0x”}¬È€Æ%-†Gh+fÅ;ôÔþ[G4´hþ4²Í°W»v5€£Ñ94¶½ê*¢ÍÁ±BZuƒÌuŸoFYAMGfÎ’w§H“ÉÁ×/¤'l§êüƒêLÉó~+ uþCC"¦à.ÆÓðìG,s¥4>%¥x¤£UWºŸÎf­•c1ŨváÀ’} ¥N€ÈÙF¼f!”ªpƒk¦ÔÑL!·Íb5ܧ÷$þ`Ka,“2œé™˜ô0£©°? ä“Z [9ÜÍ -úÜ{°Ÿtˆžø„óv|ObññP1ÂCøöèZ¸Ø[_U9*÷wE®ó^ÿòÍûîÄÎÏS4mó%©>ì¢ )Ú<žÞÅ4‘GÕ=C‘¦«aOÚIžP‘†é¾¬I"¯•ñù4 ø.éÎçéx²«÷.—1ê’*T(ˆÍÓÿã5¦>ºQx]*ìPõ+ÿ’­NbŽÛ -«Ò£3XË $´t<¢,YPÄ:L¾O*â^vÅTô/M ê îŒuò²‹±ÒW;èŠåŒÑb2ùBÔø -ÙcUþIñw´çföúöú‡·¯UA²$‹@d4Š†ï~¼vÕìîæ[†þõ–N€Ý£œ¡òÈþОˆÄß}²ŠÒvh)Ê&[®J¦«˜Mžè‚h@öaÓ³R&MìÍñÈl¹YÜ>54uÎôå;>hØíKHª˜™ŽâTeÓÒg o)¤\Š<•±§‚aÙ¦CG¬ï5Ô2yÀ9–b ¯è•÷Ã/ÔŽê<ꃫêBW1§ -ì`WAŠõÉóõ82ÒþÀ˜Ï9Ì7ÏÜÌÞ¶óMŒŒ® N“:å“ÄÔgÚ_ó€Íu2±@0°_¹šT‡ÉÙ’›ê’o:æ¤ËHÐŒoi!Ž,«ë4¸«Tz²ézVÿ–N{ÖJf†Nb‡÷ûW³¦nòD&3çMg,Âù²×/‹op…}ŽRcpõ7+z›@ -‰PÍ}n@© rüƒva¢ ±}qM›ï9îîþ@™3}]}9O!£…ìX"B¾gøzPТZ†C1ÿ8ú|ãOù7›úyü]Wï -DrÐYúûé8ÆEôȵî9'ÝȇH¥ã$5öäq2U*tìJ, ÕÔ>çÎh¾P@N WNœq‚Gbˆ¦š³CÔUK–iC'vbÂ×<Ítþ”¨È¤q8`ûùÄ9‹íÎY&ñUfÂ0ϧ†!»³{i' k’fŸAÛ‘ÖñÉ¿T‚“L?óVÜHi‹ðæäÊŸ¤‹t˜™„Ã{ì=mtÀNr§”¯rŠ—$Ùtõ)Ñ’u×*?gT2ez¶aóäjkA3;ê•Pݺ\©ú‰ÌÃ4¿¦kn ÿÉgêù.—Ö'ë¡I¤cm?%%˜EE‰µ£"]x•r(`Nß겑LSs>ÛSbxW/V¨6+*gS8`¼jÚÔG¸UáúäôÜé*ß,ˆeÆZXë¡E„ã¡Óv;ÐþÆSi8¤KÝÆ8Ù‰ⵑ¸ú”ú“EE@zp~ü„q\ó5 -¾NQü­ñ—ÿ(·‡-_às¤þ*o‡Q¶ýô`“«¶»€qâ§ÏÍôÔDømÂ_þ™D÷+Ø­ê~1¨êŠ8‚pFz¢ÃR˜1éáÇ´ÿ2< -Æendstream -endobj -1934 0 obj << +xÚµZÝsÛ6÷_¡™{°<±@ðcú”Önê¶N|'wînÚ>Ð$qB‘ªHÙqþúÛÅ. R¢ä¤7—<\,‹Ý÷´…ð_ŒtÄ™ÌFI:z4[_„£%̽»Ì3qL“.×wßü ’Qd±ŒG‹Ž¬4ÓTŒæ¿¿ ’à +$„ãë÷ÓéÍ÷“éÍÃÃíÝÍÕDd©ã·÷÷7ï¯oÿ}5‘:nà ÃñÝÛ÷¿¾ý…h÷W°½»™^ýñðÓÅ̓׫«»*õçÅo„£9᧋0PYªGÏð"Ëäh}ièH)G)/¦ÿð;³vé -DHËcH1"È´–=kè,ˆ•TÖîn?¼?>‰!âQ"E #-NìLL“.—ÛxÀ Ž ÷,·ŒU¦:=¿¥cØRv¶ŒÓ Ñßò‡z{%ÒñÌ€³tœWø›Œw›yÞ2­^æ๜Oõv·ôüѼÃsÑ®ˆTÕDY›6A9QCiÊyèŽÿu¥õ–Ô;Ô®Š†ÖÕ›¶¨«7h»©$ +"&prT^5™MÓ¶ÅÚ0÷Ð °tªFïuX÷\”åÕD©h¼È ;Òãç•©ˆ–·­Yƒ +Õ’fÚšèÎ*HˉTše>{!B1¶o’=_4.®Ä­bÅØóá*w¾‰Ò1Í~½vÚéñ£!Šu’™Ñè0§é¢Â#ƒ-øpäS+P&ñ¸2Ï8Ðcrì'S9~´ö†iöW¢÷+êm±,ª¼$2yÈìC ‘m^TfçTi2~p‹ý²!6¯)Ó‹04G§CÚ#SÀ}D@CÛߕ錼¶!©©Z +:èôàÔkk€J’œK;L§_RÇdßÑŸ eZwD$9L[3këíË¡bBFA¨CyV3Ït¬Z×BfA¨ ¬uu›š¶aÃXŸÀ”!èX…,©¨è÷yUÌVìäqà»Z––“ æ­é—}QÌÏx@‚]’(zÅ®3>p\Ö «£@a–¼²¥cزkÛDa’ly³.t»&_²-Ö¦Ù?äÕœæSÑž´‰ÎdQ8=o“.×i›x.k“§!`Š@EIÄÈ,Í“)Ë’ ƒ°p^1Ç4 X•¡ ²0Ó}͆`iwË¥ °øh;m2áIœ½’o»\gL測Én†M–fZ±ÉLZš£79„—N«ô¼jžk@·¾Õ2ÈiZô•ûµ1X}q~—Åf(¤}ؘj:ý…HÇS'd•ã™ÕëMQbªÀ' +ö(æþç蓼ÈÍn³©·-=-qÌÍ"ß•è4»MÔÍÇY#Ä·60C”RvëÅgï^ÌžHª|mzÃÁ½O. TüëŽã’§Z›@pÌÂ8´žBUQ؃Bõöý;ZÜ)ݬ ¹DÆ`gRõÒ‘ËU¶°I"ŸŽÌ'—h´NÙ˜¹O”.£ÒäàßÝÝõ5Í@AÕ£þøãÝÝtÐäí‚&½ +­ËÝšrZ‚)Žß ¥¿}¾æd|ù÷K—¶™0¹´I^qa¦àCUk¶|¬–Nbx2çÓA¥ó ŸŽ–¿^œ½Ÿ†qƦaðIlëI²j]Z SÍ ×Å‚³ýn¶:¿o1xüE]–õ³Õ]@í€øP*V†¶L©)ÚV,f²OÖ×0yùr *$£ñ庶æ’j|ùìGs?Z¹‘=®^ŽÔÚ× ·áý’þ)›^Ð{¸#›WÁË^L¾e¥~‡|?7¨'UCù)«XÓ@F(›·ô0Ï_kbðò²‚ +ÎFU˜(M¾¡‘Ý ¶Ì·®«vÅBû»[’ß/<±]GÔ³1ÝöMßÁ|î\XÅòìƒÃ +ˆr¥/¤•Ì´ôÓuð›ƒÓs:gtJ!è!êÊ6&¸ß¶²Œv•Á»b!ûÆU¼Ûe0¼<™À¢0„VÙùÖå:À<—M`÷¯&0T÷›za-q˜ÅTÕHÎëç¹ìe1•Ø@÷äÔŸ9Ϥ™k€d[ƒl_ˆÂdN*Cá¹p«kú}d!›ÝcY4+ëÇδßäsmb$³ñÛD>7mC6+íWèÖð¦6·é$H¤Š†:Ftö£qà™•»ù!”<?Sd·{UÝö…í'È¥Ã^f—(O"KAï/³ø•Ò¨ËuYžË"ëí«mÎ9`A¡Ϫç¹ôë+ +ƒ,…¤ßS%÷ÏZ3²p„ÈRÐ}3²z\ÔecDqëkú}d†CöØ Òˆ„ €Ü^ T Hæþd¤àÝHчÔÈw%2„Â'U¯ ¤Ãu%ŽË¢äŸÃ( C!¿&:ˆ¢DŸ×Ïs (x“H¦i_C†IÊvÅÃ$¥„¿&].rfJ™ÃÎÔäîGf ŒõT´@I ’8 ¤.Ò¸Ý(‘G²…Jî’)”ñ} @†Sùré|Ÿ7Ýœé4ÀÌu{h¾:Xy¬Ëø‹è“Iè4ÔçÑ×å:>ÏeÑw;€¾,ˆS ød d–WÏs è×O~I‹ì+ÈàS.FÀÀ] 2ø€âÀ×åâ›@AàÙš=2ò|¹ƒî×Zyâ(s ƒ¼©½lÚÂ]6ŠqÓú¡‡£´uÏWÆ­7™¯ø¿e@HÔ­å+×|]®3èr\]×C± ¿a$_–Á#Ñyõ<×€~ýÐ&`Kú +rmEÍ ¸¶Â–-'¥¯­º\T]Á pëkúµ®€EsSÊ*¾€²"lÅ;ÙV(Ë^†QŒ˺Zš­Ï…Þvô0õqŠcö-.Þ­ó—nH\çná‘ÁIœ›º)ìÍ(¶ Ú4™O ,´é6:§'2(´ã蕪¾ËuyžË"oújU¿Ùš¹™™¦ÁÖ4}ñÚà ä æ=«§cг‡@,½”R}E§€“™uADÝ‘ûdÏ Û4c1䮙ݭ ˜ ë#¾Œ 'ö Ñœ×q¨à{Í×ðl>mÊbVðÆÍnƆ@‡6 d{àï“T±Â¸n;WRèë:Ýr s»ZÛçBÎg?ea Z¿lPXÓCìξ Ù»‰t8¬wMK Í'ÇPW–/ô¼Î[k+«nXÚ‘x–äÌ4ÔD{£a·óÇJWÅÚï/*t¡gpü¥TS{ Z:epf)0 ÅöÂH°ùh/C‹ö²Ù&C'ò¶doŠˆ?0Aò²]ßÌ}TÒ.›~=Z£EðG%˜¢t"úDÏ4Èà¤{'Ñp³²{KºQ{ÊË7C76o+ûËÔnn³W+ö6á¥9™Û”ÒûãW"L‡ëL„q\6ƒ•“Úå6wº£ bbêYÝ<×€r½°"Ò –aÜ׎[ìîÖb=ì`ðjZ.Š9@Îé¹óAVé„._cû¹ßñ$t·x±»Ü„¥G[pÐ}ØÄôE“.*'Pý…Rˆ>øõ¨³”Q oò-}½µäúÍ™­49­ˆÝ§p ®é¶4Úß²†$rZGºE®FIN^­íã+î¾k{BúGz3IfŒuCuÙrÄt&ôaKš0ê¬ä×iôZÙ¾V„U(|l¤k^ühµÿ«}œì{†BÏ·èa×Ѓa|ã®±4–ÚÞOcaAaJp¸À펂4Žj‚ûBøí Ö°8èEDáO!¼q[2à?Ç_Áe?îe㯰ýÀà‡wÍÉæãOäÜÙqÃŽ‡‚S¯ƒm·lÉCÿIæþ[žý-EI ÒTÇ ™èÇN)<¬ˆÒã¸Éõs¬û³<)endstream +endobj +2486 0 obj << /Type /Page -/Contents 1935 0 R -/Resources 1933 0 R +/Contents 2487 0 R +/Resources 2485 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1912 0 R +/Parent 2457 0 R >> endobj -1936 0 obj << -/D [1934 0 R /XYZ 85.0394 794.5015 null] +2488 0 obj << +/D [2486 0 R /XYZ 56.6929 794.5015 null] >> endobj -1937 0 obj << -/D [1934 0 R /XYZ 85.0394 751.6872 null] +2489 0 obj << +/D [2486 0 R /XYZ 56.6929 751.9327 null] >> endobj -1933 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F53 1029 0 R /F41 939 0 R >> +2490 0 obj << +/D [2486 0 R /XYZ 56.6929 503.6095 null] +>> endobj +2485 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F55 1311 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1940 0 obj << -/Length 1972 +2493 0 obj << +/Length 2264 /Filter /FlateDecode >> stream -xÚ½XKsÛ8¾ëWè6RÕÁƒ £ËYÍdl¯¥líV&Z„$ÖP¤†¤œñüúmEJ°œ­Tmñ@ ÑìnôãCƒdŒá!c¡HR9Žeˆ8&|¼Þðx kGÄòŽ)ès½_Þݲx,‘Œh4^mz²ÂBñ*ý2yš‚<¹¹[.ç‚›åíãýo¿Îÿ3 H,°œÌæw7‹OÊ1ð7Æ“ßfwŸgŸ ía*édöq¾œ~]ý2š¯:ËúÖÌ´YŽ¾|Åã6ñË#&ƒ FDJ:ÞBÎs”|´ý³Ø[m?õzƒ`DYD=î Ôç.QÄ(kݱÚ)½‰w·!é±R†äkž 6,i„#N©°,å¡ÉÊb0.&Ês÷E_(lE -Ù/veÝ&&ûš)’,tb‹²ñ©ŽãØò4¥Q[«"µÀžÚÁŸGU½XZ9X““BýÕR‘ìU­ªgU™y¶1ï¤xq’O‹Õ”ˆ‰ªe‘Ö†ò-kvömë8 T"΄€A’sÚš¹œ?N9Ÿüëv‡“ÙÂfÒI\­~6¤o»l½3ì6ïÖè;S[B¹1öInÆus|H/óÖ|MyR»ä9++mjÍÅ`¦@àYz%ˆD$Š»|Øû‚¢0ä.pë¤p -ÍûX«Ôn¦´fªælw{µ/u¼ ²µäT=·Û¬Øšéï³dkŒ³~î°r2r‰Q©uY¥SG"âܲýì‘B¦fŒ)1±¸Ëç¤H=‚ÀqŒÇNRS%kŸ$H!œëPW:]úlÆ“ E„@¹Ã&C†Mõ.nîŒS–ŸîÛ[yäCŒ)‡6¸ØxªS@MaqQœC; $6#Ž)ÑéIbˆ±Òц\{:fycˆ¦,4Ñ ¤ß1ÇYѨªH4Z$yöw›°”–û$³Bt=+1+õñp(«F '™•nò ˜“õZ,Q‡ÀHËêCž¼Xqe˜Âd¢1 Í .gË‹pÆädŒ[P@?Œ‘ Ù[ž¢GD%‡C[Šå¡Ê€Ç£c]P˜Mmg»Ò£i+¦ªX—©Iz˜µuî1ÑŒžÔ¦4µnæ -õ§ŽÂ»m“ pFÒ"àdÝB[‘Ї£!8ðÓãÒ¾­Á2ÙÒ@Þ¡Ý!L7fÛ{+»-ô¨ÔƒÅ:#Û…—òøSj˜óìÕ7 ÞǪ0là »H•6Ï´É&e:xëE[û)`\Tjç1J­ÉI]cŒÁî û0-Tm8?"BÍâ˜:ѺÏzŠCD%—ãXád–ßÓ P}D -/tƒ¾Èö ?;½cDá„oýi}ÞN²Ú¬BžèRKݪu(FrhD¢ab:Mð;,¾ík<è- ¡o×àÝ)VMÅäXÔ~¸¤EaŒã!ÜÞ.>™žïÌágøúN5ëwU{î"¨ñOJ^Îçf³OËû·<ͶL‰†IÛ6h4H5QhboW!baät†qÁ¸ë„¡åÅÐÛ¦E]«uÖ›ªÜÿ¡^\åÀAÅ+=}ùøè@>M¬^×BX¾¶cƒåÇÛ†À".ÌÈ^ÆÛÅ ]1†K ôm 3¸7m³ge<¤ªÏ΀W‘ó¾ Ãå [–„ àòzíö¹Ìo_ív\í’œ«Œ U$×U:&Ê~FD0ŒÁ—•ŸÝyùY@Ì09¿`ÃÁjZa½˜oË -n1{wïäøħ6É1oήéew×µ—ß²Ù]ê,Òò¨ •7ÐÊAÏÂß@ëJWúj®©<àB¥7}•ƒÀÆÿ—¼ê ZÝ8"×ýÓczÝ=Ž©õŽÃu>¸ùÁi'ù ×mvœYF Í¤ZÇk¦uL—¶ ~ªÐé?3}Û–ekí¸>§Åüä4 öœÍL³®ž“üh‡åÆ úÐ Kúvxù/ñ¹û£SýdÍ)‹“žöíò†ºŽ`J,àjîÊ@ LŸîrx¾ ²Å~Ü• ôeXoÐ¥V»E›QIw%†É:q,Y×ã:k4ÑkÿoáˆÔ?]=‘Øþð¿ÝÓoì0FLêÏðÔŒ­QÚ'‹Ë‚°/mÿ/õÌ¡Hendstream -endobj -1939 0 obj << +xÚ¥ÛrÛ¸õÝ_¡7Ó3! € ¶OŽíõj»+»–2í4ñ-A7©);Ê×÷à*R‚"§ϘàÁá¹á\!2ÀðGœ!eñ ÍbÄ0aƒéò ^`ïÐ"…]¬“³Ë_¢t¡,¡É`2ïÐâsN“Ùçàêáávt3ü÷EH>¢‹aüq5útõ»†=\d4¸º»_„„§$$.ÑÜŒÆãÛëp<¼ýç~t{ñ4ùíìvâë +Op$¥úëìóÌ@‡ßÎ0Š2Îoð‚É2:XžÅ,B,Ž" )ÏÆgÿt;»êSŸ1XÄã4õXƒÒŽ5†uœ R–¡$¢‘²Æp~F4 Ú…‹4ø*¶R4ð,ŠêEƒÑìÚîé÷¼ÒïâÛª,.H0-Z h6Ó©hšzÝÿ.¯j`h€’#!$ø¯±’¤êÉ”31Ï7¥!¹Z_ˆÕæ¹,¦y[Ô•<0EHÊ£J¯¢jÅú5/õ‰J]ä3Âú9Ë·ÍßõR òV4Â`¶ý/¾ Å®FŽ ‰•+IE,x+Ú…\Å@¸VÏåws0Y#c,(æzG«ȹ"ý²YŠªÕ[Êæ°3¯Ë²~3 }Þjh]íh+€¡ÄÀÌŠÛŒé7ahœoÏã$8_Önùvn¤9Ÿ9Ø®à˜<¦<_&Üœ M kš°®¡¬Ìϥț>¨™ÅÓ;[‘¯CnYWí¾¼ ñÕ®åù˜å¢–tû*=I’[Õ¦ª95+1m‹WQjB}etôÿëBžD TÍAçúѵà Ò*J_ðúÒžŠ +ÏÐÓºš5Š?Ä 8kÎ!Q†“dÆq–eJª‡Çáh2Ýéïï&ÃûÑØ}¾ aP†¦(N}2³ª^!øX[,…Áï†|’¡˜f2SHôinÌ˦֫g£â¦±J´fgµ.ªvÏÀEå­~›ƒ·óåãÓœßPÑѱ¯ rt21 Rs‚!erz$ߤ°‹¥3ñä{‡%µ7û,!KÆq|‚¥Eò°ìZ8“f{,:¶ƒƒiúîñid‹XÕSc¦y½^æíQë°”"–2þcët±Ž[Ça)무Û0Ö­ñŒEÆm®/.¯./‡—7—yYî‹Hx‚˜¬M?”Ñay„ì©ŒÀnÆûRZƒÊÒ!<±^ÈhjpÇa‚u#ô†J²‰VïÉäyä Ù0Â4˜,L0Å]ûQˆ&ãÔ˜ÅZ®/~Œ(ÅÜ Ô+Už4»|«9=+Úƒ0JJ¤•{ùi—ù!nUæ—O•ùi†µ6XÖ:ó˜í¹~ê@Í°¡¢cà%$±n R­ŸE5“õÓ|ñ¶(”+†5ž$¼î€zß›ñ7ÀD§˜Z÷ñ˜‰#žÆanÊN J÷ËV*M‚©V976ˆ¬¶<¤Â–šþƒW€TFíNEϱê6`G9ÉžŠF©Í°W?Ï*—%ë]œ(¸ É ¡ÇŸç¤Í÷Z¿O/†XDl +z¸…1‰XFúÇ¥ùöËgOGÕ~I®ºýZû¸e’`ËýÆ«kœpÚÓµËs&Àç{üdhLdoXâd^ÓòÌ÷(Ù4ñÁJ_jˆ¨8Þ¥(šê¡èC<|«qý]B ežÇ„Ø6A§Áñí­–âê÷ñ½‡²¿=€Òû"ª/˜aÿˆQÄöÅKõÒKg[Ѳîy¤Ñ,³iíãpt£‰dFœôEÓ®ó֞ģ˜ëÎYTScÉ?òj“û BŽh’ØxõIMwÞøø˵¦³ñЋ ¢1#?4pÄc”f”÷û°«O“_ïO[v(;ÂJço›V,M•¿®+wÚb³Üñ 6ÔЉ„‰¾`®„ãƒÓ°k”BSAôáro‹'±@_“^Kh )™¾@Ò+=¿šÑÆíKl×صu]úL†û¦o«zÕ@3¼×$0ǘ6 $EQQ_73T¦3ÕÛ™. Õ)ľvÆayÕ—aø9ÌŸìjjÚ¨W´¡‰‹2ëÓºY_Cùç©MÀŽâÌC±â³b ƒI½Þzˆ²%Ôùª#z{’¨¨^ŠÊ—‹úhŽ¢xÅY¸›#ú%²uÏ“)×£ˆò´Ÿÿ?‡s'¡Œ¸„Ã×jÓ†ó¢ô1ƒ¾(eÑ/nµp«xXeÐVÅ.Wü¶ÿzÒRr˜ñT-¨¿Ìy‘#Wžöz™Õû²ðP„v2A”'{í¤]é¸Ã“â•:<5°øš/‚ÒèÀ¨ž$ûg!›TŸ@1êºEGqt’bSç0¯‹¼<.-Á%„Duí·1Ô¡ŒD}¯×ÅËÏßýIÁm|5qŠRÌŽnåVnµ>!¶YYç8àL¼‰ÌL?v«Æg&hP¡àõÌÔ´ùº=–`X†Rž}F““¦j[ŸoCIÈ 5í“kÝjãV¯'SH)^EùþzðÍ­¾»Utòš¼l½e7o:z¿z½“q$ ÓOSªónŽZýÀLWf%+¨ÊÑY!ôäm§ ›JäíG¯E¸¹_?ÕeÖûï²:Ð^§^ÑØ!‰h.åŸDJ\Ùå3 [ ‚¾Wª/ âH÷>°>¯Aãá†évuª'뙥­#sí\Ï6SÑg+†Ú+LÙzê€z®ë¤•Û3Õf<ø $$PÂÇ,Q·2†ä=âf]´°·5€6o7þNÏü™št^Ì «¹t©·'&Mç—ÉûN†ÛEÞjx¡®ª ÞBßÏKœÖÊ3]åÌH  ÍÍM„ç²U)`ï)˜¹½€gU·rÔèߧθ*Ìö +QÝ}t'1sñßì& +K/îçöâÑw…#ºË3àÑòZÈ3¢q±Äæ=yÍT +wOgîîr{ugÍbZjtìG!H\ò—OË‹],ýß?í~ƒúqNý×l†™$‚ÙÝ%Õ„6x_t÷ÓÒ¡ìÿ§ìÕÅendstream +endobj +2492 0 obj << /Type /Page -/Contents 1940 0 R -/Resources 1938 0 R +/Contents 2493 0 R +/Resources 2491 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1912 0 R +/Parent 2457 0 R >> endobj -1941 0 obj << -/D [1939 0 R /XYZ 56.6929 794.5015 null] ->> endobj -1942 0 obj << -/D [1939 0 R /XYZ 56.6929 684.0716 null] +2494 0 obj << +/D [2492 0 R /XYZ 85.0394 794.5015 null] >> endobj -1943 0 obj << -/D [1939 0 R /XYZ 56.6929 572.8605 null] +2495 0 obj << +/D [2492 0 R /XYZ 85.0394 655.2256 null] >> endobj -1944 0 obj << -/D [1939 0 R /XYZ 56.6929 509.4701 null] +2496 0 obj << +/D [2492 0 R /XYZ 85.0394 487.8207 null] >> endobj -662 0 obj << -/D [1939 0 R /XYZ 56.6929 470.2699 null] +2497 0 obj << +/D [2492 0 R /XYZ 85.0394 419.4946 null] >> endobj -1945 0 obj << -/D [1939 0 R /XYZ 56.6929 433.5878 null] +866 0 obj << +/D [2492 0 R /XYZ 85.0394 376.8649 null] >> endobj -1946 0 obj << -/D [1939 0 R /XYZ 56.6929 401.47 null] +2498 0 obj << +/D [2492 0 R /XYZ 85.0394 338.6766 null] >> endobj -1947 0 obj << -/D [1939 0 R /XYZ 56.6929 335.1577 null] +2499 0 obj << +/D [2492 0 R /XYZ 85.0394 305.0527 null] >> endobj -1948 0 obj << -/D [1939 0 R /XYZ 56.6929 244.1508 null] +2500 0 obj << +/D [2492 0 R /XYZ 85.0394 233.8048 null] >> endobj -1949 0 obj << -/D [1939 0 R /XYZ 56.6929 168.8052 null] +2501 0 obj << +/D [2492 0 R /XYZ 85.0394 108.6677 null] >> endobj -1938 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F41 939 0 R /F21 714 0 R /F39 899 0 R /F53 1029 0 R /F55 1037 0 R >> +2491 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F55 1311 0 R /F41 1208 0 R /F39 1151 0 R /F53 1303 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1952 0 obj << -/Length 1659 +2504 0 obj << +/Length 3157 /Filter /FlateDecode >> stream -xÚ¥X[wÚ8~çWð'±ª»å¾™„´i“4èžîiûà`A}jì,†¤Ù_¿#KœÐ=›óRµÏª}“E¡Âôu“^¨ÃdÓQˆBIdÛäGý\éõ0`„ –eªßÎÄ +죇<™i»,çöZûÌ,~ê!<ØæîI‘,õ),i´“JVC¢‹ÍRµ:Ȫ=EP$v‘–ËÄZ¦µ®¶áÄ›Ý!¶Æë@Aâ ¢8Ô8$Y$„-Þ‹2Ï˧m\ˇuV.øË䧋~¥‹Ê-Ë"¶+ÄæHæ7€^L -)˜¥¯çDCèå”ðBuF̺ª#Ê€ÃlÍò¤ª«H ÃE¯ÂÚ -âj×6AZÀ&z–÷ëýRª£iX½ü†Nõ<Ùäkç\÷âò^‘S{³©ô|“¿gÀ'Àñ0ŽB*Ø‘˜4¤^ Š—ª£’vs›Š„ç¶4[éÙº\=DF`9¿ -Î u€kEFÎÚè®Êò'”–ƒy¹²@yóH(1‚B±@7k±–r¦PD€%¬˜­´Êê…ªeÀBDŠ®óïi).C'™8¥–`[ e¸í„AÍ) ‹¢´¯R+ùôCvU”ë-´¶¶Ýùú% 艞#l*os¨ýöÍä9Š°„&Ã"$”%Ìñ—øúöjÜq, $lpsÃÔL¥IS2¸ßdyj–Ô§1LÞÇp•öéùÄ>¼»³÷óúœåÒ>5{¬ÃU3úR!…¡bÇä¿’å°á¬\¢ŒÙ ¶Ç@!ª(RQ´ËOâƘ#ñV€Ó¤Q2 õ(à -Áà"ö<š©­Ï§r“»å½ö¥_mtú¶ã@à@A[j«S¨¨*= Òj¾*—rH¼j¯¿Ü­Ziãây6v}Xe…£—ª\jàÿíXýÔ¯·šÈ`$¤ØðœEmâl®k½°˜Œãó8ŒC>Rçx+R9Âg”†q¬D)À«»h·uB¶q¸»+°# ›št L½ŽcÃúÓã¥ocÔ ^Y÷¯C%nöYdN"qñ¤”·bZúø•›"5oÂGíTdó=ï·ìþʪu…ŽÅd<¶;â«É§ã§ìÎÞÓVj¦ø§,tãu­FFÊ…0óF‘/šÑå͹U98é2+à PAÞywz®í´PÌÜ1¯“b“ä]Z)Ý¥Gñ‰qwqf52)TwQ.ÈVÇŽŽªëÎJ<‰IÔNËøóôý§»ãqº,ÖzUx²˜º6äÊøØähB0¥ EÃìÿµ¹™Rendstream -endobj -1951 0 obj << +xÚ­Z[wÛ6~÷¯Ð9û"ŸV(n$öÉMÜ4Mâd+·ÝnÛZ¤mžH¤*RqÝ_¿3€"$JÊž]û 0ƒ™o.˜pø“$e©•v’YÍ.’ÉbuÁ'0öêBxšY š ©¾½½øê;•M,³©L'·÷ƒ¹ ãƈÉmñÛô[fØ%ÌÀ§/oæóë³ùëW7ÿ~s}9&ÙôêÇ뛗¯ÿu9“ r æ|úîê槫·Ô÷áÒÊéÕ«ëùå·?\\ßöŒ ™\!W^üöŸ°‡.8SÖ$“'xáLX+'« (–h¥BÏòb~ñÏ~ÂÁ¨ûtT‚3©R9" )&B0›$2GbYª¤râxÿáöõû›Ã– ‘N2)X*„9²2͆Taá‘cT¸î,ß_2ÕÌZ=¹d YR–L¡™)/ùó¥bZnªûg:Ç|¹¤ÆCY—›¼+ zm«‡:ﶛKa¦eËŽÉ&µdk²Ó²R—MOåd³À%¿ú.I”î”ál¹#Y,ó¶Ýg̦Ì©O3ˆF“Ñr° æq6_—‹êwÎeÙ’¨ºÇ’`LÔ Î\³¹ß#ú»©ËãâLAÉyrNœªâ TNœ/T-c’+}zÉ@4²äPP™dÂh/ù¢Y­ó®º«–UʦR1]5Eù5`‰ÓW^Ýh §ÃÖÃ} m•„ÓþX>·e7óZ¡„Z0£•ðt(ß:_•D± Ô" „x„K¿~U{>Š¢êªÆ½Á™5#lÉŒµÖOR´G˜R 3iÏüg3õôXÖH4™i®@ç,Ⱦ‡/G³¬êo»;ú’š÷͆ÛÖ«Û·ófY”~ìS¹ia;%¦"Ù[Á„«¢†m.f¸8.6²‹LƒÒ³D\¿EtYrF¿T'ô;P9ý.ÆàéøMT›rÑ5›ç}æ„”LÁa殧a/ ™1•f&æïmÓ|ÜÑ¡Vip}Ù˜REs+ÃT^ŽÈF'Â=§‰3šh*­™RmC[ðQÕ#ó*p"|§CYî+´Ð4òœ*œ2®µ>­ +CªãªÐS9U¸>« +eýP‘GzÀ5ƒ`Ãœf­§á-v–i†1÷Së¤ NWØébó¼œq]¹s·Å=K¢ø'üýº¬çó·DFÜC· w2z $=»Ií´Y#Îz{‡±ª£g»]¯›M×"rÈd7IU·]^/JB!PfƒìAHÄ ¤¸˜>UÝ#µÖ›ê!:¼ æQëÞm¦YÑ[N€“mؤ'÷ U®bNªé/ˆndþ¤Zb|/ûáÍ‹ù?„ÀvE#•¥³8¿Kïóí² >¼¡çúã¢â›=Ÿ]®ÖÇQ‡â®åC£2Lá;˜ªöO:®ãv $Ó—Ÿ6ƒÑ +ðDÎü}Q´=½^ 9\/ÂzÎÅãõîܘéË9=ID :ÑõÁd¤i8ºx¬–5Ñ«´ÔìÕeÛ¬bi"³³0iY&­9 “ +"I+ÎÃdÂ2ž%L‚ffRO¯ÿªÚŽÌvubË”£llÝ»2‚É”ï}¼j>•ÅQ}ÑÆ2“É3ÙÈê¸ÆôTNeÞŒá&ä^‰=ïA5”’§™ë©F¸‹=¨eÃüˆ½7ˆ’[/¤uÓVÈ +„“ÒX +Êï=EN`—ñ캜mr¿’ vñHý„~Р|˜Ú¨pÖÒ¦Ó×÷ÔU75Ú> (@!e.J'½eþÂÆÇ¡ÇÀ@b±öسŒ©Úq=€%dªÓ3z0 :¡ÊéÁdzþÑz-“²æ>É•§ajxüz‚’¨˜©ÛK7GT—bxÔA>yëŸQ¿ø­!5t6›¾;¯Ÿ÷Æa •? &$RMo+?{³ö™´W¹_â®+ÂQË„ñ4±ñYØþ.8(ìù£:¡R ‘%„Ú'ubHu\'z*§íÙâ ‰›n†:{è Rð™\f¯§á/R L<Ìp³} †à>.4 +R®üIâXµòƒ.³Ò«¨äý?þ8ýŠš^;ï cå?ý”/«Â9‡ÄCR,ò:’*$œqƒ7T…BW—‹KT9ÿ¼k›åÖ±ÁxãG‰%„ïŸJêÁý0Šj¯j"~ªé\v´ÔrüI4’¢º„HÚïz\y@’mÁ£Þ®îk•ŸÿWø{÷îå^Míå÷ß¿{7ÇÐ< 8G—h|ƒ#¦’ÊBë„s$Q–@ä"= úk|†~ºÎ^PÛÁ*P¼s° +Šwàg•ÒnZÄb!§WDK ÉI#!‰ñ"1N$½<Œ—‡™~qãò" jS¹ aðÉ = …iêÂ÷í’|# ƒFìàq$œŸ¢˜ºêf4݆PœÛQcÛ¯ó:»H=i`2 +Pœ.ª,ƒX.K÷$r4ñ²‚Öªª·>Éôxl¶¾˜„8°-_.›§½BÔbÙ,|å£ýX>y°Åt©í+Uǃ]i þÌô™zÑê8ÂõTáÊq„Ë Êé‹Å8¾ÁÑÀù‰ÓÌõT#ÜÅÁ.ÀªÑ:f¯Ç7a½_Àᶾ¹1wHØ"|‹èø†¯ß„å‡ø†å_ëªÏ½%t\ù—k訂t ´ÏPÒR²¬O$¼FjH !ÎP±F:HüàZ"{m^qDd¹@PùÏ<\õÈ„}™ÐòD‚¸½»)÷p—k<Í£' ¸XCǘÕcVùJ¨`—롺nèu*Ð7ÜtVlï´ænS¶}Û;KÃN AÛCªfoÎØúÃ<#ê¢_-‡›Tº/ÇÀ@Ý<}q臣£'´ÂØŒ˜Ûa‰R2@8œtÚˆ+6ôN)ƨ’Át_¢bZ¥„4ÊŠÃÛ£²8z±Êa¹JU»Í’¿ÇÍ¢dŽjŽ€ˆD[y¦21¤:®9=•ÓœÇƒ¢fʸÍÎ,ˆF–ŒÊš‚qpÿñ’6U +¼þº­}l6^ívµÊ7ÏGÒ8*„k±N…§‡íª¬ÅçÃ+8©- Þ®Øùÿº‚ÄÊ({&¤R8@åN§:WHQ–Èœ#*$”U§yë©F˜‹ŒZ–JžÆÜýÒ‡G9=Öäï>UͶ]>Ï‚}â°kU>ZçmFsßçŒ:—ãñ”+ +aã®F]´’±ÐøGl¯¾¥Ö#rÛÛìL™”Y½»¡!Cµ©8h÷³“çÅ2¤Ca ÷–{ÊÜOª÷LTlÙËvðÚ à¬¤öhÂC-̪:Ê0`tq²¡œæ ¹¸Ü¯¨^»Àù6à¸ïÉ_šÀA#lÖˆ~³xxÆ߈Xš "Œ»cÒ«½ÇŒý©jË#ŸÀnÚ +/Øñ˯ÜÐóί긤»{xk›¦þ’j×y]ŒFZdèò`ø +ø2_øÔÉ}jð¶Ùî<˜€°®w)ÂÊ ìß·{k‰À«½šþ¹…ø%ˆ/ˆk8Úõ“V¤~»xWèúïÊî©$+PG?$¢®’²Ò˜>¤Åæ® º/¹+æ»÷T}«}!åÐ~’„Y#ôg^ZksæBÝZó¹™xXswƒ ïçâ{hš™þ/~k‘1%Upø!ÉkýZÑï¶Bõ3ïŽýLO% [7¸¼ÿÝÜÿü¾Ý5ðnŽÕúd熞×3…Û ?ôdþÇ~‡¼ÿŸD$endstream +endobj +2503 0 obj << /Type /Page -/Contents 1952 0 R -/Resources 1950 0 R +/Contents 2504 0 R +/Resources 2502 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1961 0 R +/Parent 2507 0 R >> endobj -1953 0 obj << -/D [1951 0 R /XYZ 85.0394 794.5015 null] ->> endobj -1954 0 obj << -/D [1951 0 R /XYZ 85.0394 575.4191 null] +2505 0 obj << +/D [2503 0 R /XYZ 56.6929 794.5015 null] >> endobj -1955 0 obj << -/D [1951 0 R /XYZ 85.0394 427.1073 null] +2506 0 obj << +/D [2503 0 R /XYZ 56.6929 752.0497 null] >> endobj -1956 0 obj << -/D [1951 0 R /XYZ 85.0394 329.3834 null] +2502 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F55 1311 0 R /F41 1208 0 R /F53 1303 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1957 0 obj << -/D [1951 0 R /XYZ 85.0394 262.8864 null] +2510 0 obj << +/Length 3243 +/Filter /FlateDecode +>> +stream +xÚ¥ÙrÛHîÝ_¡·¥«FLŸ<ö-wef×ÉÆNíÖÎÌ-R6'©©8š¯_ æ!‘r¥¶üàÝ@h\M¹ð'‰ …NÍ"NMh…´‹ÕöJ,`îý•dœ¥GZ±^Ý]½x§ãE¦‘ŠwëÁ^I(’D.îò_ƒ—Ÿ>½½yóá?×KeEð*¼^Z!‚¾¼ùòòûtªàåû··×K™Ä2¤Ñ"¼¹¹½}ûzyûáýÍ?Þ¼½þýîç«·wcCæ¥ÐÈÕŸW¿þ.9œáç+ê4±‹'ø!B™¦j±½2V‡Öhí!›«Û«ufÝÒ)aX„6Qñ„4”HC +›hÛ4Œ´ÒNÙþZ&A×qð-Û”9£`]ï ¦òìØüC#‚§²}$`F8«ãjS¤¬ÚbûÐD½&hZà. J-¢àî±`ÚÒQÃ!(yYViYñ½lÚ²z ðçÏ š e+Zž7ôg倄–R†©µÊ7?¤ã¶¦ÿÅ÷]Ù‰~—ýßMØÃè0ð²p³Å‘FOõa“Óðž7£w›lUäá™­ˆPX°ÉXF¡Õ*6tFZ±HµrÊÐ=žuùI¾xgíTŸh ›#FYíí„¿ÍÚSöd…`}éeþ:¬ G¶ËÐhPˆC0°ifÆÆÙ ÂZ?鸤¹¿êŠ¿ ¡6…»¼&øT7My¿)‰6ko` '2S& +ãH(–ÅoJ™¶øÞâÆ@àR+=²°"/ÖÙaÓÂP2©*Ÿ Ip=Ú ¨ì³§9"q(eâ9r³X…ÒDrlÈw%Úgjƒz×–uEcÛíËm¶/7GÃ¥¬ò"§_ÎôÓˆ¬~?C—ù±Ê¶åŠ~4åCå1PL£©y»GÔxÇü°ÝÑŠˆT6º‰’Eˆ +ÄûÓ¥3äNàgUWKTýò¶ãU]µYY‘'€‡]žµŽ!œt÷÷¼mÇ8`æ|ËW-EJ8/”’ "2HÎgÁŠ–$Œ/açµ'WÕ픇Ùf_ùöo«G5EÕ0D eЪ\lhËÿ›ÚãAXi|l &Ú†~»ô7kë}ÃûT9/‡”¶Ø3Öý‘'R³3¬²ÕãäÍqòu'wRÕþ:ÂF.éȆR–'1T‡í=ц9›èüÃòºú[Kà±ö4¹(øO.œÙˆ$°µ[Qoy‰s…vGhºõÃm!N\Ÿöö¹3Ä뇢éÝçÒtZïza0>ÆÇ¢ÈÇ©:±J÷a•Ž¶nÚͱËÇÙøø¨›šŠ«r.c“g²ï!Ö|\í°\\­&â*H îœf·P­vp¥Nã*¤{‰ô‹œuX¬ã*P'¬ÝŽ\ñ©¶1llty¸›ôvÞ’ó5Æ嘧&xu¤N‰Ñ¹Gp*޵ߖL¶i³=ykc(1Bh‘¡~q”-äkEÎÁNb“±Å½þôeV³&1¡¶itY³C¬yÍvXN³7SšÅ‚ßgLM-Ág”Ùf¦¸RB@í†p‘Ék‚ËQÙ l›(³é2[#âàöãKD±D@¯iû qPëkýjŸà$æ òRƒ¾äêwhèÇ|ɵL!æ̇>‹¡¯E±›)Š´ m*ôtåõÓ£ D'Ê £“‹L3$lê¤ÓÞtÁHÛXv=Tåwô-s›Š0pãÅÜèž ¨&^#C…uèä=÷XË!Ú¹¡úÞN‡5%Øy’06z†¼Çš ?r3&…ŠÒ1ý7µ/u:G—ëSGíÌ“ª$2O·„Ì2Å ‚“Êåè9¹õXÄÆH³3ëè2}Æ9'?0‘±Ñÿ0L¥~@Vn|hº”ìó»×4i¢8`î¡PÚBÖ´jæŪc—»&ÏÈuˆ6/ØkîÒŒ â°&y†5ÁÂH¸¤5æá¶øa™úü£[1œ¬×~1ä:¹OÁ~·ØÕ«ÇÙ¥áÞ$*~&F ±æcT‡åbT=}’waõ¾|(«ó²^…þ©Ë¬uX¼Ó8TZÛ1sw^\Á¢3.TéýF_3å?ê¢Kó¼&ÚóÝ»^“åZï”òÛÓÓg°Ýž¯9ýÉû©úý °.èÏc9ý}|.Ç€ZãBó6†ôÖ^äÏ#Mð7Òa"ñé1ƒÔºEߺ%¥Œ±/³a@LÒØ+¹w-ç®Ô­ñ Ž9áˆ`~Ðãí¨6´ôBÂc Éøõøl«WÌwzíLf6 ãA‹øG;½Sö¥bZHe.š×iÞº<’3®Ý)½Ô„B÷EzçœÞð`ieÇô¾`ó˜vMqÈë%5)9~Öf4ùäš}šÎd©a»àÖ3&ŸFsó[sñÖYÓv%£epïÌ0¨EpÑ‡î™ q¨Å)›ˆÏ¥ +¸–­:ÍW=û*VŽ}ôZqì;ò±îûÅ€°ÍŽ4p®&¡jZÀð7ô“Nƒ¾ 5Ë·ÝaÆõá¿_è«{A¾@µüŽi65xÅÛ”ÍTObSnËö•’ H!}Î +XÌÐc9;ü4k‡—Hö†xFrÒ‡$ß”MvïCÁ®nÚ¾SÅmHÐS­í©¶hZJ˜Ñ÷¦È¦ UÚa§û! ÷£QQ5ƒ',änLQ=Œ8T§Ø×z¨]G¸%owh˜þ Mƒ?KÞÓï¸)2O—Js˜«êjÊ$¸%\¥f·„»³Áð©þQ ¿ÜþBÀ¯øˆKÝj ÐQ÷*HÜ\W~SÀôû*¿ƒ„Ž úé]9hbG–;s‘œ'3jÜKzaŠ¨!:ѹêS…lØ­ìΊ©ÁiÝÒiƒ³¾ÿ˜4ìzÛi¾–»î!¹ð¯@½EM]8iL¨°×qñ ±æ/\‡å.Üþ¹aòm9hé¬^Ä[$Õeæ:¬ îF9~Ö ”³7îK Ÿˆ±#à —hßî߈0ŒëÑJÀܹN³óî¸ÑâÄ–¦è)G.ÑÄijéÖßÊœ—gOÚÚP¦ÊçÑ/@Z/¨EW+ŒMrÒ¤âx1ÑÙ€D"G—S¸øóP~Ë6®øÓ2 `ûrU¸“îQ<õ­6Z2`MH½x¸ÅÜ.Û}M–žó ¾Ú„S‡Õ®e“LÙÇÉq +È{òÞ5ÖªèBsîŽ Ò§qo!ðoõ˜í³=‡I€1÷ô¿Ë&}ð*Œø]~sœ_n[Âÿ{¦Î')+0Š,³ÒN7ðYîÝ/JÖ·²SoGRÚÐJë³>ÖB>Ý;ÒRêî3¼\ñ;75Ñ9lõHï0.ßv,=ž‚gžÿjµ8’Ï|‡Ò#]ø …‘œÏ¹ ò—èu1þŒÞTˆÒ»Ýfû–ž:9£ú;è*×ZÞ_C¸\µÍTO¤¡†\ežW ä‹î5Ô¿‚ž¢6’¾¿ç*H¤Y>ÜE’p¸€‰¯î;¡Ä²¹BÙÖû#aÑW„ÕЈµ #(tÎvë^f]Õ™<}Šéú@}àäÊeTñ–ÕjsÈû²w;þ j¢˜î^nvì-wûŒ3œûˆ™®@ÅÂ߬ÿû;¹þ‹@‡:Ifú”p±C­Sé™BQI¨êNXᄄ;çýÖà endstream +endobj +2509 0 obj << +/Type /Page +/Contents 2510 0 R +/Resources 2508 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 2507 0 R >> endobj -1958 0 obj << -/D [1951 0 R /XYZ 85.0394 196.3893 null] +2511 0 obj << +/D [2509 0 R /XYZ 85.0394 794.5015 null] >> endobj -666 0 obj << -/D [1951 0 R /XYZ 85.0394 155.0304 null] +2508 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F55 1311 0 R /F41 1208 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1959 0 obj << -/D [1951 0 R /XYZ 85.0394 117.4002 null] +2514 0 obj << +/Length 2925 +/Filter /FlateDecode +>> +stream +xÚ­ZÝsã¶÷_¡·Ð3?Ú''q®—Kík¬›k›ä–h‹=‰tEÊ>ç¯ï.vA")·¹ŽgLp±Ø]ì.?€’3rfâ0ÎT6K²(4BšÙr{&fÐ÷öL2ÏÜ1Í}®ogo~ÐÉ, ³XųŽ'+ EšÊÙbõKðm˜†ç Aß_ßÞ^}7¿}÷öúŸ7×Wçs™&2 .?|¸ºþþÝßÏçÊ`f!‚¿^^¼ü‰hÎ3\¾½º=ÿmñãÙÕ¢3Ì7^ +Výûì—ßÄlsøñL„:KÍì^D(³LͶg‘Ñ¡‰´v”ÍÙíÙß:^¯:ê )B¥c5â ¥tð¹x¡÷²¡ç}½¯VØ΂²mˆ«-·eõ@ Û¢ÍWyËãÝ°âK,ÅŠÞÚšzWE[ìNäuýÌÊZêoÖõ~Ãcî˜ißN¾\Ö»s™«9ºæ?—2ÌŒQv2dȪÃ纠Æ}½ÙÔÏ]ÿî< ö›¢Øj)‚«|¹¦Žf¿\MS>=F––.j>îÊzW¶/ôV?»#…–{«¢ùÓq¦$)2U³DÆáD`#èùÑ »`Î=#!C“Š¬Ó‚Nzwf%2¨jzv¡„¶Jx[ç 5î +›$Ðj + T‚Ýñp;ch`âH) U÷é¶Q²´ÇýݦlÖ65\ ú½®¸•W̃)À\luS>T6pf:6ýD耲Â)ßÇIj$Üù¾„)ï§=ûýLÿ|ã² +=³ÌÛ²®ˆ±`®’Y(Ð ßx=euœ‚yÓ^ •õGùÁrÚ‘ãÈ|= 'è¸:f›˜éÎ@Ë—mùäüïì¿ŒËPÈÈjý ;eà`y‘󛦧ƒ¹YŽï7èÿUa SñS‚ê¬õ½7„£;™¹h1“GAæà•6»þ—X fY}E¬< 'bå¸\¬`WcE—ìH#w=Õ]¾ —ïØký,0ßÏaÑSÛzÃv2»‹—êÒcòudZn;ÒÚ=pz œµŸqÔdôºxu1ñÆM¬À¯­1i¨”<´¾„éÐv\.´`PQ¢‘&j_k&[Ëu&]Ä‘¶¯º%0æv\›2z¸“GÒšb‰v [*z)eu¤”ó!R‰£)r¼åf¡×7‹±HÒôŽê¢ÛËÿë`]øá?ª (ïÞ-p!`4ëp›ð ÞF†‰”1•š'Uv©9T9–š=•ï: Jàøýí{lDp¡ó>0Ò§8tÀ¿ûÀ ]yK-»a3¦¯9œ1–9ðšNçœÔ=Fl6úR´[9Зo6cyêŸÌ:$Š(63tPiükßp‹~ìÁæ˜Öâw™ù=îyÈx”Qd óNŒc™qJí-ª™Ã¿üŒOC«z4Ù…“$RýdOãC²£IcÉŽgÚ0Ò±ì/ßÿGÖ£¼,K^ÉzëDÖ;.›õzl¤™[íM¾@ò v9ØžNÛå˜Fìê]ZÄ¡Nà´Ú³ëmQ;¢IXO’*WkhQ]‡ÆCùTpïºøB#ŠjY¯lŽ'…Ð3‹‚Kê^å KÁäc¯h?\pX…b}ì–£Ù( ¨F¸ýŸî¢QèÒÍÁÂ@ÐÇw,hu͈È@™":þ*·Â;?÷míN$•»AC;zƒÛ ÜïpëvÀNäßÃ'?‡ØÅèšÄJš6êXåsM§dÇeSò/c)‰_„öjÙZÛëª96Nš2‰IO[×q˜×«Ú„Æ$²oߧI'æÕ¸/º88g»Pm»L8ºIñgÕźñU•dX£“‘Ñ)Ô>ñ +zó¹NDÆqÙÈ\¶ÈpÔ§U:¦•½ƒƒ +¡êÆ}•ììL÷m¯¯‰îœ $wJ*¨ê¾K©àæ÷¥› ÷͉öXì«yTn¯GúB‡·9ÈHŸ¿T°ª‰@›ÜÁL: ¦aj’áÙN^ܸOí;—ÒöÝ”̓MñàRÄÓ0Ñ1ÝvN—a™‡Ðú\.­7¤­qxì ‹ðbä¾PªLn›_^Žm”pDÑ*í•:«f¿«gGA¾÷…ç}‰·ùx|¥š?487!BÐÍ(þ |°¼î÷<Æ:ºBŽ nfGQØ7½Ê7t@¤C'Ð%Ìñôa¯Œ›¾„»»´Žæ/§kÃà†ïøÒiëœ xÏt}7Yzë×pògº0ÃBx¾)€@ÁšM²SJË@i $aeÊWÚÕAÖÌ÷q^% ÷¯ÃÙäx¤›špêGGPëñ—B#–‹îjü«tøéU”„:MÕ¸TǦ ÚlºA5Œ4ÿtihû=Ü@8endstream +endobj +2513 0 obj << +/Type /Page +/Contents 2514 0 R +/Resources 2512 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 2507 0 R >> endobj -1960 0 obj << -/D [1951 0 R /XYZ 85.0394 84.3344 null] +2515 0 obj << +/D [2513 0 R /XYZ 56.6929 794.5015 null] >> endobj -1950 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F55 1037 0 R /F22 737 0 R /F41 939 0 R /F48 953 0 R /F39 899 0 R >> +2512 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F55 1311 0 R /F41 1208 0 R /F53 1303 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1964 0 obj << -/Length 2625 +2518 0 obj << +/Length 1899 /Filter /FlateDecode >> stream -xÚ¥Z]oÛ¸}ϯ0p_ fù!RÒ¾¥MÚdÓ:¹µ Ün·Š­ØBdÉ×’dý9¤$ʲ³À"¤ÈáÌs8<¤ÃFþØH*¢bÂ8 ’29ZlÎèh}ŸÏ˜•™8¡IWêÃüìý'Žb+®FóÇŽ®ˆÐ(b£ùòçø È9h ãËélvõqr{õãÓ·»¯_.>\}9Ÿ0Ej|q5½¼ùßù„K -C`¥ã¯Óï_°íþ<æã‹ÏW³ó_óßÏ®æsÝ 0*´gÿ?ûù‹Ž–0ßÏ(q$G/ðA ‹c>ÚœRáZò³ÙÙ…^3tpA%\(>°"œ#±”Ü[%¸0K2{-Êm•Uý©FÂH‰Q(˜fjÈ4ƒåæœ;â  œtU·6('¥½ZU•.&Oéëã®ÜäÉCšŸO„a’hGß«­ -&BDAvõà$_•»¬^oPÔ·f\æVr’i I,xdEÐö¡"!I¤¤´R?'‹M\XÃeyRUšxL¢(Œ­Ô/œçÏÉã€Bßècž¬†ô$#Þ×÷ÔÔŠÍPPÔ FÉ&­_·é€™ $§aßÌöM··»².eþÏuÖoê<⣀Fßó›úòôy0ê&V‘¯O¯ŠúÛmÂ#øI9@nF]^Í>~»¹ŸßÜM›Q­ -Ãá,±}€ƒxg¤8QÿUZWç!Ù†ÙÚ l¬Õë+«ì9-t•ŒŸ³qŽ_»sË Š%X,v¯ÛºÄú:1Ë,­¾¤XbåaŸåËÖ¬üI)ÏÓÊZ(wz£‰sÜæfÌ´RIgébï é6è‡fö¿’ -ËeªMé?³ËoŸ¬&ÈSÒŽ(–½¾€ -8BHýÐÝ™¨f}›è¤ŠHL!ŸÌ†])—¤³a#eÒ”Kz²›¦($èXå¼®sŒ3Â#€ÓIï©÷ºHcœÐé¹7Kót¡1Ç9G|é -"fµK¶ëlM“p¦ -ÊÆs'ûœä{[-‡¶äd Ùi8Á{ÂRƬàf_Õ¨öÁ©/Z;¦ü6»øz)ß!‹Ø -}@‚ÈìúBNDl|9»Ð5)ÇS€©èvrlj%°“KeÇâ·d»a˜òòKöËìQc]ƒÙl,5¾Nó|bü£Î/d3›¤ÐA/&£z1+»CÌrÚ}‘t·Î"q"YQ¥E•ÕH£;" ‘Üèå £qQê2î,¹iÎ*l®¶é";Çí.õ–(PÌ.ʾdyŽÍ&Pî+³]¡ïá[–éc²Ïk«h_@ʨ°GãjàbRæNŒ‰@ HÈ›¤]në¬,g1±Ppz -*}dÍüªLn¡¿°×XÅ…Õµ.(¬˜™·®=Xœ·†:M–Baüoñ…$”ìä,%$Žæ¨Ó3ëZ’6=›Š-ÛˆêOd€°T`‡š‰sdP½Nj‹°4àÓ†juëtñä³ÎýØZn¶I=dyV¿º¡ú”Ò5³ŠD£{œÓ²N1rì7ð^ÅÎhAýPÁcÄ ‰ú@taO°€m´Lêr÷Š¢µE|¶Ùæé&-êÞ0C{Šh;³‹ŽZP€¦7¼iÓb™.ɉiéÃê7ÜÓ:1˜%Þ×åk‘ä¹]«Êœò ;jòäM*’9vLëß>¦ºRÇ©FÊcÓÝc*&ŒË°O¦»~Ŷ°’§ýrB~y»€R`aϱYƒÞþ’Ù›…®šJ$M]ÑH;¤ë‡$Èñ•ûÛ³ÿ0æhÉs¶H1M‰\z":®Ôñx4R&Åm`XƒË]~ﱦH@£ø´sÔ€w>k`pµ£ÜwÏŠŠì:C¥|)R½‹õÆÖÎaã£'ŸàÜzÉë#PIË' Ëñ 6Ì'XØ\ý[ŽO'àV áó P›B*@íqVÿ¸›^a‹†&"øH\b…KªŒù²óñ_HNbK›u“Vt{õã=ˆA¡aä¨/H]ßÍæ(fLAy5ßÌ`oët$=½p-YR›¬ ß6óÆ %ùx]š™¶.´¶’Ú÷ÙÕ7=YÞ9Z…­ªžUÕXUÌIÂqµëÙçñn~ݵÔ. ÁFG‚oI6ÜìQø°$j†õ²4†¥ÃŒ·¬¾cÇ2~cËv¤NlY'e¶ìb˜ésÁdÿÁË¡ -ŽœvÌ 8æçP˜@,Bß³›b ÇOmV4îÀ5µ+ ]á͈ ;eQ'Y‘«Þ(Tªu¹Ï­ô:yN=9Þe V£^s‘ˆ­B[QZ§Œ´¥t\¿¬Ì°ÇepIMõfjs¿ýÖê( ô?T‘8 ƒ®Ôq4Rƒ')t«ÞÛÀI¤¢Ón9¡·¼' ÷¼ˆùnÍRC†ì#‚®øQ ™åºÎñüìJ·öÆÛQ&·w%Ûœ‡ª|H騇¦{=¼0¬jNnUd ºdY.D©Hù˜¸Ý¶§ømj‰Ö,[YØ´ڤ„ÚA<€ŽADÄ„êלÓéH€ˆ“2Y÷M*¸ùÆá&ЀÉnøCFhõLÞï²Â‘ÎIJÐu¹³×€j¿Ù$»WŸL5Ô ¯]Uïóòj¯i¶£fåÀ«‡k\Öl_ÅVi1phÃ$c¹„y<64Ò kûv¤NÄÆI™Ø<Í)“mlLƦkòs -”)q÷Ü7’öö]bCî‚׸ÂCóа£+ÈÂðœƒ]©ã+ØH™ܾI]»ÏȃÔõ¤s-u=ônºzîÍð‰•Åö9•SpǼš¢K¦Ë’PÝi‘'¾²ñZbûSKd%¨™×jnöÜl@ýYì7:–ºé!­_Ró¦ ÔŠÁVCúáN{/[\Js‚R÷ÇÜ ~˜SJ¡ ê(VG¹ ï΂ ªÛ²ª²‡Üjj˜[ÝX¯ÎîÞï¶ØÑù¹6TQ{R`‰o¶P±ï¹œ5SìQ¸Ìe”j¿X¤Àí–pË;Èðž -ß­.™ã.KÃRî 3æ6·=´ÐÃÛ”V-¢ :ø-Æs„+¨ì=ÌÚG"ÎÜÃlkúâûüúãÝô“þ­õ6Mï™m´î‡¦Q´}ÆÃiOïÜXƒ]åP¯º¨WõÊó€´Mº&mŠ|LwVؼ påVL“æe«Ó›ìõãhmßZNêD;/ì/(ºÍ€tsš&ÝW3÷"‘æ}¾;€Ú£pWÜÂipí¡ã`wBëÏÃ9[aÐÿYÍ£­!‰yÄOzåd½òo.œÄ4–ž[³Ã‡²eú°_­Rg¼"Ç~Ë’è༢ÍOEÿúwþö¿‚öRtäy‹‡’À`åœÒócŒÆÙþGÀ¡ï;úendstream -endobj -1963 0 obj << +xÚ¥X[—Ó6~Ï¯È §Î ]më1ìX.Ë–¤ç´xð:ήKb§±³~}g,ɱAK{òYÍM3ߌÄÆ~lœ(B…–ãXK¢(Sãl3¢ã;X{1b–&tDaŸêÙbôô¹ˆÇšèˆGãŪÇ+!4IØx±üLonf×—W¿OB®hðŒLBEiðvzýÛô™»™hL_Ìæ“Å‘@¤‘,¢Áõôíì2¼x9»x}ñîúùäÓâÕh¶èë+Ϩ@­þ}øDÇK°áÕˆ¡5þ”0­ùx3’J%…p3ëÑ|ôkÇ°·Únõ9Cª„(.£qÄ’j¿Ç(¡ +<Æ’ªùÑcœù<æ¨ÐcŸóé¡Œ2ÉxÜçv&ÓydòžLF#ñD …ηyV¬p"Q|¹/²{3ej3ªï«ýziÆ·¹ùß×¹i*KUÜ•væÞ}«ÊÎS¨$¸Z™©²:åžî&, 쎕ùH)Ï—O`&¦È¬eÙZu‹õºÓ <7D°ÁÑJñÖÀükº)ÊV]AƒUµƒ×Áåõüõì3iTȪöY‚´1‹F. ¬\\Úæ_Ñ0*a0Tµ¥;Zó«j_ZÑ©mŸäHk›´Éî‹òÎ|mwÅCÚÛ¨3‹¹`©Ÿ˜<*Jóo4…A¶ßžec&–…5±©v‡ c,xÒm9n®ívëVÝÚ{ÜÊùxÞ 'AÝÚàî|¾‡\M#È&™ÑxöûôíÍ›™ÝÐL0+’aæ¤%[¯«/Æ‘ +²j³1N„5”_›!ÚÝ2•I?Ü!K9M$pwa°]ç˜x4ˆ"’HYZa\ÑÜáSêr>5L×vp——ùŽii(oOzÚDà’Dk+aYÖuž…À6{ô A¢©‡±ü‘*úºg yL©xÌb.cXbž< +žåYºÇÃœ3TGN1«L8÷hÀ8‰-IµmŠªDŽ<(jó_VÜæí¡4 -!m4â2zó»Çä=Ž6ûºÛnù–!&(èÀéI>oÒºÉ15 *Ö¹+jào©â$Vw~¿%?„D(éÈ­S¥`”h7 +*ʇ*K?ð{]UŸífǹ +ŒC½H˜ó厾ñˆ )´N4š†).¨MqíR\³“×ßIqÜZWnkÚX¿jD…ÊåÜ$ö9"¢¤åŠÍ¶Ú5*´ÄàP%vt<“aôʼn¹Š\üÝù‚$*ŠçpîÙA!U GS 8CénÉMÂ,·I†Ha2'A˜ù¯Ì?Ì®aˆ´s™C6±ø\ôáõ-A¥À{žüÙ·ïjø,Ho«‡ ì—•óÄãy­ c&ž:è\p ø­¹;†ÌÄ@]}Rql"žŸP¤¸$ö¦_Ï gàÇʵ°Û°Ö².U/ï±¹ö,·m@(¢àM°¡gö+[|ËÌE¯«Ÿ©ù³è¬0uÓUÑ#'Çtt:J¬ÆeºÉ—`c¹òN gQƒD'65YLD}¨=ïØDcxw´øÁ­=¡«„fakVŠj_¯fÉúº; ¹«o0·ÌWé~ÝXé ˜­[×K[’Ìu$-™íâPp×ÃÀtZ×û?¸Ûn±#ÿ¡uñõ@¶õ¥´ ;_¶{÷‡`ò/AÄ㉟ƃA‡E‡­Õ|63Þš¾™¿ûçkÐ} F'°/„î£0ƒ›Žƒ‹gW×—FŒ¶Ò–ÐYuÍk ß÷óËL½MË}ºöe9t]® øäcÓÄ ¼~a8J*„‡\k¸T¬ ogªÁV÷M[¼|÷þŸývUBJ”¹Ìù‘E¤‹ª¬¡ ûÍQ¬$BFî¸$$½–Â8’€…8iq"Ìîó쳋ölþdµÄ×@òÕ4Q1;âMAIÎc3j—m‚U%"ÎÝ~çZ˜S<=”MúÕ#CÓc’VÕúß㡬¶5 ÖÉ]6‚›·€RÀ %ãTyï² ä +ë>‹ö¢+}—ëŽÊë!LÓáý'7zèFv#Û¦)ÑãΩ&œ©®†;‹MžÞSBÿÚ¤åº*Ö9*ãdl;iß>ùC6$‘T ½|9›_¼¿ºY\½»öÔù“Àõ„Ùyß«så«¥ÄF]0ÛÇ ØUb¥Ý7fÖÜt9ÜÒš"«-iµ2©GOèî Ã7•^ÙôµÆ’ð¤ëBN#™·Œ-Þ -Œ6¬ mÔÌÄ$øï§òØ …¢×^sã殎ƒÖn¶½ü +&Ð «MüÌMͪv­É<ÒuÕÞˆ˜«°H•â­§lko>Š2[ï—NÜÍlƒ×µï ¸NŽ{-‘e1x59B ×Huû4o²§ÆÝÊ àýDïâú1ÛZˆ¹=ØÒmZ +ò½×;@9|ród:íà¿ìß0%´VIÂýc‚Z ÍœRhSâTu%¼oÄÝÿ$_Éendstream +endobj +2517 0 obj << /Type /Page -/Contents 1964 0 R -/Resources 1962 0 R +/Contents 2518 0 R +/Resources 2516 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1961 0 R +/Parent 2507 0 R >> endobj -1965 0 obj << -/D [1963 0 R /XYZ 56.6929 794.5015 null] +2519 0 obj << +/D [2517 0 R /XYZ 85.0394 794.5015 null] >> endobj -1966 0 obj << -/D [1963 0 R /XYZ 56.6929 749.0289 null] +2520 0 obj << +/D [2517 0 R /XYZ 85.0394 672.6222 null] >> endobj -1967 0 obj << -/D [1963 0 R /XYZ 56.6929 675.7286 null] +2521 0 obj << +/D [2517 0 R /XYZ 85.0394 403.8925 null] >> endobj -1968 0 obj << -/D [1963 0 R /XYZ 56.6929 599.4635 null] +2522 0 obj << +/D [2517 0 R /XYZ 85.0394 340.9183 null] >> endobj -1962 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F41 939 0 R /F53 1029 0 R /F22 737 0 R /F55 1037 0 R >> +870 0 obj << +/D [2517 0 R /XYZ 85.0394 302.0073 null] +>> endobj +2523 0 obj << +/D [2517 0 R /XYZ 85.0394 269.01 null] +>> endobj +2524 0 obj << +/D [2517 0 R /XYZ 85.0394 233.4614 null] +>> endobj +2525 0 obj << +/D [2517 0 R /XYZ 85.0394 167.5653 null] +>> endobj +2526 0 obj << +/D [2517 0 R /XYZ 85.0394 107.556 null] +>> endobj +2516 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F48 1228 0 R /F41 1208 0 R /F39 1151 0 R /F53 1303 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1971 0 obj << -/Length 2140 +2529 0 obj << +/Length 2010 /Filter /FlateDecode >> stream -xÚ¥YKsã6¾ûWè] <µ§z}ìÈ’Ã8ãcµ96¤%˜8›{¼ÖfoÕYU =H’ ªRWUOuQUožzTÕ«cƒª >ÒF  Ϩª>lÕ¾,ì‡qvµ³?-xñÀM<wæÕS³/»Íö¼‚…¨ãò‚‚To(ØS]Vð[§|zlXÁÃcÏ -£ˆ¥R\ôÆ#0¨½vŽ=¬›¦3˜“:ØÕ¸%Q³ÿ ¨S&RÔÖÀ¹…j.¢î»¿Ô£Fj.£ï`]K ã¨µ$y«®‰…Ä4²Þ!üeS‹êjeg-æ¡jsH¹2MÏ ¶Ù¢šBÞ!µÖç%?/pÞ²>5ÅîðXyg×l|Z2è½ -ÈI(ø 9'%\ö´†$¦éqÜþ‘<îî4#`mAœµ¥5÷r£BRf(¥½2Ñ âÌYKC*Ãb þÊõOª+'ûmê =°^S4>%ê¹n“wŽ‰Nzð¨,`¨öÆô,xE3à/¢¿›Ú?EĪt'uP8V:DôªuÈ“îæ±UW"ƒ#O¹ùøõvÖgóNmÕ ºt]4¤°fÁ«0`€×ìyƒSJúŒÔ_)ÁCí&ÔÔŸ$jwª°¥‚]6àP­Z]¾J(éÌÍ®y|† +›Cëö©âl^ì.ÏmSëÐe‚]ÊöÈÑ‹²j”›­›Îê-¹S@†‘Þ6ù³Õ0=ä®Ú©ý¶l[HG°”¯ ]&L±ÅÎÅÌbúqñùr‘z„5@;…Ôvs¡êÛò©Ö^4X6|Y6 #še>6ÞÝÍ]Ùœ9qVÛ².¨òÎñ½Z+{Õºpjø”ׇ<¬DHD’DK÷ïo,dz$À/s$Ü»QP±1“ J3*Ç -ž~]þòùþ²fïž÷µr•å⥅°p¸tþÓì»ò°=ž› ¦‹kË'¡SËZ,è¶0ÆcSùÀbÐ8³‘5‡äqF® ÂÏu6c66;RšÚ‘mãNÒ©+†û -¥kšêMO´â,^êf×BxœZ:ˆM%(‹êÚ RŒƒ% €‡®5²x][øʧ§ -\_€bcWÎq6*LDz?ÂÉkìâFXßÅ!nб>KÁámùw“IŠ=]\Ÿe%‰.º—]ˆôÈÐß{±â"ÀŒ2ȺØ7£E•·mœ3$¥?ñ›UÚC¬úÑ:ÀY@(ð¾LXWùSˆq‚’T’ž³Í0,''Pù?]”ß9*àK@Pq‘^bÓþìG»ÀAG"éÑe·oº¦ðQ° 8=gà ±+÷]ý -£f»RÏaáî=¬gÚ^d -x«ê'Hæ—\­çÙxÆL_ßÖHÆ$öÁèŒßmÒ3~¾(l¥žUõݯ>bÝ´ )Oq2Æ¢ÛÙâæþîËòîókyaíÍm^sÆjˆ¼s×n5†q]»ëâc§*ý\NBþ iÞu81B¡Î‰7£i»q= lúƒé3=–FFX0wn)šíÖ>ª²VÚ ³Õ¥fÑ{‚åoú?‘¸"ROnmçFyWlNø›{Ø£×+Ám3ðññ ›o{lé?²Þ÷MYlÎöÍΪA?„]¨=?›[¼z¦pé:Mu LÞNé"ÿVx·vD&IúìÍGÙùy(yÞ2’ š¾-ZOôZ¶Q…j@Zò‘p UA{¥Õ*™S¸L¢bÿ²ëš§}¾Û˜&Ö<]C¢i{—"ï2õ¼XôœWǶY"aЙ'XÇŒ[+hí(ñAc\Ñ:ˆAþC†n?I¦£ÀÖö÷~1ýt˵œ˜êÅ/Sì˜E·‹éO–h—bãE3u¤°‹” Ç}?œ†¸=û¦KbÆB¦Ä½ïþß8>«AeRÒ°S0 u=ˈJ+Žr*zÿ·Š×²ÿ`Xnendstream +xÚµYÛrÛ6}×WèQš‰\yé›ã¨­ÛÄvc¥í4ÍMBŠtI*Žûõ]o‚$»M'31@.wgw™bøG¦ÂC^Hér$0Óx;ÁÓ;x÷Ä™…Zô¥^­&/¿gþ4D¡G½éjÝÓ dºJ>Ì^!‚ÑTàÙåÙÛåëÅùËóŸÿ¸º\ÎÄ'”Ìή¯——¯/~Ÿ/¨À ÂÏÞž]¾?{£Ÿ]ÏC:;ûay3ÿ¸úi²\µžõ½'˜)·þš|øˆ§ ,⧠F, Äô&‘0¤Óí„ †gÌ>É&7“_Z…½·Í§N4`A”yÔ¥.8Dˆ*£ZêŒ+Yª1›ÅE^˯uõ¦ Ϫ]¼ÑBQ¥ñ¾G$ð‘Ϲ5–'1ú,^ ŒBî[¯¢õ-~š7Å UÎá³n-ÀkpgÁâ;øÕõêâêrŸïò ñ¦°Äpx€ž´Ì¢'¤É‰8ÈÉ +)£‹ÍØžç!úÇíY™}{t&?Ú».Ó¼Ö ëÁ®ŠîÌ°Úm·Qù¨'Š?šüšÖè .´S_œ¦'u+Õ@cÈYˆžd´+|“IIZʸ.ÊDZoHÎ#^xܹVÊá]GBaË :tï|£¹(ò/TÕºO¶\ xžËßý+ðE`$«Â(U[T3Jó8Û%RO@Qãq~i¸J ÌÉ,·_¹xá¡®'=îØ&÷zAªð5‹D°îi½ÒiÔümëÆ·6wL>¥Û4‹ÊÌ<[̤I­†<æ–ðCè pp<·úR‡s«•jrëË^ÙA¤xx¤r˜¤ÃB¨‚˜tU°SÕÄEMŠu÷Öµ+2Ä9öžCº> -³›ØÞ•Ñö9Å «E‡ìDzRG`¥šÜâ½£&[âÛ7éb¾É^Š]=ÂzPµÂGA@ûH£ {6vOô.]ºXͬÛÀšW¦¢¼ÈUg¤§ë¢Ü«*/L|z=‹š?H[³j–ÈXàX ÉA{ៈ`OêH­TÁ¿÷"¨z7i…&ÀÂÐgdhòZ–N†ajY™XfE” + ÚN=ØFU­Zo5þ»Èm,ÖÅ®‹˜#(QŽÇž’ pàð;þ>Àz8dŽ†£/u8­TŽO{á`j³ +›´B“ƒpªƒ`C“¿mdÞAŸæwƒÀ(œíV£w Ûù(ðS±+s[6÷Ӻ妪®ƒ  sŸÈí¾Ô0­”Z™ö[Å{l:Ψü¸i+ä0MGÐóü¡íUƒ ó›tS£@ç3<Ñ Áƒ½}]½mÁæèÏníj£P,½˜]¬õSu|kĪ{§ê{™¨c7‘D®£]VWÆWÃ8œß‰gÛû—²Ž_vÛ:ôØ@’AçûAq Œ(C!Á¼_Fã¶RÄ·Í»FíÝrõþݥΚ_çÎvgoÞëË‹QÀ¡ë§Boÿf#Õi\CÒVv#íöQÓôÔQ½«†TD† þ4RíÔب„4(ÒJºÑ±îà¹Y.õÇgon®ktò'œñø¼èµj)]ÛíëF û© 9Á±q|uqùZ+ É6Í¡¶! ÃËïäڀLJ·Q¾‹2‡»øö]ïhš0˜@Û>âìýêÇ«w§¸ÈaÃÈ¥‰èÍ#ì[«ó"¯Š²NwÛÎ,G¬aÅF‡öÏ÷Âö*n¾€Jßï)uå궃ë›*Ã8ßTÎ{Á8e•¢axŠí}šÉÆ€n>(õ;Bî7$¦²4Ië¶A¥-“ÛÐ@a@§Z·Ïë¢Èžp ¾yÌ‹û*­ÆÊ€™ØU œÚqqÕ-jç=Êí} Ár··Rôæ bóa‘|´£M;úÔŽþjG_ÚQlŽ§¬O_˜ÐÞØŽ!΢Êu¡GC`DØuµT«qíЀž°¦jì¥å„b­Æï¿FsÏç#©>¼hù°H]X ¨|[$®V[ ±±ßŸOúý<}Ûÿ¦õ½ýÆþåßØ¿âtÜÓ®Á_ZÀñ§»Ûnu– g]Œo.ŸçluÒÙª~ÌäÓëèæG§>©ot³3d!Ž<ÚÞ~¶Jþ¥¯ÛÑoõž@¾`ÏÄÀ\Pc„ƒ®îu˜ê.UÙìg”ë#µ50ç±·›Èþ1©ûÝ ²˜©S¼³õ¦¾P÷äžuJ­†¾Ð0?;íûþ +6¦ÿendstream endobj -1970 0 obj << +2528 0 obj << /Type /Page -/Contents 1971 0 R -/Resources 1969 0 R +/Contents 2529 0 R +/Resources 2527 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1961 0 R ->> endobj -1972 0 obj << -/D [1970 0 R /XYZ 85.0394 794.5015 null] +/Parent 2507 0 R >> endobj -1973 0 obj << -/D [1970 0 R /XYZ 85.0394 752.1618 null] +2530 0 obj << +/D [2528 0 R /XYZ 56.6929 794.5015 null] >> endobj -1974 0 obj << -/D [1970 0 R /XYZ 85.0394 531.002 null] +2531 0 obj << +/D [2528 0 R /XYZ 56.6929 681.0754 null] >> endobj -1975 0 obj << -/D [1970 0 R /XYZ 85.0394 468.4168 null] +2532 0 obj << +/D [2528 0 R /XYZ 56.6929 404.8182 null] >> endobj -670 0 obj << -/D [1970 0 R /XYZ 85.0394 429.776 null] +2533 0 obj << +/D [2528 0 R /XYZ 56.6929 344.3155 null] >> endobj -1976 0 obj << -/D [1970 0 R /XYZ 85.0394 393.3396 null] +2534 0 obj << +/D [2528 0 R /XYZ 56.6929 283.8129 null] >> endobj -1977 0 obj << -/D [1970 0 R /XYZ 85.0394 361.4675 null] +874 0 obj << +/D [2528 0 R /XYZ 56.6929 246.6193 null] >> endobj -1978 0 obj << -/D [1970 0 R /XYZ 85.0394 295.9604 null] +2535 0 obj << +/D [2528 0 R /XYZ 56.6929 214.3762 null] >> endobj -1979 0 obj << -/D [1970 0 R /XYZ 85.0394 212.4297 null] +2536 0 obj << +/D [2528 0 R /XYZ 56.6929 179.5818 null] >> endobj -1980 0 obj << -/D [1970 0 R /XYZ 85.0394 107.4752 null] +2537 0 obj << +/D [2528 0 R /XYZ 56.6929 116.1573 null] >> endobj -1969 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R /F14 740 0 R /F39 899 0 R /F53 1029 0 R /F55 1037 0 R >> +2527 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F41 1208 0 R /F55 1311 0 R /F39 1151 0 R /F53 1303 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1983 0 obj << -/Length 2949 +2540 0 obj << +/Length 2741 /Filter /FlateDecode >> stream -xÚ¥ZKsã6¾ûWè(Wh$øÈžœ±gìdÇžiª6›Í’ ™5©ˆ”ç×o7 ‰¢[:>F¿)>bðã#q&²Q’Ed\Ž›+6ZÃÜç+n0 š¸¨ŸgW7ŸÂd”Y,âÑl嬕,Mùh¶ü}üs ƒkXÓû“_ïû|ÿt=áY*³ñíׯ÷Owÿ¾žÉ PÆÆ_nŸ¾ßþ“ƾ^gb|ûù~zýÇì—«ûYG–K:g!ÒôçÕï°ÑNðË BØaô,àY&F›«H†ŒÂÐŽ”WÓ«u :³úÕ^Vpˆ0=¼ÂáEÊ™er”È,ˆCj^|ªwד0 -dzéãç›pâšs>þ@ƒí‹¢Îk^îMw³oZêÍõˆß=Ðó™dwÅꚧÐeÂàTYnò -&9®Çã‡/·'_î¤û8}¸¥é„ž‘³p¼ çA&¥Ð´FˆP"äÝ[BÆz„u#aj1x6!;H.à6C&ƳÕ(šÔGk¨Ÿïx3±È-¤¨U5E[¼ª #, @¨RMØSÝ"2ÉÆü'£±2‹ƒDr>¬±.ê¼Æv(­±ÕE­òjß·=*K³aâ:TužÊ -^œ ŸÅÇ`Bd’äE —qLhgÊE4L˜õæé<ƒd“x”=VKˆrZ}/:ÌÖÑ¢ ¸±<ÄŽè¢7Ý.irQWm^TEµ>z‹D :ÍK½/ ú%UNŒ›ÎæØ‘Ú¦ãÇUµ!J£I>&Ó”ˆûbB+™x‘Xª»O~ÐHýŒD)4m‹‹:/J‹Á‰YW—e<ÞÒ‚z¶t/8†n‘‹·¥f¡#ýú¢´K¤ÂƒoY€d]¸õ¡ã•y‡š’”wmFÕ_[0“U{ž9Æqz‰j€¥Ù¹êÑ*È(Ó06Jµ*óõ‰NÚ¥q:L–õå²<“8î“5U&º!!‡Ž/ä 7)…6Eu„>Lr’çréÆGòàˆh)_CM5³èºÒ¹ ô,n]AŒÜGÅZnNå©Ø¯Ó_mÞ~A™ôhZ¬«N¸`ÔxŠƒ î’³^aÀS™]È‘\Ô€ˆX”‘uÄFIddÄh0í8ä‚ ) S9L]‡ê!ϹÐLg©Oªg("O=ñ9§æ¨†#]B€Ž¢bõC+*Ž·/hçœuápácý(ãÛ²¬ßðÚ`²ÞÔ:e|f¬2@iÞ~\‘lD ú‚…~ØQ+Cæl«‰šÌÕ$™L -~TaRw»+6Šº+MO½¡—¿}úHÃB†õÞŠ²¤Þܼ‚vàÅʬW7M1/Õ?P ýÃ(ñ­h U©'ÚXR€áû qV|CcøAñuQçÅ·Ciñ}9qqÀ²ä–Ô³¥+’ X’mùuWT6²2\øÎð¢Ùo6ùÎè|½:ªˆÔ[ ¯š£¤Ë¸‹=VŒ!Eö^e R"1z¹¬šF-& ã M=‰2“© ŸÎߌø¥»qPwcQún~œ½›¡-ws²eïݸ[~&µ2Üî"[ßìŽò!}AÖÝ»ñÑkg9(À&)ØËAº¨óìPšƒÛ‹éðvW·õ¢.ϦÃÄÒáSêzÓa<ðãºf”™Z‘@ã¤-‘¤§l9Z˜¬Ãƒ3¨MŒ;e, ËÌίJ“Ì#ã¸h÷ÛOl¿ýô®R˜rj:§É\§ ÌÀtf®?ÿòÐq£)˜Ï8ó5n±ß™[ûMð%7ÂS™äRá‰+ed»ß·TVˆº |ëyy!øðèBµÄE È‹Eiyi{½ø k+û¾;¤x·i6L–õåUK@žð¿YnRØ\>U„É23®Dô—Ã4JNtD¤âœIÿ‚0ú,°Pr´õí÷ÙÃÇç§Oøg‹4ôô|2ÈÍ APA•‡1cÒ·xOÏöÝ€¾ì›Ø,vc³ØÄf±GApž4üJí XıµKæó¢,Úw6ßÃ|Õjæ›Áª›ÿ+PòczÓž ]ÎwXÛ)Å«j±{ß“‰Ëžÿ:ªŽáÂÇñhàÛ¸iY½Xö)Õ«:I+²$ÈD*©²˜Sªüj»2–I,Ê(¼”y©æûõº«œiª‚sæ¨ÿÓCÙËù¿ÿèsøCS”€.¥gbM‘È^Ž-Qx>ÎÅé=›¿Òþ?™B÷0endstream -endobj -1982 0 obj << +xÚÍZmsÛ6þî_¡ôLˆâ• >º‰Ósï⸵ïÚ¹\>Ð"e3¥HG¤â¸¿þo)‚’fæ®™©@`¹X<û`± š,0ü#‹T Ì_HÅ‘ÀD,–뼸ƒ±ŸNˆ“‰½P<”úñæ䇷L.R M7«®á4%‹›üCtvuu~ùæâ÷Ó˜ +ýˆNcqôîìòŸgÿ°}W§ŠFg?_ŸÆDJ@ˆ`-—àèòìÝù›øõßÎ_ÿýßï/ÏO?Þü|r~Ó[6´ž`¦Íú|òá#^ä°ˆŸO0b*‹GxÀˆ(Eë.œ1ßS\ŸüÒ+ŒšWChp™".1ã(M@C@†(TpháÄ €'–B¡„QÖÃÉIN/¥á¬³u‘ÇËfýPVÅŸM]œÆ àù!Î?úÖ§¾õ¹o}é[KáoÌDÑ 0Oϱ¬²¶µb#ƒ¨Bi*•“ê5¾hd°^áºÉ‹>†Á|_ß꨾U³Yg]@ãX¬×ø6 1f©W'r‚”ô›T—ßyñü5}l_ßú;ÛWgû6ßY_{T_Û=UÅ»Ó^ÀVÇq•Ò1G>Ä]hËËM±ìšÍS`&ÁQ[nßôÇ£¦ƒÒ7}ë·€úD )ÿ&ÄM‚Q€XA„Òá*d,CRÃjuó‚:¬RÄdâ!']"¬÷ìdÊ‘ÂI¢·´ÞѼñæüúõ¯W7ï/û—v`x+(Žé0ªÞË?LLµ/Ða0æˆSééf$[}|±¨»/tƒGíSÝe_mgV綳¬»ânSvO¶¿Y¹q;j¸îøÆ´*àÔcp^t¶ó¡Øèx4™Haºvvð(këd ¡Ô;Ϭ3°º˜S +Щ½`˜7…Vžòèñ¾¨m«j²¼¬ïôƒ]Fj—¦sB£›û²µcëì"d‘@:BÒ¡IÇ —TyVmÛbµ­ì¼Žm˜×{«ªÐoQuk¸-´jZñÛZöCMíbû<:Šy&étRÐñR/tJUrdJ/˜r„NŠR)÷¦ qò¶96Áœ‹mP0gpò’Ü‹)泓>5w›lýz2© †tÀPjÞ½”qÀ§‰‚mÆOé…SŽ (½äxJ{š©O„‡Îð=îfݶig–ï j¶›ZêæTržóHÛ®•Ã¹å1PR@õRTC$FÄA¨M.ˆ††*PA´¬— +˜6Ÿ@B8&cÛ®õQ¾zڃњ3¡ï]U]¸±ºé&‰Á+ç3(•..õÿ/ZŸU@T.òyg‰„:aB\á„Œ'Ê€'Ôs@ÊqÅ>òTX +~Ш^hjÕÈ Pûc‘È‘YW¶*P9”¨MÛÅz+ØG—™òQá«l¥ª“ÉTEWMÛ–æô×’z­•Ê\}ÈÊdY©ò Ô.‚2°2®š†- +M¹Æ»„šäU@=ç™(¶§=ÖVŸ™%|.‘¤/™¦j¡®N€ÆÉ^Ò«õUÍ2›3J"Á‰8 ˜#•>0ר;f/Ä1æ+Bº„BLÈ¡â<:g&…Ù #›æ!{s­:¨tßõWKtïÎ äéóª8Ù»‚a\]ºJÐ\z÷»í±€[ÍI¢f`2§0M÷Ý=çà2£T“Ù0Ù_aƒÓî`à¤;ïËåýpÜ@fÂjã+¨xwÐõ ñ ÇC^÷<¤ºÖ$Ï&@ºÇhêÝ­ë_O…ˆþe¦ jÄýjcÏìOãº&J¬Ž@bÇx°К&€tŽÐñeÀÿ”=Xÿ'D I’>›ÉÊÉe¬T$PSVÅ]_Œ‹ªjóX¨¯.q«3‘Aÿ4®Û²bªÄöíX¡ŸÀ$>M†Ž1‰÷n½^éò¶Ù„¶…"š%/üBÊ_HÍæôç®ûX>¼`Zf[ÿ*«ÝV/VÖÄh'½­«Â__ù»?ÿi5¼ûý§U4÷çppôß°˜ˆûPùOåvÈ!—MÓ™èÇ0.Lo”ÆŽ±oºÐŸÁR*¶ÿ5¾ê©endstream +endobj +2539 0 obj << /Type /Page -/Contents 1983 0 R -/Resources 1981 0 R +/Contents 2540 0 R +/Resources 2538 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1961 0 R +/Parent 2507 0 R >> endobj -1984 0 obj << -/D [1982 0 R /XYZ 56.6929 794.5015 null] +2541 0 obj << +/D [2539 0 R /XYZ 85.0394 794.5015 null] >> endobj -1981 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F21 714 0 R /F55 1037 0 R /F41 939 0 R >> +2542 0 obj << +/D [2539 0 R /XYZ 85.0394 677.5149 null] +>> endobj +2543 0 obj << +/D [2539 0 R /XYZ 85.0394 533.7824 null] +>> endobj +2538 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F53 1303 0 R /F21 930 0 R /F22 953 0 R /F55 1311 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1987 0 obj << -/Length 2192 +2546 0 obj << +/Length 2753 /Filter /FlateDecode >> stream -xÚ¥YM{›H¾ûWè°ùÉÐÛMÓìMv”Ä“XñFʳ³›ä€¶˜A ÈϯßjúCHj„g×>Ð4EUõ[߈Œ0ü“‘dÓ8‰8B 6Z®/ðèž½¿ †&°DA—êjqñ÷wTŒbó^a)Éh‘~Oî·7¿\!Ãã+t0ŒÇ·“Ù×É'½ww‡ãÉûéü2 RD\‘q<~;›Ï§×Áüæýì?ŸgÓË‹Ÿ/¦ §XWy‚©Òê÷‹o?ð(…3ü|%=à F$ŽÃÑú"b±ˆR»S\Ì/þévž¶¯úÀ`T"&CáA#$#BPÌXx‹§!máx?M¿LÔ‰Ó·úü§ÿž«“ÁûaM<‚§($±Æñ_«¬4T¤CƈÆZ¥e]gËà·ìåÑQwyò‰ˆâeµÞY“Õ †ˆÇõn¹ÌêúaW/—„ñO°/Å8oÔ7Û¼l m¢·êöõVõ ÷šU¦7ªíZ«(L1¬cb”øXÂz“$É›\ýy”oŠB›šJ³Wr€vD¡D!£|8ì¬n’2M¶—DŽS sµk6»‹<^¬òZoÛkRšû4+›ü;Æá2iòÊ캓¦ú¨°¼Í˾®ÃÌm“&KQ¯ïâQÊÃÀëPµ®F¢.B°”´ÃK!ðq,”AÌ#q^ª£:{`J‚añC±Êž#†EØÝb~ -`™¬³^¨¸äQtª.U?TŽjª³R÷PˆõBu œÞ‡w { *wël›/õMëßÙF_jp܎˶Ù}3)«mÞ¬ÖýsHÜ1¨qàÕ€-Õ0Àç¤v>ë¸+¶/£ÐQ!ù 7îsAfBþ;f؆ÿCU5mR„M‚<¹9`…Ô5DB"_•£†—b«ÜRÛ6iÓ4¥Ñ¸y®Ô‚•ZEVC–¦ŒŸÁ°š@…P­Iî“:Kõ®òŠöuuHõ¬ÕÜ>Õé ùÒ5§Hà°'[#Õé€'EqLŽrò²ÍËc¸7»ûÂ:´âgkO›”SN$Ÿè+ öpyÔ"e rã³ê˜÷ôAºÖ„`ÉUíïZt±Ê|ZB­ …Öƒ¤Å˜c[Û´IÁ$˜w´Sw‰ºÕé{èôB»Ç²²•Ní5«¤1LTUS‹ûL3†ÙV›vÁª>þ³*ø®*ÊéÓÜHj ;hY©0POçí™üíf˜ÒÌ—òÈ ®?}};µU€^gR]Ï0´"± ¶9cqà -ÙVÑ.¼Q'5õ&[êê¯éÚà/ÒZ5¤2¿kO ûÕýS^íÌëÏ;xýE?2[Weœœ‚AòzÏΪV™y¿¬ ˜}%'‡€­’§¬ÛMÝÜŸ˜îf“m×y]Cö÷âxU‘<@Bá†öqÀGâQlS€?$Á"»6ô¼EsÙÍä0@A°±îÖ8‚ï'ý¬í¹Ô¢~Y¯³¦-€ê6+—Û—.zê5gHÚڕánv>ÜN®{ª)ì¤ÕbŘ]˜¨H´ÍJöG¢F -“…oø€S1×Ø(Œm=Rª¢¨žu“ "ÅZƒ -Ïž«]‘êý{C¾¾ËÒxt -BΑ aïLÙ 8 ¡A¢¯-íƽ¾@fÃP¶Ãg»:DOöjM¾? ÜØÓ03S94N:85RùŽ|$öcGIôcú&ä„ãa}oÚjÁl¾Â‘=îOžîFDÐÑSòúÉÆmáíjZ‰™h3ÂiŠÜˆIlsUÏ{Rá ,tUgsì»Zìè\Ac5:3rÜÑ?ÓzPÈ{˜ÛJä üÀ™ {>5Õròiþy8CÔùc©ª¹ªÝR•WcBw?ØH$cf•ºº™™/±˜®ó2LÛó~É2m»riœò6)wP“| Ã`Î9wªôqÒÕñ/ï®5G˜æc¿Š£²À_f'#ö¿³‹ŽÙÓGƒìü¦1C2"â ÃO¾.>|þ2lØh×·efÒÅü¥†ÖÉô®×ÐjTÛ&ß­÷b¡²GÜ”ÚÖØ èWˆCYÀËŽ\Åö Î ï¶Ä3&zT“p.áõ93*…¡Ð+ýO¯÷ϵKuMUÃÅpþRV›:¯GI=B!¹8µÀLø&IÝ!SÖô·ÐQ2ÙF÷žÅé”ig`Gå=½ªß‚ä‡]-õÉ=˜EbÑý˜W$µ/é…1’RØœä8¦Ž€“äÌæGèסW¯¶/¦,BÊ‚\õ‹”§jaW)ÿï¾ö_w!¿P)÷_ü?œ¶_ú¡!1J©ãBUw?‘êþ_EÞúíendstream +xÚÝZKw£FÞûWh1 tNT©'Uµtlw¦3ÝNOÛäL’¸Åi 8ž_?·^$@î´É-(.—ª[·¾ûDdáG"F±¦z!5G±XoÏðâ#<ûöŒxžU`Zõ¹¾¹=ûú“ tLãÅí}o.…°Rdq›þ}ƒFK˜G×ço¯.Wÿ¼ºø×¾¿¾Z®ˆ$”DçïÞ]]_¾þi¹¢?0c½=¿þpþÆÑÞ-5ο½ºYþzûÝÙÕm'Y_z‚™ë·³ŸÅ‹6ñÝFL+±x„ŒˆÖt±=ã‚!Á ”âìæìßÝ„½§öÕ1mp¡ <½ĤœÐA’`’L#By§2JÆT晌ÆVŸÌ6¿~%D‘¤´¹,˶J³C]hŠ¸Vñ¢·Þ‘PçX(Ú[KKÄ¥ +õ.«ï«zë$lc„ ^²_(åëM¶þ´*“mÖ˜[ÿN râ_±ìÍrʼnóvcF4j7™#5Ù:ÿcš¥ŽpŸäÅ®^y£ @Ä |1"LŠgâNb=H+ø( WLbıìÂyYdb”ñ_óÈìqÍ 3pYd–_”ÍÊÕ%EÇreE¹:—K³.wI"ëuÍýõ»y]Êhçu ƒñº†Öy]C4hµŒYæù†à¼®¡t^×½.âkÃáaÝs!`ïJa~ßœ@·Dš‹È)^*ÒŸá×…þÿO†DLçúD©Òçš6ÌŽËf5n˜ŒËà-îáD–e#i1ÖóÂu\#Ò ÅHqÐÄ@¼—’GuÞÇÎHdOF8ªvíîuÔÖï÷w ñJIJGöp°0—HQ,»€ªF¯ïG¦$`%BóÓSÂÀ¶CÚ7cs']¸XY ¢’hƒÏ(Ýfƒ6°‹‡@jZ€bÒEN €vüFn7yã¸sŸ°Q(Þb ú8ˆ­™¢­ê§9ˉcÄ&Úä§á ªÅ @2ï× ¼—Ul=obÅâ¹°cS5/V`k _ ÄòùÕÔjcQF›X‘´îñ>V²»IZl€4Ž+… O g² eëß=¹ëåõÍÍÕ…c½Ûù‡½™D+@B›¯“"añäˆÙo;¸·ÌyéHE’—¾`P:™øÛǬ„|ógÃà.Ä0ã?§‹°ë}©Ôìï[*pc¬Þœ5Œ>×´at\Ö0š1¿f$8¥¦}*ÆjezJ³‚¦Ák©™J¶OÉ”v]$ª±ÆÒªûƒgénû` ˆ.B˜‘i9¦¯Ä©v D;†ùÇ9×["‚ù FØ“@Ô¸™ÄŽYj;1FÀÓ[¥ÎŠ¤ÍŸBç˜ì£”M¡ávxkÛp \ÈíGU½MZ7vÁAY6žÒìò6q•”ãuƒ«£j Ùi^~t´d×V0“qÆSÒ¿&~²ì!©“ÖOÖ¬ëüÁ&)¢ïKGlƒ€•mw˜àaq³¥}<‚fì¥Ó‘£ìwE¢ò¶U×Öêf®må=göèìyðZ»Ù5>²î3{} eiÞzE¿kl%õq÷ÕhÅÃÃyFîÉ!VaÚeFD*u”V™••qãREëd×dŽ–”Onùh°n=÷®Ôûqî_4æãIΤdgF0ZWe qÄV$:Ž^·~‰¢©z¢Xa‡{¬|2¾I~Ï‚õYÆ6KJ«DscË#½ bŸâù|Äž®eôñ£›¹Íþh'=(ƒ„ÑS%mŸkÚƒv\ÖƒÞ|QI;+WWÒË5VÒä +½áû|pMÜåæýRˆèwsÔp à± æþý®á" ÑU¦–w¦á›/ /Øp¡‚ñg7\$éæqÃÅ>Ýpa„‹ãzú%ê:(³ ¸+S¸Ñç J!HÑiUvN‹*3&!†âÐa¿œ‚°å’y°Mš6«ûLnü××o>\^¹»dzŦΤÜ豪?OL°¯ðûÑãÆÇê ¬îéªýuás3I9¢2Šáté e†À<îÇ”uÐÞ'ÁIËS…MŸkœ—çåá’±W¬Ùü’idÉÁ‡o† zˆ‡K^Bå”çÓ&…Cö*ujNʪ´¥u/§™<ŤxLžü ±6ëÍ@&‡cìå›3ꊫ~¤Ï5sTËÕ_ô¹jV®îsÕ±\£Ÿ«‚í?ÄBÆ»ÿ 76#‚ëÚ'YZú’hp¸+0òm^š¶¯æEºö9“@K®¢ëy.GÚGX )luæ¼X—놔€îÿvA»jë…ý­š¹ÍåÌeð' ûbå®»2…ü¯µEÑ`¾˜Žè]o\þn&.>VuÞn¶îÖäXï_]¸‚7™–ý¬¡öÉã Ú£Ý‰Ÿl™ž-Áü/ØÑ9™ñiš,'¾Ó´-&³œ±ðѽý·‹â³ËvLÇëmE!Høä`áÛ.¬TÛ$8:+‰«á‹º½‡¼ËºÒÏ7›Ö“àÈ)¥õ¸f´¸B¼ù·‡Vàf—L#KþÛCDZ®ÝiîYÚ +ݬÓÎdÌ_šl7œgHšßLÿþêöÃûk÷òKÈ”¢ó7®nÆ›TÁ‹\=¿)Át×çrFÚîê2˜­GAöGî tp'í®î‘ Óà¬vÉmíÙ³Î9pe-ä+!:ßì§4þù1o24õÿBpæO#gˆ;M~ñ÷³÷Ä”šH!¨Ôh{¡Œ‰ˆ±oŒ ò¾cÙÿyÓendstream endobj -1986 0 obj << +2545 0 obj << /Type /Page -/Contents 1987 0 R -/Resources 1985 0 R +/Contents 2546 0 R +/Resources 2544 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1961 0 R ->> endobj -1988 0 obj << -/D [1986 0 R /XYZ 85.0394 794.5015 null] ->> endobj -1989 0 obj << -/D [1986 0 R /XYZ 85.0394 752.3199 null] ->> endobj -1990 0 obj << -/D [1986 0 R /XYZ 85.0394 504.8188 null] +/Parent 2549 0 R >> endobj -1991 0 obj << -/D [1986 0 R /XYZ 85.0394 359.3246 null] ->> endobj -1992 0 obj << -/D [1986 0 R /XYZ 85.0394 298.3625 null] ->> endobj -674 0 obj << -/D [1986 0 R /XYZ 85.0394 260.8495 null] ->> endobj -1993 0 obj << -/D [1986 0 R /XYZ 85.0394 224.9084 null] ->> endobj -1994 0 obj << -/D [1986 0 R /XYZ 85.0394 193.5316 null] +2547 0 obj << +/D [2545 0 R /XYZ 56.6929 794.5015 null] >> endobj -1995 0 obj << -/D [1986 0 R /XYZ 85.0394 129.6476 null] +2548 0 obj << +/D [2545 0 R /XYZ 56.6929 85.6141 null] >> endobj -1985 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R /F14 740 0 R /F48 953 0 R /F39 899 0 R /F53 1029 0 R >> +2544 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F55 1311 0 R /F22 953 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1998 0 obj << -/Length 2985 +2552 0 obj << +/Length 2176 /Filter /FlateDecode >> stream -xÚ¥Z[wÛ6~÷¯Ð£|qq%‰î“[{Ótc'»Ýí¶} EÚæ‰Dº"×ýõ;ƒ ‚¢¤œ³öÁÁÌåà >cðÏg:MR#Ì,3*ÑŒëÙr}ÆfÐ÷öŒ;ž…gZ ¹¾»;ûÛ?d63‰IE:»{Œ•',Ïùì®üuþ]’&ç0›_ÞÜÞ^}¿¸}÷öæ¿n®Î<Ïx6¿øøñêæòÝÎB3`fÆæ×7?]¼'ÚÇs#æo¯nÏ¿ûñìê.6ž3‰RýqöëïlVÂ~SZ&ZIé)«³Û³…½öÓIep–™Š m>ã<1Z‹HÚ$©ÒªãòêöûOï>Þ½ûpƒ«±ßì4Èf ‘&J -Ë[6]W-]ýØüÕ6•ãþ,K¤P|‡üÈØÊR5/ð!çø(Tj>×é±jªMÑWŽñLBESéÓ'0Ñ6ç<ŸWËÖ>K?61Êù³%·åvYÅÓ¢ •íKµé궡Žöšsr/‚º@üþ©.¤VÒÔ@*V]K­¡üØAZQC-r‘3áÔò¹zíª~1¡>¥’,å^}¿1&VN„eÛôEÝÔÍ#½Ù`0kЃ£SëÔ3ãBÞ€ú™×.ÐêzúA¬>x&ÀsãB¡ƒÚ̹…Z/Oõò‰šNÀŽÞÊjU==è¹{ƒ3¯{ÇW ês1oŸ±»X­^©Ãë‘Þ.oé¹op Ò A ÃQŸêU¹“Îó‘?¬iB`®7Öa±ÕZGJ[§KBÔ "máY2‡ˆT¹ý⃲}ÐàIÆy:KK”‚øœrbZ ¹|Œï#^àÂyÅxÊT%Æðüø”žibÊ¡VRhf’ÇSþ|Î9ŸW›úá• ìL oæ’^ÑëŠ~Kf&eNéFçp‰ãºrÖM಺Y’ý´Æ+*À(z¹*ºn,˜I“œ u\0Ï4!˜ˆ¦ƒð–H²ÛçjY£“YoU‘³k»oQƒ$³ÍöaÄD˜uH:‡ KO¨sÀuDžËªóó”:y’-wè7+O c•ÊñL5T¥án°³EBÝ怤’‚Ï» Ü’(•m{Ftà1æb» ä¢yõòxì0‡r~÷T»Ñ ü¨½.Ü÷Õ¾pa}Lä1L­·«¾~^9k÷õúXôpd0÷€ëˆ¹=—5÷jÂÜ&áB{”,Û5ì -cÁÐãÓ\ñã’® ÑâøÙR­bÙÞîöŸèùå{LÝ~&À%ÓNé.XU‰„q£N˜uÀuÄ®žËöq/‡Ð°W™Sz¦‰)£²%Z²Ñ”ï¬kûøÓÒç@$›Zì"y”uj•4©ÏÑÝ˾¹„°ùCÆö¹ºLM¶ïÊå§CÉ(L}&Ž+p +4mÂú&ˆÙPëòÖl|rŒupÓ¦>-ŠŸ%Ý¥Å@}©m2Ä{Ç7LÊÒ(oN…ûÊH„a8QÛ¹!B:¼Jͯþ¬»žJè#HäÓR[ip©,.6î#@[·_ªò ˜É;~YŸc1JkÊý«›ŸÍv}ïE«Ýø¿Àßõõå"öV -ÈË~¸¾¾?—<›7moQèïtÒ!ü¾q¥4cȪ¬€ ù¹úVéo}×Ow Ù÷Ô¶9"p\Û’õOXÁKe‡ÅÄ’‹ùqÅZBvR„¼^%¹SInUô‘;}äóonš„ µþà“ztàMéhì€7ò0h,·’®é]·Ÿ$ RÓNnŸ°…03lãJ6•§ŽÕ 9Ȧß/Ê,K´†â rÆ°ÑÆ¢ºäšZëºÙº}™Óã©Ýn¨…I¡OÔ Úm_v©†+ÖÚ¥K?ºÏÕ‹Ë1kp#n»cÇòDåPfG¸×„ó\áªi„Ë esš„ôtßÀ4`?~\¸À5!]œ²¬æJÅâ|ãÆåBØ |ÖÅ7Ûg„-·ˆ€oøêð¶oH¬þ|vÉ–66¿p/XS>*% *ý'ÕJíýÙy¤’‹&9:n³©âšÁ¹sE®v›3\dBšG&Œ<®7ºr„³8]ëxž‹ÇU/ʸXÁŒŠ3’´g;Tä@Å8hÒ ½î@O2w bÔî8Ó‹bÂv ³‹2ôMØ<ÎmQ+-¹Úјqôûq,R*1\¤TÜ-;šöå››„ÚqØ; q\AÊ™²|"ÜÆÎÃØôápðájKɨ§,^ÏNƒ(†]­ý”4hiV_vEî$ê+¥p§ÃFA„BÁ¹kY=ÛUÂ`IÀóOœB ¹CXà²ö0y -‘æÒGd»íŸ·ýâ¡^탘 =cŽ‹¸&ä‹“´,ᜋX@[ÿKžºº# ¤%`E$¢?øGúðàß{?–¿ÓÀö_-ø´½£Ð,ÛMç,BZ«âŒ-½Ó¹Ãš¥°•y/KDAáj3Êàœ‡ªd_öî`Ô],훸XÔÌAÏáyŠ'`'6¿!×aÏ \ÖsžöªÚ4a&;1¥gš˜2ªjyÂ`§ü¸©›Þíø…KžÚSF·]¯‹Íë³:5ô7îjÙÇíº -÷íÄ]žPÐC„“¹Ó—y -TÅøÀ&­£ubÌ©3‡!×ëx.kúÔé"¨²Ú@²Ÿ™À†,<.[àš. -jž')T\±tÿiFAº}¬¾Ôí¶[Ñ¥œO8èä[µË$ž‹®ó½…£Ù À‘‰é¼Äžcã¾f/4“KU0ø'blo„Rz-ªPðV:v;`gÔÝ8Ë]®|Y᧰o…ã,ÜàÚ ùÀŽªãœUÔž,¨…wÝD5fÕ¶ª¡ª(h_Ó%ÖíÔÙÃ.t7‰ÅC_íÝ9ºÅæ<,ÖÞuæ᮳˜ãÖL -jžXù¾Ô]uàXMW—îÌÊÝlZÍÝ© <­”tÈo]Û6hÊɌŌ;ÿÑltÆò¼*–®±Ÿæà™Úí`Ò£°¥p#¼¾3·}ëˆÁ¹½œÿ±…<5ˆ/ˆkØÛ‡Akr·Üféè÷UÿRQ” ¸£+C"UT_„Ô›»»‘±Bn[ú€½‡´©qûñƒŸsõ^‚†ÓÃÉcf”Àä_[Ñú9‹p|‰¿gÕ´#4MAˆLñ¯züõƒô~ôƒŒ‘º;%Rô®–¶Ø(ÒX±;aeF'DØL]1 4LP‘€ *:­b¾:bA<>¾€2è°û"P¡Š'Žb£>EGusÓÏ°é&¨Ýgt( ŸU»CJ {€ÙÄ¡GÆc¸(·UØwís‡ábÀ>WUŽõ G£Uà¿Óíø.xi·«òD°NýIê64±í±ðC…ÿû×I»ßa)ð ¦Iº›Ý6ɉÓÝÚ>(¶l ±%¯%%ÍùõgxS$™¶ ,ÎËA€hDŽ†Ãá77šŒ0ü‘‘3ÅG‰âH`"FÓõ -`î—âx"Ïu¹><œ¼ÿÈ’‘B*¦ñèaÞ‘%–’Œf_ÇçwwW7—×FTàñt ŒÇŸÏo¾œ²cw§ŠŽÏ¹šÀ+S,&B4_ŒÇ7矯.O¿?üvrõÐêÓÕ™`¦•ùûäëw<šê¿`Ä”£xÁˆ(EGë.œ1?²:™œü»Ø™5Ÿ†l ˜DBÒ$`JF °‚ö¬ ŠeÆ +“«+»ÙóO“[½øŠvL‡G¡Rö"]g³oX` ÿÈ™ýÔ FÓe6}š–ż3mä1Õ‘G8AŒ€4läݼ°2À\"°ƒi6Â}ÛL^‹rSåÕÐbpHæ*FŠ%<„wzSÁŒ°º"Œ/p-Wgß1XðkÄ¿{*n©©Ýš`]„€>BÄ!Dã?_Dó|å Ý[6(Œ;ÞVî, W[,„ceÍ"ZeÏÙêçÅ^›‹¼È¢¢…Åψ7ЊXÌ ŒÄlµ l_£E˹( ¢°÷×ù*]V¦ñD’áÊÅÑ ½›nš*$à-5¸9*pþ’Ç"xÇ4UKM’ûö|·NDU9} +é :I„ʯ%ßfSu¯!¡ÅT¼YÕœ"üJ +ß»S$î›ÀRv×þìšÊûúðìh¼céç–ú£¥~–Pż çÓ’Ê>g²6RÝíì„fJ!7bFúáçòjrq}÷p}{Ó~u8ã‚&ŒrìýbYyœÚÇ¥‹š6A×P6¸[Z'ÉË›‰N“vÀÏ„C–mñx“ôÌT9·ÏzéÙ4§)e3âòǦÎK·êܤ¸Ò­v=¹@–ú¨Ó &Ö¥M‚ΙÝnz¾œór»N­PàýÓ(¢ ØÁ™ýn2zÕ¦tvÖ’Ü‘i1{ËøÈg)"Q‰ߟË̬£@çòÉæ"9~ÉëeÙÔv&5Ê/šuVÔÕYà‰H“‰ÏÜ{Oê«{½ä«••om“º¥Ý~ÄáyÚ¬œë¿aLͶ5‘ë‘ \I‚gmÌxŸÕÓ÷F+¤sF@5 UZÌd·ôwTW[máWK@åSçéÊ¥ì´N‡G°ØdîLç¾>ú»É¶yV¡ŸÈã·Æ‡&;e°KÂTa$ã‡3u—ËW­»™ºåÒëF|¸¤bˆ1I/é™Kv M#Jô—üR9|_ß=sï +ghÈËΊù|à!˲r5Ó‚d[Çç|dšnÒÇ•,çí1 +…V(4•L|·VV¬Ú‘ÛÌ¡O:E…˜H<£ø¸*ì>šŠåvë?¦«¦ÊŸ3´¨%­£ ÃužëMñ +-ù†‚%ƒ(è.ÙEAü¿Gÿ?B”`„C¤=Œ‚×x.£¸¯ÊEWqŒ(#"\”wÕ#1ÄSÊÙaýZ®€‚ýv1F‹¤¯¡M ˜ÂZ·½}COn ©@Bvç k %\9 øn"Ò³.:/ Îëô ¹M5ÑýÜ%µ³ÖHŒ¸PÉnÒò=…š z€= ­_>B="c>~Ðw,åiÄ™€v¤j<Æô{½LkMq—àVe:Ë‹…Ÿt\;»×ƒ~÷úc`¨ó¢É*÷¡[í¥Ü>Y†t½í@ª+Ç ½L+»]¿ƒþn—i±ÐE +cP±Ô•%´t£«~ªÜlÀVæv¨É,¡Õé>SûØ”U•?+ Ê0RÇá’¿gr(‚HÒ6åÆÁC+êž,PÍèAkƳ|#*%ÂILúÃKD9÷‘«‚rnå*‘ÇÌ—&îùX•«¦v£›´^jØí.p(’#Á¥Ã´?¶x&Zf¡ÐBT‚…ó~h¡àµG”k™vµë–ŠAÈF]õ&æ6F¹3ÔÄ,ÍÖeñ¯Ê½iÝ,iŒô]€³À-ˆ)²ï¶¡ˆ½6ܘ‹d|©?YÀ¶éTû›^°íDE:¡ˆÀËñ"]%m%ü˜E¾uÕgÆ Ð_GµŽyo~,}úN«A‚ö¶ÒE±µ•- §®´®\AŸ¹’‚Vã0ú:\àç¹ þ®ŽâopƒÆß!ý:ÜQ0ŒÀ®†¦b”™¨E!Ôn_7&ÁÐÒÖ ³—¶nУºï½ÝdÅdòÉظ>D˜>DOØÈDWh¹Él|ª,w^ÛñªÙè«šJ÷Îœ!#ÊÄ°¯­êÔ\þ2é[½¨Ê… Ø0¦{MKm¶ùsZ;֧쵲T§½VØì«lÚæ/Çî&jEð–„&®ÃÕ3€Ö ÄÊYoYx÷ûÅä!m{ܸÛjè*(±%ëžË½¡Ø•Þ+JvŸ¦ñ—ü­«dëMý:¼úµÛ«2/"¯û¢ +÷´Jíu%ˆ-ŒéÞxö»‘ã1N4ßé(‡”Z̳ì,ÖëD ‹»‹Ý7Ã_GØp2˜œ;X,,šß—k'É‘F #ú²ÝÛÐß¾›0ŸÿÇx Ú÷#HÿrØn[úüÕÛ/p\ß·H6Ú.H0N)m+"’¡êíOY»ºÿ%Ǧendstream +endobj +2551 0 obj << /Type /Page -/Contents 1998 0 R -/Resources 1996 0 R +/Contents 2552 0 R +/Resources 2550 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1961 0 R +/Parent 2549 0 R >> endobj -1999 0 obj << -/D [1997 0 R /XYZ 56.6929 794.5015 null] +2553 0 obj << +/D [2551 0 R /XYZ 85.0394 794.5015 null] >> endobj -2000 0 obj << -/D [1997 0 R /XYZ 56.6929 751.9327 null] +2554 0 obj << +/D [2551 0 R /XYZ 85.0394 752.0294 null] >> endobj -2001 0 obj << -/D [1997 0 R /XYZ 56.6929 651.1304 null] +2555 0 obj << +/D [2551 0 R /XYZ 85.0394 688.0859 null] >> endobj -1996 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R /F55 1037 0 R >> +878 0 obj << +/D [2551 0 R /XYZ 85.0394 648.5014 null] +>> endobj +2556 0 obj << +/D [2551 0 R /XYZ 85.0394 615.2083 null] +>> endobj +2557 0 obj << +/D [2551 0 R /XYZ 85.0394 579.3639 null] +>> endobj +2558 0 obj << +/D [2551 0 R /XYZ 85.0394 512.4986 null] +>> endobj +2559 0 obj << +/D [2551 0 R /XYZ 85.0394 427.6096 null] +>> endobj +2560 0 obj << +/D [2551 0 R /XYZ 85.0394 321.0146 null] +>> endobj +2550 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F39 1151 0 R /F41 1208 0 R /F53 1303 0 R /F55 1311 0 R >> /ProcSet [ /PDF /Text ] >> endobj -2004 0 obj << -/Length 3048 +2563 0 obj << +/Length 2873 /Filter /FlateDecode >> stream -xÚ¥ZKsã6¾ûWè¶tUÄÁ“ã¼k’]3öÔnm’%R63©ˆ”=ίßn4@IÕÔ–€F£Ñ/˜/üñE¢C&SµˆSjÆõb½»b‹èûxÅ-fé@Ë!êÍýÕ«2^¤a‰hq¿Ì•„,Iøâ>ÿ-x}{ûþæݧÿ\/…fÁ›ðz© þõúæëëíö:Áëïï®—<‰y  a ÞÝÜݽ»¼ûôñæ¿ŸoÞ_ÿqÿóÕûûŽ±!óœIä꯫ßþ`‹öðó ešèÅ3|°§©Xì®”–¡VR:Êöêîê×nÂA¯:& ¥“P -–Z…RK5.22 "XÆ -VRÐr"|Ld…"[~¾ú õ™†Q"5LŽˆ²ÚÛå¦>ì²öT(<ŠBØGº®|Æ_‡aP –å1•ÔÂçðþ±¸^J®Ë´UPoˆÖºNÃ%õý]W–ø;cb[5PÁmÝ4åj[ˆ&k—®y$ Of û0Ž˜°²ø]Õß[üµèá.ÕÜ™fy±ÉŽÛšÜ.Uå#ËD”N·_å=O-‡œ'Ž£ ("‰E(l¦Z;Ñ•°C‘ê Þ·e]QÛÑö‡r—Êí‹%WmQåEN_m¿Q°*èûظ5ò—*Û•kúhʇÊ!ðìMm§{Ä“£–1?îö4"¢#Ã0·aEˆø}VuµÄ£ /§Ø^×U›•UY=Ѐã>ÏZÃvf5VvÚŽq@æ%)º¡pÎAºKÉRRAƒ¨ú‡#Z’0Rœ„¡×n¹ªnÇöµË¾dvÇõ#µš¢j,‘D Üd/f цg¶É€(a‚&eÖJ QÓV¢C+ñ稕àBÇVÿ,Û¶8œÙ ‹JÍsÖ¡FXóìƒÞ8O}ÞþýX Ø£È%z5‰¬fÂsÙ>-#*×wsôvlÖ­!0ýÛrS´å®ø >cdÛ-Ñ¿|A£¬ºÔæ7o¨¿lš£›Öè$ÐHë€ TÈ\]›ŠtêßÜ~+qß÷V1q…T¥ÜQɪ¢>6MM“àÓ†´Œµû’QT ”Õš&ÛpO¶æú™îî5-„…™05²‚Þ= y*ÍŠËîÒ$lòîâzR°`Ÿ5ÆvHÁƒÌÒœµ†&ì"K.1r¸ŽUÌH™à±§—ƒÎ;4;õcöTø3¯ì7Á -˜ìãȲ‘­êŽ#â¦Ïv£;Ã3ñ(0bhÌÍPÃ;N#29»'ú,“0¹³ú΀H.‚f_¬KÔO³+8ÞŒèv*Ó~.«¼~¦6™W>—FZ@3Û†_²ÜUæN¨Þ•n°møwÀ('Xƒ$…m{ÊÙŸ%wI°ùxl¬9³*“å¤ÇšjžÅ\<}rPdTZ?‡~½°;˜4T‰"ÆîNæRiw‰éËÉO(T+㜀ÚÚߦv8ð+À"µWÀEÛÐ÷S¶-Á¡Ô‡ÆÎSåvxq-jõb‰'b’Q4l¬³õ㨂›­±Jwa¢rC”-Å,Fd"¨Ž»­ }Æ9Ñ*KËëê-‘ýã“d£à—lŒÞ‰$´Qïìc l¶Ðtã‡ÓMÙÜÊžò¶h¬ª€Ã~(šþ¤A›m‹vël/4<ᣃ,ŒÒtÛ{åCw~•¶ž¶nZcì´3¨}v«¥s¬ZC@š$é¼c¢¦k‡2Žµq¬ -¸tÒÚ…j½‡;uêX!ÞKÀg9ëP#¬ùŽVd'¬Ýy6H¹X[)«lD4¸étzÞÈeG ÀS¼y¡£uà6TvÖ~XÚe›6;¹VŠ"#¤ž/¶ò¢…€­È­7…èÄ׸··_§O–A€Ÿ*}ád¨™“u(s²7c'‹¹£ ™š:[‚Í(³íDv%ƒäa–É5Â¥—70Æ*Š|6Mh«XÜ}~( –ˆèNÛ.ÄF ž:ÒZ7Ú؉y ±AŸsõ34ô1s-Sp: ÃA/€lè[Qì'²"©B29žzý4²Š࣓aÊ…îɸ¦‰% —Iwzã‰x#©c9˜õX•ßѶLMÊ”ÁdsÞ=g - *†B†ãÙYv˜så Ú*²ÓŒÉÓ[„ÔŽæVuÓU=»¢â‰(,û®v™Mg–órsj–2RRDÊh†2B`8#&°di‡tARØŒ°jRCüZ¨­Œ.°`A#ø•& Ÿ†ñÓHÌ´M‡}ùð– òŒeæL¢0¿]ýô [¬@ôo¯X(u-žá…\k±Ø^©H†‘’ÒÏ”Wï¯þ=0­ÚWçt ¢4Œ„ŠA ƒ4ç5ÅÄs J$è…ƒ^S‚ÏiÊS¡¦–O‡#KÇ‹1³£-=ÑÌ–b´eÂÂH²ƒ-¿ï+Òu·14hMóÑ44.×usÍÓÀ<ÙŸº¯V4Ÿù#È}V–4(맧¢zrìj<狪±FhŽÅQgBÁÚneš†è&ÇQ˜îÉÂ#×púOX +™ª FQ1’§²FÚ’P ž’«0Ž•vB­ËìÈ’: +E qV.O4#×Xœ±P(­¦‚=\kô ˜L*ÔöW[³­›Ï4×·Ù“¡áÊ<öÎ"Hõ3c2{j1É»ºm‹ÇÒ‘º5zÈÈþNrl¿X‡—±Óíul>¡Ã4M¼¦¾™a‡\ lº&ËO²I/—Æäu³ºèLù´Åg…‘PL¹\|| ÐOG‘°k'Ç{pÊ(‘îýmÞ}:¹‰ü~)9 6¦u¡'$Û´»ÚG#Ú4~ïÞ¿:tLhk½ˆuŠTŠß¦"ÔVûsPºô —cŽÇN,¢$ŒÓ$ÝoŒçz{ûöHÀT†Bð¯)¡çxIÄV9K¦"¾¾}ùÛá?Réø°2mÞf5àç1Ð?¡pÞ§þ^´ù ˆÒpó«¶'‘¼ˆv>aÌÒä<Ú©N£Ý@eÑ®šC;¦:ò®ø—|×·Gp—†*‰ÅyÁ<ÑŒ`S¸“¡Š’h*Ù+òö¬›#‰GVÉ¡„‡Ñ/CÆ™pTÏuóŸäÆq_!îqe#É.d Íd«YÕ ÂB½¦ßm_vÅ®tD¯ÞýкÂæÎTuGkíÎäx0+<sHŽùp®Ê¶fÁ–RC)ɧ@ó\ØÌ ˆÝ!úÛ‚`ýÊt¦Ù•qÓ7¨úí£MüŠNƒ´(?Í츘ª£ Jù0È÷†°ïÔ{Î^‰Ž…ç\C¢½[ÓLá˜n·¾ÊlþAª@ “ŽO1F¸á0¶§€_<Å7® qEd¾Ò½áíNlF"ãZá ˜G³ÃiW§£‘éA^¾#ª3Ñè©l4î.Fã®nº£`¡Òé¹<ÑŒ\coS‰>뻢íLµ¯íà·Þ4…qÀX»U/Þa„JìCqOu&ϺxçŒlãÊÚvWSçX™uñéÀ¹‰dGÐœ2i”$¡TZœ7é˜ê´I*kÒ#èƒN$=¿¥'šÙr’>t¨xħ[þç:QAStN)¾Bı«­»¬³y{¦hç*ðûš½îç 'S(pbOæ}Á|*º#…§<Œ´Ž‘@GûÉ^¦¶Ý<‘î8àôqŸéé=¼ÜпqP9xé–*cbµ;RûOëEš€ð©XDˆöfxîû‘f¢ôhs4e»ô¿®—1‡B~‹àöH3q¨¡á](ðÈn½øma7Ð’ˆFc{Ö½ìÄ‹»­X¼®áD‹ñ¡ã嘳=T~3úY÷]ß7¦4ÔØÀõÈW„—Huº{×9˜ω5”ùËýMÄ—¹ÿÒw\ !`}¡DT +’C zÁ*‹`ï/—ˆÛìÓ²­óG`Ç@ÆÂxã#ñªù&. +T‘š +xS–õóL…ŠIö­è© XªTù“øŽª÷mW¿›Âã$­A'$åÐ^NµpˆÔZÿx¸ý*Óµ'ÑQ1HÃ*M¿ +:r Y"êxïðÊ)|q « ø(µÈŠ¸ËK3ø á ù‹ŒßÛï-VÞ c¼9…˜‹ó$qˆÉä”"”O ¦<ƒ˜cÎgS&°OÊ'˜©Ó=f¸ÝÔ}¹¢±…3øí«Êä¦m3ìJì`vÀga ¨´…¼Ìâ*q†q;¶¦s[aœQìóõ¤Xì„€ÁŠxPŠy]¡>žzè:`ÞÉ ¨¾–Ƥ‰ Ìì×íùX„·¢¸·¹sŠ]W7îmw%u(" “ï°y†öƒPÉ»hêjk;B¤´þ‹*›„Ÿ+š¶­3L·ýn‡N©Xà^ö˜h+ÜÑurVˆõœ%QŒø ¥sêèïëΚ +†²­q„¡’u4猋y×ã‘p à\li[šË€Ïdk˜¯7g%7–ý”Eו³AdÍjPÎgäjÛM«€¬ò#Cƒ‰*¨ÂÇ8¡<-ãI•É$=Ni\’ +³ýp7ÚŠÝÖÉQoDÞ…p…Sý¥*kœS¾0OýÙe–PP¥ìÂÇ¡Ê–YÝL™¥Cu¯³äªhLÞa/wXdq åiÂLæWjºÄÁª6mõ׎¦Mù,wâ­ÉûQ jïÈ+wG^·î *°Ú¿aIǼÓü3¦WúÍ(‰…Œ%þn‰Îú3‹˜€øŒÂY"Å|ö³ÖL"Hl²]`¾-©†±Ë1] D{õàƒ³ŒHD@'þX”æɸ—mϘ`jͳŠ"‘GF « Ï0 ~ÍŠòtFê—ÅþŸÄ”øµƒ'Ù[ìtN]…ö;}~$ÔÜEøX¨÷¦ë õâDa¼<¼æ†äÀurû€%¤·]i:Ê{ð¼kœ£¹-±T·I¨µ€%w¾¡%‚ÑÇ('I· ØÔ8"ª”ñµÒ_ì#÷Š\7B¥ðûî8F'¢¸Kõãë oH^üc›å³!Ñ|ñßôìÿhI%!øꩼIjY'ž†Géñ‡ +hMfdÿþ½¿Ïendstream +endobj +2562 0 obj << /Type /Page -/Contents 2004 0 R -/Resources 2002 0 R +/Contents 2563 0 R +/Resources 2561 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 2006 0 R +/Parent 2549 0 R >> endobj -2005 0 obj << -/D [2003 0 R /XYZ 85.0394 794.5015 null] +2564 0 obj << +/D [2562 0 R /XYZ 56.6929 794.5015 null] >> endobj -2002 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F55 1037 0 R /F22 737 0 R /F41 939 0 R >> +2561 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R /F55 1311 0 R /F53 1303 0 R /F62 1352 0 R /F63 1355 0 R >> +/XObject << /Im2 1341 0 R /Im3 1500 0 R >> /ProcSet [ /PDF /Text ] >> endobj -2009 0 obj << -/Length 2546 +2567 0 obj << +/Length 2383 /Filter /FlateDecode >> stream -xÚ­YÝsÛ6÷_¡—Nåi„â‹ùè6n.uëäFδwMh²8‘Hפì¸ýíbˆ¤h%sw£‚‹%v±Ÿ?@bÆá'fIÊÒ\æ3“k–p‘ÌV»3>»ƒ¹7gÂó,Ó¢ÏõÃÍÙ÷?)3ËYžÊtv³î­•1žebvSþ1ÿ¥ìVàó××Ëåå‹åÛ7×ÿ~w}y¾™f~ñþýåõë·¿Ÿ/d˜9Ÿÿzqýá⢽?ÏåüâÍåòüÏ›ŸÏ.o¢b}åW¨Õ_güÉg%ìáç3ÎTž%³'xáL乜íÎt¢X¢• -”íÙòìŸqÁÞ¬ûtÊ:ÉX"u -fÑL›4Ÿ6™`F`2š3ŽìÁdRL™,p¡É7šj–ç"›õ;˜&DʞȆF‰¡È·wuóp.²¹%“_-¯hð‘sUÜѸ©éùÉ>Óàic=©´}ØUuUß…©¢£Q×г­îjväAo&Ã3¦SPþ´-{\'l¸œ-Šüþ§$éq -ÎL–'°:²´Å¶ë• ™Ö+0MèÕ7xž2e´êõÆÖö¡èÀÜ"Oæ>Òù5ä‡"ÊjST5QŸªnCÄnc‰tW=Úšhû™¶^5¥-‰÷™$1qhº,Z¿ÊGžpoÕSSf)Äu–¬2ÚŒT,ÇT#&XJx} ¯í­ßÒ¾ º` ¥ªËj…[†Ug %&…¯ -Áò$‘nÁ.†MÂõp£ªÔ­U’4ŒÇ;2o Gg9xãЙøňL1´úBDö¹^ŽÈÈå"òS‰Ìx«VÓ½©Û±rBq–˜$;­]äšP¯ïK¡–$F õûíE#Ó&Œ^¦ŽÚµ/U·Q©Ÿß‡”v]ìÇ.œ¿ì¥˜‚ærÚ/¦nñLÎ+G5×0“ -uR^à9–×·³‘Ìh™ä‘••ÌVÆ÷‚ÞÊ8ôVÆak;¸€ÆÁ»÷7X·ß}¸¡÷P°qÜø¯ŠíöhQªö+ªúeëë’eCϺéZRòf,KÌ0q{Aq´2×ðêC¡µ«}¿×”vkïBp¼àô$ËY–ªÓNï1½ìôÀ„JÿÝÔì%·ö¨þK–¦&?)7ðËTÃR @£/7¿N¹ÔÔ]Ñë ±d¡–Ó•[ª-_6 ¾`µ× ³.ÔÀH¦Q8ý™iBæ _2&31’¹¼·«jõ$…–¸©V‚.-ÚM³ß–4v‚§ï )u!Ç6ó”gBcYJ²ùÛ5‘êf¼zCAeÐy¶|ã¼å–5Ãe½º& × ì Ì(ƒìç”SW…|ÄÔ|uù/"gælG“$WÅxÁ©{û7Æ5mŒêFëù;úºÙ×^tÀÛg9ð+¬íÝjC± -o÷Õc(|¸-´à«ú£È†:@kÖ¾þ—•ßb×<<Ÿ !æ¯â'‡C§ñf„±Þ ¿AOæ± ôРÜz¶Ð÷x -Ž,l„¢Ò|ùûů﹜?°5i˜æÃQ§„m·ÍY#,ÔìvdD˜Cù- qßnQõ»0œ9$ÏÅ0¸ßZ‹LhBFdià ¦=FDá]Pêõò‚×ajxIœ·ÏÑ&=m -dyî%”u åzKÀÇú,¢ÆLçC§#ļêí„}]é;a¤6!&ÈÉ~°€ÛÇ·Ø‚2Úž‹ù³ÙíÛŽXn=«k„™Ï2$슰C9E†ÊÕýý)e y[Þ²ÓöÎK³TöànÔ½j Èj)ą̀E°QU?6+×Ô@Ì·Mó©¥!†æ±b¹˜»cÖØ)ü­r(‰ÚD…pØ_*ÍÉ6Ú‡ù¥t:_øiÛ„O‹ŽF¯—ô<Æ Ú£}8·À½Ðr[tÜdQÄ£’i„·#¨ow¡ W BQÂqI*á·º¸›rø25ï[v.—&8,r–r¨»ÈýÍù"å<8f)eA=zöc„¾Æ£}J E y0U+‡Ë2jïSŒßL'ÚŸ?Ñ‹­˜·Í#¤–ór^MØ=Ï™™V€h cÁÆ0‘Ëà… ÄB;ªö¤5rPš00‰™ÌÉžƧ8@&2GQw®”—GØ*BØùm8€xçXó–%í×¾ñÕ«ÐOBï*Ƙ¬í`«»ØÁ|ÇûIÂxž†âS;oûÖS…^2À É Ï).…a -ÎC‡G×â‹ôûY„.„q@÷4óX5ûvûLSÞÖnv(CoZï¬ °¨½t¤ÓÕŠˆ›GP(øúå¼hÛýn:¸Ç(÷¿ Su€O€ÕýTJ‡°›Êö‰?YL¾²ˆü?êÁÝð!¬¹º~÷Ûµ¿dýðf9‘ø#xóU™Ïs‚ô©@Gk<ÐÅ@Òµ¤ú« TQV>)5¨\Sxê˜`@€8ë*8Áð –ômi¼•tá{ø´Ýߺc²›\ÓÅŽ—ДHAý#¼Šgz^[ëîÓ ÆPL²¦)÷+K„‚ë=(èL…ð¥$¢?W6Ù‰+à=i×¾ö›9E‰—¨m½:®Ñ®?óÄÃY`uÛ¡ú –7Ÿ[q"<ýú&æ²óH"xè(Dð3 B|ëN8€ÅšGÿ(ëZ( ä #ÞZÄ0¢§€ÓžM@€5)i(ôD¤ûbYðÉ_ÜÅ;¨P©b™ŽËû[ëXÆÅàÂá™l¾¯ÁÒݾvåKiòJ»°kÜèê qaTá$]u!o]ìçê¶ÚVÝ3M†)÷èFº±øú6›1‘ÊØ–ëק+¸ÚØÕ'/³!Ò®ød‰ÒÆ+|« H»o=€UV–‡<ÑÐt'%üTHJ$¥ÝÞñá$‚ ¼ÇžoaP•D¤lr|n·øèâlãjApOq 1%'Ú ~”õ`T„_»€Bâ[Çt{ú@‚Z?´½6žV„ë‹€‘ó¬ÿÃ…>çê{éÿO•0üÓrâÊG@ð?ÿ7zøXþ̲.ï¤I|œ¥Ð”B¤Çw”œI'ëcÝÿ&,±&endstream -endobj -2008 0 obj << +xÚµY[sÛ¸~÷¯à[©™ˆÁý2}r'õN⤉Òvfwh²Ù•H­HÚοï9HS%w›v¡´ÏopÎÃc_·"¨°­aV4ª–WE4®íWÕó`0‹µjßâ¥kÀLUb皺Û-¾ét]nʶ™@¨†Úô[µB?ôòº*oÝú;dI_Á”–à—² ‹7.¯"×ö>oû‘›ðS°+ˆQÑæy7áÜ „ÑHRoÛ²®Ϻ¼uLCÖQ¢{ëB±|Ä,­ƒã~Ãp2›>Þ»j"k¥Êµâå¬å†õ¹]F–A@‡›ƒ™´®ÂìA‡,c5ù5¸r‡éý +“” ó ,0à™µóíÎñ`¹¥™!PhöÂêYºÏšè´)+Œ0¸2Ã'öCYwM >g‹² ªº 3°›jÌŒÇðz¼i`Ò'/,ºuá}çÚ¼¬|Ú"‡ªuœ dß +Èâ®<»c Ñ@wä1ÙaVc“áɸ†ÿ`_àxZh“óçîöc}kŽÊÁÇ94@ ŸÆ š –m"°0‹çnD' Ã@å7Õá_,o(šŒ™Iì‰&DŽCàÄh} ò‹ƒÊÔ<âë%Ü®ñ[_ªnsr„²…÷T¶GA –ÓDj‘ #ä÷À`LuÚ?•÷Ïßü£As:+²'š¹W½tjc÷Eþ—þ¹íÊu†2ؼúCP;ŒÑ/xpDuƃ=•÷àSØ›RîžiceÜ›Ë|yïæ+¨G`G€" Îª7PMè·ß, ¡@?ÙÓïCGÿy›‡Ñj7£P¬7Qóq/Ð$SZèIÍÄ)(èJõF–Ö½½ úÕ1d«ƒo…[åÝ:¦ÁCé¹E¯¢’²ŒXCÿ'@Ykiö”øàH\dLZúHP.”Ü»ëS(™fR³\z|üÅÿ¿ñˆùz³ôýIÜ,$”REiÄÍ$³Tˆ€•Ç㸙ŸÃÍcÖgp³PòP†í¾ðЈK= o<†nÚðÚ+ |Ë„'`âmŒŽŸ.ˆ{Âh¿TÐQ]à¥B÷…Ù7×7oÃȆGzþ :¼[×[(8DôÝPM´I79’/¨>wnãÛà)pàø]?YVᙇǪk»ÝÀdíòÆ€yªk“ê‡ÒôÿгG™}R5.—£Ìïë%‡vÁ)µÞÁ_¯ßß\~ø:QO L‚ "ôÑkô pîkUׄ +»S §ìîª!~lîëÎ÷ Ó +'oãJL«0òµ +žËºjƒ€uX +|Aܸ4¦?G]Ç­€3i6 ¯]U,',bp쀉žU;Ö³¸i]^œl`œßxf=ÝÀÆT§Ø@ò×oŸÊ „Î3ê¼ÜjBð^iàŽ€ö$¿«½ë—±%Äæäç`‡ömë¨u„¨Ì´HO; 2TùB·SqVOu}³À^ÑL,®¾|êÈy Ž93›ºˆß¡?±û·iÁ€§Û<º¬ bñF +2€S•^¯Â— ¶9‚ÉÒÛïS½ N]zîK™hÐòé¿ +É#ÃÉôÁeD·¼F¤9jbdú¯ºÛÁ¾“QG¬ˆ–§•óÚ™þH|Ÿ?¸0³Èçcè⛲iú“¬™`3™vÔ(ÑæeqÞO=.Bè7yaG†ýáŸÓž/:ƒcɉ”ãHÁi)*…†RiU—ü†9ÖýßÙ¾ +endstream +endobj +2566 0 obj << /Type /Page -/Contents 2009 0 R -/Resources 2007 0 R +/Contents 2567 0 R +/Resources 2565 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 2006 0 R +/Parent 2549 0 R >> endobj -2010 0 obj << -/D [2008 0 R /XYZ 56.6929 794.5015 null] +2568 0 obj << +/D [2566 0 R /XYZ 85.0394 794.5015 null] >> endobj -2011 0 obj << -/D [2008 0 R /XYZ 56.6929 485.757 null] +2569 0 obj << +/D [2566 0 R /XYZ 85.0394 388.8031 null] >> endobj -2012 0 obj << -/D [2008 0 R /XYZ 56.6929 207.615 null] +2570 0 obj << +/D [2566 0 R /XYZ 85.0394 246.2919 null] >> endobj -2007 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F55 1037 0 R /F53 1029 0 R /F48 953 0 R /F41 939 0 R >> +2571 0 obj << +/D [2566 0 R /XYZ 85.0394 128.907 null] +>> endobj +2565 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F62 1352 0 R /F63 1355 0 R /F41 1208 0 R /F21 930 0 R /F55 1311 0 R /F53 1303 0 R /F39 1151 0 R /F48 1228 0 R >> +/XObject << /Im2 1341 0 R /Im3 1500 0 R >> /ProcSet [ /PDF /Text ] >> endobj -2015 0 obj << -/Length 1499 +2574 0 obj << +/Length 1411 /Filter /FlateDecode >> stream -xÚ½X[sÚ8~çWøfŠª»íÇ”Ð6Ý–dÙÝ™6.ˆÄ-Ø]Û$¥¿~,ÉØ `ÛÙÉLÆ–?sô+"†?Daó Œ9˜ˆ`¾îá྽é‹:аz5ë½|Í F±¤2˜-[²"„£ˆ³ÅÇþÅÍÍxryõ×`Hî¿Bƒ¡À¸ÿábrwñÞ¬Ý bÚ¿x3ž†$”Œ(Ô0‰û“‹ãËáèíxôÛèzòzp?{×ÏÃÚÆÌ´U÷>Þã`gx×Èőžá#Ç4X÷¸`HpÆÜʪ7íýÞl}­·úÈ,B"¢¡‡ JBP,íÐ!b$e5ÓñØœúâýôZŸvч8€¯H -Êkø"+K5~UÛ•}ÂGð¼0YÜ&Ÿ ê@€Þ÷êjriôÄVÝbfiYI•féV-U1 Q_ese–>$Ù&YyÌ"2BTJiÅû à(Ž³€Û×##lbyœ ʱhdú†4(Še ™D!COw³·×·ç™»Ê*Udª2fL·e¥Ö¥yåY™UºYïôrĸ¤VXE46L¢âCÌfÉZ-†óG5ÿ:ϳ¥Þ«ÁL &Cžäˆi1D6¦í ªúDihžêÏæ>˜>lÀmižY$¬¬¬ÃÊmV%ß-X L³óVåùÊG+vtJÛ,ÿV¦å~jIÈA.0E"äÞT pB*8<{‹FXD:aZ"ê4áÄS4”—! ü>Þ»§§æéKóT™ã -Ö’NqŒ(©m¬Ó)-Ô`k CG’6!i¥.Ó•ÒÆ8?îý¡*Š8]n/ÇÓÑíÕÍìêzÒìòÄ«ÿȇQQ-šZk¤ èê±/ÌËç þ,¯öqjdU:/-4·A˜üLú³ÖYÙaâº&azP¿mˆ0 ™®œŒ£6Ê•ÛÃ8jPZïðq_%”lÎù•äQÙvH#®ã¿£ò¦H³}º7eòà˜ß¬× ÄŸ¡;³,«ïi…Ž²†GŒa§…:ÁŽCÕ츌íC!BEèË—¶m„‡°äœ4®Ay¬ëtAQ̹ìš7z¬»S®£—á*š'k¹€f,C~w”‰¢°9Y™[¡‰ŸfóÕf¡Ì ª;ã¼JŸTiÒÏÜ.‹;H½è -´~NŒóòÍh® ©/êþÁ‰¥æÊå—ؼNmZƒ¨¿±¹÷yÛIÕ2]§«¤Xm]pœ¹®sùhlј!"ä™Ìk£ŽÇVƒªcëé ó˜îægT:Ge'ó"ðe¸§Ò—yOª(›²åªœþzXa€„¬ÇnÄùÙzl}ûP$ëŸIn*AJÄÏ9 …:ᇪðÃãÆ"zZ¥yTî9€‘XtUÞ¨b™ëN|Vª´>YåÉb¯Û¬VæaÀtf§Òy¦lø/óã0Í<¹O!g°¬í1tÄY0ƒ‡0ˆ·N¯;EœÐ3µ¶:ᇪÝñåÀÉóÓ*È£²ã ƒÔ¶ŽÊ?U¶£¾ “ÏíIÒÔ)ç¢&¾ä›"KVÝz”VMd—UyœLé0ÇçÈl¡NéPúdÆîÌÛ¾Da‡È<­»Ay”wú’žÚa îjŸÕÜ°°oCÊ"Ñ°bhƒ…ñ ¾6tšY½öÙmÐ…Fjh¢µ4«frXùMÍS½_-ôÈÆ­²PËd³ªJk€¯G2¿j‰t£íKUÍ_îÚ‚žr(üÞÑmºÝ„Ž$e(&˜ŸüåÆ¡<“°;ÞŽgw·7 €Yø|7žžŒù/bÈ„mé -ñ®Û¦Y%Õ¦ì#Ò qU˜z^Xسr\¿-T£k±M¥ÇV$„Añœ–ÿnBå^ &¥u°kõ†)“Ý'® ×…žðÿç¾»¹ÑóžxÄ gÿùVgwó(ƒ_öþlgXW…˜8£´á„„û¦7÷?‡¶ÿN¡‘-endstream +xÚÅW[oÛ6~÷¯Ð£ T/º>º‰Û%H,v€m‰¶ÕÉT&Éͼ_¿Ã›,ÅJ[l +yÎáá¹~$‰‡áG¼0BQJS/NbzÙ~‚½-ðÞOˆ•ñß—z»žüòŽÅ^ŠÒˆFÞzÓÓ• œ$Ä[ç§o¡h*ðt9ÿ°¸ô¯oî—ó›»û«åzæ“0ŽÂéüîn±¼¼ú}æÓÃÇxúa¾|˜ßÚÝ,¥ÓùûÅjöy}=Y¬;ãúÌ”eN>~Æ^~\O0bizÏ0Áˆ¤)õö“ d( s”r²šüÖ)ìqõÒÑ€Œ(‹èHD(ñAiÒAHÂEŒ2’Õbaœšß¬n•?Ç´Gìù4BZ§Äïß]@œR<÷˜§´'`QË”ô›…ÊDF¬@_]ðÿª @O1J¾¹ŸíDöGVÉÍ'âþÈ9ûïJŠ—ìZæÙKZù\ÏH2M>ª ¹mBÃ9wÊ' £4ˆ"¹ü©ò½Z^šd¥6gù¾EÓÖ¼­jCºav—™0¤\x9%ˆF°‹‰²"ƒ¢ñ;!Ÿ%=iÙùÃú×Ûû/êåJ¶¢–¢5–¬ŽM+ö™\T²©ê¶8ìOûˆµz†â4Š»Î…ÔbèD“/Õ¡–¼|ª Ùªõj‹ÅI ,AjÜ<¦ÚóFtiÛ>Q›Q¨ÒoFv™Ò|w‡=—¾‰=Ïùci…7U½‹,v M#eõÔÍKLaÅIļ âC6†¤À¯Š öUh|ÈbvR¯H»ì^@©8p]è¢3ZMNtPM—‹ÕÅýÕÝúêvÙ­zµ¤^3i甂3$¶i)[víÎ溰¹Ú˜/ÿf®?aL]^]Þù÷Ó¯;ËóQ>IPš$Æk§Ÿ©Õߘ 7ÊÔ$™òC[íy[d¼,†ŸÙÍZ‘Âãq$z$0u¹ÑÁ‰ £‹×óNH»ÇŽËí¨A{ž Cn+óÍ ½ÈÌD°qN…X - d1·Ò§”¢0Lã!âÉæ𔃃cXN©óK!)œÔAM×;¡D›µ¹Y¥¿¹¡ ží̈çyÑ•43…Ÿê›‹Rô¨+ÛWØ@ÆÔ@áëù6ÊKëêPÌÇBòÚÚ£J·ZZ–Õs!·†¥ªR׈sk†. n.*Ü4„l 37Ûûüé©,T%t2QWì©«g ™Üž˜0hDýUÔF°húZ›–×­SÊ7­“âváîÐæÕ³Õ§ øf5ov ÆÒéÛ£¡åbÃeûÆAµñÎÜÊŒ˜èâT#Û@éX§.„I×… ©íšŠ­6ÆGÙ딉¿ ñ•d]V¤‰ººÅ̉_äØÉICÔµ”ŽõI=îÜ çn@‘ØÀ>U`Ù |Þš¼3¸Åaû‚!ã3‡Ç>žü<2”âÄü€„…„,6¥¨'€T3Ý +±ièâmñUcPºÜ¨‰ËÃÞUoÅH½%dÄŒL‹8¼´VB²Ð ¬Š°,¤p­°-¤òdú\´–‡xM®>†PÕ'ô¹ú¨{YDºž* )™Â=ƒV`ØE¶•’3TÑ’¼±‘ç"î¦Eäv'.-[E·þ°!Œ‹a%çKïÔ:‡ µoÓé|Úó¦5WB¿|õ"ý½›Éùá[W>]€ƒ‹/,u@Þ£Ÿ_{ PÌ¢À–åO¹îÒ˜! O·Ÿ}Ûeî¶Û;ÿå×ixq³½tǵž,WfЗ=´EY´Ç×^¹,Dêi:råÄ]Hÿó øôÞbÄ’„ž·@Ž‘S[£”ã$Âg¦»·ò¹íÿ÷ +)íendstream endobj -2014 0 obj << +2573 0 obj << /Type /Page -/Contents 2015 0 R -/Resources 2013 0 R +/Contents 2574 0 R +/Resources 2572 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 2006 0 R +/Parent 2549 0 R >> endobj -2016 0 obj << -/D [2014 0 R /XYZ 85.0394 794.5015 null] +2575 0 obj << +/D [2573 0 R /XYZ 56.6929 794.5015 null] >> endobj -2017 0 obj << -/D [2014 0 R /XYZ 85.0394 752.1815 null] +2576 0 obj << +/D [2573 0 R /XYZ 56.6929 751.9132 null] >> endobj -2018 0 obj << -/D [2014 0 R /XYZ 85.0394 689.7995 null] +2577 0 obj << +/D [2573 0 R /XYZ 56.6929 674.8216 null] >> endobj -678 0 obj << -/D [2014 0 R /XYZ 85.0394 651.2999 null] +882 0 obj << +/D [2573 0 R /XYZ 56.6929 634.4081 null] >> endobj -2019 0 obj << -/D [2014 0 R /XYZ 85.0394 618.4832 null] +2578 0 obj << +/D [2573 0 R /XYZ 56.6929 597.1931 null] >> endobj -2020 0 obj << -/D [2014 0 R /XYZ 85.0394 583.1153 null] +2579 0 obj << +/D [2573 0 R /XYZ 56.6929 564.5425 null] >> endobj -2021 0 obj << -/D [2014 0 R /XYZ 85.0394 517.8114 null] +2580 0 obj << +/D [2573 0 R /XYZ 56.6929 496.4842 null] >> endobj -2022 0 obj << -/D [2014 0 R /XYZ 85.0394 458.3941 null] +2581 0 obj << +/D [2573 0 R /XYZ 56.6929 434.3126 null] >> endobj -2023 0 obj << -/D [2014 0 R /XYZ 85.0394 396.012 null] +2582 0 obj << +/D [2573 0 R /XYZ 56.6929 259.4673 null] >> endobj -2024 0 obj << -/D [2014 0 R /XYZ 85.0394 145.9047 null] +2583 0 obj << +/D [2573 0 R /XYZ 56.6929 194.3308 null] >> endobj -2025 0 obj << -/D [2014 0 R /XYZ 85.0394 83.5226 null] +886 0 obj << +/D [2573 0 R /XYZ 56.6929 153.9173 null] >> endobj -2013 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F39 899 0 R /F41 939 0 R /F53 1029 0 R /F55 1037 0 R >> +2584 0 obj << +/D [2573 0 R /XYZ 56.6929 116.8171 null] +>> endobj +2585 0 obj << +/D [2573 0 R /XYZ 56.6929 84.0518 null] +>> endobj +2572 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F39 1151 0 R /F22 953 0 R /F41 1208 0 R /F53 1303 0 R >> /ProcSet [ /PDF /Text ] >> endobj -2028 0 obj << -/Length 2089 +2588 0 obj << +/Length 3959 /Filter /FlateDecode >> stream -xÚÕY[sÛ¶~÷¯Ð#=¢¸À£ë¸­{N·v§¦y %ÚfB‘ŽHÙU}7Š¤H)N|δã –{ùv±ØÉ Ã™‰%šê™Ô LÄl¾<³;Xûþˆxš8Å]ªo¯¾ùŽÉ™F:¡Éìú¶ÃK!¬™]/ÞEß"…ŽŽ.NÞœ½ŽO8;ýÏïo/ÎŽc"J¢“Ë˳‹×ç¿ÇT` bŒ£7'¿œü×Í]k|vuüþúÇ£³ëV±®ò3£Õ§£wïñl6üx„ÓJÌžà#¢5-¸`HpÆÂLqtuôSË°³j_ƒ`DYBGРdFÒBÐB£„Qfá8ùåú‡·?C€œvÀó˜&ˆ -Gv^6ÙªÌÀÕ¦n²eíN«²®VM¾^z. ”#ÆêÙpl0èÎ-Óe¶ˆç÷Ùüã_U™™w 1 Xjˆ/€dB3xÒX[ª£WN+?[-ò"³ìô”J7êÌaL ?~L‹|‘7÷d™æå{ªV~¶*308Ì7UUlMßâm¬ÀÓ’Z=¯6eõPçõ0hAR%l&À-Šh6ædöWà‰@’68Ù-ÕzÇq¾y/Þ‡Ñ};úÐŽ>µ£Çv4w€’[‰4Qà'bô6²æEZ׎¬§xS)©=UËñv„#„‡J„ð¤·Õj™6#ûd-Çï^Ž£ ט‰8Dú,nÝ‹ïâ| †4]à,«E6†„%bC½?Ôûyü–_Çù½yaýÊÖ¯>ȯn6Eöù¡yõRû0¢2= aD|5Ãh‘¯²yS­6#¢G d¨úÓAÕ¿€éëvôëûD )ÿ×™”d2”{º…T^ú3a4ƒÂvÄŠ}Uí°Ø“AU'ƒvOšaý‚Ì a¡ÄçdN5ôÆé oÇÿO"†ÃRB±“Èþ6x.ëü…sÇ?=÷–/¬_uØÙm8àÉ%RËÏÉ¿Pé)d˜öÎÎgæáæ‘ÌþUrÔ_}´öø+f #N±ê{a:íkܘr¤±Ù³ÝR÷õÙÕéÏç—×ço/Ú—¦:‹‘>`Pï+*Ê`·¥´­‹š{[¶ó¨Þ”Mú§›LË…›Ì¡g¹[ùbžEÕ­_w«¡þg¾þ‡>A÷w޸ɇle2ÏŽ ‹Š™ÚêÁ£´1“"„Ò°Á¬#ÖÅœRH{Zö]°¨2Ã\ñèé>+ݨ¨Ò…ë:”3C93@u(!¢ëû¼vkËôc6¦‘Âœsª«Ò!è%Õ!Öuv».œÜ[Û Á Ó#d*Ì;T½ 7™¡'*ò‹ÐB™õ»Ø@4(„bºŸù׫m‹uŸ-ÝœZ¹QºmôܨÎVЗK¡ñ¨# -²“H&Ní]ëµ@”$a+;pAL¾Ì‹ÔZO ÷)@Q®?e0Ó\L«Tt³nœ¼¼q¢Òâ)Ýxë僺Єõ½mP›¬lAåß÷ê?dó;Nš³A -Îg Tc†EÛ3œôn.u†QÖÔ&¥ŒNÐFçU™Åæ˜bÌbD[k,“‡‡"7áaY5«|Þ€ïì’…Ê-ÙcVÔnúfã~Ùmº.Ão”óÌ-X$Ì[pŸÐ ¨jÝ<T]•…Ýdî¢{áFiíKÿ;oÖ©§v(›Q q;3¼}³ -d -q @6Öš…óÓ^=ÑèW› ëeZ®- ö©ï˜¨ÕS^›;Hì¿¿ ßrEûŽö8›­p6ãåºö×´TFn¼ŠgVD¢‘]¨$´R Dž•éM¸ðZd7ë»;H´hÒrÈäÝ-Í«µù~Òæia[‹ÂFíÝ -»„c¤ÙF¬ëô.„èz¹LWþÂÏ×8ÊþÌ›iD°¹ŽÕô&ª=¨*‹Ë§I\ö‰Ü"³#r›®ÈŸÖy¸Õµe§Å[•gXªJŸÏ'Ñ!°‰2yYíÑéRM£ÓRYtwЦr: 2ˆì¡ƒ‘`x r,v Æ¨Û<ãŠÊ©|íÔ58yN½Å4 ǃ-™ª»Uº|NxHkŠIyÀª=TÖvÀ£RïˆFDvmOüY_¤;ûì!Ô¿]gŒßâ»R3] ˆ?TëUir{yÏ…H릞ÃY!}ÔÕP•5\ÿˆ^à È`;·?]Åt‚¡|¿bhD1Ú˜º£§Ù•9¼o72;ÁßzÃôQGç~­¬šRàUû-†Ÿ_˜ÿÞu¨# 'g‹IWH‰¨„²|¯':DÓŽDÖùˆ4tpBÚò®NJCƒ¤ô^Í®N½fZ-sÓÕéÒ5¡€(‡Ž´ª›Øì÷è QÞësÍ‚kLMí¨ttYÕun{Ci,¨UêÛ±‘"L&P„êÐoÿ@×WX?íf,ó%Nê©`}}Còj„=ç+ÍÜc£%lï )¶z‘¤ívÙB ²ýCZöE5O§´‡*Ap"öðåH+ÒÕÖ²;¤®Fœé ®ÉÚ#gƒFLÈ.ç<:¥'E‰h¯@ÐÔwgh2øøõ7n+à¯þ&½ýúÎ%bJMTT -#{¥Œâ„¨ÝMí¿^ïêþ7Ü°Mendstream -endobj -2027 0 obj << +xÚ¥ÙrÛFò]_¡·@Æ8&oŠå$ÞÄŽ×R*»ëø$ e`P +“Í¿o÷t. eUm©J˜³§§ïî¡8àOœgq)£ÏS£Ã8ñùj{ßÁÜ÷g‚×,Ü¢ÅxÕ·7g/¿Sé¹ M"“ó›Û¬,Œ²LœßƒË÷ï_¿»z󯋅Œ£àÛðbGQðöòÝ/—?ÑØû #ƒËï__CWj•À"¡p]ï®yuy‘êàæõŧ›œ½¾éÑ£."…8ý~öñSt^À þq…Êdñùt¢P#Ï·g:Va¬•r#›³ë³öG³v«±ÊÂ8“©‡Rœ š8–bÄ&L”T–×ǺٵU;¿Jø(š*J‘hßÑ-c m/‹¢0Šä‹1‹–>¹UˆUÝvEÞ•‹XóqQ|r­«¾uGÿÒgÑL»›i÷ˆ÷{ù]¬F'K™†BgÐÅ3?®·ùê›OŸËcoËoÚrµ/;Ú6AX(TN2ÞæNøì;Á„YæàÛjSz jfZñ²O¸à|¡£8Ô)JxÏAÄqÑùŽQ¡Aq#]µ-›CwòÑÄ„ ªš¦?|÷Š¤PÉô䜺HF¥Üß—{4! 2ßa"Ç7k{‘ùfÓƒ%Ïlš¶ó2ëÆJml|JÖŽ• ™«Ð¸ +Æ•Õ#‰zåƒ9KúžS>°W}ÌbAÈ’%úY,N¤qnfß36ÖÀwÉ}k´,ò<Тm"ûGb¨)ÛPQY£4ø0¨˜–Ã¥¥ :uGÖäø]óøŠ÷ló¶C ÃöØZðdõpŠ¾"¨ +[¡Á@:á JÎ0t¼}wùö55í:+K° ¹ !ƒDÖöúçËg(uÚˉ'æÁ¦rŠ¸(<ü¨‚Âyá†9¡À埋Ÿð>QabÒìY¬W*@—{òe»â3Šry¸ããšùkãÜ îÈÜÜÁy¤Ûç+²éÌm³ß挳_’+À…k¡5^q’°æmooY×ó±ÞæE9Soâcd·©œ`®••U&<Ùd'yaënf^ø¹LIê4lqåc²µî£2ÇdºÑ &KÈ„ž¥ß`´t ™;ëÝ\…‡9ûjù}gù‡Ý ÿØ.ú.¨ Žžcf-- ]`˜`.“>“Š*2NX?ù©ÀôœŠ‰vZÖM'1ܬ+ï¬EÁAK–»Ã–ŒŒX+ß?K ÝÓæuu·v{ÛÒÊ$´H^ ±i ¡Ã„Û6å}¹A›ËàÍì€ØÍú­D «IÌT/*–Þ¢jóå¦öüYðê°'äëðB¨GZ› q»ù°C»W2ø²^íÎD@?ßÜ5{0[êÞ6maqˆ‚ üðöòÕ‚“0F}rÕ·W±Å" ÖÕ +í¸LÚœSAìÚDD³ `C +ˆÜðr&ø¹¶I 6™höh2¼Q0õ8ß!³wxAxä;ð€« Pk¼zKƒÕfC+ë²,|rjƒ³ÌÕÚCbfUèH3m¹)müqŒˆ|'qŒ°ÛWäÐq|Dlì¶ô}(-YÖô>Ó9HÓ²æ]ƒa"k‹øå–à™£‰Š†ú»fï³4UÝv9ú¦•IÕ¡YEh:¬ÐñéÀ lìJt-õX]`Ù’¸š^Ï)³$Lt«½,»ÕK÷"„”æÖ£+FBl××dÚ†a“ÎF±3iš”†¼H +žk“{»‹°Ö `#oÛfE\®Î…fÊCœì[bY(H,Û¸Œ]rÂÀoÞóÊ¢`“ßÒúßÑJÀ ZÍ'‘ STâ“U¢†-= < õŒ\P_o`‹‰%‹‘ 5µ­[?ò voÉU’Ýa¹±nÚ$#а椹Ûç»5™"tƒEï¦1©’<>Á±SJõAòLjhŽH3 ±=´œJ-Ùøµ]ÓÛzkÁœ­£Ï¯ÿMëçÞγ–ê9½æEËã [­æ¡òEÞÖ ̺h¼b8-èÑjM)‹ (ÂíKIŸWÍHy^˜%ÊyÙÅ݉øYKWïÆŠJ~Çh^캩狢PÏ ÛŽ.Ó.VÍô4¯9Õ¸Ï÷CÇÆ×ñô²Ÿ¶îr¤ï¯1Æ=…­e‌¢hVÑs5š1a¢Àe,C-ÈOH<ÃT÷áÇ¢ùbzæóXªÁÑ@®—%ñTF¾T`Ó}å¾ +^&šPƒ•w¨ýå¡Ód¨Øy2)ÆIê4Ê=°<ÅdÄj1NüŒíÌ$À´ÅÁQ€ ób¸9‚we튰‚ë‹l aàQ4³·ìÏB¦a¬Ò™{3¤+¶ƒé +6úBƒ1“BƒÄT·ùaÓÑÖiæB.-Ud´RW„ÆÈYËÔØÀç1Æà‚’Ø©Òøõs‚›}lŽ&¨Á‰„Ïk>}™·e¢é`H^«D81V8œ)’fÁ/-ãKP'„HF@ü4ý‚%éðà„(•=ÆEÕ® mÏï8X¨8 ÓLÅS¢.KWvÏ\M6“Ó›dbb:pÞ‚ãŒi•ä\Áš ü€ÛÙR s›ªæCf5„Vó†M™ïi¨+ÿ@¢i ¹¨ óÛüH³Ku_µ•ÍŠ7e§ÔºÝ¡ó•w-†~‚B¿ñK“{œâ§ÀÂ8ö‡ôæJƒ•}ÊšûÌþl 0€„ì+vží,¿±~ÖzJ©N{ŸDÆOº ˆ¶ÒlZÆ|á‹þT§F>+ø“Ãkµ‹ôÚKÛ˜ˆœf&8?¢ûxÓò±ÆŠ8 3­¥ïSô&ÿÖþˆüŽ™Ñ$ñ†@Ïòyh?rl Wõ‹ _KÄTa¶y×~ƒ±˜´r‘ˆáéÚ½X$Â=prÕÂ÷[ È;“¤¿ŸŠ…§¿XPAØÇÔ8LT"¢ùÄ„2êKá}ý‚«´\.IœÎ%T—ÄïØß$¶(Ù`]ši&cB.=‹ø) ëªË£ã4Ê!S5†¬õ-œäÁ< I9z½`°'à–!&ØåPõ؃$X¸h¬Áƒq¤7ÂhW’m§'öÔV‹$T™vÈÿø‚ü;üZ€µýú/ú­Æß®Ê.l•ÝL-”ŸA2ÿ›ŒkqÞJ|&ûjÿ‰£wûêÞ¯Óë2Ñ+yŽ÷&åÀÞPÒŽcÞã°—Ó˜ V`—<ÁNˆâþé M¾}ÖòºEP•§Œlà»39WX[ÀZ—-Ó~J…/×Ø?²Â·Ý•«êö8<¯Ãؼ6`\©Á`V¤£`×vlm^ Á.¶ÇÁ.Ö* ÷¦f°ëÊû⹂äÅÌËPý½ ^¢s£þ©‚Ruû(G_<¨^â¯"?3“BßÓÿÚ‹dH°ÑX%È‚UüÍé³iÀP,@;;êsÉZœ|C‹ëFØ<< 0“ÒùŒÅÆï£4}”_K“¹hC(÷ž$œ£})…pWÊìªft { ²ˆIFReSþ¡@ÑÃ'E£ëÌß3Pè>jµx¢Ö(Œ‡§f”sig]ù‡ú+˜ù`˜E"b4ë<0–ï«¢(k”« Qðª©ërÕ§W|yãHe4Qar¤¥ÄàZ 1(Y@®z.Ëa#§W$ W÷°qÛj¶?U}â׋‚CWɽÏ÷/÷‡šÊL/!¯o±´xÂ+Æø³µTž°ˆ )’Iz¯ç ±m„<Ìcê7 ¬4Ç:Vsßk-þÇô?:¨nù%°>Rƒ©¬Ìðà æß|Akóûb[úB¡3ȉœØJ/vͦZOØê,r–ÝûØ„%Þšvßf:ÍÌ`óS¥ù÷;|§á­´¹u/•ö—F²ñ5C¬5>%µË C2zFæA˜ŸW“2à…Íð‹Ï'KRfj‡§~7 ¡>x~Mõóÿ÷oª‡ßŽëb“L?—–³_&) ™C +щ˜£Þÿúú1îÿ´qãendstream +endobj +2587 0 obj << /Type /Page -/Contents 2028 0 R -/Resources 2026 0 R +/Contents 2588 0 R +/Resources 2586 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 2006 0 R ->> endobj -2029 0 obj << -/D [2027 0 R /XYZ 56.6929 794.5015 null] +/Parent 2549 0 R >> endobj -2030 0 obj << -/D [2027 0 R /XYZ 56.6929 751.9898 null] ->> endobj -682 0 obj << -/D [2027 0 R /XYZ 56.6929 712.1227 null] ->> endobj -2031 0 obj << -/D [2027 0 R /XYZ 56.6929 678.7055 null] ->> endobj -2032 0 obj << -/D [2027 0 R /XYZ 56.6929 642.737 null] ->> endobj -2033 0 obj << -/D [2027 0 R /XYZ 56.6929 575.4649 null] +2589 0 obj << +/D [2587 0 R /XYZ 85.0394 794.5015 null] >> endobj -2034 0 obj << -/D [2027 0 R /XYZ 56.6929 435.4781 null] +2590 0 obj << +/D [2587 0 R /XYZ 85.0394 749.2922 null] >> endobj -2035 0 obj << -/D [2027 0 R /XYZ 56.6929 292.5265 null] +2591 0 obj << +/D [2587 0 R /XYZ 85.0394 666.7399 null] >> endobj -2026 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R /F53 1029 0 R /F55 1037 0 R >> +2586 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F41 1208 0 R /F53 1303 0 R /F22 953 0 R >> /ProcSet [ /PDF /Text ] >> endobj -2038 0 obj << -/Length 3060 +2594 0 obj << +/Length 3279 /Filter /FlateDecode >> stream -xÚÝZKwã¶ÞûWhÑ…|ÎÅ“–ŽÇ“N;ÓÚisšÉ‚–¨O$Ñ©q¦¿¾O¾)9ãENí…ð¼¸øî 3 ÿd¦ÂLó™Ô LÄl¹»À³OðìÛ âihѤúæáâ¯ï˜œi¤šÌÖ¹ÂJ‘ÙÃêçùÕ‡7woßÿt¹ Ï¿A— ñüöêîÇ«ïÝ؇KMçWßÞÜ_.ˆL("eÈ<¿»º½y»¸þÛÍõßÿóÃÝÍå/ß]Ü¿ýÉ.‰šgËÂþ®Êæà:;8ÚªpÃW®[|þ†&qT±ÀEµqù~ñßbŸ¹Nº÷4űZk÷–¢3Ë$l¶ i!¨]À¦(«}ºËJ˜’À¾3‚ÇĤ8l U 1m‹e:&'Æ4µØo¿8¼‰™ö­ÇeONfðy“/7ÍçVd¦kDf~ãºM'.¹Õ¢§qÅÉ$ì)#g@±îöS¶Z÷ÿ¼bþ/×éc€êÌ«…û½r?…öèMâæh`(j @ÇaÀÌÔÀBŠÂJÿ<ˆÂú“&‰:`öd -TK@E2_eÛìSZåÅÞ=¹»w¿ íÕ%~uÖ2˜ŸÂ;Tô'qc5*L¯!˜Ä¡ÂΨðpˆI,Úp€6¸fó÷•{–n˵¢@Ûë´>m~–tµrÌ–ž¨¯0˜ïà ö5:¯ÙØ¥•Á€{Z”qÚÏÙ¡ÊËle—ƒÃ:Ü?z´Ùéìòíê¾’\’á›LâÛíø+CÛu‹@ëá†çe±Ëê5’\lkkÝG~;æ®±ro¹}2­ì÷¼¬Ê7ÝióÈn¶ïÈÔ²“>¾iî Ó†è]Ó,Åý:K'1Dz£“‹2ÜæûO#;“pDçþ%ƒüþÄðm¢xo¯OͬÁDˆÀÎ*/ÓÇ­‘csÿ¢éÐ TŽh€ÑÇcåS·nô5;<ç¥Á ×LÂui9°€Q6™ëö&Ÿ6[`#Ô)Ñ0!ù2ó^ÑŸ²e•Î@%hª·ÅŠ"Î1?Û“& {ήH{SÊžú›}@½0ƒ<à]!!²ó8ƒ{¢E“ÊEd T†ÅÚq Ýš¢RÅ„gx]ÀÀu# C¨«ø4g‘j€µV@ 2‰–mÞîa›òu×Pz~œ‘YwÖæè#Æt›yƒú¡( þ[3øXØcÎÇ-宲߫Iäê@ íU¶NÛÊø&ÿ©A8Cä+µhø‡ôyì#AÄ 4Ž.!ËJè ´4¨&Ш,ZÞ  Ô›qÉNÀ…"*`-“¬EªÞÚp‘Lh3áÂ÷nZ±3hàbÆüC›†<+7èãÆÈÍ@f\²Q#¨ž´tÄã‚01Fôy]aŠŒ"È~jA “ÆÝìé(Ñ%«'ïÀk(EZ±Ä“§ºZX{B÷ÎÔ -˜À4XÇè°ƒ÷]Áúí ¯ÇËôXfAI¼Âgk#Ö5XjO}Üomˆf=¸quÜ=•£6`Yì«l_M˜UÌP¢‰:¡( ª E TVQ~V¥EP”÷,-5¡).¦ù -D|µ”„ -H§’c²ƒïÀ.sX.¡MŸf÷xáìaIp™¤WnPdþœÛÜOÑ k¤©Sn`æÛcˆ4Ì€‘ˆQ7Ì[êæ”nº s-9RR‰f,_á|ÁA*€ÿ®ÎÔZ}Åͽ†¨¢­Åî)ßf#:¡AR´ÎMA£ß EøˆjÕÌðžÓÃ~<¬HtÒ·/æû¤&‹×Sž GÑÜ€üÓ¾8ŒÆEÇaÊN93ž`ŠdÓ:Ú¤×ÑHeut7¤£% W“: -êDx2ÍX¤ଭ¥ðh¡Û¬Õ® “ؘÜt¨«Þá¡ËMq4™Œi?f™´µC˜ù§ùÚ?Ødþk1ö·:56% XKK5a§š.«S(áºïë+HÃßyê -Ðâ‚×.eÀ|"ìëTç¼P¼ àü$ÀIb´ì„jRMæ¸YÐùûõÀ”´Dh~zJA`1pÈË¡¹ÀŽ“è.CÚ‚¨ŒåÊV»ÍbŸƒ4\]Þ •@1žF@:~!67Ô¹Û(dq‰Öƒ–™¢*_¦4'IW˜¼Xåõ)xS• Xì‰zg“jÞ‘Ê -¶‚7„ތٗ՗í€ç5›Mr©Xk°Ò“6oµïQÚ—34öìØ1[îl>3åë^`З=”®KŸœjç1À‰9§æ+åT6MX-yöi#±P? 6_´ó©›×!Û¦¦4?ò!c;d,EùÂ=§j™T«‰ß[w`jnØö­P -„¶S.´ô#å1¯Üq‰§u'+¢b ^ØŸ˜±ôX0S¾L·æTÍ =úßÔO–=¥‡´ò“•ËCþdPŠù{7XíKûŒÐ}ƒÐÞ§Ž,œÄ9¹‘zUdT{WÄ,F7GPæ…IWaØŸÄ7^«6ÇÒ[#@¦– òÀól•W^į[N½}.!vN?Ïð±‡+L£µ³ÅC©CñZ®x(U,J틇Ðha ¡ûCñP’Q‹ UL'ö\Ù~ž+GVÜÉ‘g¶µ{±¸¹I?wk›»,Ý»Ã8SËìbWÖ=íÈ»eSSL7¡XB†rÒ„6¨&Lh ²&ôþ«b÷I¾bìÞçk0vo1’Jáë𛺟úÒ tz™¥èd–@c=iý~Ì,E+³1·´™ebj«¯˜YRÁÎÏ,%‰Aú©¥a|<µd„‹~âð,I8ÂÉ t6ˆÆÁˆ,6«ÁãLÀK}(~«`âš^ô -Ñ\ÂØ$g‘¨ÏZ ŸRh.©ÉÛõƹ£½ ëá(• $T2Èl7¦4ñl\–½ìb&u\ •ï—Ûã*s•¿Ta½KO&~Þòt`ôLôðéxð÷‚Ì`<úYÔMßèo¹€€½ i›û´l[ºÃ¥ƒìÚá"Œ¿‹Qæ»|›êË*Afá>ˆuã¨û‘Hœœ€UƒjWÊëy¸XLði`E0L1©¸kC H“6wËÙ`„øª Àg}“ RSN ²sZP™V;ü0#þâ§Â^®1viYe‡&‘kÿåýÝõ÷?¾½q½0=†ÀÀ™SÝ–áy.¿úcʇx–~=lÚד¢C­?ó™å¶>rÌ÷"£6—Æ|ËÁÔc=$5sIœLj¤„àtc› ¢qh"‹Ì·ÝïA¦kC÷©ïšþ÷Ú•! `²õ½·5 _¶h_®Z¦ûboBäf 3ºéö9ýâÛ€&𯫩ÄÂ7Äc¸Ø„Æ.Œ3°_lðLÏ¿ú2y}mü Sjäž 2¦I`Ê0Nˆî²¯÷yÿ´¨endstream -endobj -2037 0 obj << +xÚ¥Z_sÛ6÷§ÐÛÉ35CIÜ›{q;é\Ü\ìLo.í%R1/"©ŠTçÓß.v‚¥¤sã‚‹%°Ø?¿]¬,1ü‰…N£ÔH³ÈLéXèź¹Š`îç+Á<7Žé&äúññêÅO*[˜È¤2]Þ]ßH™¨tyûæÍÝýËWÿ†w3pÆñòõíý»Ûí͵‘ËÛŸï®ÿxüåêîÑ‹Š.b…2ýyõþxQ ~¹Š#er½ø /q$Œ‘‹æ*Ñ*Ò‰RŽ²½z¸ú—_0˜µŸÎªBÄ‘T©œÑ…”sºÐ&J•T¤‹g8Rœ.ËjS¶Ãx"øNß%ÈãvøAÛve1TÌnà¡bÆC_õ´ö»—op-‡Ž}Õ–Dáµ,u-òeõç¡ê‡~Ê?üÁÖ]ÛVkÜ7"m*ð:“çÙTOuO¡ÔÏ4°Š€çŽTº©öÅjË´ÏOUK£‚™‹Áj†Ý†žÞ“`|äI@·++’,‰ ÏJ4§tàifœÎwó:OíÌÒWnGòYpdñéº=ÚC³²Œ¼Ÿ¡ço6ÏŒú짬¬q@’¡‰ØžèT§À6ŠR¡²ïÔF,sé´1ÌkCÅ©8ö@•:Í(Í0hŠ/ush˜Z7L.ø oQ•ÅÖŽkϦѪBµqÌÃ{ͬöÈJ/‹(Ÿ£,eõ¨4PçM—*Ž½z”J”s_ÁV»”=+ú?•Ý• C‚‘=µ]Y÷£o{?At‡á¯xge²œ=óöˆã89¶G¬=FtÕ§5k{Ø?ÓkÝà\ÅÎ+fÍš橧§rË;I“._mˆú•Uõ¼ŠdÜÙí@ë2:}Åóë®ÙÀvl‰çΧ²¡•›y­²óÛ`µåi(:8!]x,öuÕÿ5à Ù4ûyÓh§Ç¦IcgšTð1Ò@D ZS'"&"Þ¨D°‰`j4QʱDÅ\Ö*ðZ%UË®Ý>óN-oïCÑïæB&Ù\0µª|ÐäRÉ©f Wzs¼o‰C«#‹Œ’³ìÁœ]SVsyQg‘©9Vµ–Ë~W­kLþ¶VBÁôî`Ϲ®èÜBò.-”6ø3Ò!L°Ãç2×P·x¡ç~¨—Û¥íP¶ë>Õ%«Î` +ÏÓ©êŠýd‘Lœó¼€c¿ ÑfNŸBé+rÉèE2C Ö +Uk —<åS½®Ð”ó;KuþŸL”ïV)À4*…è5??VÏ«Žê­’8¡:˃ÜÑ”„LêżdÎeL”%Æ-Mm©2—h|Ù¨r(=ÖOžX6²”ÓMY=ÁÜ2 m(ê–Œ«ÜÁi„µ0ÏïÉ (u ÎPð‹…¥ôºc$È8Œ¹ ²`xûæb'çH¥+ÖØ å\Ug¢\g.=ÔmY¯!Î{Újx*Û su»;ðdÿÔ¶L^±”\ÍR¶p™aÌ> —}á“Àx òBbК£Â±Õ»mî}äËZϸAõ)8¦Q¹ýìÕý›wôÍO¿¾}}‹÷·Ç™r>ƒmã\çßQK©=øXL,J<©È½v`èÓÒ)~e:ÒÆùû¦†PD75’1‰ +ã–ìp¾Ñ&nW[ÝÄË»ÂÖǬ]ÓP¦CεÛÖS­Qð_ ,ö ÃØÔmÝ26„F¹8Š:tc%¥ß]K½|è0ÞÊ»÷ôæ¯dJ +ªq-µl ¦úaó·;ìw]oó.hÝéD˾§‚Õ䲪q†Æ.[‘X°ð5!Ñ“Ø’^£Jwópù­îk»Txë§jý±'.T>mØÚI@Q7½9šþ +Š„S$èqOU_Ñt¸"¤{¿RYs­Ok³B…+øíNûñóÄ *A±kN ;M˜º¦zÙº-°þëøí[X‚HN­vü¥¦û|ß1­æO‹UO™æ‚J f¸„QNJÇNH ÏŒïÍ¡çeVÌÑTﵡ‰ê…c3Âþµ/ÿk£ŽjÃrÃÓb5<ûÃz]YÌJ”Y¾³Ÿ2 —70ZMVû/ÜËl͸Ã ž0¤»\89ïh8hcæ„›¢ÞÎÖ wpóƒ°UÙxiRY6=5NÂò=Ù§­«ÂókuÍU]Ç{z6þ:…ÏIÍ+Y|Až¯Õé:éd×òÁÈNsÃéÁ.²ÝvŸû9W.J©C=À½É<îú“cÂ*‰a<»<>;Y'¸âBk¡ÞÇX&'¹(X,Œ!üà$†u%¿WE¡Ÿtû9»6ußSM‘çaôÀù ŒÞeµ-Ú4tù&g´¶#Œfëz¼Ìi¶“RF*ISß»hçj,ËßTb@g„€¥×7úBi‹õú©šLc¹\°‰*×(3ÚLÕà®Ç+ßÑhùÞVpÓ‚r ^>Ök~¹¸Øš^¾ýÍp¾uræ†ÇÍ—J©EÓ®Ùã©°zÍ7ɦ*¸RDLÁq6uù¿Ÿt‘E”Á}*bAÎÏt}‰é&䢦¯˜iúz.²47OýáGe¼ÇÕÇ"‰4‹àZ’]–ÉsÍ5¹úfàxi>ê¡¢:ŠÂ¥³3¾øðö +×áSX­v4C‰œ)m/Â÷´“PÅéD$>¼*fîpåÈ|ŸC1ÓËß°1IW^£±n̦ÈÕ¢Ppïq +·ãNÑ$H*ÉðÜ˹.¼Hò(ÁÞþ·[µ:R2v’Rú"!,LÃèàò¾ ,#)MÑ^Ø@pªôÌÈÐÇÈ­s½s)Õ4®t%®éfÒåëûÛ×wtA°@k/@·U‹Ñîîüúo=Q~½%âziÒåét *„Ä°yvKñžî\HôtNÐÇ›F3sܶ›;ƒ˜)"¦»TÙ`wbÀÀµ€“ ï¤±¬<ÝÎä‘Š…ú÷L!¢Dâ¼ãóS5N°w9âfÀ¥>é˜ëå[vimaë6™p³C[·öG!ËçpmJ“üÈýƒÆšk<Éõ‡Krêó-sקÓjº<Ý<ϪLTY1¹ ¨!×y@õ\xÐm·ö]ŲÜS'ä<˜Â§:M“Ëòx®ä0è$˦1šÊ,&4•™¬ŸÉ2ÇÖÇY.H2× rE% +êp +˜&å‰#„*Xþ7úmFÖ«ü>–d±òÆ5ÁÅõñs ¤"! ê›@šË(æ»`TdÙEaFQ¡‰S‹–æQTÿõn¢¤¹4ò¬Ÿà–ÛuõL4¾:&Ü;œÃ!ÛÑ&†Ûy8Ë7+\l…³ pŽg¢¬*zR» +G”R•ýñF§iwMU3Ì…«]Ÿ>Ú×ôŽ"b.H$µÝ8ÅŽs×®d´‡8Óï;A’±ëêÛÓ¶îêë­/%Ï„Èt”ƒo^†‰ë_¸Ã¯cS*OSR$”üø?!\ÿ~6tdi°ÀåÈ™.3YÔÚ.£ÚáÙÈ‘™¹(‚g:•á$rb#'BØÀÙ<_ªY¬pü«ð+.PfU(¼ÇÁùNý3^–§“Jòû+¨@ku?+ܵvnøê~îGJ¶¼‹Á3fÏ!ð u]6{ÀtÞìŽÉ6†­»£Ú“OLCŠŽÅÅÝÏéîÓcÆp{ƒ‹K¸ýhpw­ÄÁäGoþ§…˜áž[ÛÂÆ_4èZáïªa¯5àw¿pC>~2©N~ß™â\žŒ)½=s,'§ƒ¿¤o«bæH\f¸›'GQ¦ˆÎý³›Òþ‡ÚŒöcï?ÿ÷?Âÿð—`!—ó†”ê 6nX(”]¤òÔoù_æNeÿ“Qcêendstream +endobj +2593 0 obj << /Type /Page -/Contents 2038 0 R -/Resources 2036 0 R +/Contents 2594 0 R +/Resources 2592 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 2006 0 R +/Parent 2597 0 R >> endobj -2039 0 obj << -/D [2037 0 R /XYZ 85.0394 794.5015 null] +2595 0 obj << +/D [2593 0 R /XYZ 56.6929 794.5015 null] >> endobj -2036 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F21 714 0 R /F55 1037 0 R /F41 939 0 R >> +2596 0 obj << +/D [2593 0 R /XYZ 56.6929 507.1706 null] +>> endobj +2592 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F41 1208 0 R /F53 1303 0 R >> /ProcSet [ /PDF /Text ] >> endobj -2042 0 obj << -/Length 1827 +2600 0 obj << +/Length 2967 /Filter /FlateDecode >> stream -xÚÝXKoÛF¾ëWÈEÌ;¹{tb'u‘(®%§Ò‰’‰ðáòaÇýõå.)RZÉŠ^ -8¤†3³ß¼I¦~d*$’šêi¨9˜ˆé*›àéþ{?!Ž'蘂!×›åäõ;N5Ò’Êér3¥VŠL—ë/³7H£3€gó‹W—gåœÉÙÅÍÍÕüòú¸˜€ãÙÇ‹ùÝÅûìæLÓÙÅû«ÅÙ×寓«eoÎÐd‚™±å¯É—¯xºË`Ä´Ó'¸ÁˆhM§Ù„ †g¬{’N“ßzƒÛW}p¡ \NÆ‘ý~  - ¦Ph$e=P”ø€ê¸ PÁïæ ¯ß 1à$…!V Ý°dÅ:ÞGCKÄBN¦CvuL»èP&ˆ Ádž-âU²y> ˜–³§û¸¾K{SöººWß Î6…û//ò ŽË,É£Ô½š¤ëUTž5[Wàð«Ùü4—}dïb« J³¢ª -Ó€h -¡€ H A[s£ô)z®LœÑ˜j +¡jÒÚÞ{ìe%iÓii_,ìµÉ×qYÕQ¾Þ84Ó>É¢zuŸä['8ÝeRßgööO,ðí»·ö‚–Ã0¬f7EU%ßÒÖ³à®ÑaŒÇ+› -mŒÂ‰‡HÌ]üI)ŠÊÜ\óÐÇL@ìÉŽÌZÇ›p19EpØC%¡d $ÙæES£Ã@–ä°K”C61Á^Ȧ׉l긌ƿ‹<Σì ]{D”â§5÷\Õã„QˆHŽu/Û $×E%¹¥[cZª=¸Ö›±ÕRßb@@¶9¯"'C†4Wáiä†\Ç‘ë¹lL`šz±ÓAyä§UwLÕcä0Ð2ëî‘û)´¬¥¨Ö>q6P¯9¢!ƒÒÀâ‚XÇÜ^-ïnçöåÏg„êÙŇ;Û`ö4¤q ÝÀ¼hÌY­KZõ‡ñ®8ôÖ¥‡MÕº)ó.y]Ä?’ÚRPTꦟÑ%`ân㲕S”Ží)îK” ®¸ŽWu¼Þ%mK`'ÒT駤:OgîžÅÕ•}ùâÃâ“çŒ>PLQ¦vœïçZùfðw+éa ph7Diš­Ì„G=pSÞW Ÿ@¡Gºšóæz~iåiwª5´™¤ªË¨6MÊ<º7Ó|å`ýå ô¢CõD*D¥”Ã’v€+tO¨ÅD½¸[þòéöeD¯sè…yì"dñ\Õqæ|ÿ¶È«¢¬“&ÛérIÎÄ\t3×Ô0ìÜÑ5&¡¼å˜»ô>´‡ÁˆÄ%ßyØ奡¥ÆFúK\—¬!¼rÏyñP%Õ~©aPÀ”dSuU2îÉ ûk*Œ»O–À¡ˆ¶q_ ì¹ç–à—€í(ÙS+7ª±a|€=BÐ҉þdl’Ô=R+a®¬kٽܵG.4l%a(´¬ëø[³ Òø1N^즧¶=•yTAí–œt¯oÒhëÑA9â¡"û:r{ÍH -µ/¿~Ù‰I ¥»(Ÿ}B!©8€·yQhSu·ï.*0}üj'h&M½R¤sÝÙ¾Ÿ{ÎÅ°/ÁŽG»H Ü t‹ÑN¿¯hSÇ¥áòjñööúfyýiþ“ Ú7†B°rÜådb -.ÍÔo.—®vº-ˆ-eË®¥Mûºœ/ìll¸Ârè? ñì!‚Ðkÿ2MÜ\ÛAŶJÛËÚ4Ÿä[S'…Óº± Þi»^¼E–z×nQ@dÅnêoWÏö4£lJrع`ùh…¶­?ß›˜àç]]v ×V}³eç=ÉÏ÷Æ Ó‹Q¿™(Cƒí ¿ßÇ­ <ßmŸP°Õ÷ESÛìʲm²8¯«s‰Sa×SzöówA«Wjå[l"§ÚWÏÜFco ›9qÛ”=DÊMŽžp%!Fœõ5ãu\¯^·V!SÏ}s,Ê’©áPb>„ÝsÔÐZƒð³›öò¤N¢ÔµÓ¨Žö]BØÄΧ›nrù«‰Ë$®ÐOôØOm-Ž-Z"ŠÁ'›è€éøÑ1µ_3ø¾> Ó™&ꤾŽçPßs dÈÈHß]å"ûúæ‘wy:ˆ¡[æãѺÏ{ó1¡¥²È¬ïîqâ²c=Df5é B"_©f÷ »ÚøöbbR¸ïýª=BØEØͱ<*¦Ëˆh¸dM lô«´©’Çøø")wž^#{žK¤åÙ™ìsþ e½ï÷•ù\?P6ô¼üï=Ïÿžïf^ÌWO3p_NþõÇÕÝÇcnj½¢~ÇÒÔ@;£ÌáŇA‹e°ôÚþàEqendstream -endobj -2041 0 obj << +xÚÅZ[oÛ8~ϯÈÛ:@ÍáU¢3h§è St›3@'Š­$Bm)•ä¤Ù_¿çðfI¦ä´ì"@DQÇäá¹~‡$;¥ðÇNµ"Tdò4Í$Q”©ÓÕö„žÞ··'ÌÑ,=ѲOõëåÉ/¿‰ô4#Y“ÓË›ÞXšP­ÙéåúËâüãÇ7^¿ûëlÉ]üJΖŠÒÅç>Ÿ¿·}Ï2¾8ûæ^¹ 1t ]|¸øüñõùY*—oή.?ysØê³Î¨@ž¾|¹¢§kXÁï'”ˆL«ÓGx¡„e?ÝžH%ˆ’BøžÍÉÅɿÀ½¯æ§1QH¥‰â29] +ItcDF U €eª2’.‚À8‹ ÌS¡À¾OV.U¾-l«-VMÑ×ÏTJ( ?Ç'ž( ïqÂNÓ#V.î‹Uù7¥¼hMÝ]ÞÙV¾ÙØÆî~wþ{Þœ1½(qmŸ×îýòâÝÛe[ÞVÅÚý´-«[?pËûå7%z\q¥ש†¥8É8™À/àe/–ñj(#œSæ~wŸ— šARP!ÍÀ<Á`–Œ‘L)nˆ.= ±Œ°$Íö Äfƒá2-ͪÞnójmW?MS®xà5¯œjƒŽÛ aÿ‹Ê>Q ¦1oSV®û¡Ì-+²Ï.× ,˜y^–Qv%‘`ÅŽ¤n"À\t¢¤åkl':KB|Ó9@ÊR" 5ï%=ª/ñT8ãmÛv`K>ÁB9×óªÈ̃ErF(•l8õçÖéàíÅÅÚi¬v* éÐúÈbš`àw¥³ÿ,¾íʇ|STÝh(´Ž›'ô’ˆ®3ZJ¯¥Û㺞°-´ªI &:%\=¯Á>Õ´•áf³žR¢ ðSXÙìÜ*2ù@B‘LêáäV‡R:YHµøóL©EY­ëÇÖ~á”Rû œ¸-ð »¾±=åã0µíuÊïÜS>Õ^ù@`Ÿj¨üþP¨ü¥ Yì•òaÀš´ E”†ˆïÌ¢ž4‹ìEf!A§*ÉŽ˜EjÆ,<rÓùfkùøbÛcë‚È$K,KüœdZëxÚ_†ðËdQ†0Œ)éê€ÉT’Ds5/§@™x ¯’r¦;˜øÏ»4'„ô‰Tˆ¾YÚ±´Ê8'QíI|´!@dŠfÿœ”ȇ‹p'Ð_E_¿^ÊKæàÓ’ùLÕä`Ã]:@•ÊŠÄØ5v­‹›|·éì‹E*ÆÖ¨¬by8P,øÒ×æZ9 k'©„µ\rUW71&É ú\i²À»‡ò\¬ïñÓO !xi›?ø¾‰ß®6…dëi?¦` ` Gü¸G5ãǞʀ®¦hŠonß×õ6/]œ±í¥×hŸ+ÈÉ {ë,[*Â×Pî xqsÀØ' ¸V, '–yT‹-T>Ýçzg«¢ß»ªÍsmû0àÓ@;3ØÓ½#/¾—Þlû±ìîÜÁ‡P7I cÊûäHF£…%Š¤J¨càK¥œ$J_}ªiݪ±nŸ~D·"£zž­@ák¬[‘B×€±±n…Õí¡¸¡ÊIµ~¦´S’„d¯T±ø›*z—»—ð4¦$à{mg»êª°˜Y‰‘Y½r_Q¢3žL}3*$ÐÚ€ 6m€’¤fÉèQÍØ€§:ôï¦i‹îÐl_mò¶½Ú3|`(a%ø<³*Âí0%€A©†ì-ƒ ækYh™ ÏCõì{÷^}Þ +°mtbÆs?è‡ìˆ£‹ J´ÔWN^³)ãUdœ¥PÈp#bPÔ‘ñ ÷ŠTûZëÉ,ȈP©ø$RZdT ‰Rú:ÏŸ÷GŸÀêmÙt~eßÞ}°Ot»²êŠ¦*:´ýaÒƒñwÛ™„I› + Í:DŸjÚ!ÕaP|±C0 +*e6PE¸;…z~È®-D$õi­ï’z÷ÀïyŸ¬ïûÞ½wàOÑ#ð›ñlñ RÏÔ³Ã#ØÿÉ%4@Qé÷œ¶»Ö©ßÄŠ9Á\”©g9Hò¿p¨rOTv}ªñT/uK—w9!Œó Ê2¡Žp¨"¬M‘,ñ~ߟ„J‡e>¶!{ñE(î‰nŒ£ÔXuÈ0ûê[Pí£0° ;î­gçlK³ËÚ'éŒ cÏMÝln€%&í]ÞØ1QèÏ"‘¦Ê¯«ÈªtŠ¥z©;‚¸i0Ø)³æó°¿ +v,BE}œ;£iú<_¿Õaƒ#ìJãêaÙ×¥Ù‚F!àf öšžÜvX}@Ãú?}jÁ‰%mä´Â–|>ÉÚ˜u–Y`Oø¥m¸˜­â{¾ê6O¸%DÛ¼C+À~‹! 1=ˆ 'vßÞ îîÿð?lb ÷ðQ;nˇ"¦o0 Ã*})"Z9ì‡ÎØ„Â!u€¦³ŸÁ%’Š)çU$K3vÄyA4ôÀŽ¸f‹ÇCoe_J÷´²†FÛÁšòñSñÝØQœ·EÕåÝ]ÔLöŠ`R=ƤÿræȘ&ÔÐ?¹ó3üw>õE‚gvJÍGý>ÕtÔT8½Ýþt¼Ø¡}ô»ns‰ÿ_ö à‹ËWûm‚cùL¬#PE2ÈmiÆF+ym¸oGõþs¶ +Ú}éE + ç-?fáöHËä*ɇ®EB1;åê áLˆcȈ%GSŸHöA ÔGÖòë‡rm‘‹€ [a0Ä&Úðö̊̌ʥ9‘„Ïײmýà6ߥ æ“GGö-Ä*cé +Ê•¡“ƒSP.£RÿT±SÕµ»ûûMÙ;.ŠE¯ŒNiHÒÝ&&~¨ùPüÈømU»]ÁW~7a=„ˆNÊóÖ~É$ÃÁ=­ërSvOg "øt\a7p¯j>®ô¨f⊧Ç•|½ž*(˜Ÿ„”I&Õ<û*ÂÿR&©ÒÃœ¯ÑtEj!<ªâ*bõøy\iaŸÝVÄ–Ýä†Æ‘Z‹,ÓbÞnXJ2ës6Ø?]iMÄ“蜴9ž2’¦É‘¿O5msÊÂèúñइ"ÖD3;k ŠL;£CËMîËb>Ó5(˜¨²ìÈ¡sŸjFƒžÊ‚sk}C ‚ãÝ—ÙYUdÚ¡~M‡ó^À¼íø˜u >èpêûákf3«fe¶kðq½É«¯û[#“¢fY†ÞyäSŸjZÔÊúyûX4‡4R’h°ëÙyUdb>:ÉL=œ¸ç-}q;~ü= ¨, nd*9’¬úT3²ðT&ž×»È]A4à£ùiUdÞ¡Ýi¢)DíÁÄ—g€;wM5¼\dع‹ñ§™‚¤‰À)ˆ&î§ïÁjœ ¯ ®‚…Ù¬Ó³µ¶Ø–«zã‡ß×Iî2h;‚š$!áV7 ì‘m4|ó×ùß¿¹ˆ$Š'D +–†] +¡ÞÞÞoì-5ËPc?˜ˆn:]h?8òç}.¬Z;§–x0 ëU½Û¬íöúdzx×c/Æq@¡mÑt¶Ï +¡F‚Xñ'"ðH÷ûJfƒ™N¡$䣒Љƒ¬ = Ü5À°£“Ňº+m(Wþˆ$U>Uà9ùýÎeSôB—ÝÄ2-;®}q駵o¹§É4úŒäc|p7Û ÕÖãÉsK}k—¸»7K£CìáOÆÜÝ•6bemœyÀ¹âÅÂrÕ¿­Õ?Yÿ¶+ÚQÌ ae ­hol6¾7ÀæžØÉÔeVæ½ÊIƒG¼ø¢ëþB¯L–LEW(™ˆóL¡œY"Ƭ+¡‰Òàœ‡¼ÿ•³¥endstream +endobj +2599 0 obj << /Type /Page -/Contents 2042 0 R -/Resources 2040 0 R +/Contents 2600 0 R +/Resources 2598 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 2006 0 R ->> endobj -2043 0 obj << -/D [2041 0 R /XYZ 56.6929 794.5015 null] ->> endobj -2044 0 obj << -/D [2041 0 R /XYZ 56.6929 627.8052 null] +/Parent 2597 0 R >> endobj -2045 0 obj << -/D [2041 0 R /XYZ 56.6929 562.9454 null] +2601 0 obj << +/D [2599 0 R /XYZ 85.0394 794.5015 null] >> endobj -2046 0 obj << -/D [2041 0 R /XYZ 56.6929 498.0856 null] +2602 0 obj << +/D [2599 0 R /XYZ 85.0394 107.2827 null] >> endobj -686 0 obj << -/D [2041 0 R /XYZ 56.6929 457.8644 null] +2598 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F53 1303 0 R /F41 1208 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -2047 0 obj << -/D [2041 0 R /XYZ 56.6929 424.2917 null] +2605 0 obj << +/Length 1792 +/Filter /FlateDecode +>> +stream +xÚíX_oÛ6÷§0°Rõçe€›8YÖ&ËjØÐöA‘èX¨,¹¦œ4ß~G¥H²ìtkæ‘<w?ÞɆ~l(<â…N8ôC—ÊÄ0^èðæ.ÌòL*¦I“ëíbpzÁýaHBÏñ†‹eCV@h°á"ù4zK˜KÆ ‚Ž>ÜœŸ'Ž„îhz{;»9¿ú ú‚pP:ºžÞ|œ¾Ç±Ûq茦—³ùøËâ÷ÁlQ«ÓT™Q®uù6øô…Ðü÷%< Äð:”°0t†ë+8.çÕH6˜þ¬6fͧ½&`”8Üszlà²>¸>ñ|mðËxâÁîrµÛ$Q)õ†@ê„1 +á–_‘Å2:‘™¬è"KV…*‰ü­7™$q±Æ‰i[;$,J«„|ì—x.¥•PÓ0ß!Ì#Œ°#+™'zúôÂqvfÎt˜§ùÓxÂ)×¢u³³`$ã´‰ÒƒÎh ]3Û»[=áwØAû$× `…Äòä•œÎJ8U/Ôk =ñ˜–«¾M_Ý"8Áœ(X)hØÊôSU39££ÅJâ ,›=MÌt•Ôc«¨aWÀ&‰žX,ìAùLµÎÓ]ròDÁ(#è˜@;Ž9 +Íš6[¹•ß,û÷¤XGin{iü5Ö²eÆÃø3,ûdtqyv3½žYØk¹çºŸE):È÷`¯Æ!øÿm—ª´43b¤m›–i‘#ã½,Reõ­Þò*¹}8]`¯düµú"*‘¾­€­'¢f'·Z¸;CÄv‰½s¤Y‹¥•£YéiÓtÌ9pDÐk} Z´0¶t„/¬Ž'ЃȎ›‡áÊ·š®¬'U‰Ë(Í”+¬Ø¾Ä“Tv*)d5VØOå÷T•v±B0ôàwÀ,m«°­Î¢K¸º•€}k\°~êq%µŸf7ÔÜ«u ‚zÉ8ÊQwMùgJyWRul±+IŸùýD•`+¿ïóÔv ¶Í4·çô¹Ó퇋3$ ºHYÝŠ°±Vj½Sv +5ÂXÕ²+ÛÌQ‡r/:yR¨ÍÒ¶M¡ª#c<‚´ŽZxÞÌ +¸½ž›0‰wt'µ34… ӱܫb9ŒžßÌç³3¤SËi,¤ Gp”>ˆº²¬xDF-Õž^EÒÊø0¿º<©×x7ûÛ +È­7zÙvÎ&ÑÙÆ 6¬·h‚ u‰.eôgWï{jF|Ƽ¡Ë)€¨QiÒäÂ%è)Qj.½ê©,ãÓ-Ä—ì¾ì*À„C ðãÔ\û*´â.>áLxmvªÊ‡&Zê,šÈ¼L—6ã%rí²ÒæP.hfXŒ‡!qXý¨Åš\‡-Vs‹=DÛÓí.?Õš$§ +JH ä«|êªâ0G»—×¥æÚW¦e;‡ù„†Ìmk£0‰:w̵#¥4„þTÛÝš;Ç6+â(›yf9×E"Ú׃b? ½ìÛà:bߊKïèžØhƒ‘„¾ïlçmuÓ”ä’0`Ü2ˆì q8 u-ÓýKRÈÖ7=‚\F—³Ug ‹”Ž.à ñ’B•Æ½£až£î¨¹öýч›•ç¶r)9ñ\„„ÌãÂ$+Ó3´¿]OÏ&×碃´C!m=pWè\A¹:Æ{™›:¶.[{±Æ= ü öÌti–é Úf›>ØKA lÜ!” ÷¨?j¦=‡´¡Æ!š1/hy¤F ›HÓ=4Ý>#M÷ Ò4ÑBš¸³GÖÍÇP¶óò|6CÐNßÏÿÀu—p|Â8nk³0ÁYòznàR*?ké“y‚ˆ@ø–¡Ç)õ_Qœø|Mq+^Qœ©k_Q;]þgqÞž¸³7Lf"DRÃîßåD[MHšõáÐ8‚xŒúíbø_ ¸SU¾ýx9ï¿#hYã:£Å˜°b€Æñá'¬ÞT’]žDy™ÙIUv™L1m ¢ ¤•ÜD[¼ BnEý𩾔Á¥Ð^ÊôÇ +…FØ#)}“ÌͽÆM‰úÝÂŒîf$½êª÷-ã|¾°%Nz·¶ÝJ(­Š¨xû´)‹ûm´Y¥±Íq ªC‰§Nì»Ln³Ùºz’‰WQ~ß©¥–»r÷|q®žz2 !N5çîzµãq<.ê÷Sa”§yW›‚hûlqS§Ÿ½Ç ¨®}7Ĭ ¿Æ#ÇñѸ"/šEf Ä2ÍÒòéÐC,¤ýzÚ“hÈŸ~¤}~„vácRw´UJïœyî~EaŸs÷uÿ¡©Ÿendstream +endobj +2604 0 obj << +/Type /Page +/Contents 2605 0 R +/Resources 2603 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 2597 0 R >> endobj -2048 0 obj << -/D [2041 0 R /XYZ 56.6929 388.1677 null] +2606 0 obj << +/D [2604 0 R /XYZ 56.6929 794.5015 null] >> endobj -2049 0 obj << -/D [2041 0 R /XYZ 56.6929 320.386 null] +2607 0 obj << +/D [2604 0 R /XYZ 56.6929 462.0323 null] >> endobj -2050 0 obj << -/D [2041 0 R /XYZ 56.6929 234.5807 null] +2608 0 obj << +/D [2604 0 R /XYZ 56.6929 288.682 null] >> endobj -2051 0 obj << -/D [2041 0 R /XYZ 56.6929 126.8791 null] +2609 0 obj << +/D [2604 0 R /XYZ 56.6929 209.4795 null] >> endobj -2040 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F55 1037 0 R /F22 737 0 R /F39 899 0 R /F41 939 0 R /F53 1029 0 R >> -/ProcSet [ /PDF /Text ] +890 0 obj << +/D [2604 0 R /XYZ 56.6929 155.6441 null] >> endobj -2054 0 obj << -/Length 2977 -/Filter /FlateDecode ->> -stream -xÚÅZmÛ8þ>¿"À}8¨]½ÛLÛÙbÛÙÞvŠ[`w?xeâ«_ÒØî´÷ëÔ‹c;N2@ \ Œe‰¢(Š|HÊ¡ ÿé"‘á©XÄ©ˆ$¡r±*¯ÈâÆÞ^QGz¢pHõêþêåO<^¤Qª˜ZÜo¼’ˆ$ ]ܯÿ®ß¿¿¹{sûû2d’¯¢e( Þ]ß}¼þÅö½_¦,¸~{ó^…à -ˆR$S$¸»~wófù×ýÏW7÷½8C‘)á(Ëç«?þ"‹5Hþó‰xšÈżˆ¦)[”WBòH -Î}Oqõáê_=ÃÁ¨™:§!“H2¡!'°ßY=‘ˆHØw ©XôÄ蜞<ê)\á>_þ¯JJ"ÆAÝĬêj“?†›¼ÐSPE#Â_ W>’¯§š —U*"DÆc ?6ډȴ )’x^Ä _•F*‘ÌÑfÍ2ä© Ú­Æ†ÀÉ»}ÖæueG±§Ð¶WM«³µ¥®7“ék½Éº¢}aC3ª"!S/åKÝ®^VY©×/B®X”$`!¥Q*AD¿™™]0¥hw–Xj¢DpF\/CÁe «¦Û/ihûÞn³["°½E­óêÑ:ª£Ýc§ß=N‚6¯:ݸ‰nµ§zÿÉd›Vï'\½ÿâ;· q³]¿·[먫mV=jT.Oƒ¼ml¹YñeÛ ¬ÚzÿÍuuÚ6Pœá3³]Ý4ùƒ·†ñ¡p¥„(§H`î«\ÆE3´”õΙ -êžÖ - qlDÐiÕøbÆ|C–XÅŠý;N"@*êÄi¶uW¬-–=hûÌ*÷|hê¢k]ï.k·hvѤ9àP1€K -³è2¤:.=•A—õºP Þ×ú¡{ ýEÇèÂÀq/É×SÍ8F—8R*•c ?h𖺓ÄÆ:Óe]ý½qo(žmZCq¬íøL©ät~_Ó£”Q,¹88³qð§<³7í³z.¸1P—Ž©“AtQÞ ¾Ì¬ÈÁùbž8ªZŸÏ-N§vX:Û)k)ø>ýP7ÞØû´šƒ†×4®°™W+Ë"ktsÚ9Ä~ÉDg ÐûÛL×K„6ÆÏ®çiŽ×*4#F¹­÷[WMtâÐjb2¸qÊ}´§ÛUÎÿ$’äøkÈ)¨µ¶½UÝ:= Íÿ«ŽžÖ(¬ƒ¦—T: :£SOe”úx¤Tt(uaIO4³äH­I”Äñdɤ×Ì7ÁÊ[rálµ¨½ÿɃ“£hœ¨>&4íZï÷sî&£ä@vò$ä&ŒÄiHuúz*sHåò -@@á1`SdG'I!F+ -ùæYÁzªÉFË {Me: rt{Œ‘‚&V -”`Ó&ºC_×dÚ6×LD*ˆ¨<{l0O&ï}”7¤n̾d¶f2GE¢ãZ-صfÒ­R3ÀEK5ÃUDEÏÆ€õ)6És¹@*Rï×Íé"ŸÀád -)†\ 0œzÈDì!¡«Ì„¸4â2ö ÊUûõ9‰*‚ØýVû¸[´‡Óìjïm=qáÛ¯§¶É!ÁÐ!/c©žQ±(5꟫¿Âža8àxlÅ,²„ Ö¯‹Ûzwón*ýI•ü8ùz†çåãàÖ@0–ïÍÍ«o‡>¢8ß°qºYíó½îáóçÀ˜P4oPÿÈ›ÕKpÑhûÏgd3§À, r ìTgÀÎS°«.¦™[íºæíÕ@~V²žjF´ÚA"‰h¯]îÓÎALˆ©ˆ§"gn„Ÿßae„SÞⸯõ¨°UdŸ´íÉÖ_²ªµp -¦z…g k¾+Ñë÷wCrëL²cÍN¯r,dôúÅLö‰6J¹”}B¥ Ù·à“zç)7‘ðºEì7ÚÜÇ€‘BUYæ•vÝ[רºòÁ~awƒ´(¿íÙ9dÑUk;lȇÆêpfN}àì•èXxîÀ5²´·Û“;¦¹[­«2}Æf  †Ñ‡»Â[¿ h›]ÀwñÂ%$.ɸW¸þÜ-›È8–ûÆ‚‡Ý®Oº£ˆ^hœœwÇ!Õiwì©Œ;î.ºã®Þ·ÇÞH¢DÈóry¢¹Æ™‡Ä벉`¿äM««C -hŸ;½ÏµƒÆÚzù¦ñ –|ñ@u9Þn&Yüȱ¦…”¹RrðÜ D2-ÉOŸ)ÞœȸΟé€êÌ™z*s¦ÍL%' Š³Kz¢™%'µT¬¨/ùïe,‚}îo1|‚ˆm— 5¶Y Çš¯š3Y;–æJ°CÒ^wsÇHo”¯à½-è¯y{¤pJ`dÀ‚$ÃØýŒ`ÏsA}"ÜrÄxC¡Î\-Ûyx¹¦Ÿ1ɼt!ç PÎFjïñ íô ñ]%VñwÕHŠ´WÂ’3â]†ŠB"*Ü©˜r&HZI”ra\tñyB¤)·Tƒ¶ÙíA ¦ãåmÉojØÓb¸-Ï9²6ûR#ï‡"-MH Àej±ø~k])îoò°mûTPfyU|sã7Vz릵o6GƒW·woìœÔv¬õ’“àË’I¼d…øá–qåf ¼‘à›d!:†\¿¬—Tºyë¹èa *Nw¤øbª]xfö±éÚn¯m{¯ ¼eA®G+0ƒ>Î$’ï·2ž@Šº‡/ßç¡+— ¢âñò30Ë°†ófI ~}¸œ"–Ù×°©WŸŽóD© Q#jÑ/y—<ÉT¬ñ$…Ñt ×uQÔO3y(">”Ÿg.õD"ü|ÕùJ«Û1qˤˆ8ïKÊñæ§ù=‹˜RýPé¶9 ‰,†ª&åü‡@"åi$bžç[k?å(RP›dä"(2 ø—¤ÊE£P„Ü"f¾Fº6pø›ù{gò¶o³àíI˜¤ ¥s0 ÀF…°Ð8lŸ€I~&‡¬ÏÀ$ã -⮃É49À$´û¯ Ð6Ï®ªôJ7M†åˆÅ7èÝ Öä‚w«žX”Ë ”Â[™ý)§òÖLs˜‹LÄOƒ`¡ /úYŒÄ‚…cŸ›oGlð²~+56 ]YÂmG¶™IƒrÓ¶çA¯2ãEHæ¾ñðaÆf;즊Î÷0³Ìr_ñÈî“—F‚:ÖÊ­"/óÖ€ƒÜ• Ü0ÐõZ[ßìG<m¾A>[Z‚ë÷·‘í½]Ò µMT‰[g¯ÝÁ¸ݺ¥0ìÍ(öi‹zD9! ±¶öQäm[Ì:‘9Vr>!WSg˜Š^lª -ªð>F§mwƒ—jT>Å<¢<Ž£Ú—¸€PJû+ÑF[|±¾Û89ì*hyÂöЄÜ.Fb(“xb>ƾLþÔÃæVm㓬ÖÛ±)ìê.%Vðò¡êÿœYQ(jhréKoOeò«v&¿J#¨Ãã¹í£@(b˜ùÂpÙãËSÍH7j}ó#ñ^Û“ÚßLÍgDxåÉùs~  |éoõÝï­½~ª1(ÚÏHÌ¡'6VuYÚ’^ -{'„¾cæèÍá,¼û{änÌ› -¼B&bí]ûäg î2<&:õ'.#Ág „ôiÒwÿøéðã.8W0ÝSwÛ³Ô”z¡ps”Ñ©è*w™°xFöÿs ÿendstream -endobj -2053 0 obj << -/Type /Page -/Contents 2054 0 R -/Resources 2052 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 2056 0 R +2610 0 obj << +/D [2604 0 R /XYZ 56.6929 121.3428 null] >> endobj -2055 0 obj << -/D [2053 0 R /XYZ 85.0394 794.5015 null] +2611 0 obj << +/D [2604 0 R /XYZ 56.6929 84.4903 null] >> endobj -2052 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F55 1037 0 R /F22 737 0 R /F53 1029 0 R /F41 939 0 R /F62 1062 0 R /F63 1065 0 R >> -/XObject << /Im2 1051 0 R /Im3 1185 0 R >> +2603 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F22 953 0 R /F21 930 0 R /F48 1228 0 R /F14 956 0 R /F39 1151 0 R >> /ProcSet [ /PDF /Text ] >> endobj -2059 0 obj << -/Length 2424 +2614 0 obj << +/Length 3314 /Filter /FlateDecode >> stream -xÚµYÝsÛ6÷_¡·R3Šâkúä\œœ;‰“Kœ»›iû@KpÌF"]‘²ãÿ¾»XP"%J¹^’ñŒ‰Åb±ØÝßb%&þÄDf¼ôës¦¹Ð“ùêŒO>ÂÜË3‘hfѬOõìúì§ÊN<óFšÉõm—cÜ91¹^üš=cžMÏ®Î__<ŸÎdž+“¿}{qõüò¿Ð׈€„óìõùÕ‡óW4övêevþòâýô÷ë_Î.®·âôE\¡,žýú;Ÿ,@ò_Î8SÞéÉ#t8ÞËÉê,׊é\©ndyöþì_[†½Ù¸tL¹tÌ(c' S\‹ÿe[å¢"Üø¶|2óŠå.÷ÇyÑ:¼R³[1d5s‚iïõdf¬fVônHʉÌk-ñŠœeÒ:9±ȼ´ñŠþƒŽ”ži“ $„5ÚÂ<çÓ™‘Ù»øÿ -þ‹ìrÛ–ÙËýr†y¸‰å–9í£®&‚¼€ËDýv<ýN+qà§Ë•š<¯áŒ“þ1ãYŸs<¦‘=CRÁew«$sÜÑ1¯ïÊLËÛ¬¾o˺¶ɚ»z³\ÐøM ï¦ i¤LTóºúcSÍ»e6{,Û;jµwôŠÛ‰ eΤ‡6)p¶!š¡˜9(A䉄„úq:S\dE’t~·®ë¶¬>âr°=å™äpþí•Â–•Ý¯ëyh꬧3¡³MUáÒ8Rt3À[2[Ô¡©~hi8TwE5ÔiÂ|CÊö‰†ðÜø]ÕMZÑ<5mX5?COñN hÔ$yÿã˜S xSgœ[™@gýk.áŸQx¾Î¹Hôñ6­Îá7Îe¯ ºÅrYã®qÚ zpx«ì¤Ûƒ©ƒèÄå2| iq[ÓdhæÅ=pfQ -«.+Úå’í»Fnàw“¾£~ï+pjã!Îvñëë"˜sÎúì„´~À@ÌÑÀÅé3J1‚ -[ª¾?hÝ÷Áœ×*]/8áz_{^²Ü;3éïx WG4"Wߘ¼e¹õ{r½í¦Œ¾/ñîIFÕ[•KfûžŒ{¬¥aNø.x·-PE–ózu¿ ÑŸcÿ~Ì-mY߇ua ‰q@fÍf~GST6_O…ËBÑNE–ø€/ÖóOÚDÔÞ--[–à¥Uâ^‘;ÍòN>0à(¿÷õºmÌ·ÃÃÁz!0~#bÊ‚ÔWØ.9†ƒ¹óLåù—pPGcñ*ªàj 9ÓJv1úMľëˆzÇPO+Ÿ„óê Æ㑨×>‚zòêõ9Ÿ@= 1FB’ȸs“½(<Û|þ1ÖUƒÁ*ÓYuU¬À -ïÒLkkw¶ßkŒý±ñi*ym]gUXþ0;J4>‹›rIxýU˜à”Í -»6ÆY^¬ë{jA§F ¨d· ®t€0aΑDœÏópßRŸ$4>ÛÉ€£õ& ¦¡ò”nÊjq -’rÐÉÃã1€sAŸ¡l k:Ë1iµ FÚnU=£ ‡ÑF›¡§Œa½M½Y#jçÊ‚«¯J°!dÓ²Õ-ê¡ÛoSmX>ð ÂK°ÖÆ”¯BQ%®<¨5šÚð îN§6àž\ŠAjC<ëjù”’‹aÌtpºG´Òš÷ ¯Súìñ.T#V È’ ŸÙj•“®—4 Ë.Až£ìF÷ ˜&%“D€‚áزÀ˜®£"ÁX¶ã# <0PÌûÙý:(:¹ ãf†Y@ê7`ÍmÖ””—q„‹hØe½iˆxo¿4º@ÃUÌõ0Ÿì’"ê: Fã…E7úëÐeL«"‡ˆb‡ÖÀ‡××D=™Ä)xy¸å'Hýþ•¨ðÝ3$w:AÊKw§ó£Ž(úÔþZ Ä™ð¶Çê`¿Žæp¿¾þ-"î÷. ÜðÇX‰‡°nè½j³º!;ã²°>—íÁv§Îáíe…Ô_PMê„n:ª¨œ(Ç2k„:½eG4²å@=r¥nùêçfS.S“B ¦uCƒ\0ññ´wD'ô—ˆ¢ú>¥ÞœYȽ»—X1¿ ³[û¢Ác€I Þ{J¶-Ñ¡pŒ ÃƒÖ ¤{UI5‹¢-¨uSÞz5’Žƒ1››Q¹÷¶3°›1ÝË*>íú÷W§ÛºÝ›[„Ûb³LðP†G,NÍŽæ™àæÛdÇÖBnæþN(®8^"’?ÒXû…ÔXa‰ˆƒñ|בB.ÆÛo_"ês>‘,CrzÉ{"¥w"l¯bÞËÐ#HÕT,Â/‹°|éàÄijËsjݦ™ -P4/ª.àè³Ë«çÔòôYÎOÕÃ…ÍXq…¢ˆuÙ*UXb'±à»«ùÄ%Qb’AuŠ¢úØ Æ"—u] ãvÓnÖ[&ËP4’ÊcHÝ7¨¯2Ñï€Ó=«çÌA0ìÊžÕw‘RB`•NP2óþòåÕù«÷#Ánù–Þ—¨? éx SxÞØ>ç1ì+©ÜǪÀ$ '·…G™Œ -oÒÊT”©%c²¥ –´†bÌ`âÛ„5ÀÑÏIÒ>(ÆVº.K^W‹ùXÅÀ¢c"Ú‰v(ÚpÓ†bq¶Ö©ðÕr·úTÇkK•®ãŸÞÔ„,ã^ˆÓÛvD#Û¢—Œ[xîö}QGÅÏ$T¢:Ìr‹W˜Aw2µyv\UJ -+š§UÕ£:¡ªŽ*©êòêA*e0p}ñîõžÃûÕ;›Ÿ–dK5"Ê@}b¶_Êr·IÀ¹¨«ÓJ‚›Ê~4§C5ïsè+½ÙBq§ô&T ª†Åìê)ÍÂ6)'Û¹î^KÛe"ÚTÛÂ2ÛúU/b@P ¢S”"þãÍÕ‹Ë—Þ£Ò¯/ß\ˆI1×ÝózpŸpnãýH-fÀJ匃–»Ä§®PÔ -7øbSŽ,ã[.'D‚±¶®©A•ÈÏ4Û¦ÁEhæëò¦[Su£ð\Rõ‰7À°~Àô‘2•5CŸËýNÚ<ÇW'ƯTÜÀw 0CD{(]ý±ìYJ<>ÀEÏè5Ë1™§ã~"µ§ÏùbUVeÓ‚:êt­ïÂm’½êùuQmŠåˆr…q˜+šcoÔÎåH¡Ô˜Ëð­¥|õ¯“»__s ¯['Ç}œ†yüÁ) …‚ )#‡¤ÛÈÙÿŸäendstream -endobj -2058 0 obj << +xÚ­]sã6î=¿ÂoufÖ\~K|Lw·½tn·{MÚ¹™^[Ž5kK®%'—?$R–ím'31B  >ÄfþØ,W„ +#g™‘DQ¦fËÝ=ÂÜWÌã,Ò"Æúþþêí"›b4׳ûuD+'4ÏÙì~õûüæóçŸÞßþûzÁO®ŠÒùÇ›O¿ÞüÓÁ>_>¿ùñÃ<ÊÜH@bñ4ÿòéý»ë?îºúpß³³Ì¨@^þ¼úý:[ç?]Q"L®fÏð@ 3†ÏvWR ¢¤²½º»úWO0šµ¯N‰@‰œ¨œg2àlÆ1JñDÊ-¸°B¸{©›}[µã­hàGÑLH¢ 5SK30WÆ“GC U êEL²%ÙÔÑ,äêP¯–× ÇñûâY{ûƒÑK 8J !vÛËrQ¬V‡²mzº† :×ý@y9AY(’k¥<격×Õãb]mË ²Z‘L 9&ûåU²_Ê—s4eFrN³1ÍöUšmyx*…&œK6¦¸Ÿ ¸2®f‹^oà}sè&sA jùˆðoýèeb‰Tf ˆ±âq–ƒ‘ÙŒs’ •}qbò<Ÿ¶¡EOq“´š˜°Æ9#Œ6¬Œ,V«‰­3N„:Ýú²ÙíŠÚ£§¦·`2' yjvªí‹ï?ܽûåöóýíÏŸú·†E(°.‰‘L6á°xÂ5Q@}PØîpÍòy³mÁiQ5ï6¥4ûòPtUSûǵû-ÜO]ì<žW¤LÎÁÓqpz·Ÿ8…¶\•åS®¹4p@A4Ó<Ãh´y‡sìªmÕ½¢…_î¹ðëì݆žªU¹r*ìaëßß~zë€Ä %JQžj°¥PnË¢-[Ø•ùüv=Á¼¢$—<0N₈<¼B&–žš/–?¸2ž«nãÀuã A7,p[Õ¥7{<O¢9¸ßÂrûxÜ•u×¾¹^ +ä;÷ÂþPÐ㹟vƒæigÛ#¬rxñäÖN"™$\Pâî>§pÅÁ¡¢y[ÎU¯Ã­{ràG/žŠj[¸ |plÿy,ÛÎÓ3=¾WzõJnü»6~¿Ýƒþ”È?ìðf»M±Î|daÕÍÝ’LÂrS€L¶îawl=æCp/ çÁ·<¼xŸà~¦îþ\Ól¦2ð± Wß|õ‚‹ˆ¢ k€KÃPiúuýÅïø¬›çÚïºí>¾+O ¯&¢}•Ã˜§¹Ã*œ'v¾^á5Rÿ‡Rþxìor˜CˆsÈÜs(櫲+;wÏxÓ<;¸›·„ºbÙyàÆ£ù @‰^}êý:]‚z»ñ³»§qº7QgÇ~©‡«Ý*¯(p{·~òˆz9=Ñ4júÙLw'É—Ï7dÆ ÄÔærRc…\é4)é±pÝ>Q±“d$7JœÍDb¬®9¤8Yì±&xLƒ(E4PÂä¯m9us +ѧVò¥„4XÈUHB +{å±pµrû>ªç²tHÈùé`úWXä9=­f„0²$\Qy.SEúxÜvÕ>„UÝvE½,Û8Øðs{Ôÿ®l‚éÛ­³4Þ®³·»umkï¤{_ÇF~ûùIŽ"iO$’…EdQº€gRG9›‰ü°.èhÀ²:ºœÒQ + ;“Ó& +ª¡\ŠËüõX & +ª5¡Ô(ápZA1#РógÒî„®Î7“‘v2ã5‰™ ‰Àà#qŒZžÕ=à¹3#†×Wåº%{3•ðR8™Œ.ß–Ýò-:s‚üN™QRv8¯ H–«×”!º  Ë*×WV\‰H4A‚ÃUJ^f®Çšà.ÑÈ 3ˆJRöÎj‚É$Ÿ¬”$D!W£23‘pbg.üMþzäb8zœ°&ÏÃõ€ GÏTNrnò“£÷Q̈·,#Íuò3ý:ž5dgb)!ˆÉt¼’óˆû \b]à¤nrx~®0Øã,sÁüÂ}»r#ëá7Îj¢ã„e!ŒÞpÂcCÀ‰ãj=LN\Fd©Œ}­­&ƒëZ5¥g¤nº F¤ÎFiCùߪíÎœXËôeƒ‹±Î\e ®}ÕûeºÄÜ# RŽË¬õX§¼¥&$4a,ËRæâašÄjËÞâ\AÄ,΄ F®@aÒûÞN¬GïôÊcŸœápWtËMé_*NQá6ïÊÏv+óÄdAWîØ5ˆŸ)“žzêöE>¸}‘» ä4FÏÑÙ+¹2O™l9£ +«G–(Öwp¡¾Æ0›" ’ÞmeóNxr,…(*JBÅ’X¨`lÓØD/ç>ý¶@L¢äM @9arTuðžl1„ñ©m 0ø8bœ¤C©÷ ÈʤxE„h‘ &?Îbh”ÅÐઢ<]ÕY{憈1Äe{Ž±ÎÛseíyÿêjã‰5s,#ªË|¤ ¾’«“C +Éõˆ±»²ž,Ø…(×VµlÜ—îS™ÈúÂÍ€•žš&’?=\‘Jغ«™ï< ^õw}9z¢\€Ë¾ñ¯Ã­wöx5' +«à—7ºp¼Ëïoã% 8N +Žóâ’ibÉää(„ɹI—üPÅS°Ì‡&Xä¶y|„dä¼'Z õŠ"¬ BXV/Ó:.Ÿ7Q©aLÂÅœñ„¯o*ÕôO71b BªÓM¸&Mjƒ†äšñË‚ë±&$—œ¥ØP骿ÚÃӡǃ>K»•¤IÕ…ž…x‘ õ÷I³§8!Í$ƒè$£\L‰ó$ˆ'Êèo¯YïF8uít®Lú!N3ÙyÑH"!}ŸhzŠ¯ˆ{¡´þuÑø*(lü!¨…/!"C­Ã•Ž ß"Ðj¸Ô1DÎr3êbµ¾<§â²¸}t·JŠÛö¹;ø +‡oš)‰Q`¬\X \­#_­æ;ˆïŠG¿âS±­Výu­üMƒMÁå²Ä»y!¸ ‹ +aÑD¿Ú(Â4çç[qȘEþ.Gmrñ͇ÝS\Ä$O[Á]§y¦†•Ï6i€›³Q“ÜF}‚§}¹¬PãËÕ›©#z¹¯è0Ê!\rÑÒF²R¼1š/.±tå6j+ëøcóK„ÇxüøëÂKʆ•&>ÚÆÇ€K܇ҵĀFeo|—1‡€BÂP—0H—廡2ŠùUóKŸ~„¦oÙöNOMß!ÈCÏ)mžõÙüÂeÛØM °ñ¹¿QQ¯jèÄzžSmdÔ¶ÅõüScsdjúžušífÂÂlâ:„®¨ì‚07©pv°c’(˜ªœ÷)<2ÑxR.4DÄ“åh3§ÑÙd0ºA °])uߌJø°¢coÝÄÅXL×í`SºôË3¸¸PV/Ó¶¤o´B CWÅ}§ñƒ}K†Š„´¥‹ý¶´$Ö':¶G€h³;”0ùð2•ê0…Í¿-¾ k—#Þ|à ã7«]UWோ.lä—rí…Y/ýk‹ú2sR +VÊÓ# ¢;\ƒnÔ{€l²¾øòUéÞOͱ›hè§zâvi{;~fSn÷¾3èî’Éö8ipá4O»<ÿ¼ýx{o¿¿Ã}ÇçÿýF&Ú¯"ÅjùRvÉç}¯`ÜíL $NŒGéP>™)kbxßá;óiŒÁÅèÓÆXè‹pð´&g,Õþû`wXX4΋ÂoômÅÈú`ø}.< ó€¨ƒ€àÌ`&ñNܤQ<;×̱¤3Q4W"L¥/…x‚ÀÕ«ðÛ0ûöÏÓ[ O¿;Ä0òjV½Üñ>Sl¶{l]pÅÍ «SÇÀ(žú\ YLV ho'ßü)éð©¬Äî^Χ3A!Y ¤ž)Ü4Óê$R žòþ?†â¾endstream +endobj +2613 0 obj << /Type /Page -/Contents 2059 0 R -/Resources 2057 0 R +/Contents 2614 0 R +/Resources 2612 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 2056 0 R +/Parent 2597 0 R >> endobj -2060 0 obj << -/D [2058 0 R /XYZ 56.6929 794.5015 null] +2615 0 obj << +/D [2613 0 R /XYZ 85.0394 794.5015 null] >> endobj -2061 0 obj << -/D [2058 0 R /XYZ 56.6929 243.4864 null] +2616 0 obj << +/D [2613 0 R /XYZ 85.0394 749.4437 null] >> endobj -2062 0 obj << -/D [2058 0 R /XYZ 56.6929 96.2114 null] +2617 0 obj << +/D [2613 0 R /XYZ 85.0394 680.7174 null] >> endobj -2057 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F62 1062 0 R /F41 939 0 R /F21 714 0 R /F55 1037 0 R /F53 1029 0 R /F63 1065 0 R /F39 899 0 R >> -/XObject << /Im3 1185 0 R /Im2 1051 0 R >> +2618 0 obj << +/D [2613 0 R /XYZ 85.0394 501.4297 null] +>> endobj +2619 0 obj << +/D [2613 0 R /XYZ 85.0394 100.9714 null] +>> endobj +2612 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F41 1208 0 R /F53 1303 0 R /F22 953 0 R /F55 1311 0 R >> /ProcSet [ /PDF /Text ] >> endobj -2065 0 obj << -/Length 2296 +2622 0 obj << +/Length 2462 /Filter /FlateDecode >> stream -xÚ­YKsܸ¾ëWÌ-£ª/‚äÞdKöjË–\•Š×Š¤4ŒfÈY>¤(•ŸºÁ!)JV*©9àÕh4úñuƒ#~bŒ«X/ÂX³€‹`‘îŽøâÖ> ¢Yy¢ÕêýõÑ»*\Ä,6Ò,®o¼"Æ£H,®³ïË“Ë˳‹Óó¿¯dÀ—ïÙñ*à|ùåäâÛÉgœ»<ŽåòäÓÙ†R+D‚[:×ëo—§'Ç¡^^Ÿÿ¸þýèìºk(ºàÊÊôçÑ÷|‘Á ~?âLÅQ°x„g"Žåbw¤Å­”ŸÙ­þÚ3¬º­sªTÄ‚H†3ºbNAÌŒ’Êé¢Lvyf¯Är@¬à\H8ÁRå&¯‹¶±Ú‘Ëv“ã=dH¦…iG·Kšû9¾.DõøœËmŽœÓúXDË@>©ê¶èv‡c5SÚHb£/¢HãÍ¡Ër(­Ê¦ÛgYê™ -˜Œ$Âʨ÷™b¦8õ 0`¤ ±wúÖ)R\¬±3¤íÚb[´Osjâ“ z*«}S4S°0P˜)ˆn% ‹„Œç°B€à2ÐÐÒ†,Òæ곞j|sŠü¾Ê~øÞiß»Ãο±YUã!Ý=PC/ŠCpîSá÷Í.IýqŸ[uæ¿6yZçíL¹ àÞ£?á~æ0^…¾°Î·Åv®”ìÁ ¿R;Ãr¥BðÒÊ[Š0¬æÛb—W]ûvÞÝ oðÈȾ€è²ýË\¡zà šr­ßÂÔZyó"×xÊõê§\ë¤Ìª]–?Ì1ÕÌŠøžéƒïY›X‹ÿ˜E¥#j -|0œž­?\_^Ÿ½˜)ÄÆP2Œû)¬ÃIkíß`÷¥Ÿ ÒÚ¦»Ù-öÑ.|´Cç›vè#ŠþÙåMKj³Ü¦ÙÒ³we)´}¤Pf|f‚Õ ‘×€Ððäc¶š!¹#NâÑ=F Ÿl·Õ£=Ø(©šÞv¾÷³iåÚÌ‘RM‹7D”d™“º.U îÛU~að²;°±Ié‹vcÝØMï\Rq•9Œò¬h‹òXžÃ¿Uõe  5d-ÝÃÈk`û6Ž¹+P‘˜”}µØ&EùŒ¬×ûpqìø y¸6Žw¨¸Ü¿ <¾ß0Òz?ëµÎú;EP¶Eè² ’Žm‹½ÄŸf]™/¸næÒìÝÐ[œx(’™×¢O௅dIÍ}ôVtf‚Íéo.±GΉ}zšÙ~Y‘ô7$¸5xN‹ð¸u-hŽô°’J³(pÙ˜ -§>Ë ñ†Ä'`ÿPEJƶ.G•ï0;ã5i;œê=Bž¨“6»Á ­l«¦5–«±UϘû0;2;IV…ÞÁª0 Y1<”á>øìšS}Ï‚ÏN¸«Î}$€ -72úM&62ö¨oy'd…í mÈ ð4ÑPÕdk)Τ0jŒ@6ŒmèòªË>Ä´<\Zj®S¶8íT®ý‡X² þB{v Ô€5öGPhÙ;(tKØŠe‘Û‡)í>¥¸â.—_.N¾œa×Ñ9_‚êv$†ôbÌ€ÏúëÉ‚Úô~2SÍØnÿ‘f5÷Å@Ø>ÕV{|â*”Üû<>²½QÌÄaô&Ó+XçµÃOË» 3²ü¦»£ãªÌÚ3Ð1)ÜNÒcòN3ðªH¦#›ÛªÞѳ\Ipø— -á†Ü’—½â$½€æM·ëɆwI–O»݌˜ì·…G²Z^<ø=Ã/zƒ”…ƒqþoŒ,L_‡®N猬á‰ÝtÞÈx£Œ,ámó¦ø ÐÒ³&%Tþ[@Laóøêì}‡99˜Øpqî‚ -ª\þº“ioF[Þû, 'z Oq¨)›$%lj'Š»2i;BYœs9ÝvFA‹µ›í9ô‚6éÀŠ)zvL`;})綔s,0G€£‡JYƒ6Þ×ëóOcX2A¨'síÓžV!|Òº¸ÉiÁ…_¨\mé']°»6´ ηß8~’~éYÖÚ²†zšX»h¡Y+1‡vîx(Ê>­×+wu7²Å­2rt -L»SŒ»€2€3Pí[Ü m’ÅX´tÑ'Ø4 -kbgŸƒnÜâvÊ Ž’Ê Ç3'–¯¶½/«G⌞;÷O çX™ç,Êֳϟ/®>\þçt!5ñ§ Íùü׳«¯g¿íó©“ó³Ÿ.®QØÉÅÍpñaWxŠÿžüöŸ­àÌ?Ÿp¦œÕ³'øàL8'g›“L+¦3¥"¥>¹>ù÷ p4ë—&'8“ÊÈ„õ¤LYO;f”Tþ°×åc¹-j:W¹Ýž +;o·ô¹)»®¸/;úZ¶»zEÃÛ2ê²ð+ÊíižÍƒ¤˜ ÁœÖwå³…oiÚíâ‚Vžýrý)pUfp›T@Döm³Z²eÛÜýÎ5×ðŸxCËqb÷eƒsv4×›r•$&E¤3‡‡•Œsð%ÇûË«´Ð…“¬6USuý¶è£Ý¾”w%™¥YKýZ4;°òñ‰…±Lc‚ø¤ ™æÈäÈ”™s§_oþõéËëV¼lúrÛ”=irýÜõå&øô¼mºvÛW»Í~ߌ©ÌD×eŠI®ö@#¶ÌŽÙ2Ál–çáƒÏR‘w¡4s8À%Wàœ XLŽ_9—IÁ“ЖÖFÿ.e¾“½(\ÞïÀOUÛ)u™4y”x`ñëç¦}èªn +{%Xn´æ̘̥`*@[©1ŒÒ† $ ºz/ÂCøÀ$Â× ?‚_<Á‡‹ëó/—Ÿo.?]½`ñüRÏ™t±}ës+äƒÕŠÜÜuDÀ÷ôÒ¿Ä,t*æ^]ß«.´T1ÅÃìºíz=UuM£Û°r²#Ì­Ë&Èmñ—ÈåÆQê}õTÄo¯öý.x(1÷Ë)$Gõ{J"ž-Ó/8RæÌæÒNüˆáy,Õ8Æ¥6S'JÎçÆNªw¢tÁ‰@ˆÆqÁ+–¼b HZW˜2Æ2«X¤ÂÊ-Rçq‚‰|h Ó‘ÚØ̱ àÊ ÅÌ5^=ÇÁEø\@_>¿DÅEoIîlj¿wµJì®à§÷JÆͨýx¬ *Wþ¤@ô­’‰„m©ƒEV.*Ä@Æü³¡8CRC)ànËuþšy ÏÔÔÏ “”µàç]ÜÆ7†< Ÿ›¢_®ƒ1ÁGÌaY5÷©„]©<òRQpUÕö(£ÁÑ3¡ÀJ^?+bÓ—åÉ6 ÙH¶T‘RìÀÖoKM²=°D@CºøgØ'8!|‘é“2P°öæ6‡¸í eSŽÍó iÞ˳ 4±õHX&Ï°"a“›`õA‚5!Áê˜`ÍÜËõ£"°¥!‰¦\FzKK|PòØcŽ»iû *ÀFÁdñ1l  Ëø$"<¦ø ˜‚+ÄbLP/œ®).×î "’ÌX^x¶`&r %&` H{lñ=¶¤œ´4U Åv¿KÕ½£ì¨îâ>Uб ®4~°b€àiæú’´æI$q‘”ó’0GQŒä”rzüÁߥ<@)ç!x ˜|î âÜÁMjÚJ´»í²\`=ÇZžx*Qš '">Ð7 ³@—Æ Öƒø¥7Y<šÔ>Z2aôa:Äö¢:”+è|çKß?Í¿† ‚ßv¥ó.Hð* .??f4G "‘L`oé~¸ ̣֦윢nN\€\è7êx‰MÜÎîú}SžrN†O¹x5/[¸§Ûl_UžZ¯ÄêMì½c×[äqoMŸÜ;w«24ÞE¸7ô[ŒwOŠÆÎìpÁäb»FiÇ·ða‡ƒf á™a¶°œ ©'—ô‚P»u¾ ?4tÅð3£f–Ð# F— ü|h»®º­Ã¢:ïR À*ᆖ$]—¡v;5ôjoR ³VèWPGò›°þ‘C9‰<2…B­Xš2f’±¯“ãöÝJ¦¹™ÔÃÍÛmiå8’wM<‚$a…ß‚~èeü üÂ^‚ +WBF/57‘Jù GÍnsëãep¨ßì&R"€4P†éùÚ°Áå]êÝ yéŠq3<œ}ÓÒ|â¦^JêÊð&êÊgêº#Ãaæð$Jà8º L!_¡¼¦ëË"|x‹Ç&Þï! ctŒ¿}«ùEáÝv¸¹î "ã°Q¾”`ÊâÏ’FDÑX¿¡j@ ÷¯4@@»ûm„ïoʘš»ÛWKˆÕ̉Á¤ñ òP$öÂC|W½àŠY=ÜÚ ðØ9¾4ÈܤÉ'•Cy–ö$ñï,ÁS£²wáI<…aHÕeüüª .Wd™Äˆæߨ#©?rA9Æ¿L%ž³ùðýÿlÿ§Á,gÊZ™þÛ–Ì5ÞÄLT +­'Œ9R=þ©ìX÷¿òzWqendstream endobj -2064 0 obj << +2621 0 obj << /Type /Page -/Contents 2065 0 R -/Resources 2063 0 R +/Contents 2622 0 R +/Resources 2620 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 2056 0 R ->> endobj -2066 0 obj << -/D [2064 0 R /XYZ 85.0394 794.5015 null] +/Parent 2597 0 R >> endobj -2067 0 obj << -/D [2064 0 R /XYZ 85.0394 691.7632 null] +2623 0 obj << +/D [2621 0 R /XYZ 56.6929 794.5015 null] >> endobj -2068 0 obj << -/D [2064 0 R /XYZ 85.0394 587.392 null] +2624 0 obj << +/D [2621 0 R /XYZ 56.6929 713.9465 null] >> endobj -2069 0 obj << -/D [2064 0 R /XYZ 85.0394 513.3346 null] +2625 0 obj << +/D [2621 0 R /XYZ 56.6929 649.6644 null] >> endobj -690 0 obj << -/D [2064 0 R /XYZ 85.0394 475.0295 null] +894 0 obj << +/D [2621 0 R /XYZ 56.6929 609.8446 null] >> endobj -2070 0 obj << -/D [2064 0 R /XYZ 85.0394 438.8551 null] +2626 0 obj << +/D [2621 0 R /XYZ 56.6929 576.4481 null] >> endobj -2071 0 obj << -/D [2064 0 R /XYZ 85.0394 407.0157 null] +2627 0 obj << +/D [2621 0 R /XYZ 56.6929 540.5004 null] >> endobj -2072 0 obj << -/D [2064 0 R /XYZ 85.0394 341.9916 null] +2628 0 obj << +/D [2621 0 R /XYZ 56.6929 473.2964 null] >> endobj -2073 0 obj << -/D [2064 0 R /XYZ 85.0394 270.8991 null] +2629 0 obj << +/D [2621 0 R /XYZ 56.6929 411.9792 null] >> endobj -2063 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R /F48 953 0 R /F39 899 0 R /F53 1029 0 R >> +2620 0 obj << +/Font << /F37 1018 0 R /F53 1303 0 R /F22 953 0 R /F21 930 0 R /F39 1151 0 R /F48 1228 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -2076 0 obj << -/Length 3928 +2632 0 obj << +/Length 2068 /Filter /FlateDecode >> stream -xÚ¥ÙrÜ6ò]_¡·¥*šysb;ëdíx-¹²»Ž8ŽÄõ 9rlË©üûöðe9µå’šFßÝ :àŸ:·I˜ä:?Oó8´‘²çåþ,:¿†µÏ”À¬Ðj õýÕÙ£g&=ÏÃ<ÑÉùÕv„+ £,SçW›·Á÷¡ŠÂ @//ß¼zòø"ƒ«§+­c“_½zúòÉóÁ³ £(xñøå›Çÿà¹W¹ÿøôòâÝÕOgO¯ÞÔå sy9 6ÕoQ¤¦" ê†_?ûZE1.~iÊŠ'[8Α‡žLÁWðù‘Ë2:÷LGq8ìêòB½ãÉõnÇM/ãÑ¢é™úÖ³¸ÖüŽY†|¾å•®ÚUeÏcæ~†»ÁNz¡=k”?Ϙÿ~¬ˆÀëf<¦÷¼ò´jä­¬6}]ÂQšk¡¯ †gŽg¬*±NƒgÀŒÉÁØFë¦ë `4°Ç•Ý©î‹õ®B ļ)H)MdÒ$¼ØW{  ãçíi'`kAPl6Õ†‡ÀARýxl*:[‰ÓLtÿQÕ—PÝ7aÙ6Û[É5Ø–µßµ‚û¦èycâN‘ÑŽš4 šöD î *ƒ²hxPt][²”ð‘©Ü ÒLeˆ«]U²&ôüLÌ",È, RÆÇ0œ!~þJ 7ÆÕu<Ñn'@ã®N 4é0)ð¢®27T"z#üž:R²aãh¬HmC~8 `õ·2ü§Ü»UÇ£ÃiFDcÖ;i¯Åá†]‘ ºB'Þz²%ÿÜÝщ3†à‚Ö:бeÀ`êzöYkq~]ß2[ÅçÕÎ×ñÏÏOÿÍð T2ð2ìç¶;aZßÞã«ÍÄW³ßÄtîù¡è ”nÚJ¼pÓö<`â‹Í‚y­ ÅÇ(™*ÈÃf–u‰qf‰þXEÁ——+‰›Ypôsu\Wl2#†±A¥*vÝVn‹•ÊBc£üA>Ø["$‰.êÈiÈìä&cp½º]@¨l¨âÔ!dï8âth“Ôñ~õþa,P‰0ÔyíÝÿ‡zS ÓJwSxõÄ…±GÁu Fn±EÁuÕTGòAQð¤˜2LÌ5W·âùWJ§¡5éÌÞ #y<¹õ Ç——<ÙИ7úýTu}G±CAôݧ]ÏëýíA )]€œãwpSu²ÂÜêøaäð°?õ§b·»]roÕ§rnìC…j™ªà× kr­:½O28¸û’ cŒDj"Èo-7Œâ8þ*ÃMãØ!tVÚ dÒ`¬N3Ö\ß²öìg¯až³“]­#üòkÙœã¶Þ-’§Â,6Ž<ÌŽR ÉEÛÉâÉ€$HÝ8f:Ì•žzb TFk§Ôµm¿ ȯ“,wåç?ýŸá7ʦá7!d¶û?C¯–™©0ˆ…ƒG²:¡œ†6½©ÑÕƒ -ïøY¸Ýv¡rÆÑ@ߘsScu˜©4^"Ñe6ÌLõTˆB |CRõ}qË«k¨ë*~¨»š*¦1" ÚS8õ 9òå°rè0õUœúèqŒ#£ÌÙ·Ýòƒx/!¦nzø#…€çµÐv'gÖ.e‚ ý›diÝ ”›¡¥aWËÎ&#ë]ø}AÔ˜Ôµ2˜[&W‡#ÊÌá]¦¯œØàLw¨Êzë^àŸiy€3œì`äŒò˜ŠQYŒqYŒe1fšÅ°“ày#æ¾%Oí¼´ª]Š fù-YÖ6â³xÑhY…ñ—“v`ʼn¿.9påôÕBÑQåʹÀÕõ=†šøRÃ;«9ùD·}‹—–¡ê‡ -N¨†ÁHÈÖ[^¥8Ï(;òFÙ}š–e¡ÖÚ_t… H°Sª -¯ã>Ôt³˜«ˆ²‘þÀ+¦` ´e )RÉ/dÈë¶ð}zM7ˆ*8ˆ“›wuÆžÌ/‰seò#1l–Ò˜<̬ï¢AºLYÇ[q¥€ûÌ kuÃ…2zzÉæqz-TJúÆÑÂE†!úÄ’çxOª0ßÿV*ŸõïöÀ ú°9÷Ñ……Ü"û°cA⊯=ùêÍ¿óì—×/ã-×ÕBþ¯i nÙ¦_‘jmÓ…†±Ê‘PðŸÀÈ÷«\|?Ìýp¡a¦fý×Sv»[mƒËv/ \Ù½ã'_ƒàíÇÖõƒ‹ÍlªëÑm~÷§ã¡í(ž!Â+צ‹òNîSl:¨jþìÇ.Z1Y€øŒ°äë‹…ûI¢CùŽ®‹ouWÈðÊ›ª|ß1õÍ\‘Á)Ƚº’FÝxï"ñ65ŽoSpyŒ±£ÞcÚÔrËÂ8øn@˜¡Êuúi§ãðú‚Çà,ÁÝ8N\wÏ®ž:ÅöÍë×€OZ80åØJãO5ð~+sµ¼Z¬;Ž$°6ÊÄwÛšÇûþZ fÇgÆg¹NÄ—à Ý®à^[^¸§e†í¤áZÊŒ.ÀÌ,gɅøÛʲ"Ÿ›Î/.+®Œ¸± ¨Û¢^n>…Ú»(éP4™4ž}Ç2ÄeRUøý\]HV×Ê‘÷¾œÂ——¨LܢÏÕ]<Éëq e'Y.áìvجY,vSí>w¡ƒšIqÃÃÙõüìÒ×J}Æ…Òæ‰zËbc©žvdcÂîØ‚NÉïU±ià+óÏz$¨Õ]'MúÎüÉœgø˜gÖ»¢yÏCo2ñÖ4Bk&Õ˲áÚ`í´Ö¡‰“Ä_z4K9¦e±ï¢ˆC¨é’ ›Q[”å B5‹† \›§$Ls;»ýpå±+œÅ£X¾> â¬‘¥¡YŒÔ,¾¿ç1-¾}e(I¡oú¯?z!\ÙûHjéž~_¸vŠŸäµ’ûªD¼cfÛ’Æwç{I¦P®P—&êžÏf5úÂÇ4þ–j8øÀˆ·øÍá»9=*IC(IÒ/äîR4½•K² E—' ô  6NÀøàíÚ·&\/K¾UMf]ˆ>€»›ziHßl¬|CzàÃBñµFjGŸ×Ä©å»^®usFDOMº¡/@²á< Ÿàñ#ù=ø•€›¥~³Š³0ŽÔ×|}dC£#G©|OFD†ÑÉ6|è…F¹mÏ )ïzOìˆpNñò|ž8¿þ¾} ñ3¾U‰|žþ<|ð£öezYé4dÚðrâˆBî(ßµ;ùdø.íÿÓÔàendstream -endobj -2075 0 obj << +xÚ­X[sÛ¶~ׯÐø¥ôœÅ•šéƒ“8©ÓÚq·“éå)‹§¼¸"Uiûß»À‚©0qÚsFËÅîbwñ-ØœÂÍ"TX9×VE™š/ËßÁÚ‹ <‹Ži1äzr3ûü¹ÐsKlÌãùÍj Ëj ›ß¤?Eg××çWÏ.Þœ.¸¢ÑrºP”F—gWߟ}ƒ´ëSË£³ç¯aÊ¥Ž‰)rúËÍËÏŸ+1/¬%Z*§–“üÝÕ³§äé««çŽuv~Óë;´‰Qá”ýmöÓ/tž‚i/g”kÔ|J˜µ|^ΤDI!:J1{=û¶8XõŸNùH C”ázÂIœO9IY .¼)7ë í•lÀÊ)ÑJò`î¯ÙyFâ8'”Zxš6i³2«ÚÓ…¤6ºÍîòªÁñ.o×0b4J*¤ä)0æ«}^Ý!¡i70~i£TòÔ*)è^¡€~É©Ä‹àPµ1ÞŠ h¤Æ: :´»Ú™0_HNt,ì|Á±Jq¯ü²H¶MÖ O ¾q°2)îê ˜SNøCi˜Mü™Rž +BÔ]eÕr³¿oóºÂ…ƒP?]Õ› }¨ÓŠ0Ù(~S¥Ë©3D˜Ú%‚ma¤e´Ün6§Ì€ +m±ÇźÂ¾º<{º¸|¦ÐQÜ*kÁÇžÊÁ.ã¨ÙÞß×›6Káø÷f+ºçXÕEQﲩ·{¤&8m²%êÑ"Ç»u¾\#Û²®ÚÄÇ‘[ðôÂ’&[Ä©àÍ:õä–\ Œx{ç~Öx»hgÖˆáY¸Š0ˆ+ñæãÊÑ[£ÇÞ\øAEÝxs5ˆKëímDü¶­Ûc^ M¬¦q—„èçL%‡‰ö‘ë©Ëº,}Èq—ì¤ú3Ê]Veˆý@]‡¯{½µÓÛ]”¡üuøæp&`¼4w+O.®ž!³E½g¬ï6I9ª’C±TÜ BuÑ%_Xg_]­@ý‰p†ä£AAÐÒ•. <Û-ú[¢ÜÿÁ þ쑸Iª´.qÜï#œ:'8ζ«‚㜃ۄS-Âþeéc-›Ê}N¸¡]îÜöIŠ&høkU猪^3µ'5D +Ù‰*ól*ý¦‚‹#T¹Ë`æèºØ¢ë4í\ï:ø¸Ö“ÀÞ‡}laë+4±Ä•Î(æÕý¶%†ñXeãOò¥„q`LkW?äªnqïfß# o7Âu«6h¾mÑ!‚$°|ªŽAR&o“¼HúíÊ@™Tûëû.”&Ôƒ×Y`l»Âpþæìòú›óÀœ-¥Äg˜§&å}·KbGœy•5GÌY²\Ü׫¼r%C(Âö8ý»m'.,EL¬pÇð-Çó¯}‰ƒ½b@@xÇt¢GnI³U²-ÚE“mÞBIZ0üE½LŠuÝ´§*h÷‰Ë,(´³æÈ¿˜Üé¯^˜dÄjE„}ãá¶Ñšõø`Àÿok¨Óípþù½¹ õ;9)IÓMÖ4YSº GJ(ñ‡ýsK¼JñÐzpA¤;òu™,eªŽŒáÁSËM†šÒè$~~¹ú¯¯šw²Øßrùê"ãù‹ów¶X±¢xùê?Å»“bƒÛ¼úà9 ,ˆ?Õl'߉¯.Ìuüäëýq÷fw%~øñëí·_~ù­Ù@ë£Êµèsî9˦ê…/÷]É6Jnë·Ò²ßý=š¨—p÷hÆäx£¬ +L»¼(P®‡[°UHN$"¶G´y¯Uà¥#ÿL¡¡àšPø1˜0äÂ6”…‰ø¼À{ÙG`¸úgDiz¼Cxvˆ Žã)HW9ÇËÉýû]8iôÞX +Ö ~6ÈG¢®{Ä +åE³îÊÚm’fÎWÞ6 {Œ6™ 2T P÷gÎíᬓp·…{¯ m"Gñ·0„ûLTæ–ß9RÕÐùú²  ›cASË¡!rô¼Jó%Pšnì¸OðÐDùÚúÊå·94 ßœ²¨O@O©4ËÛðéó›æ7# ¯› €¾}€þ”BHø~ëÖæój"[ ¬ÛQ²B.°há,‚Öjp¡¼ŸÄÚ#;é |šðñUMì¨$ÑR<\´ÖGõ¤ƒ¿+À*aƒ‰‡jÀ‰q¾+^QnÁ]Q¦x(¢Ë7 …bÀúòŽ•€ pOãÈ=ÅÔèüUEá¯Gñˆ³FçéófKKðlÜ÷¾ùp³S"ÀˆÀüE€VfXß9µÐ„ƒÓGñ€Ü£ð9s¸u@ò­z|QÐxËQå'Núô“ƒÒý«V÷ˆÎÎ!Ä·˜.n;ìòLp#$ké»~spvŠŒƒÒèÄ`ȸWÝÿ’¼Íª ¶Š×þý¥J±M»ëSg>ÎÈzÛú>Á£jWó¡Beé¢FÔ~äÆ(ÑV|ü5ŠÉûtpÕgBŽ%BéŽÇÕœM]4S~…P½Ÿ¶Xý}á±$Ö¨.Õ\±N?tl1t‹qܱöݾv¼u`tÍ–_Á.†hö4ÇÒƒI3~¶øÔ¬‰‰2F?Ü©IK ëûüÉŒa6&Ò½HŽ’=[®kÄi'¡uôø·HœÉ¿ì["7Hšõ¨í'âßP¹©wXd®ÒL¼šÒFþÏo´‡Gj©‰0†O?¿B«N„°¬SÊ9‚ÅúXõþ5÷}Ýÿ>œ´endstream +endobj +2631 0 obj << /Type /Page -/Contents 2076 0 R -/Resources 2074 0 R +/Contents 2632 0 R +/Resources 2630 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 2056 0 R +/Parent 2597 0 R >> endobj -2077 0 obj << -/D [2075 0 R /XYZ 56.6929 794.5015 null] +2633 0 obj << +/D [2631 0 R /XYZ 85.0394 794.5015 null] >> endobj -2078 0 obj << -/D [2075 0 R /XYZ 56.6929 258.0612 null] +2634 0 obj << +/D [2631 0 R /XYZ 85.0394 627.5418 null] >> endobj -2074 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R /F53 1029 0 R >> +2630 0 obj << +/Font << /F37 1018 0 R /F53 1303 0 R /F22 953 0 R /F41 1208 0 R /F21 930 0 R /F48 1228 0 R >> /ProcSet [ /PDF /Text ] >> endobj -2081 0 obj << -/Length 3216 +2637 0 obj << +/Length 2488 /Filter /FlateDecode >> stream -xÚ½]oÜ6òÝ¿Âo]Y–Ÿùè"iâšËÅ.z@šÙ+ÛBvWîJ¶ãþú›á׊ZJë4‡Â€E gÉá|ÏPì”Â;ÕŠPaäii$Q”©ÓëÍ =½…¹·'Ìã,ÒrˆõÓåÉ?‹òÔSðâôòf°–&Tkvz¹ú´8ÿðáÍû×ïþ{¶äŠ.~"gKEéâ×ó÷¿ÿËÁ>œ¾8ûæ^¹ 1Šx]¼¿øíÃëó³R..ßœ}¾üåäÍe$kH:£iúóäÓgzº‚ürB‰0Z>Á %Ì~º9‘J%…õÉÅÉ₃YûÓ+”ÐDi^fxÁù€ŒÂX§¥2¤\X^üÕnk8˜”Åâò®†ãšbñëûó_ßàP-þ ”×땃·7ØßU½ƒà¯èôâßç¸;czQ_·ö¹r“OÍzíf›U½í››ç°”ßsSu}½sÀ®Þ=ºq±¸iw¹M rþÇŸ•œž.#F)nOvßîz‡•pDJÈˆÓ í*û#ÉÅöase‰h»Íl%(~%Gó¶ÚÔ™= N“Ê£>ÝÕŽE£½WÏðóæÚmÿp¿ªz?á°ÿ|¨»ÞÓ{[÷nÐ3A|‚ËŻڶƒ£-À]ZHòg@êù@Ý}}ÝX™¯^9ˆ§Ž.VõMõ°îÝËë÷nøE“嬢ÀS‰tù‡®^‘›¡„*°Ì’J ’å­Ýã,HNÁYÎØ=žrÝ^Wk·{µZíêΓò )ÿ<¦…•À Æõ,1éšÄÜÊ‚h#YBÎE½]!%c-¢d¹4Ê&FrÇÙ®ÙÞºI'€¹ê'çà: -ͽօÓj§dDKÁ<j,ÿû]½uY}ŠûXP×K§\B€r+ôÄCåÚ€^ÂBLZÙ &÷ö4í#Ø?è–£"'’»ÜvžjaeLɺÜ aå6r¿ìØ3 ‡ÕÖÍ##,c».L¬ÜÀ)3â\ßµ]½uЫg³ ·[=ƒ«Úä<Ð’ñ’(S^°#ŽÈïqm‰£–¸¦oÚ-(dzƒ\ÕãF}랛ꋟKEP¹¸n7~îÆñ}ã×whç×îIÄ(PëF´m÷Sâ-ÇMç¤ï‘ˆ~Ƈ8ι±h—]×Ün½çð®=ç -Q% €Ízˆ!Ö´‹ˆX!ºíq|xâ”"“rž†ˆ•!"ñ -Q:¥â"ò ½ˆ¯ÞU(ê6¾T1Š rëP¯üû¦Z%3!Ί=nÆ_F‡1L™g²$šÓrà0”?… ?™µ ˜ÁÒyƒP2"Yc݈s3 9%µIuÍmŽ:UÆ‹òÞE‚>3™¸Ü ê˜ûÞ½¬jHU6UxuŒ…¤<>÷ñˆ^±§uÏèÞa|UY“Æa»-å=”_ÇÆS?í":e^݇Ž¦ÙÞ?ô“æ£`` -!çÍgˆ5m>Ë:¯u¢ªN*¥˜§"beÈ80 ¥Š”k@6±œÌ[,}¨°Œú|‰æ– AŒ ¶àNx¨-úJ­’dòåIÔ€oM—¥¡ %Ó/ÿî}†‚` Á§d/ $«\‘ýkFö wì{ïÄ;Hø1µËø(e)ç)ˆX’ÓB¥#¹Ö) {¹Óàå`°g5B›[C„çºy´é+ ªFuK—â_ùßC€ÆÖ–$—a¯Çjýu©Ü 71«™ð{ -dÈYês`Õëu]í&NåS/àÂA^"™Ö -JÇ|ÀkFnú¥övg?hÄ®îdHP¢ÏR2”¤n€Åôˆ”4Žjâ¨)·¦ƒ8ŠÐG¹uÏ+ÿ~yñîíóçª÷)¸¦Á…NŒëR{ygE¬ÌÆiÿË¢:ÝØõ•„Ø·fÄP-ÝD.¬2ΉÆÞ6p|tìEEÍÿËqÅÃÃ&Ô ´W1”oàr.á+ —±ÈÜUým«´?Û>ãCPÌcñÅe*VשÙæâ [bÑ–¾ì®”Ï!à줔z”/BÞ~“# - ¼ÂØùiÍdŸz&ÚÈãPõ`¿uY/NM·Šè>+K~ÄŽX3v°lÒµ«wõŸþŒ_Wí¦j¼Ÿqãe®¶…˜ ²¶Î’±2t¥|Æsð› aÑáú¦ÀÙ’™Õâ…O?Ý>ØÁu=„îoc†áŸ6µ³‹=ß{ôúkc›ˆ8~jú;¿ETä4Õ-JÂX¬PG<_‚(¨f…:–| ÐMÅŠc>z€5#Û€5–íó·ÈVªçÉŠXºÆ²%€ÂƲN¶‡ìV†”Z¿Û%)b ²ªXüA½«üK|ZU’ °½®w ÛºÂAN­ÄH­^ùˆ¯(Ño"‡&ÜÅBµ È`“:€ze0w˜Õ!Ö´D¬CûÞíºº?TÆmwæóžàÍ@+Áç‰XjÓÀI!¤JÉM5ƒ jYá¯eˈgÜÁ,hŽ­LD¸E‚ÁÐeçzÃ{³¡r -ü˜ ¯r$’BÈHFh¶½j¬'3i!B•â<<i™U%JYþ­ö_»iú>¶þÞ½wO4»fÛ×»mÝ£î§AÖØÌ<Î%áZ¹bÍDÀ:tŠßmŒ‚Hg‰XjÇA¡žOÉu…ˆ¤4^yíÍCÒ`8_ цֱ‡î­ŠsÖ"ppÄ"$pݨY„|EŒZùÿ˜IhHEeè9m:/~ë+æ,c‘Q/2â0ƒ¢ÐG dˆ5m ë{ ÄáU}EÈáÜ@Y&ÔÊ#V†ô„єɊí—ùþ$T:Ì߆äåK¡x@Ü!Ëröë;á×'½¡ñ ÀÝÃÕÑ8»ÆÝÄPzk¹iwŸ7È%&Ý]µs%"^vâÃÞko²_ãèKõ½æì¦úص7DëØ_=˜BemïÇiü\áˆ-‚ÝêØàˆ]i<=ûª±-hd‚ý –R9€“ ,³þñ#ÞvJ:Ïé˜-Á¡ÊÑEªSkã¯á ¿tï`T­®{÷Y]lªµáþ.3³ˆu'®oo6ïþÐß“cQ¼0n›Ç:'oP H†Uù½ ÔÊ&~ûòr36!p…ý@%qçߘ—H*¦ŒWSvÄx5ô@¸f‹§ºÞ­{iüÓ_:ÛÏz¶«*¦Œ8UõW'noßøÕYÕ»î¢öÉäp¡LNªÇ9é^Ó"Jõñ£ÿÂÿO{}p{ “„y¯?Àšñú ·ß}‡w¶ë:Žœ~߯?güÿ§}øä#Àçƒ~›àX>Ó#çˆX™ƒ$1¢-5lt’×–únT¦UÐíKÿl–¡ uàñ¾åÛ4Ü]iIü*CŽ:ÄÙlÂC,f§L½ œ q,3bÅÑÐg’äê£ô áW¡è qÒ:CçÞ^X‘ÙUy¸ì…é«mÓ>úæ»ô·ÌíÕeGî-ú*«éª”2óiÌ>sòéÔD*g¨Ô«ØÙ¶>êîï×Íàº(ç½ %œÒ¤ûuŽý”Hž² ¿Ý¶¾+ø*tViŠèÅ¡ì5oûŽì®÷ÝÁ=8­«fÝôÏg <8™ú|[("óÝoï¿ûÓîý'ì’-­ùTj'‰àò=QÈÆÕ˜ôøø!íÿO*zÕendstream -endobj -2080 0 obj << +xÚ¥Y[oÛÆ~÷¯Ð£DÛ½_pžÜØÍqÑØ9¶sp€$2E[D%R)»î¯?³W‘ÒÊrQ×ËÑììÌì7ß,ÉÃ?2ICÍHŽ&bT¬Îðè Þ}:#Af…¦}©ŸïÏ~ú…©‘AFR9ºìéÒkMF÷óo㟑h*ðøöúâãôãÍõ/Ÿ.¯'Sb¸âãó/_.¯/®þ7™RA$1>¿þzþ›Ÿû21t|þéònòãþ׳ËûdVßt‚™µé³o?ðh;øõ #f´½ÀcèhuÆC‚3g–gwgÿI +{oÝO³® Q&iÆ”ŒAF:p†0H2Êœ3®Ï?_ú]Ý]ÞN`ûÿ…‡ûÛºåêÓ×Ûs»Ûû«›k»[ÐI{þÅ#E˜3í”Ý/ÊÉ”9®g+7ã¶Ü<—?»Ú¶=„·ESǘ>m7¢ÇåÜ¿íÿœE¹î¼ä¦ž~~S—EW5uÄê¹—‰¿óÊŠæ©®þ +u‹°âïå«Ÿi×eQÙÅãªUm7h·ä}æ“ÅþÐ훓޾! “„­Œµ YÓ Q4HÚõ–åXšñ¶­ê'»6‹æ1»¹Î™ß,[?Óv³®\•uçÿôV˜ù!tXÄ:~Ôƒ”J¢Üܘñ]YîÙÑö<ÌÆM½{Yü¥:ݬù‡‹O9HQª¢©ûEo‹6ñ`‹îéŒqgðêúÂŒœÏWU]µÝfÖ5?u[>–>îu~öyVogK?~Œró²›UËëBÏb ÄšuwNÆùow7§“ßfÁw,°†ÿÈÿK;7µ‘x*ëýw+ØqÑÌK;Oü¼[ƒ™¾o•BBÁØûöŸyâp DjD¥”)2^™2.f€Mÿ÷Ííi·\Õ]¹©ËÛ»×BÝ„k6]µ]íÖå°‚ŒÑàq#uBm€hŒ‡^g–q¸0Í¢OÞ0”&*Å+iqö|‡ÌÜÅÍ^ØH•à媉ÙÙ4Ë÷$Ñkݬ۪Ý/ ÎŒ–lÄÁW\é²0 +Àþ#°!œ´Óà@p6#æG¡ÃKpè·éìG=øMÁº½4kNx>i-²B'HsF‚\ÒYdt‚“´b§ò±Zþ •‹4ú=£\ÌÆwÊë”ïQ¾>iïò6£2@{Ìöõm2ú¦Ì@m§œ±pÕ¬Yñż“úö¤¹³ù|S¶íû=ÐTY,6MÓÍ«MÎN ?"¥KRº=©t t!çV(µS—)B)éáỸ¼ûx{õ¥G^H¨2xpˆ’!ŠiL©€¥E2mz<&"Lúb$l:4p†6´G$2KS€AÅz%›ªñUVž…Õ,¥²OpáÜfaéY²ñ¹¬+_fíôÒ3Øû~ié“}¾lªnêpu +€ˆ˜ær˜£Ž¶P#ð‡ÀqÖ÷#Å©#¯Ùq:jD ÆÒ¾¯jíº©çÖ„Œ;ÁSTsš‰0ƒ¸T1ííjmiBèDrÔ ðJÔ“ˆLëmÎ’5 'Îhú²&)°¥'¯^ëÌE>>ÜÖKÃÍ0>ç»È._'@ÏÆ–rp°Ç†žó4\ø¤‰ÍD·aî¥ê~6…wè¡Ñ\«¦³œ[00B oÖáPpÏÑ­îÖ1˜Ø®ýÄ,ã*¥‘Á„ô3)aã¾Ç²½zŸHVÿsS̓ ‹°íº,Ôç‡GÌ B©Áÿø€^|Ø3‰&•ˆc²o#P o£dÜ ÁÝïJiLÝOÅ yÙ5O%l|c{¼<Ï#X#Î@YÀPÏn|¶º~€Ï€¥€ëßä(}©Ø™’”$µË«þ’Þ¢ß^2 +e–œ,*({ƒ%/øl»fǧȄŽ¤V\žl†¥½†¨_,€ŽÝ/ªÖ/Wx\‹ÕDzÀ–1E2ùÈ-™“ì]çB*«k¾wj—óOeWä3WI¼;^»ã6¾,ÀìçlѲ¢™ˆXܾ¶öX$¾0ì ô!Zb=ı[ÁA¯n'â‹—…¥°vä;#7_>l«eg+ÿg¦º;žq‚߃N ¯îÙþž +à”’’‘§ˆ“|Gê +ìkÓ/¹ãL‘Ù¹¯ Û„c½é¶kd+u÷-™ú©”‡hÅ ´?\ë!Z-lÐy™}´Â|l;VLk—¬X¸du³³í²óÍjåA  +¨Wu¹ôoÒ,œ± Cøà˜E΄ÃõŒ\.›—|•g8#7âd$61\®ì˶µ]² >jƨ{™Wåsê1çüTäâÀ©{‘Üf,›"ÞJ,š6às(º0ª›pc±Ý8¸v@ˆ³pPÆ^¦h„-7µëÝnë:ï7 úXÐþ¥U¿ýUùJ®€ 2“ÉE¥õâñ.Bú»u$Û5¹#øÇ3¬ûÁ…Ž€þ@iíaí¹¿#[O«`»?Êëå¬Hü ~n}v¶ª±ŽÄ–#¬åàåL$þß‘Haôñ Ú³ðT¶ña/3Ê?«¶óäzpë¥s°­À*•üzŠFˆÁY)Díý’ÙK¡«G»®o$¯ï]?Y.gm}üŸ‡LÔîF×;¦¹ñðš;_\3hú)jŽ§¨V1y\UQoóÛ*\-Û˜HSöñçlµ^F€@ö÷úœG{Q«ãÝ3Œ¬rût7Íðt÷Øð„ 4›q·àªézì›q=~m¶^ ]4ÛevÌ;ã {­¿+%§»Sa¹´‰×l»`k–ÅC5co2x R¨=oõùëv»2¬`)¼{“ÉSعå û®=ÑRJO:“üðLò¿Ÿý³pøæ!/ +ÈHtŒÜ¬eL½MnûRÇÉm’r.·lbèrmRÀ{—l}Ó¤g„½m[’Ê7Œ20IBÕк»D·lºs> À õT`Ô<‚>¨ævÎlA&ª®µÔ€9~öƒìdŸÝKYI´ºdƒ Ô˜Sñ/ê”Ùc :uF†¼fÇHì7…vBõÑhK8º7c½“9é ãâ\äâl¿×‘ÌÍç ÎÐŒ) ¼ä «’ÌYÃ3Ëúv} µ_£ò8ýS \6û:ѱÔì÷*œãﯱÛM-©»¥èÑ¢Ý/ÓuÙðÔkh¬ÞÑöp «þWÜgZhsí=UƵ85ÆÿøîîS5·wiúHC +W£¬áDêÃ\ {mÿ?»³· endstream +endobj +2636 0 obj << /Type /Page -/Contents 2081 0 R -/Resources 2079 0 R +/Contents 2637 0 R +/Resources 2635 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 2056 0 R +/Parent 2647 0 R >> endobj -2082 0 obj << -/D [2080 0 R /XYZ 85.0394 794.5015 null] +2638 0 obj << +/D [2636 0 R /XYZ 56.6929 794.5015 null] >> endobj -2079 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F53 1029 0 R /F21 714 0 R /F41 939 0 R >> +2639 0 obj << +/D [2636 0 R /XYZ 56.6929 752.3759 null] +>> endobj +2640 0 obj << +/D [2636 0 R /XYZ 56.6929 668.0781 null] +>> endobj +2641 0 obj << +/D [2636 0 R /XYZ 56.6929 607.6906 null] +>> endobj +898 0 obj << +/D [2636 0 R /XYZ 56.6929 570.577 null] +>> endobj +2642 0 obj << +/D [2636 0 R /XYZ 56.6929 534.8112 null] +>> endobj +2643 0 obj << +/D [2636 0 R /XYZ 56.6929 503.6098 null] +>> endobj +2644 0 obj << +/D [2636 0 R /XYZ 56.6929 440.3004 null] +>> endobj +2645 0 obj << +/D [2636 0 R /XYZ 56.6929 370.9227 null] +>> endobj +2646 0 obj << +/D [2636 0 R /XYZ 56.6929 274.6697 null] +>> endobj +2635 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R /F39 1151 0 R /F53 1303 0 R /F55 1311 0 R >> /ProcSet [ /PDF /Text ] >> endobj -2085 0 obj << -/Length 2191 +2650 0 obj << +/Length 2259 /Filter /FlateDecode >> stream -xÚíY_oã8ï§p/ ¶ÑXÿlùå€ì43×ݶÛf=Ì΃+‰1‰Ý‰vzŸþ(QreÇMwïîñP –(š¤ÈŸHÊ¡£þèHÆ$NY:JRAdDåh¹;‹FkXûxFÏÔ3MC®gï>ðd”’4fñh± -d))EG‹üóøGB#2Ñøæî·Û‹Ù$ãÅ|2eLðx<»½ß\\þs3pFÑøzvóÛì -i·“”gçw“/‹ŸÎæ‹Ö¬ÐtqcÓ·³Ï_¢Q;øé,"Jýdr¼ŸP5Öuu°ƒ¥Æe¤.+ûÌ‘öT45ÇV?èeñG1›]½û yh -‰P\ÀŒ Æ=–©c/MHÊ™r<çb¦‚Å„šðRJR)™å´.Çá åeåa4%\&Þ.–AŒ“Ô@™Ž¢æá”À¤¤o@î…éâ“QWoª§¾FEI$¨8©Ñók ·¦b1ðy¨ñ¢¨¶Ù3 „%1FØ –‡=b¡l°Óu­õ9Ì/«²CP”k\Ͷ[T«ž ƒÿ¿Šºh´Sf‚dxÌ5ÄŠr©_¤‚wD0κÈ`4xàj]æ¯.N$qšœŽ\ÈõzèZ.;  •&Š°„¦§•z¦¥èqÂ$lº£ô”Ö.ál\¾éÆ.vÐ9Æ‹MáÞðO—ÇlÛò7•£—ÞcŒMÄÇý6+¿âp[”úu? ‰‹Ë7üpð³ç³]?žú§ζ€c{R­gPzŠgáz%t¶³’âëž ’0 -yç´'®žð\6ƒéûÃúÈ€ŽD¤§µz¦­GDDȘuµ.&i4>ìKÜåžÖ–5€…à åœ$1Ôï)U„&˜k®/Î÷xË[Xc”ÕzW,«­—ž! ¾«Ý Yûä<źÄ"¦1Xw¶Ùb^˜rIÒÈíiþûìúö -ûšž€“ÁîSŠua)PÏv[»Å`?[ÈÜvÁæpKtɼJ**”¸ -SÖ®Ë8V-L[“ø¹¬ÛUÜkTp¨µ£Ø# ”¢¬õ¾Az¹Þêƽr\÷ G·î»=­ì¬Ú9 >÷R•!˜ìf_ç²´üÐ`ü«*mÆQñø¦j -LáÄd9RQ>\•)J$él¹q#”‹WvjœeNÎ>+¶m%òé LzÂQ]õ•gȽÆ-ìÖ¢î–l-sxËÚ4ÛYÝæ̬öçÁw}ÏÐ!Kœ„¤/…ºî¥Û6§ì ’AN±ã—6ûè©«Ê ·;œ Ú/‡þšÅxÿ6™ÆÐÒ‡ëoúïÈâ 6c3®¶ù¦ªÒ ·Y˜ýIa¶¶Fè§aI*Qä…ÚMž’ÚUBC%¾üßгò0q#Ú<Ž€Ï#†Þ5«ƒ»5 -Ìýyf*brÇSšØqk K­¢Ag˜›<{yÛÞJ܉vø |Õ©ñÀhMÄÀA -ÔnŸ§v)Äæ‹‘†¶ñÐv©™ú[Í3 w;ü#’‘ âŽk^•þO¡ù°×{ýͱÇÛ˜›˯æ¼tÜøWa9$£Ë÷7³ë¹ƒ]µÓG¡ûÏQÊ‚"óJ÷ܦ¼h -[ M"ÓM¿…w™Ã¤?Ÿ9Ìråü^~õo)¹Ín¦A'¥{q €´×É°€—Ì:«É܉œãÒ™ô¾-ãK›ÓŽð†³ÑÜKâ6…ª áª~ÂUãŒÚŠ•N¬‚7ñ¤¨6ãÂ>*íi•{U/êÆ)ËÐ ÃÌpW -Î`ãž5>ýYõݸ2Ýv}pÎE‚‹ Œž6ÚÄYQ·AÕBðH¬½ ©Vå2+Ñv3®J¸Wñbé¥bÓ¥¼Û@<4\ëiÝ@µ3u`Oû øÖ”cš*[­išŒ?}x7fD´Ú3$ ? aw¨G«õ'ÒLš±¯´BeCmiý¼dÙ,fµX9{B¡uO*N­ÛŽM¾²' 53)o¦÷Ú†S/“ ¹/Æ@½¸¹»›¿Ç±íd`|·6‰D{ø€×eÛ#ÉTw—7Ù£FʧOw—Ï[é?ÏÿéØÖˆ7­ÂÞ $&ïžì|ñZóáòjàsž»”P“$yã»ZÀdoB Ü[<“QùN7Ëw{H!ÛG8ß媯JFàÄó“ê[¦#ýÝÏL2!œÊ¸c€k›ƒÖ«È¡‘+VÏþ.³ÊÛæ•ì5_™­ -™¾á¬€ë„·<—±ögŒ"!#I“$vƒ•«®¡$AREýG,»…c!ø¥Ë[¿%…ü`œùÀ A‰œþYsö€^,’=9€KKù–AÞbòU?}TàºÉ$=Ž–ë8Ýo”Å¢û¬ÖÓXøo$Ë*oï±þÊðëÙûéõ…Ä™±oxH]ê0×`¸²†vi -Œk]Ú>ªm›±Æb"é[ß°B®Xó\ÿÇÚ)¬=ì‹G×—vðƉ¸§CÒrǤ÷í9!U7(-ÞhâÍ̪>_ðffofÐÁ›!Ü»…xë× È¯ጧÝ/&wó9Bwvu÷ËÛŸML¤<>Çw`Æ£(y™1ÀF0SB¾ÌLk¬A1 f)§ç/y:o·rþ×Ε; °Aó›Ó@£Ö%ÿõO[/?á ¨MJ±×~Ðo§0vF/,ŽSBD‡{ñíÿT#æôendstream -endobj -2084 0 obj << +xÚ¥Y[oã¶~ϯð£Ô\ÞE>f»éž»ÙœM(ÐöA±äXXYr%yƒô×wx“%™¶{p ¢©19œù曚,0ü‘…3Í©æH`"«í^¼À»WÄË,ƒÐr,õþéêÝ/,]h¤%•‹§õh-…°Rdñ”ÿžÜ<<ÜÞ¸ûízINÞ£ë¥À8ù|sÿíæ“›{¸Ö4¹ùxûx½$Z +B$5r'>Ü?.þrÿËÇÛûë?Ÿ~½º}Ô«N03:ýuõûŸx‘à ~½Âˆi%¯ð#¢5]l¯¸`HpÆÂLuõxõßaÁÑ[ûÕ˜)¸PHP.KN ‹Û #,àüË”c”*u°%1{)c¯åf~N8çœ,Æ‹m„"[ÒÑ–Z#NÅlˇ¶¬ûÎ9#snÓ´½î·Û¬}sšµ{ö›ÂOìú²©Ã—ëÜÚk¢’—ý¶îs®™(׈RšÂŒ"m¯–«¦^¿µ—+/Á/”Q/ŒŽðà­žbøŠÒò‚kFRg\¤¬k¾;¥„I‚”Ì+õ½x«³m1W0…Ò4Uçu¤"Êí@8@Oh2ÕîqW¬Ê?0¦…µ¸ >’F)7°ªÙ‘óãHƘ޲=LÖ}¹ÊŒg+BÀæKFUò´)ýÛ}׻ѳ_(sYUæn˜7Û¬¬XÇ-–Œ!E˜96A&ìí!ž®òbí+AØÍž]$)Š‹1tŒšÇ°á)RËK°‘2E”‰ °K†Í ea³»›‰¶9f(Fæ|gõ +B½&ˆ¡l gŠMôGƒ¬ˆyÌL‹dµÉ꺨Ü«©½n +åE,®1F0 Ç3^Ï#žai–©ªìú¢öª¬›6¨›¯<ÉuÖv×fÙ–0àuÌù‘]Ád|ØreqgQÉ1E˜>…åö î; & +|¬N¥ÓL#©3` +RLmLIņHÇ5ÛuY³€…´R絤"êM0% —(L¦úM1%¸á&DÒ5{ë·Uᦠ™§ÓÖÉäYŸ¹Yç}@"(Z ¢úʼn8„še¥š¶üÛ’8QR–Üù5½€ä¾ì|«‘`|Æ8Ý  ’SYî”$©›ÞMíÚ~”yá&²¢ bÐÞïòâÇ;®HQ‰ƒ³Ì9ͪÅ_û(x×íK”«â'óÁÚê7ÀDÆ5/-¥ÃÓí\]çNM”4ÙBL(ó¹qéÚÓuYïö=ŠœR™êˆ’ Ì@ÏÈ…DŒ§ÁÝÉÄtœ|öÊi³U_ë`XkxÉÖ=Í‚•ŸŽè!ÅX”Ød6ß$U LïjR4cD¨Jà‰]ö‚Ïû®ÈÝLY.²ÜM;Û†²ÇúÇzÂäCN}Ö‚÷ö¨YådÀŸû"bGÊ‚÷âP2ÄøQS©¼`Yç&)ˆö›¬w»Î|ï¬Ýù)ã2Ul†úM³¯|±öìS®9ûIB2ˆ$ú<¡¥NÚ e ­‹eG Yj°P–ç­‡ó´¨J!ü¼jA(¢Ú´¤Ú7ùx¢Û´¤¢Áÿ”$wn¨f“`ç%ÎeEùs’^ÊŠ ¥ä<+šÕ-/šý‡mf‡m?Œó¥ýÎé| U¢šýoùÒQ)•ˆ˜.è_oÓ–¡jšÝs¶úî[…‰a‚О9E ÂP'ŸÇâHê ƒ”ÅbM®P=Ÿ­6mÓôyÙªL-¡w<«Ü Ñnš[)Òì;Qï›#'­“ײ߸Q¿‰!Mˆ™ +ñ³Ì"^ÇÑT×»6Î/Ù¸§%³õ›û`øR¿”ÎY«¾iý›³ˆ‡N.#^§$4v¯eU¹¥Ûk•ì½V`y‹ã¦7,}¸Lnü«,_ú–‚0ˆbSºLؾ4gs¬Ì >voã„É&œf; M•ÒQh x{aHš áꕇe]JaÉk[ö×@×Eí>;cUP—üð. El¬˜D?33¼ì!Gû,)ý¶„õg»®›½¥3õvÈ„e5 Ú!,ÇŽ¸R¤(•ô"wa¤5»Økqn +&u¡×KŽàAÊB}±×‚4מêµÎê5ôZÇzE{­‰b>v­»lìJ~*v9JSAÎÆ.X™=ÝJ<éŠþn;h^k[N™áz¶ÿ´˜eêE¬ÿòú^p(È`_¶ÛHe€-¨Ìš +$ðЗî^W!ÀkˆA,ɪ.œrÈϹ'aJ|¬§oêêm–ƒÕ£©ôf/‘0¾Í*üÕØ&ó‰ª W[Á´Â¥â_FÙãz¬¡ƒvKHšL!"<©ßþvóùáÓícäô¾ :õ> endobj -2086 0 obj << -/D [2084 0 R /XYZ 56.6929 794.5015 null] +2651 0 obj << +/D [2649 0 R /XYZ 85.0394 794.5015 null] >> endobj -2087 0 obj << -/D [2084 0 R /XYZ 56.6929 553.8035 null] +2652 0 obj << +/D [2649 0 R /XYZ 85.0394 390.6346 null] >> endobj -2088 0 obj << -/D [2084 0 R /XYZ 56.6929 216.683 null] +2653 0 obj << +/D [2649 0 R /XYZ 85.0394 257.7108 null] >> endobj -2089 0 obj << -/D [2084 0 R /XYZ 56.6929 83.2768 null] +2654 0 obj << +/D [2649 0 R /XYZ 85.0394 193.2733 null] >> endobj -2083 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F53 1029 0 R /F41 939 0 R /F48 953 0 R /F14 740 0 R >> +902 0 obj << +/D [2649 0 R /XYZ 85.0394 153.3455 null] +>> endobj +2655 0 obj << +/D [2649 0 R /XYZ 85.0394 116.3439 null] +>> endobj +2656 0 obj << +/D [2649 0 R /XYZ 85.0394 83.9066 null] +>> endobj +2648 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F55 1311 0 R /F41 1208 0 R /F48 1228 0 R /F39 1151 0 R >> /ProcSet [ /PDF /Text ] >> endobj -2092 0 obj << -/Length 2606 +2659 0 obj << +/Length 3141 /Filter /FlateDecode >> stream -xÚ¥YKsÛF¾ëWðª*σ£ly½J­m$§¶ÊÉ"Ae`ЊþývÏÀ€ åªÌ4zzz¾~’Í(üØÌ(BE*gI*‰¢LÍ–»+:ÛÀÚ§+æih1¤zÿtõî_"™¥$Õ\ÏžÖ^†PcØìiõu~óððñþöî× ®èü=¹^(JçŸoî¿ÜüÇÍ=\§|~óéã#¼J“J b é4ÿvûáúϧ_®>>uâ EfT ,]}ý“ÎV ù/W”ˆÔ¨Ù ¼PÂÒ”ÏvWR ¢¤a¦¼z¼úoÇp°j?R†(Ó p6yS¥x¤•-¸°JxÿåÓ#ˆù@at - išpKõ´ÍA Œ§k6¼ûä^¾å¯8`ó¢q‡kfæùêX­²ª-ýbÓÖ~Þ•{¶Àê¥vã&ßg‡¬õ›üA)/sXn@×R(Ø>ìàžlž¹×e]5ù_ǼZæn¾^»…ª9îWž!››¢Úø]á$p\< SÃÂíã“»ò²x>d‡W÷²Éí h7X^÷m½9dûm±tSõ>Ñ äg7‘U+7ØežÏr›U›Ü³ª<ïc{tzqïn\æY“ñÝÀõI"¤æþJ$'Z'Æ]@ñzÁ(@öP­–áPB‘„ä>Ûågî6%‰P–È~l%øƒóÄ*üÐŽšüð=÷Je·VʺtǶ(‹öµ¶ÇJ’Ť¶›<¾Võ¾ËŒÔ V)J¨‚ÁÀHΕ„ñ¤À šÁ€…¿d £ê®Aƒ_ÏîJ >ã‡Áa#¤nêãa™/²Õê7#÷DÈÿ œ—œá–ŒVÊ“‚b×Åf±.Ê|‚­†UBŽÙ~{“-˜ç9ž2!†Ód̳y“§ÇÃ)G¡ ç’9î'8.„†—„«`‚ÎÇìëC;Á˜ ’¢/1þ½½Nlë ýÔxœÂ$°EïIÓDÿˆ¯æ$5ÆL{êEÇq1di‘‰Æ9# œR¿3ŠX¬&ŽÎ8JèøèËz·C3at & ‘.¼ñ9˜ß~|üðÛÝÃÓݯ÷ÝWžžõ6qê38G~¦lð該nÕ:oè_×‡w,0ò@J䜠c–ó»Ö/C“¯òçS©¹Lá‚‚j¦e† ÑhóŽ&8+Ï4óÛ½d~Ÿ½;Ð÷beÌá ¥Ÿxwký,L ¸#8vá¹Ìün=!<ø #yþœÆ&(Ü…="}¯¿…@úR´[7]Õ!:lØɲ¨|<­÷6<¹iÒà™Yi7Ç]^µ¹ö­û`(ªÖÓgîÑlÑ<]°>Â.6D"»µÓH" TÇQÕ¡ÃÈqæ¯B$±r6£xÙ‘gß³¢ÌžËÙ,‰˜bËH&震ô™ i`¦ \ôW Öäy0qáê™2Ä _½OdF²% I¨ÑÝÍCjÌ|·öñ¢¡8[)¨0±ÿ0ØÉyDÈ~H.qTÝž—´žd~)0ßã,qùÃá.k—ÛÜ”’B4oó/xSÿ—Ä€-`eá®]ƒú™Jã[ݾ0½ÛÆ%%§9ºaD'o”Ë ÄDô¶œP… $Ë[<¸Q×f0îo;uoYØÒÞœH!‹2ƒ®ÎbWû,41`n[ÛZÏp_ÛI¬£p*üa²`”&GïÉÑÿeÿÛÑå8Q/gx ƒÔèLËO@]&Å*„¢@‹¤7ùqCU ®jPJ¢«:kÏ©")wÝóæ< :oÍÈóþÍèzã‘)sl#ª‹BšS¡¢¨É¡zä:–ê1¯&»u!¿µ--›ÿv}ûØ7𔈤ëÚôTñ}i"iðÐ}ЀÁ6]í(ýÉ‹àAwæ_©¨W€Ûú¿å@›g/¬\ð7’äžæüµz{«¿7KÁYRp–6 $'›E×E!-6ép³Uß-;|®ƒý•õf¥9÷O5$ÌøÁ„,´+Œÿñ¿Øý¿ôë=çÏ% gfƒPx0Æ“±èÝÿݧ²ÿÌdòyendstream -endobj -2091 0 obj << +xÚ½ZÝoÛ8Ï_áGX³ü%Þ=u·i‘ÅnÚÝä€Ú>(– kK®%7›Åþñ7Ã!eI¦8©(j4g~ó!‹‡b–f¬´³Ôj–p‘Ì–› >{„g.„§Y¢ÅêÇ»‹7ïU:³Ìifw^ãY&fwÅçùL¤ìXðù»w7·‹Ÿ>Þ¼ÿpus¹6Iäüí§OW7ï®ÿ}¹ b ä|þëÛ›½ý…æ>]Z ûpu{ùõîç‹«»^¬¡è‚+”éÛÅç¯|VÀ~¾àLÙ,™=Á gÂZ9Û\èD±D+fÖ·¿õ OÝ«QUΤ22¢ )fB0ÜÕH‰eFIå”qû\7Û¶j§[Q‚¥™Q³TiÆ…6±¥(Z& Ü ¹X*„±,œXZÄŽ(P¡TEQ·‹eS?<–õå€þ?/rñÍ{Xïð²à‚‘YX_Ë×Í®êV"¯£˜Õ©ñ”_×U?ú#Âß$,M”ö/ýQ>×ù¦Œ0ׂeZ‰)ó]„¥JXf’Ä“îòºh6Õ:ÆÎ)M“lʵ}‘ë )¥eYØýMìE¸-”IØÙ9Î_Me šEkŸˆù-ŒPš¯ôÞØ :c™0àÅ +Œ á‰cðîêö§ß¯?Ý]¼é_:,Ægà‚pæiÄPˆZŽÏO؉4å.ïÊÜ8Óó/ +O•îš ömIîŸ#‘±$ÕÁ’êv¿-€idu­Y–fA1pÒ1n–ÌÿppE„“âÌZ–HÒB̯;·­6Ûuõ…sI;SsPÞ>îa·USYó@׸Zâ* ËÔdpZö¬¬E¸«×]U?Ò}NRÞÃî`Í·»K‘Í›ïUÑÓv«2²sÉ%À‡¯Ðc¸â/ê1Ó:ê‘¡]DØâ¨, NÝ>×]þg4ïhôT­×^%]ë²,ÊÂÓ5¤=%ç35Ñ™ĉªûÁêåzïõ·yM×òÏN.¦! Ø„2’‘4³Ø6ëjù7óuÛñ¦¬;FR ++™Ð°áX®²„û×` J¦xŽJš9€P^Õ4åÐÃÍBXp3í¶\’ô ñ¤x²n°l6gøt]Õ%ì\iàÐÑé)ïý %O^™™^€ÔÙ,Îôë.èÍ÷ÈÇ'@’€#8Öp¥÷39oOi<3 ¬7}•ý¤LJ¥Fö.™òlþ!ôGûCìl!f ^GºÁ«°ú&²¸ˆÌ6 ýS³_û½ÕÐ]î-4Õ þ’±~Èk [¾^;£6Ùü‹”ÚIs)ˆaað9Ús*½³Ãû'Õ)!ÅÒÖŠWú#OF÷†„ì½?‚pKØ'ÈåEu>i‚ ៸ƒÆ‰«â ‡‚LdËŠí¹®<>‚7üÃ7:Ù7ë­Ìy±¸iº2¬ +r+ð_%/c»bÆôØ^um¹~ð›Îë°û€çˆ­~Ñœ.둆˜ÍÒÈpæ7%£XäÄ$ÚU.|VâHáÞãúp&1“•é»ã'P% Ü‚ÏïVÞÌŠò!߯;Ÿû´G¼ÙI³’’¥D>oVª3f¨œY­¦K‚¿p›¾°d Š,94•T6e“%?íªºó{Ͻû­š×J»‡0·{¦—™Ãµ +l¶JíDãtî{Líü3JD§P®-$(2}%òJ–¨d„ã±£QDj ußÙ£R>šžÊÍ1‡zÚ&ê¸îù;àÝê¼l=UD¸‘¿‹„iZI7rx%´Ï$aàB¬IÈVUX# +ÈH”ïa²îª¥7ƒwû„+rœïÝoª6Rq+¨v„Õ£ØêSái”†Â1}¶¸"ƒæP´c9‰§€`厀¥ƒ|kmK쥞¡1V¦f6ísܺÙEØ@*%l0ÒІ8Ã…œ‚d«@¶–†ƒÚäŸ0£À{pOUëjê +>T,¨;ªXˆ©±çœÔë Ü̽,9±nËmî3q˜/×>JkÈŠEbÇ©èC³^7O®¤I\ÏÁ]Ij Ýžfœ IH5¸ÝÔÎKöÈ~ˆµixŠ}B;ÙÜ0Åg±CP¼Ö„üä.¬Iöoÿ0ÚìÛÎoTeÌ*51¯Uþ½œ „ÅMÞaУå÷|]yä Õ)Žq9œÔÚªíúº:0X—]WîZOUTT‡xö¼˜"ë¶ÜUMÑž?Ì5tπ߀ê ø*gößNÅ¥³KöqéxÉX\-ùÛ¾*½Â7MᲈÝ.Zy-bÒ=>¥€T^‰®„ ÃhB'c»Îë¼kBHëÊ?;_UíÛü±õ=Në[Ú„e™|!Ø ©N뻧rúÞE‚ ÔY_²ãôRìDªóÒõTñ¦n%”2cùÆá&!DI’yÛPé·,iš@{i‰Ê‹œf]®‰ƒaÓI<`hŽ ]ýËE#ˆ?F*ê%!zu³ /SÈ°(h1I']EÕš/uª`Mš%Mä1ÐuEuÀ¥7EùýßW$[RÃCì¡âVºZ àÂ$®,**ÏLZr–ÉP£øÐa\iåºl[ß<Ë K%%µã¾!€.h¦ª·ûŽEv™á—)FfržèOê¾oG%Gb‚W†6Žø !§jÂϲ+ç%^žrGWd¸ös£À«‡Q3?(6­,db“Ö‰34T¢«r ÷ýÑ÷c¸+‘˼ iÒmÀw>î$°nÐÒ× ðÜm•šáýÚ 3¨Ëú”ÆŸ@ÑúЀ¨ê³¯`¢¡µÄ§gh¡oÙŒìáOŠ(j»!˜Ý—ßÊâ4 ‰ê%@P´@5̾¦õ²Tbú1h(—…ôEAúrV®@‘k¨fÄ/aÄX®[°&´/¥“ùªi;ù€ƒßS)€¹3Mpm°Qª_ÙCÌtÈÛ(ø s8¨§6HñD4Z÷¬ôDØeÃkhyáØ·ÚݘàT'á;)}l‚4’>cNv)Cq0üµT4x¯ÆÿùGY‡Ÿé”)¨Ýâð#SÀ c/ +.R~ŒÄþç[Dzÿ!ºãendstream +endobj +2658 0 obj << /Type /Page -/Contents 2092 0 R -/Resources 2090 0 R +/Contents 2659 0 R +/Resources 2657 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 2100 0 R ->> endobj -2093 0 obj << -/D [2091 0 R /XYZ 85.0394 794.5015 null] ->> endobj -2094 0 obj << -/D [2091 0 R /XYZ 85.0394 752.0715 null] ->> endobj -694 0 obj << -/D [2091 0 R /XYZ 85.0394 700.8318 null] +/Parent 2647 0 R >> endobj -2095 0 obj << -/D [2091 0 R /XYZ 85.0394 667.6704 null] +2660 0 obj << +/D [2658 0 R /XYZ 56.6929 794.5015 null] >> endobj -2096 0 obj << -/D [2091 0 R /XYZ 85.0394 631.9578 null] +2661 0 obj << +/D [2658 0 R /XYZ 56.6929 749.2278 null] >> endobj -2097 0 obj << -/D [2091 0 R /XYZ 85.0394 565.5242 null] +2662 0 obj << +/D [2658 0 R /XYZ 56.6929 677.9694 null] >> endobj -2098 0 obj << -/D [2091 0 R /XYZ 85.0394 493.0222 null] +2663 0 obj << +/D [2658 0 R /XYZ 56.6929 495.229 null] >> endobj -2099 0 obj << -/D [2091 0 R /XYZ 85.0394 308.5213 null] +2664 0 obj << +/D [2658 0 R /XYZ 56.6929 83.499 null] >> endobj -2090 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R /F53 1029 0 R /F55 1037 0 R >> +2657 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F41 1208 0 R /F53 1303 0 R /F22 953 0 R /F55 1311 0 R /F39 1151 0 R >> /ProcSet [ /PDF /Text ] >> endobj -2103 0 obj << -/Length 2134 +2667 0 obj << +/Length 971 /Filter /FlateDecode >> stream -xÚ­Y_oÛ6ϧ0°e‹’"%±oišnÚ´k\`ÀºÅ–ca²”Yr2ûÝñHY²™fÅŠ5u<ïïwŠ˜pø'&:a‰‘f’Å4z2_ŸðÉ=ìý|"ÏÔ3M‡\¯g'çoãtb˜Id2™-²2ƳLLf‹?¢×LHvúçì×ó·:0K`\ÂÈõéæÍ%»üpó–8Gbeš²TÄƱ^|üxuóæú÷Ó©ÔÄŸN5çÑû‹›ÏïˆöñÔÈèâç«[vr5ë +xŒVü}òÇŸ|²›=á,6™ž<ÁgÂ9YŸ(3­âØSª“Û“ßzƒ]ûjÈyJgLK•€Y¤*ìb6 -`Jg&S¢w±!{.ôÈtçü«œB°XÁaä´¿ŠÝ¡3²„锧“á/yCg–…}1õM)–¦µIÆ&”‹Cõà-5ÖïÈm=WÀorè ž0e1>õs[@Æ$:êVnáüt«Z/¹~Þ—"5,N¾£/½À€/‡Š‰L²¼ræ¡ rMâ‹h¹9YԬ̟7õÎåýv“weS)Uªa!áxaÒçÇ)Ë Ò¾›c¼Àáb©Ù7;f½m;2ûΧDÝ<9OÜíð7‰ê|],ˆôTv«½Aúd*Ó˜¥™Á( -f´–Vp ï <é(¯î› ¼¶võ‚m1·Q):÷ÜmÊúžÖ%j UÔXŽE±!ò²q \G!­ˆ°.Ú6¿w'>æU¹ð…ç®q'lçó¢X„ÆRG×K¢ÖM Ô±ÑL$R>jÒHˆµ4ŒËÌüïX÷§C‘ÇÁVpßÈLˆýÉÏ{ª h7˜ ŽKŒ\·HûPÌKÌ÷bqæÞc0–äƒM½˜Ž1SIìk⩬*’b7˜\øP5Í_¸ÂSmhÓ&:×.æU¾EˆÂ5fþÚZEæ¶Ø<§w—wź¨ôf9âå#Þ»ÂfŠád'x8cqšÄ㜵ÙeTTbf›öÙ‹CÚàhËÚùR¹í7(U ÖIîH«¦íÎP“5­‰HX‹E±Ì·U7µÞÀ½7p³Yzažð€éÝtšZÃøØ"T”!SÝ4¾Ë׈gNŽv {†./í°Ó®r²wA»ûRv O«r¾¢=ÇItŒ€S¢q¢ŠÚQò-z¥+ç`Ìbl eíAÑC¾4ë5ÀIKOTåÜ¢­(n-Ö»àÑu稫f[-Ü;«‚Ô[6½š(¢q¼«üёØäî`âÍ%=Ê9m™H(#Ž—›ÈX¢2ŠÌ[û–J] T‚Ö›)œ­UÕçu¨Dl. ·]Xa•…(Ntß>ª -ƒÃO mWVe·;BD>ýk ^W.ÿ©˜g¾òàxiGáw¾Ý¸êª‘, -ÃïSî#æ6å -ñp;#|’fÜjÀ33,r2H¬Ö†¥\'_ëòú¦“ î>n¾C—G§C‰öâi†Í i¶?øk]ž Ô˜¼m©ËBGzÃ?}ð¯:qÄÛâqŠEδ+ Öça¹w>5«ÂEisšª(XiÜ—XJç]]Ñ»ïn?¬Û–_¸æþgl`cŠ€ê¸— öl³$E¤3Móf˜M0²pÎ}}ì Î8KpH‡8 -¤=ŽÆ2Zté0\)Í‘ÉŒñêâóì—Ÿ^öâuÝ›ÚãÍí®…þÇEõZŸr»ÞŸ‹³c⃧$K Yû/#®Ü²!›,Si:xëèÄ©çÂ]³7 ¾Á ÿ¸ŽÑ ¨ä˜Ë `9þÌ ³ÌÏD_¤L÷yâó÷°B4÷ Rð†pG¿ÝÕÍC Pwˆ'(hF¥Pµ o`ô˜5Rc}õsÊPÄ1€øÏ)=×3¶ß\Ý^~ºþˆ—Û3•_Èã)Œ:Ü{ÜÎ#Z¸>änÜõý(2 ‚_XZ­úëoëx`ØŸLŠÇ"P;‰„~ª ÷½(nŽ/¾i" X‘]| ¹€–Òs‡¬¨ƒ ­-×e•ohRtÀîhÞmý•‰T;HÛíôæÿкkqŠCÙ$þãØÌB’IuÖãÉTÇ:ºõCOëŽê(U5¶¯¥¢¹ ¨w›|^´šÚÙþÞ>Û¯ Î œÁ¸-ÇÍaŽ£ :~]\WM ú¨XE—v4²Ó¤oFøÙHîG´–6ö>TmãØz©îý^9wÊÌ Ü¶[{ÉöSnƽº]åµð‡†°¾WÕïîÐK×Ç¡¬W4©œÿH´ÏÇ/¸ËŸ~ -¼r>nmiª´|UY¡ã?×å?Çâ~øÒŽ`¨éKÛ¡íþT­·vjTó†¡ ‘a`­§AKg½ŒoËêNŠ¯2ûAWÙ µ%j·¢º}V½¢×óšøö£øëŒ6}‘C>¨8Eî¿+èÑ' ÛÉ{çôC_†|칯ý8fÅqèšà=²ÿï¿ìÿF¢RˆB&Ãß¡ejïƒÄ+…V ™©.8¶«2 û¿’Zendstream +xÚ½VMoã6½ûWèhË‘"ÎÚÝz±q\Û Èæ µäD€Ey-9Aúë;IYr”EŠÂIÃÇáðÍã3I€áGÉf* +b!Ž vÅ0öyD&ô °‹ºÙŽ~ýÅBJPl÷\a)I°MïÇÓÕj¾œ-þœ„”ãñ š„ãñítùmúÕÆVEÇÓÏó |G"ÒàO×vt9½O¶_Fóm[V·t‚™©éçèþ)ìàË#¦$^à#¢ ŠQÄâc>rmF´ ;£ÍÔ!*8“ˆKpAI@RœÓ\!Á(³d|Ûþ~·68íP‡ƒÆH`eq ]g'Õ– ÍkUgEe?>•º*Ou~.\X5B,Ôå‰bLª&ar Œ'§c¢“"3³ ŒÅˆÑH6°¥‹¿-ŠHÓÕfhêøNilßêS¢«CR»ÅÊ>“4=MˆgU•¹ÚëÒ=ŸvWžæXê4×6ì»n¿ÌšÕe³ŠÍf ìÇM}›W]«¼ºÖ‰€f3è$¢$&C}%°kÊ#xÔ?F˜KÓýNŠ¦çЋê±Öl€³äG…˜ cÀ–Eö2[$sH„ÐÐçq%xŸ–Ù|ói½XmwËvÖ»ÂëWÛSC#I„¯¶m:´–a×u¥®»n†¾cŽ«çÈtêg< "6l¤a¢VF3kNg³5êHÀåÉç—#ôÐW¶DAñ¢Ð?JJXIÍçN‘_7wÏÔûìÝ,–3‹WnZZä:¯€¬Ú”hBëlŸÙé;·‰>'‡ʉ! !|߇»îA½®ÿN#½Ó(ç4™q¤eÑ·õ/¬æ’âÊk` ;µV“¸aŒé¡u]'À¹·’nš4©“ÿÀGìÇä#>ÒMñ¾´¨+J|êG‘ ÙžQ}.~€ÖÞÚ ˆÒˆ8ØÃ@"ÏŽETù_™]vŸ²Ž?\)Z(ÿˆÿô´s¥Α”±7A¯c226R`R´R0¡ÆüP<®ŒÈ ¦Üۀźù]ÝŸtÌv¹f© ü<'ºÎë×~ªc•Ó2ô 2!#¶_¬ùÂ{ôò”ïžœfm_~8Ÿ+³\£ðª§ôª<7Þáìož™®›xy|µ½·› õäFQ@.céÖ¬ºGþ%¯]Mº8?Ùs¾ËÐ{÷0Æ‘¹< ·2ùðírgó¡—ëWW+ ƒS1E|Q†qøG¾.½½Í½­ýoŒ ²*endstream endobj -2102 0 obj << +2666 0 obj << /Type /Page -/Contents 2103 0 R -/Resources 2101 0 R +/Contents 2667 0 R +/Resources 2665 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 2100 0 R +/Parent 2647 0 R >> endobj -2104 0 obj << -/D [2102 0 R /XYZ 56.6929 794.5015 null] +2668 0 obj << +/D [2666 0 R /XYZ 85.0394 794.5015 null] >> endobj -2105 0 obj << -/D [2102 0 R /XYZ 56.6929 605.5421 null] +2669 0 obj << +/D [2666 0 R /XYZ 85.0394 751.5568 null] >> endobj -2106 0 obj << -/D [2102 0 R /XYZ 56.6929 504.7499 null] +906 0 obj << +/D [2666 0 R /XYZ 85.0394 708.6012 null] >> endobj -2107 0 obj << -/D [2102 0 R /XYZ 56.6929 441.2539 null] +2670 0 obj << +/D [2666 0 R /XYZ 85.0394 670.3846 null] >> endobj -698 0 obj << -/D [2102 0 R /XYZ 56.6929 401.9804 null] +2671 0 obj << +/D [2666 0 R /XYZ 85.0394 636.5029 null] >> endobj -2108 0 obj << -/D [2102 0 R /XYZ 56.6929 368.8669 null] +2672 0 obj << +/D [2666 0 R /XYZ 85.0394 564.786 null] >> endobj -2109 0 obj << -/D [2102 0 R /XYZ 56.6929 333.1161 null] +2673 0 obj << +/D [2666 0 R /XYZ 85.0394 498.9559 null] >> endobj -2110 0 obj << -/D [2102 0 R /XYZ 56.6929 266.6983 null] +2674 0 obj << +/D [2666 0 R /XYZ 85.0394 418.2058 null] >> endobj -2111 0 obj << -/D [2102 0 R /XYZ 56.6929 206.1673 null] +2675 0 obj << +/D [2666 0 R /XYZ 85.0394 349.4108 null] >> endobj -2101 0 obj << -/Font << /F37 802 0 R /F53 1029 0 R /F21 714 0 R /F55 1037 0 R /F22 737 0 R /F41 939 0 R /F39 899 0 R /F48 953 0 R >> -/ProcSet [ /PDF /Text ] +910 0 obj << +/D [2666 0 R /XYZ 85.0394 306.4553 null] >> endobj -2114 0 obj << -/Length 2593 -/Filter /FlateDecode ->> -stream -xÚ¥]sÛ6òÝ¿B“—ÊsŠo‚—郓8©ÓÆqßM¦½>ÐeñB‘®HYãtúßo P¤LÛÉÜèÀØ]ì÷BbÂá'&Î0®R=IRÍ f2_ñÉ5¬½=aÏ,nšõw½¼<úþJ&)K­´“Ëe—cÜ91¹\ü>=¹¸8=}öéx& Ÿ¾dÇ3ÃùôýÉù¿N~&ØÅq*§'oO?ÂTêÄÂ&!Ùñ—ï¾cT¿JS–hƒl!æ_Ï_¿b¯>œ¿Á­G§—¿ý; ®Ù?~ÿƒOpµwGœ©Ô™É&œ‰4•“õ‘6Š­T„”G~éöVýÑ1å˜q2’”cB2)³J*•ËUN÷Õ¢·UÀu••áºõM[ÔUCû(µf)—q_Ófm¾Î«öx¦x2×U›pÎÏþù¼ÍÃJ™m›¼h'bÁjÆ5÷"_fÛ²5ùæ6ߌ°â,j(²BˆZ8XÖeYïòÍ®îèۮ¶*[{>&3% Óšƒh…`©¤^ -Ø'Å4[,6ÇÂMó¦!@½ ôñxüSÏn¢§h~RÁe‹plU7-vEYÒè*œÞam•W/ «ï“ðøý8"¾.nã™,€²8÷œ_oƒ’ÒÖA–}ÙóáÍ7Õb>"qÉ™NT8^O›t)æéTù9¿ÁjSÆ¥±‡z”.Ü/íë ^%= -' Šq¤7Ez¾[óÕg±‰h£‡x³±û¤‚‰ÄF&Ç/"“\§}ߘ‘}i îed¥Lá -uR´ÖNÏq W©GˆË N¨=íb1B]AÜ0iôM›No¼þëÛliáo -Àº¢/IÈz}{м^¯³jAನòç0LA¢U8;Ê¡ K¸IžåZêp³ô¼dŠŠ@M×Y;_a‚Ž˜³Â M¶¨®Çb -dÙiä¡H¢ <'ƒ\] Ròü9í˜&d\ŽGgvÁ™]çÌ°ÖÖɶ k°·9 &ɶD‡†ˆñ] ”f$zØIA(HÁ$̺ä b57µ)Ì&É®iæ}àš7õ¦‘L¢Y’Ü÷MnCŒ5ƒkCŒ51ÆÚ©ÇëGmˆf0„ê6P?rH'q¹G>æ…ÐAg'{¥¦L¢˜d¬ëd¿‚w!{×[¬¸¥UãhHÚµ:hAX7â7£Çƒ¾-ÁŒ›= Ê·8eì)CqÈC)žá¨Ú®¯¼]".pª7›,qpi€t Òï«HhÑÙzn b¤îQŒ[ž~¤-è$=ÌðRRU†ßf{sS>êPÕ7 #‡QÇÑUØââ«š6ÏÂÄK<ñžJta£bðÎ\MO3¯¶!5R9ô Bóg£x)A”ÙçœF1˜¿!k@ -ÏJ Ü=ák…°wL˜Š«Û'S´Ý©èDZoÆPb-ÜÙ÷Wå ®˜3]P†ûÊñ êF¤&C:!'Q ¤gyP9{M™˜jqä;Þd—w¸ -ûBveÙp¤Ÿ]pËþ yäÌΡ—Òòñ^C2ÎSwÿ™Bs4ÍkÿHã]Ñ®°ÌçÞLBáòÎ'P²À&¦„RðÀªtKÈÝi–8Gq ØðÑí®Žm"K¬>0èørr_Xl9Í2+¯ë Üf=æ䜅Š¶Ók}1¿¨Š”’Ó¼šoîb {¤~ºŒÆŠµD»Y7¢Ä‚#2Q\MçÛ6>;;ÆS)^²‚Ûf·YQfÆ0°Îª‘›;(¨ÖMˆóü QŸ~:yñóiØŒé6âðæ¡Ùú&èž'p‚ÏÍÁæj±½ø:–ýë1”H©£?"Ù‘„„Åöê2Æ࿆™å|ú—LD=Þ\‡BQHØ_Öó¬Ä.íÅXí¿;Cpàñ¾0:Ý!%²È¿;d5¾öºTÏfGö®EWž@ð4i9JÚÝ# qºíÏ‘µ1:ê(iß|c7¤GFõ‚†»=K¶/'oÑ+A4ª|µÎæ³õ¼k†0QäÄ)Ÿ>³oÞ/ÿ«Õ‡æ‹.ﮤþp–Ëâíé—´\Š²|÷áå—gß®Žé Õo¹}ørp¯¶g¿ªÏÜ…}ùÓ.ým÷iw®þýÛOÛ_~ø¸û\ ÿ<ù×wÌýßÿQîÿ¤Õ SÎÉñ¿!0¥R™Âû ™²Þý›yŸ÷ÿf¹Öendstream -endobj -2113 0 obj << -/Type /Page -/Contents 2114 0 R -/Resources 2112 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 2100 0 R +2676 0 obj << +/D [2666 0 R /XYZ 85.0394 268.1239 null] >> endobj -2115 0 obj << -/D [2113 0 R /XYZ 85.0394 794.5015 null] +2677 0 obj << +/D [2666 0 R /XYZ 85.0394 234.3569 null] >> endobj -2116 0 obj << -/D [2113 0 R /XYZ 85.0394 420.6717 null] +2678 0 obj << +/D [2666 0 R /XYZ 85.0394 162.6401 null] >> endobj -2112 0 obj << -/Font << /F37 802 0 R /F53 1029 0 R /F22 737 0 R /F41 939 0 R /F21 714 0 R >> +2679 0 obj << +/D [2666 0 R /XYZ 85.0394 96.81 null] +>> endobj +2665 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R /F53 1303 0 R /F39 1151 0 R >> /ProcSet [ /PDF /Text ] >> endobj -2119 0 obj << -/Length 2226 +2682 0 obj << +/Length 2018 /Filter /FlateDecode >> stream -xÚ¥Y_sÛ6÷§Ðô¥ôL„ÿàú¤ÚNêNí¤¶rÓ™$´[œP¤*Rvss÷Ýo)R¢-g:z ¸\,‹ÝßîBtÃNdBÃÌDAdLåd±:‰'ðíÝ <Ó–iÚçúe~òÓ[®&†˜„%“ù}O–&±Öt2Ï>E¿ÊÉ)ˆˆ£›ëó³éÙûë·ï.®O§Ô%¢Ù‡×ç—žN™Œ8ã8ºš]œýŽ´§†E³w·§_æ¿\Ì;µúªÓ˜;þ:ùô%žd°ƒßNb–“'x‰ 5†MV'Br"ç-¥8¹=ù£Øû꧎š‚Æ„ñ„ØBО- #Rj1QÒ„3îmñ¿ŸÝ~zËXsÊ%щ”0ˆ‰H˜ô¬—%ì^ÄQ³´0à&JïªG‹4ûwºZöM6XVE©]M™-FVdŒhid`zÊ‹åÞ}Ã¥2{Ÿn‹‰Û:(€š¥¶›G» Z®¢Z¤Å²ª$ŽÁ2L‘~^(r¥e¶'ë« kÂôÂfat5ujO¦”Q"U žG)1R2¯1ìÝÍ£”Fà/üå¬Z­@x ó‹š*<ý*Œ´z·øvTÜhZíÍŒ*½]ó{UÑÓ2_,ñËj‹¢i”uXü.Éìç8f¥ßór·ˆÛbÜn £¥U "ãG·¥¢EU: ÛMÚä•›®tä(…E†§¼Yâ5‡Ï yøXv#4¾ûh›Sª#Û8ëApÍ—·êXš´±+[6HÏË,_¥n—ñÇŽë ö‚Çu„n[G¿^ÍΦWçßÒâ”FÕô_Š×y¦î”Å÷E‘âA¹qU6i^zNµ[ä.­í4øbËE•åå¾U÷Ï)4¢ÿ`i"UTµ?Hxó ϬÚÞù“€ñ_Û -ŒD:aB¡°Ëû‘hÕÄŠôƒbFS·#>bë&8Äa+M´àan^ãÌ-ªÇ½•#+JA”àÇñA)µ‡ ì]ÚE¨¸CyïäÃxÖuµiðƒä’·šâ¡ð6Þ€À€úï"‘ ‘„;lVE@»ÜP¡ñli!DÂQ¤øØ€GU+›CQ–MbÖ³Ñv~ÿдo«rl"0ÿ 9„îã;‹ ¡Œ>PýˆÜxÈ=ƒHU€’•‹·Æ†e'+I"ÈOœôÑR¦J8IÓ;ßb¸¸åüÉpÌÁº*¾!¡5v†Œ=htbÐe܇‚îùAÞÀFQlÕ€›2Kýádḡh`pæCt¬¶ÍzëQ‹"æBÙl -äƒPÈÔÊ´0jßÓ!ã².úŒÈ1„KÕò8ÌÙTE=fWpÐ;0vZ£·ÝW›በPi´¡æÀ:{îØFX’´¬h­ÖÙ1ëÀh½ÉIBÐp¦¡úRô;ƒf ß5 ‘Z« ž;^;²aˆ¦L¿1Ô$D¸Òj ·],AëÒý_Ëê©ÄñºHÝ–ÿnðÕ™ÙR|8õmó¾ü{ÊÑI‡ú>î8Ô-œ ¿æõìê÷}{qs -Yùßððﮎ½|÷ñfæ¬9¿|=ÄL¥e0¼÷wš„¤Ì©ìÐÓQ±Šp£»ðu—úý døÕ‡<ÓÅ®äÄäᨤ¡R¨[™!O;…-ª‡2ÿOP#x<;J½¶‹Ü-Þ®š—c92”1û!“Ãó,Nª°ˆ3ÓfNy«Çèsê»ô”^¥â^órTˆL©_dP­Cæk5¤ÆD·ÖîéQ÷,Ì}Úk?á%Š u@¦"oað2¬CzÅX¯ðÀ´éš¦Ëës|̲U^æuí¢Á‘nì½Ås/aÚUZnÓbNXÍX¨¨ -,aŽ„ÆíEˆŒÙï·ï;¿ó×h×¼ Ù¹—÷¿µAê[ ¤û5¸éÛV¹\ÆZPüg–8ÜM´Ãܤs‡«L¹€þ Êè¡uf翾¿yÉ,"ôyÝ”-¸Þ~«á¨CÆ8ƒÊ)ß®vë -(‚’ö4ƒºBʮ͆ž:ŽãƒÊÂœ…>ÊcšCŸqÅ ‘ŒÔ'^ŸÏÐõìÎ GX²í 6(Î;«ªx}+«u×û½=‡˜Ñ ‡–0jä‘^³aÒåÛñFÝuÂ.”z"ûôö¡ã:Ü»KŸ¦é—vt‡û‚•{ž -˸ƒ<0KíÀõ ue{ xÌňÌö^ yŸß!rÙ¾Ž‡rZÉ®òáe篾>ª¯/úå1€ó}y›yЛrðGÁ†pˆ%ý3¶@üÖûâë£ê¦Y¶±uýz 4GE.–›ªj²|¬îƒ>ŒÊÎ]:¡Û£B¡Ã“ÇÕNÜ(NQF$ÔYƒø;¿¸=»¹üЫ_èËþR+%{ÌZ—j+KfÚŒÜbhò}àè -佺’v¤c…:^ñ^Öf*ºlÂÊiXÍßÈhÓ6É0JÃÒi§ã£-sÌ´Ž\8l}ÃLßójìf `"áZì¥lìmMòLIÀ!ü=ãkê#%ºb¹»õ1¡¬cF†:À¸Êoƒ‰­^W¥oâFÌ –bÒ˜ãÅ7D$]eÖµFl¯5Ò”²[,à«Ð±®È$ãõZg4{eS¤X'þ¤.AÝÐ —2Ø»AœíN¶Ø]ê ÐÇ_3‰à4B¢Óasª£m … 7 vÇ;4‹„¶Kwß43 4§\¶ŠWëËt'»Æ+/m×HHGL¥411¥}O?éÎ]±}GñáÎ ä?VytX†m—Ö–ˆÏ¨A&¤R=‚ýð½Ä°‘æ4™oûöu”íűïPÍ ƒ¹_åÒ1íîjöÊjöêÁÂÆ7®Í#ÏýÙhì"w¤âˆ;´ýÇDìþp]4ëj—¡¹\Íb`”r»¢<>P½ýËâP÷ÿº÷” endstream -endobj -2118 0 obj << +xÚ¥XÝ—·ç¯à­pOpý1Ÿd—$´Íf»°÷ôž4³ƒ9e†ú×W²ìa`g7͹‡‡‘eÙ’eé'Ñçðý0bQ*Ó~œ,ä"ìçÛï¯`î}O8™‘µ¥ÞÎ{?¾Sq?ei$£þ|ÙÚ+a[@%ˆôG‰ ÁÝ>Îpv­)QL¶Õì¥ÀŠâ”ñv5°ÚR/V#…ê«âo}­4 ¢àu¥^¨CiÛ0©â8¾T:÷g¶Ú-e¾;΃ÂÐ÷bS>jº,”.éëèeÿ ‚8ü†ÿZR¯øÏKáQå6+̵ÚT°0éëj½P‡Ú¶ÓQM^ª_ºéAÞ_Þ3Çu‘¯‰Ügfa³èEVgî +Öåa³ úÉ-?ֆ¹Ð¾Æ‘JY^TÌÂ"í™M&´tüËìSGFðþHFŒË€€MÁU˜…î.3›®y@f6³]6ðKåãÇù‡OßÖ:5µÞ]“¾Ù©ªõ¶¢ÁMiªr_‡íYxy}„”N£¦*BäPéŠ*­·Y>Â{øzØÙLGóBC²âwx-ÝÆ¥,Ž$áÀ³èz¥ŒÏýU;s±»ŒÐ§ê2ü]ž\bm€Q–üKï«z™qo§w·ÿÂɳ“)wUQ]‡º‚äI"ÕW”¡Ò®PGà“¶P½š~í-l]é×H]xmY8ïCT­U ”ïHy(Î6«b{ Y‰pPé|áÐå~óeÝídvó0½ŸO?ݽmt¡ÿ +!Ë•"—+™’Ë-'¥^7N`ÖâR€ˆÂ䛃­F× YDÄ:s¢‰<V4γCE ÌhöaüšÏ¦ïi‚â)B +¿í +uÔ63¢t°)ÍÊÐõ:3žrÓ‹b¥«Ú‰j³ª×DÛhk ®³ÊM¹KŠÞ r0ù ¦"C ÀnA.Ú_4CDœˆ§¢®Î«euÌíçÝ‚Ðï\\fY~7 u»ÎEK´¸ ßCe³fàÞÊ=¹-¯7' +n‡‹–Æ­ÝêªÊVn£ì~2u‘ƒ\iH./n,¬‰w̪˃QÛŽÚ·;XûäKñ¨](ag‡·w3W.¶»Þ‚B«®bÍž $AšºŠS` ÈÈEp…Ž£µ! +Q +.ò+úÇ…ã»À + _ *|( iw®QÖõ…B;’ßf'"0žµßÕŸ¯ØõÉQ;ê!‰¹ÔqùFéÆã6.®u.šü†ÈãZšt)…LŒ¢0ŽÎµò RH(•±Ãž®Rq… QÂ’ ‘nÁ¶\(kAÔÔë²Òd†ÜØ…`< X«ê²ÉUs^Qÿ)ZÇ¿ðƒs!h÷½ãûÍ*áÖ¢å‰h¶-9·3’ÁÁtø"….>áwù"NTäÛ,HmµÓyc YñCåì:C¼6 ë­kjSZµögméMa ™)¦KrŸˆS˜aí{rµ‚~„ äƒC:tIøye™@7™¸K5ÑíÓ%Üemûb"—垇œV/½†°ÙjM6›TÑ_ë½{d6°†|~o69S+ãÚ`»ä±.زJ_m½<˜ÜuF¸º&9ÔÁðä/ýÕ¯2ü°ã›´ù¿ÿ†<ÿáÄL%‰ì~ÖË8d°8òF¡·E,Ÿÿáþ°|nû?Ï|÷endstream +endobj +2681 0 obj << /Type /Page -/Contents 2119 0 R -/Resources 2117 0 R +/Contents 2682 0 R +/Resources 2680 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 2100 0 R +/Parent 2647 0 R >> endobj -2120 0 obj << -/D [2118 0 R /XYZ 56.6929 794.5015 null] +2683 0 obj << +/D [2681 0 R /XYZ 56.6929 794.5015 null] >> endobj -2121 0 obj << -/D [2118 0 R /XYZ 56.6929 513.8248 null] +2684 0 obj << +/D [2681 0 R /XYZ 56.6929 752.0628 null] >> endobj -2122 0 obj << -/D [2118 0 R /XYZ 56.6929 427.0967 null] +2685 0 obj << +/D [2681 0 R /XYZ 56.6929 603.3016 null] >> endobj -2123 0 obj << -/D [2118 0 R /XYZ 56.6929 364.279 null] +2686 0 obj << +/D [2681 0 R /XYZ 56.6929 539.7009 null] >> endobj -702 0 obj << -/D [2118 0 R /XYZ 56.6929 325.4767 null] +914 0 obj << +/D [2681 0 R /XYZ 56.6929 500.3546 null] >> endobj -2124 0 obj << -/D [2118 0 R /XYZ 56.6929 288.9693 null] +2687 0 obj << +/D [2681 0 R /XYZ 56.6929 463.723 null] >> endobj -2125 0 obj << -/D [2118 0 R /XYZ 56.6929 257.0263 null] +2688 0 obj << +/D [2681 0 R /XYZ 56.6929 431.4263 null] >> endobj -2126 0 obj << -/D [2118 0 R /XYZ 56.6929 191.2867 null] +2689 0 obj << +/D [2681 0 R /XYZ 56.6929 364.9038 null] >> endobj -2127 0 obj << -/D [2118 0 R /XYZ 56.6929 119.4786 null] +2690 0 obj << +/D [2681 0 R /XYZ 56.6929 304.268 null] >> endobj -2117 0 obj << -/Font << /F37 802 0 R /F41 939 0 R /F22 737 0 R /F21 714 0 R /F48 953 0 R /F39 899 0 R /F53 1029 0 R >> +2691 0 obj << +/D [2681 0 R /XYZ 56.6929 107.6861 null] +>> endobj +2680 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F55 1311 0 R /F22 953 0 R /F41 1208 0 R /F53 1303 0 R >> /ProcSet [ /PDF /Text ] >> endobj -2130 0 obj << -/Length 3036 +2694 0 obj << +/Length 1217 /Filter /FlateDecode >> stream -xÚ¥Z[Û¶~ß_áG/pÌð.ç)iÒ E»ÙÓlm´– ±%×’³ÝþúÎð"KZÊNqàQÒˆÎ|s¥Ù‚Â-Œ"TX¹È¬$Š2µXïoèâ3¼{ÃÍ*­†Ton^}/²…%Vs½xØ æ2„ÃÅoË×÷÷ïîÞ~øõvÅ]¾!·+Eéò§×w¿¼þÑ?»¿µ|ùúý»O·+fe&ˆ ¤ÓtùóÝÛïVß}¼ûþý»»Û?~¸y÷г5dQ<ýyóÛtQÀ~¸¡DX£OpC ³–/ö7R ¢¤ñÉîæÓÍÿú oݧ)Q(aˆ2½Ø %T¼2Îà#˜<©„@´RÅ…JˆT¸î*Ÿ.iÂðËKF¢Ä’|°$¨[0«ÆK¾m@»F/óS×ìó®Z#^5'&“Ã/Žu‰†³s`‚sˆÖMý;¥üóés65ÀD2³|ØV­_n}¼…û2ïÊð ÷ühWúéå&‘™æ&È—ò9Áˆ¢DgTªNMÆ@ $¯Ê.¹!M2M#ÑïTÑæè™|Úß_Ëcbf@‘*J¡}nA›¢:&æ_ mˆÑÔ,V=ᛧ¼ESËöP®+”GYøñÅÓ¶¬ýè͇»·áY|ùxªv0Ëüm¬:{]V >Ìùø®M·Mhž+BàìŠê9‘L‰@”×Eb&{¥& -¦Î÷e‘˜IpbÏâkÂ6Û.?v§€ˆƒ zئð²äzˆQ‚T e€}&ÍDÊiè0öL,®8•Ë¢Ä»Ú¡•*‡V÷t“Ÿv¿Y7û=îݬ·y]—;ÿ¦ -FvË– >°3gþ12ã w»æ©ª?'ä'˜"FZuUŠÚ¨®®9svªqÉ2ÈD+à™Š2ñ!à©Jc€ƒü¤¼¦9A¤‘b 9Œݶôƒ]³Îw~¸mÚÎÜ‚nT7þº9á“£¿yáCïJÎ 8vPµÜ³þó©®Ór“àëTï–Pl+4ÉÏ¥ã0 .w²™LLdLN+­'÷Ç•^Zÿ vLj¥®zL*ÀüÊ‚ K?ÿ©E»wK„µ gºÍaUÞ½)vùºÜ¦Zÿáƹ©¯ÙÒxÑq.!àë‰)ÌØ«%BeQŸé 0M”Ͳ@óŸ9¥¢-|v–ƒˆh&È(ÿªÚuçÀ3õlp]ëL2š}ã¥ë–»ü±9¢ý¸Û 2ýCpµçQçg˜•øYá_<>§ìKZ’Y!f jç!j²VÔóüç©òƒu¢y„ìã¯|ØE/„L…½@rÜxкNŽWT^¡x„‚7+¹[pßtåîù–1†pÒ,Ÿ›“'h·Íi×Ã×uJŒ~%#Y$T üÛ>B#ðp°ž×$FÓC4‹S'…ŠyVÐÍÁ+çs.Üm£ +œáM§°sLB΢åç¨4Wtk¦=½MÊ—6)ÿ=úó`|EÀÅIæ²[…ƒÌ'êóÙíj>»í©œÈ=£`¿#‘Û+"a[ý]NYcÍg ý"o=U‚¹‘–%ØŽ²lÌݧ>ÝB¸Kî=GnÔl&¯  ¢9>sÑUxðXu-ÖI9þtÂØç–ñÚ=•e daV6(Æq Üÿ…¡é‘ Ä01Ø9#uWA팛ym‹ŒP B»¬íÕmG*§íuJÛ`ÞÉœµ½©v mg„1y™µH”`m¬k.ð5âí—[‡Ñ*í1´„€Ó»Ù´Ó à‰ûÄ,:a¬s™üæÙßäáe¾ëÊcBŠOÎ_¢ÃNØ¿ÁBïz$3È…itc󪧚PNõÕ¨.¨>R91m_”±’@ -yeÉH”XrTÆZ"¹š,y¬BD]G©o›c0„ö©ù1( ÙL2¯²øq‘;WùùÔgVNŸéðÍ9Ͼ1dQH¼¿¦™Ib3qÅ©æUÓS9Õ|ùŒ¡eÖ_äíìƒ_2—ôÁ#îF>sÙ #J$8ÖÜÈëq@ã3MÝrœóâÃvhEÀ‹ýÉ×#ºO½sùšïªÂ‹fŸWõ™rÁ?D\M}q¢h…rÍÈa™°ºdÑú*lð‘Q{6ª °‰T6‡«°9 µM1Ã)Áý]ä+%ø!†+¬ð'Œ£¶ hÀA_Ž ;(ÇñãÔž°ÖtY~®)¤p\‹ku/ÀWôuÒj™²¬¸¬Û³‹¯ƒ“Av6¾’Û§ê.A £}¹=W:R"ûEÑ™4±/r¤ó8ÆÆ«™¨oLl`7D]ÓjL=•Ó1&K´½%€âš}27P$¬1—¹ë©ì0¥ –ÊÆü1¥$ú¡Ô²mNNoëÒ?vÙ \=·ž¦È»Ü?õÚ‡A¨]‰‹$¡8-x©æXý;¤š W…â»@¤ 8Žn-QBN‰ÏQ¢å<ìγkv7]Ü¿/¿ŒfËƧ¶ß3íÐÑ·ïØ Áý/#Œ˜’Âù¥¨“Ž¸`HpÆê‘Ýh1ú£QØš­–á ˜DBRJB‚v +yŒ² +‰Ålfž~]<êx>Õ‚;Ê‘â„WâW÷ó#¯ì²0M²¤(A™ÌÐs´‰c"Ý([Gfè!ÈŽÁΨ§´¥žxQÏóÀŽVÿaÀ°. ³ÏŸ¯FJ0ÐÇ ¢\+¬DØOŽ¸b΄ Dö #^–wÏ{ÜgetÈ¢Òx±x-Ê(-ÌÇužù¡LŽéÉ,GŒ{ÔêábeÒ tOÚeE´fqPÄz™–cyÂS•Ü> endobj -2131 0 obj << -/D [2129 0 R /XYZ 85.0394 794.5015 null] +2695 0 obj << +/D [2693 0 R /XYZ 85.0394 794.5015 null] >> endobj -2132 0 obj << -/D [2129 0 R /XYZ 85.0394 751.8648 null] +2696 0 obj << +/D [2693 0 R /XYZ 85.0394 752.4085 null] >> endobj -2133 0 obj << -/D [2129 0 R /XYZ 85.0394 153.4294 null] +2697 0 obj << +/D [2693 0 R /XYZ 85.0394 692.3565 null] >> endobj -2128 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R /F55 1037 0 R /F48 953 0 R >> -/ProcSet [ /PDF /Text ] +918 0 obj << +/D [2693 0 R /XYZ 85.0394 655.476 null] >> endobj -2136 0 obj << -/Length 438 -/Filter /FlateDecode ->> -stream -xÚ¥SMo›@½ó+öR™îì»GbÇQ‚]C¤Ji–Á‘¥°V1QÕßlg£8Ê¡BBìÌ›·oÞ H¨{HÊ0C#@R”dÓ”<»Ü,À#&>buU߯yB Å)·—ª5’²z ¯9DŽ‚†«|:‰'‹üz–åQŒF$"L—Ë,ŸÎF1“Ô’Òð>ÍÒ»1¶Œ ÓYVDOåm•gY¾t¤¼×ô;x|¢¤rܸђüq -h #M $)8?E^‚"øq&ô²CéE+ãŠ]ð‚!A#%{g†4 8ãƒE–M¥wÅ¢ïÇU1ÏAJb&À¼µÕæ•T»~+ûlövÛ'¤—°ë¦®<ôÀÎÇŽ‚j©Ý5Ãdæùt,5GQU³³»C×®»};†Võ¶n#Ôam7õº_Û×õËñ¨40¥Ô‘Žw®ÄÜù'$îK"U6}(o«¯ ™Û®nmÝJŠ¿‡®nãa²·‡}Ûí^›ÏöÄ]Ø÷ÂTéYâïÐÛ¿"àZ³·õðûb‰W¬N¢úæ³ÒOÛöQû?prÕ¿endstream -endobj -2135 0 obj << -/Type /Page -/Contents 2136 0 R -/Resources 2134 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 2100 0 R +2698 0 obj << +/D [2693 0 R /XYZ 85.0394 623.3704 null] >> endobj -2137 0 obj << -/D [2135 0 R /XYZ 56.6929 794.5015 null] +2699 0 obj << +/D [2693 0 R /XYZ 85.0394 588.7135 null] >> endobj -2138 0 obj << -/D [2135 0 R /XYZ 56.6929 752.4085 null] +2700 0 obj << +/D [2693 0 R /XYZ 85.0394 525.7396 null] >> endobj -2139 0 obj << -/D [2135 0 R /XYZ 56.6929 692.3565 null] +2701 0 obj << +/D [2693 0 R /XYZ 85.0394 468.6524 null] >> endobj -2134 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F39 899 0 R >> +2702 0 obj << +/D [2693 0 R /XYZ 85.0394 396.6452 null] +>> endobj +2703 0 obj << +/D [2693 0 R /XYZ 85.0394 211.0639 null] +>> endobj +2704 0 obj << +/D [2693 0 R /XYZ 85.0394 151.0119 null] +>> endobj +2692 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F39 1151 0 R /F22 953 0 R /F41 1208 0 R /F53 1303 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1604 0 obj -[706 0 R /Fit] +2034 0 obj +[922 0 R /Fit] endobj -1472 0 obj -[706 0 R /Fit] +1880 0 obj +[922 0 R /Fit] endobj -1212 0 obj -[706 0 R /Fit] +1579 0 obj +[922 0 R /Fit] endobj -2140 0 obj << +2705 0 obj << /Type /Encoding /Differences [ 0 /.notdef 1/dotaccent/fi/fl/fraction/hungarumlaut/Lslash/lslash/ogonek/ring 10/.notdef 11/breve/minus 13/.notdef 14/Zcaron/zcaron/caron/dotlessi/dotlessj/ff/ffi/ffl/notequal/infinity/lessequal/greaterequal/partialdiff/summation/product/pi/grave/quotesingle/space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde 127/.notdef 128/Euro/integral/quotesinglbase/florin/quotedblbase/ellipsis/dagger/daggerdbl/circumflex/perthousand/Scaron/guilsinglleft/OE/Omega/radical/approxequal 144/.notdef 147/quotedblleft/quotedblright/bullet/endash/emdash/tilde/trademark/scaron/guilsinglright/oe/Delta/lozenge/Ydieresis 160/.notdef 161/exclamdown/cent/sterling/currency/yen/brokenbar/section/dieresis/copyright/ordfeminine/guillemotleft/logicalnot/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guillemotright/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis] >> endobj -1641 0 obj << +2065 0 obj << /Length1 1628 /Length2 8040 /Length3 532 @@ -10479,7 +13098,7 @@ endobj stream xÚíte\Ôí¶6Ò ˆtÃÐÝÝÝÝ¡Ä0 00Ì ÝÝÝÝ’‚R"‚´t ÒÈ‹>ïÞûüž³?³?½¿w¾Ìÿ^×Z׺î7¶‡Œ5Ü ¬‡¹rðpr‹ t´P(ÐWç…C­fL9g0ЇÉ]Á¢#°5@ ðòxDDD0rp'/gˆ­+€ù‘ƒ…ý_–ß.+¯ ‘.[€ññà …;9‚a®ÿã@=0àjØ@ `€œ–¶‰Š¦€YIÓ †P€¶›¨C@`˜ ˜`w@ÿ:@p˜5ä÷Õ\8¹d\@€‹y {‚ÀN¿!v€ØÙââòø €¸l0×ǸÂêfý[À£ÝþG“3üÑÃñ{$Ó†»¸º€œ!N®€Ç¬ÚòŠétµºþÎíy„p›GOk8Èí÷•þ`4¨+s¸‚=]粬!.NP ×cîG2'gÈn.˜í¿°œÁ¶@gk(ØÅå‘æ‘ûwuþuOÀ¹=ÐÉ êõ'þÇëŸ ®.`¨ '&ïcNëcn[ “ë÷¨¨Àlàî¿ìÖnNÿÀÜÁÎ -Äü{fXE­á0¨ÀlƒÉ¥ w}L `þŸu™ó?×äÿ@‹ÿ# þ´÷×Ü¿÷è¿,ñÿvŸÿN­è…jÁ‚ÿxcê€ßÌs:B ^ÿÎýïžFà¿4þ;Wàc!d`¶Íàáäæù €¸(B<ÁÖÚWÀ}¬Ô»Ìì …ÀÀýSL7÷ß0};Èö»ôA`˜õßå?6éx.U%Sc¶ÿöªrèA§Ë‚GPè¯íÇ9pÕ÷rþo:# ¸õ?¿ùdeáž^7Ïãú=*áðû7¹ÿñüë¬tu†x^psr?Fr~ÿsÿÎýOÀìo4 +Äü{fXE­á0¨ÀlƒÉ¥ w}L `þŸu™ó?×äÿ@‹ÿ# þ´÷×Ü¿÷è¿,ñÿvŸÿN­è…jÁ‚ÿxcê€ßÌs:B ^ÿÎýïžFà¿4þ;Wàc!d`¶Íàáäæù €¸(B<ÁÖÚWÀ}¬Ô»Ìì …ÀÀýSL7÷ß0};Èö»ôA`˜õßå?6éx.uY]¶ÿöªrèA§Ë‚GPè¯íÇ9pÕ÷rþo:# ¸õ?¿ùdeáž^7Ïãú=*áðû7¹ÿñüë¬tu†x^psr?Fr~ÿsÿÎýOÀìo4 0Üú÷äè¹aÖÃöOÃoäæìüØã?ûÿxýœÿŒ=ì a.ÌÁAb¡ö™9Y® Ä£ò/z{xÂœ*Þè—ÖÁ»2#×Dj,ïêÃ8›ÇEµyÍî;Ýoª²n öA™ºÓÁß‹(üèX>ã.3v±ms™W`gÅúϨ¯"› rn­êèš—ß¡RŽwð9£_²Ò¹Ð_8=óe4%v>oFÀk(Ù?`LÙ½¼`êú4ð±ûåÃ&9[~ƒ˜;26cLà«|r)Sƒj…×Íl(ßÛ b¬Å7ÎßÊçÏVð™h9Žù,¢I‚°RÊ• e®äß·RÆ%=²ìÙ êt›œ(†Ì%³LÇî)®Ž>1Ù¥‘„µ…^Ñ2¼éˆO£Ý %õ‰>•pjÕr{2–ÂwÍ<–g¬™-j—!3cäáakIè,AŒ$ÁLˆÇÆ‹J¯³nöùU»Ïm›Þ‰D3 @@ -10502,35 +13121,35 @@ $O t‡Í=žÝbóÆÃwî6ß"£“˵?”JËOP2RÐ oQo+†â1)©w†¦ÜèådîI½ÈZ¿VÍ­(e÷åû È"QÔüFØs(úF$'‘qL ®/¶!õÔ ¤HvkÖ‰Œh¼È‰¬ê؉á¶o?Ùa:Šÿ±qêcŒ° gã!_QÇ~ÏWê¡1üaœ¯UÝGmã§Yñmn%ìRãr9÷¬ß0qˆ5†/‚E…(êÚ“†,W‚˜$Ù½ï¶åçLxËÎÔ|ú奕£w†Z|ÂV€ãž÷,éOd ÞyŠGÝ ŽÎ¨Ý3lÍ4©¿Î\×T2Zª½Ag—.7Ù#ÏPæï™v¼eŦQLÞ»±Oþ¼Ô\’ ¬ÿĵJÅñ¾(š3Ç].Å*,MÎ>ÛBx(ÃSÃó|D³uû‚Þ¡ï†{:Ò‘Á¨2G9¡Cê{É•<|?ÒK áéá@F)Ø,êw÷ó?È ¸¢Ëa„Çh%Ù±o^Œñ{‹6™Ý @¥-«ä%Å~jÉwXjz1îi´·î¬%uÕ3^¿±g¸`d+ÎK[ŽDe—„]âò†YèÖýÇ?Ï>£³HjË,èkѸÍhÔ8Š” ™v_Å [ªJÖ®²9m=·âú?\‹k>¼à¬‡¤*³Ñ³ž,Y ê<‹ý¹uÓ Z/ZV$S·é#ƒmNOš¨5M@¿§rãÝ0Hõ7¬&7[àçŽAØñêOõƧÈêÚ5±pE6~d»Ž^.x¨T1¬µ¤$£Í7¿ÿ4òÆêüj§‹G1¬èípoóÌ3³QýÐZ:œNÍÆéç,0½‹Š‡Zg‹ðâ£à)‹Q©¯³‹X""œÛÆ0ÏÁ¾äBvFA‚)Y9(ÎYÖý…ì¬S…|¸Ôü¾“qbæÇN.LÔX§…_ï‚¿œ%%½¥åŒìé|°D>W²7}C–Í#—ZR¸­$º`bÛGο…a¿9gÝS%\”Á/œîñhC|?s§ Ø…šg¯ÎÙÈ)ª¬m}ÐvÖËk†Ÿ.bÉ&O üõí+uqfº`Îa‡„°£â,I§ã¯½/‘˜÷ÇÝ›Á¤'P6ߢH‚Ú?÷›½šÙ¹˜Žà9¦ŠmHr7:pMRYŸ#£ 'æW¥¿ðKCß|-¡mWÝ躖nᲶË0–«ÞÐ3äÛÙ=j’¸Ë-,n–³e±€¢üb½iÙ;‘˜Hâ°l<)žL.ßÐYÖÿ°Ú·)wL=(‚Œ£± L|)=å'ÀÆ-Å@²öò¾µ<ÃNrä³6îµEôʃ3±d¶kÓ»¬ÿ‹%ôµøü·(kD~ô(¬_yñ‡Í; ¯åä²fùOî{&*‰äyÒ¯9ÛB±T¨d>è.òY[a-³ZyÏ•px9ÝØÜ>穾„»*|,4°ç Žð=Ï añŽ©{ZwLVqžCÅo, H;ç_7Gg[åGx d½DŽ…*~ÂJSÛ/ *ûÎÔF‹µëújQ‹jw Ý]_-Òq;Œ,1t³õ2ߥÆíËòê{:Ö§Ùo$<×ð¬žôôJ©Àëóüλì„b›F=ÍçåcT”u;ÐuË›÷#³»Z1q“ÒYÖgHŠ^fiyv|‰¢,PkŠA±¢FH£s^…EËRôƇnQWEÛt%Ú·y3™{æÈŒõFbKã<%Æ)â"-L+{墒zS'“#é²ÊòZÃ+•÷U­Á׎#Ç©ÃCcæHŸ,êä;÷=íÏô .óYäg:¯jÔn¹¶Æô×êS:c¤¬UºW¹Þ/Ëf¹ŠšcO¥ÛøŒM¯lD‰Á¦9²ú:­ÈùÈßÛ˜ìÑËr6½õx§ç±2ú]úS¹‘ p7O¼,j1îöÐËÚ{ž$ªS7O–xYŽróæs÷â»ì(è˜Ýš‹ÏD‚@§­Y#žC²L%¯íáž›1A•Ã¸©3¾~M+ÖAîDí>¤¶¯cãµã-Nˆ¥”ûÚÔß ÄÖtzâ"¹tãØ'>(˜“”hSðÕœM]ˆÎÛ…0ìŽ ñâSPÓKD³—dOj nÌó®|KHtÞ‘Ñ+㢟S'÷@6„iõ“¨C,÷ág3B½žpÖáΡÄêφÖÑn‰Ü;ɦc“ _7T,Q1çTiHøBÕWL8­¡¾  ,œ²£.±ß u2†)¶=–Oš ¹ÿêÚ´­Ùê², Aq¨¿râ^T!1í¢ëç2)áN\§‹¬‚)æÄËR…Ëbž÷ž6Cb5ü´çêÞ›Ô;ð¶¹mH“üÅL¸^Ȭü¤Ý¸Ê {>«m@Ë›ðzéN‹›´×»ÔÌÃBÿ]¬—š@)õp[jÊâá…6붡²BSHQøר.öØ«N÷Ž`ðG¿§zŽ^n)?ìû±«892ÉÿxÈÌÄ÷Ù%¼­Ø3ÕÎZJðô]\ÿ^¸Äé„SXA㣅¸r}[(â0Ò@¥elöÉmi¶ö­EWÕ9úQѲ´ˆC¶Û¯µAñ=°g>MF{Q’= †*Ëk¨+™×Øõµk¤i@ïħÕW:x<›ó"Í}<=<²šC½Q¤4Æð÷i©UµSöA-ÒiMÛk×qnñÔÆèO“¦R<)D¾€÷/ÇT#î¡ÍM© Æ$ÖžåÔ3³Ð¿Á¢\ç{Uª÷Þ<UW=ˆ$®&<ƒªZ€0óØÒgÒR*¹ÉÒO¦1‘'£ùŽŠj*5wË-·‰ûùT j4ÝióÍu``òh߯µ“K…ݻʔÑk‡‡A›”ôÈÔDôìtk¯ö2ÅÛö÷ú—¨§$ÌöZ¥ï@Î^ùÝêõ^E~§”Üúí¨u4߉<*ôŽ±§¸KJßùy/žn•C*}…ÃåLgI£J·8jŽ[“Þ³ ”ØT7%JÈOïä,Á!ØžÈ+ÌÁ¯f—ÉȘs‡h`Úq¢O”1£<ƒ3(©dØOfBOŸ º'"p=Q£B¿âäpJ}ÝØü™ŸZ®¤!p{òëÈa}÷qÑ¥³äƒ£DKXôžòxÇ(žÏÑã ©¨“{ÏçÉšj¿dqX·ã·ŸP¦Üv£ä£Ï€³i¬¾AÕ;³@øyŠ*œoLœOœÕøë…ú¾›ºxOÛÝËc -@YšUʳªø;žBiäMÖð.•\rž;ùU´¾Rø'î…ç)眄š˜ …@ƒi/_ A®ÉéÙêr«0áFx<×Er;¾zÇ´UÏšøSÂö²Ù„.¥mô÷Œhâæ¨É2Ø’ç/{I;õŠjÑm÷¬ -*s"}Y ;Ò‰¢ú{YÌÝÇí]p¶Òݯ€Ž¶Xo³êÙ}U¹ôZø: hÁ‚)8f÷EµÔëÛDäµsüð¢ qTMŠ:ù‘ɸX!±l®ûÔ”Ëû ΄,ñº17ýbŸgûŸ&fܽ×Y'jeAt ]ôÛïwV^þ%ÑåµÛR¼”tμ‡Ël¥¿é˜¦j¹„‚øϸ3èm>YjŸÖCƒÕ¸ÄžÄÈÊjbÆn“ªŒUý©?ô‹ïðu«ÈÃWøìý#ë,M€¾ߥJBQlŽ‰âXè-ebtxÃ]€s<—ÿ¢:XÝQ…¸w¶²-N;N¾?Vl¤‘vG‰…,Å%ë9êçöË'bìη9|1.…±!]¹¶DšÏó=RԌݬ¤Iˆg‰=Åh_ìŸ5rÿ/˜ÿŸàÿ  tv…;0ÿõ½endstream +*s"}Y ;Ò‰¢ú{YÌÝÇí]p¶Òݯ€Ž¶Xo³êÙ}U¹ôZø: hÁ‚)8f÷EµÔëÛDäµsüð¢ qTMŠ:ù‘ɸX!±l®ûÔ”Ëû ΄,ñº17ýbŸgûŸ&fܽ×Y'jeAt ]ôÛïwV^þ%ÑåµÛR¼”tμ‡Ël¥¿é˜¦j¹„‚øϸ3èm>YjŸÖCƒÕ¸ÄžÄÈÊjbÆn“ªŒUý©?ô‹ïðu«ÈÃWøìý#ë,M€¾ߥJBQlŽ‰âXè-ebtxÃ]€s<—ÿ¢:XÝQ…¸w¶²-N;N¾?Vl¤‘vG‰…,Å%ë9êçöË'bìη9|1.…±!]¹¶DšÏó=RԌݬ¤Iˆg‰=Åh_ìŸ5rÿ/˜ÿŸàÿ  tv…;0ÿ¼oõ³endstream endobj -1642 0 obj << +2066 0 obj << /Type /Font /Subtype /Type1 -/Encoding 2140 0 R +/Encoding 2705 0 R /FirstChar 67 /LastChar 85 -/Widths 2141 0 R -/BaseFont /QJGZXQ+URWPalladioL-Bold-Slant_167 -/FontDescriptor 1640 0 R +/Widths 2706 0 R +/BaseFont /LBYYIR+URWPalladioL-Bold-Slant_167 +/FontDescriptor 2064 0 R >> endobj -1640 0 obj << +2064 0 obj << /Ascent 708 /CapHeight 672 /Descent -266 -/FontName /QJGZXQ+URWPalladioL-Bold-Slant_167 +/FontName /LBYYIR+URWPalladioL-Bold-Slant_167 /ItalicAngle -9 /StemV 123 /XHeight 471 /FontBBox [-152 -301 1000 935] /Flags 4 /CharSet (/C/D/E/H/I/O/R/S/T/U) -/FontFile 1641 0 R +/FontFile 2065 0 R >> endobj -2141 0 obj +2706 0 obj [722 833 611 0 0 833 389 0 0 0 0 0 833 0 0 722 611 667 778 ] endobj -1627 0 obj << +2047 0 obj << /Length1 1630 /Length2 6133 /Length3 532 @@ -10542,7 +13161,7 @@ x Òy¦§aáèha …«pJí•Ž HÀÈ(ã ±@Bá0Y $D¤±ÉB¬@¼¼ #Hîìå µµC‚XnxXÙÙ9þ²ürYzý‰ÜD" ¶0Ó̓;Äîì!o(þ×ZiÙ@! u %5‹‚šHƒ¸Þ¡áf鵩@­ 0„dw9þqYÁaÖÐ_¥!¸n¸¤ Âb½ ƒxZAœA gˆ«¸yA [W ò¦H8 -³rt³þ%àÆnÿ-ÈÙ~ãátƒÝiÀH„•+Ô ºÉª!+ÿ‡N¤òWnôÁmn<­áVn¿JúÝÐÜ H ( BB<‘¿rYB@ÖP„³£…×Mî2gWèon(Ìö/ Wˆ­…«µ#¸¡¹áþÕ¿êýSõÎÎŽ^¿£á¿½þ¡ŠD@m¸<¼79­7¹m¡0ø׺(Álà î?ìÖnÎbî×ß bùµ3¬7",¬á0G/5ÄVƒ#oR‚XþwSæúÏ ù?0âÿÈ€ÿ#ãý÷†û÷ýÓKüï¾Ï§–wstT³p‚üýyÏ€T@¿.Я›jõ?b,œ Ž^ÿ*êïžz?¤þ"û;ö·Ìöf&œ"\"X¡y¨'ÄZŠ´²ÙX8Þtë·]f qu„ 7SýÝP'7÷ß0m;¨•ìWûþ€ 0ë¿k¿Ôoå`C9Ueiö}»þöÕ¸Ù¤¶—3ô߉ôTáÖÿ8üb’–†{‚¼9y„¸Aœ|7rx¸…ø@"|>ÿ"ëo"ž¿ÎªHW¨'Ȉ›‹››tóûç÷¯“Éßhä`Vpë_{£…´€Y߬Ú? ¿`+7W×› ÿ~ûo +³rt³þ%àÆnÿ-ÈÙ~ãátƒÝiÀH„•+Ô ºÉª!+ÿ‡N¤òWnôÁmn<­áVn¿JúÝÐÜ H ( BB<‘¿rYB@ÖP„³£…×Mî2gWèon(Ìö/ Wˆ­…«µ#¸¡¹áþÕ¿êýSõÎÎŽ^¿£á¿½þ¡ŠD@m¸<¼79­7¹m¡0ø׺(Álà î?ìÖnÎbî×ß bùµ3¬7",¬á0G/5ÄVƒ#oR‚XþwSæúÏ ù?0âÿÈ€ÿ#ãý÷†û÷ýÓKüï¾Ï§–wstT³p‚üýyÏ€T@¿.Я›jõ?b,œ Ž^ÿ*êïžz?¤þ"û;ö·Ìöf&œ"\"X¡y¨'ÄZŠ´²ÙX8Þtë·]f qu„ 7SýÝP'7÷ß0m;¨•ìWûþ€ 0ë¿k¿Ôoå`CU9 C=ö}»þöÕ¸Ù¤¶—3ô߉ôTáÖÿ8üb’–†{‚¼9y„¸Aœ|7rx¸…ø@"|>ÿ"ëo"ž¿ÎªHW¨'Ȉ›‹››tóûç÷¯“Éßhä`Vpë_{£…´€Y߬Ú? ¿`+7W×› ÿ~ûo ÿóü{é!Oˆ`zn%lŸš‘†¬"Ïéé—5úÐÁƒÑâ\\£ý:ß¿Þî—¾(Rf~QÂU;(zÕä5¾í|¹ªÌ¶ÖÛAæÈÜž ÙË£ò¡g}ŸO4ÏôNˆ}-lZŒŸöU/Ê{LeÓP[wm©_ó™iÑÅ=àà;>WìýSVz÷|R†g_«”·¯´ÖÞ"®*ØþÊ”°yzÂÜÕ÷±§»ýðîûUJöìW8Œbî˜øL‘þ.Ù”O uJåÊߪݎË;BbubÁï<_^Ë¿Å`i¢KÙÅy¨yc@–‰Ÿ'\;ø$·®Q;S-”âs/, 9D¦Ô#,9ƦïKv²±SÐúê¿»èçö‰%…÷²õ-âÁ]3ëãÝ“±Ñ][™CæºÊlëŠÑLü‹¦ëÀ¢€5‘ؽrô›ìç3üÜ°˜üDÑSjÛðôä)Wï8Ž*öÜŸèž“3@'}~+ÏÝ6‘žˆ•Ø\Žpµ<züuÚ>AbåPóبLbZ÷a3ÒYÍEœVÁ= ¾‹­{·^®2<¿}5aq€©ÿ_5¹Ûðòµ÷>›À¥´ê$C}ÀXŠ¹­œÕ÷ji—û­€G‡/§Œdû-!j¹;Ë6#ÔÜŠ.Oé­×ôÎc´¼$z¾I(ñØÇ/ Wj®½"¹ßKÒÿ¾ð{Lš¿ÞH¥hԻí:iÓFRF<g] Û39}—ÞÞF™8|à0­‰å‚Ô"¦¯£G$¼ ºêÆIª˜Ê΃ .–Šô‹µŸE·ÛCqüQmæoi\7yªàmûŠJ…0:næÅÊØê®óÆ XeŒ`Ãé’_ÿî½jâì…”Êr‰ÇO„DŸÓÕ6xÍ·o¯lŠýP¦ÿÎ*5„$8d”#ÙiWtu¿÷¾žG= kŸoHÉ]˜Ÿ:ã3ùN»­g}„™?&ì b݇a›yKÜ£%t×TcaÖËF˨?B:äÐ 3ÚZP ‚ÌÆŠ} fñφôˆƒTU‡J鉽žj:»«Ï‹ºôN)/ÂÕ äE½¬^gº‹ ^/«k¯&6Ö7%³"”-ήQËòÍ“ ñÆ‘r¾“'#LwDEëЙ}`?—$-`¤¦ÍC5Õ‡ 9æ3ÖXïžÊºUFC:ׇ¸T<íàìe¸z&îÄŠù @Õ!˜- “Ú½¡…´cEҼŸýÍó2¦±h’—Y#ªªÇSÀìjzaT €Õx…^ÉÊ9%î5Fõ¡ƒ…™y ×±ªälš2$g$?˜ß{v€¢è§à,¯ŽÀnD£ÍfGªªSH4‡S"€ÚóôöóãNƒ^œ¤ä½t!¢+ÏøÝ÷n©X#õg«uW ³}ceS÷ö¸ïcZ¦BF%×# èS=ªbÁõËFñÁp%ˆ&ˆ÷Ñ ÿø‡@§{›Â§ F$ ñÀèHvo»Vüy½¼Òç³³”ÎjÁÕŸ,_Âh^§–p³/â#Ó„HÊÀç„»ûÄŒ[‡¤Ê»B8Ò¬’%PË ™#¹&}Ô7uo(à–îu•úµÒ95ÀŒ¾?ËêcÕ8—ÄñâθÑ,™ê:f”†.‡Ðà¡ÝõÁ41hÀ›3):«;Ícƒ·ú‘¶Þ,èðY½:Nç5u…QEð ‰rŸ–²ÌûŠ!&.ÜYâü×É ú;á$¤`×yme~b©@{•3*¹‡ô÷¤” ¥Åêg`iDÕ˜|)1IŸ\°êjñ˜Î™+ Ä&j‰wé„™–£Á{÷…á«-G3µ«®ô*UÅmÖ­ïè, ï!¦ öOµìl•yóâúŽàäç?MµŽÇ¾Ä팼®sÞÀ±x»åÅ!¼´œ®“X>ÒIÙ»—X,×EAœ;¯è%Š]"N?v6ÁnÁ$W¥0O«W4¸»Æ—NQI…>Äóq†z#ÚQû3]º¹Ñ @@ -10560,129 +13179,133 @@ d ÕB¾ª\h~8©$‰¼¼·ý˜7!g;É¥ƒ\®cf>}7›ùâžÐÙZسãÁÖ–Ü^-Už&( ÖËÓ»ÜIFÙØS­˜õOV_ºhýÐn-® X{$¢½‰¼û£@–rlZ™âɞˊ1o(­¶¨mèö¡Ðé»÷ÝõäIŒ]Œ_-ô‹ ¸Þû ò'zŸT¶n76Gت–·& úìIĆ‹7ÎÔ‰‰f¾uä3¾õˆ;)EO4,Źk&l‰#õŽ¾„˜¬Ù¶³ ½höâiF] ‹œx'´ÅfÊb\ñê{Ý?¬¹¶=ê3¤XTÕW©*®§‰\Ee¶©x‘@†Dz:ƒ!¡X¾ÂK ”G½èß>c{BŒÍCŒ±¹0šUÕ¼ƒ¿ªÝ•5xfœéÉU“Nhèòã»Z–$8û훎·òБÞåú¸;ß¾2~%~QÍ÷*|6οÀ.©ó¶H&l]ážçµÐ[èù%¥κƬ!ÙrOxÆ!.B˜“zuW,Ôêr‹9å™ÊT°CHÖ‘_e‘‰ÿð:û5r€û3.ñ4v—W”ò]ª[)ïó–äÙÀ—݈H¾ÌûùSŽ¸+¹ºfS4çHõ¿ÞzyàÂ*/ç%Šâ׻͠Ï8ôæãmº'7…\ì°Å÷K)8ÐÁ@£bÅî\ç±ÄÝÊ‚×[g“©»5é«ÅÖ¡’'¯ÔíÌ¥ºégˆ<‚â¢Ï8TŠqùœ_U å=¢¦#fœÞ*ª6í¶²*æ›\oi›–•`ûlj[ÛW*ˆ»ºœ2Ž(ËtŒp{ˆ¥6Í]š†}„¯>{?'CÆà§5zíEëÝÚÓÞ&vø¾öŠ ÷dYcØL‰8àÇÉu°à•GËÝšÎñtûëV²­ˆ’eÓëû­&KÅàჃ‘oS*.m•»8ÕîŒWQì3ÊDÌûj OpHY²ï®f>×¼ù‰_ôŸö‘Ƥ‰´»ø|EÀ’=PzêîXDƒ%½+C£ˆ1_ù¶‡=AýYœ:&Aaú;æ¬U¾öÝ*“ÍXJ·=à²ùˆ1¦¬ý<ð»©,|# O'Cƒµë“M]í¼æf°ºÜS4‡AÇ÷Mj€“Ò·ÐökxõÊáž™ËG‡ÞÕéú,óÔ92‚¬ ߸gp0o9)ÁM£«&ChVF=Vv¯ñõ­Åž¡üÜÈT·Žïvä(Ê´ãé¿7jzä­ ¾¹Â6]E³ÚŸÉÞeIGOIùç…&˜+ÊZ Sl© -Í`ƒ©c½G¯Lsé:JθÿÍàÿ þOX9B,\‘p' WÀk yªendstream +Í`ƒ©c½G¯Lsé:JθÿÍàÿ þOX9B,\‘p' WÀ^CyÆendstream endobj -1628 0 obj << +2048 0 obj << /Type /Font /Subtype /Type1 -/Encoding 2140 0 R +/Encoding 2705 0 R /FirstChar 66 /LastChar 78 -/Widths 2142 0 R -/BaseFont /ZEMYJB+URWPalladioL-BoldItal -/FontDescriptor 1626 0 R +/Widths 2707 0 R +/BaseFont /ZMEPZW+URWPalladioL-BoldItal +/FontDescriptor 2046 0 R >> endobj -1626 0 obj << +2046 0 obj << /Ascent 728 /CapHeight 669 /Descent -256 -/FontName /ZEMYJB+URWPalladioL-BoldItal +/FontName /ZMEPZW+URWPalladioL-BoldItal /ItalicAngle -9.9 /StemV 114 /XHeight 469 /FontBBox [-170 -300 1073 935] /Flags 4 /CharSet (/B/D/I/N) -/FontFile 1627 0 R +/FontFile 2047 0 R >> endobj -2142 0 obj +2707 0 obj [667 0 778 0 0 0 0 389 0 0 0 0 778 ] endobj -1396 0 obj << +1441 0 obj << /Length1 771 /Length2 1151 /Length3 532 -/Length 1712 +/Length 1711 /Filter /FlateDecode >> stream -xÚíRkTSW‘ª¡¬òRIÕzX%2yj   `,žò˜{CnIH@Ä•TeYÄF—i`QÈQ •*XCÖPÈÕ@†)˜Ð3H­ë&od‚up&ŒgÁ“ÂáQ`#œ† Ö¤& ªÄÿ- i3Þ¥²`<“¼¦dÒ)ÂPµ@°’ÂZƒ‘Ý`RËCÖôâ¡Zµz\3Y~Ê©¿äåD­ÿi2´Œ)Á8:¿'…!D«™ž•r5¢¡ij08+™ì•oq$3ÑÁPB(T@)WgÂS8ŒBÓ•þMé`Å$„‰"DÞ¿íT2JŽ D´>ì?ØS1ç˜4 Gt ‘Íd³9$‘ÜïNÉÓš‰Q!hàò|€Çåz -9DdÄ@PÖXG*f1QŒ ¯Ò™\ ÄpÊä¿ú°K gfN¢o.`¥MÎéÞ$öקa:c0¸<²{¥/àóع"*´8£ÄÔø½‹•é) ë`ÅrSømýtßéíµyâê®cöôÌ…¦#[;Îo;eòc÷ù¹\Ç›~Š†?úÍy›ó§Èq§Ò‘ÈoX’×O=-Ê1d¬m½ÎfG7zå~Ù¬‡Šá¤”—ËÛÛ>ÐÜqϲؚÑäýðgÏgw³ÎÛׯ¾ÏáWQGŠfÖÞºùêI^ú¦Î~‹Ã×çP)%¹üÌê½pì?ï_x†Uc–šËó“ö?s}m¡¶ÝéI¿íhË¥v7Lþ/ç°é:å@'…s }±%¾L!Î^ès=¶Âl>ô÷0Å´4GJ=ØM z˜Þï‘ä–†ÇIbF«tQÔ.Pû‡ÕPmᆶõ­šôb¡µamKzC׿„“Ñ´—¶.uüí·%;g>M~ñ¢ïù#µõ¡Âàaã~bFœ·ïÀ,/ïaz›jí ³G‚\õÕ=BÞç°ÊØ®ù{à@N˘Ä nä»Ý<ú…§…K¹/×ì«ø›t½÷·Íæ=Ib áúñ@Õ£]j5঄'ö¥ž¾å}¹®ñBuˆk]áÌdsshhõ’æÙXï`Ð|×…~sDIÖh Úe¹Ø£+~ :—ã›_t\ès°ç¥ßÐO¥1榑#>‹ò쇶,HßÅ|½Üàû«ÝùȺT}—oÝIóó–탢sk÷¥¯¬Ý®Ñ?ÌÙ{LÐðˆcW‘sùe9^ ê½"7=[No§m¸R÷˜p*ŽzQ•ÊÄ϶¶¡8j=1nÈâžýdÏ/)íuOÀ‘u‡j »7=||kå¢(B‡ÞA5CüyiÞ›­£½aZgqsG¢½wÌtçÇ~D0¸åÜ!g­§ü7KZ©õþ1¶j-ƒë¬Œ6°Õ ÞE¶4¨¥JSçFƒÜ¬—ƒäi^w³Ôõ{ÉSwÔÜ’aÜJп:Y]Ëʳö®:åãA¬«¢²¥’Óêå63îÌ{Rên}†o>x-œßX± -¼]µ~´rÂÿn÷„6ßõÊHQç/gVH•Ò7‰²½©ó•Ùz]×¼ìæî²Nº`†×Ö3Ÿ¾ä~uÚØ´Ùf¾F}g«êØ~Ýõjx¬£†³%N ã>?ßY`÷~nQ•új\Z?¦Û_^fí?ºóRv̇…æ»^±îeâÒ׶ ±õC¶åI‡¹B—&ESƒqÏŪÇcÕÁxYt¢ývÊ–ˆai}ã‰Ý;8‡T9%Ýs [f-ܹùg·Ç˲d•_¯8Ï/ÈŠ=Êëœó½çâb¥äž*×L»'î ÏyøÃÐ{ö!£KžÄ5¾°ªúÎøV”H†¯t‰nµí¡Õu«›kÊ -÷HçÖºlx/ÌépÇá5'ÿÝ%¼ÏÚǩˈ—¯O-wûVŸZÌ é1> -k] ¡GZ±Ç5}M.íÌü|QYP÷]#ª”ÆÎëåù¿ 1²FêD{õþ9œ˜|V@û,|±ÀnÖý®&|þ]j p삸5ùZï—£kwò_Z’Yôäb†œXÕÛgÙø4;êpA5µn€ý.Êÿ üOP¨a9N`9žNù7pQŒ‘endstream +xÚíRiTSבª¡¬2©¤j=,Œy5„„1 ó$1÷†Ü’ÜK/7”AÄJª²,b£KFQQ*¬*u@©%Váp"­"<ÂòY¤jUœzÁººJ¶¿Þzçü9ûÛßÙû;ßÙ4·Caà` %&G¥R ‡ È3›M¡ÑqXN $'`!à^`µV ¸+›/ä­òøÄÒõ8’ª"€G }’Ä" Œ# +9 +¤rBkÈ +¹È0z&©Õ`Ýä °΀ñLbR8! +l€S”šÔ$A•à¿!múÛT&Œg¢€Ç”L: EBªÖVRXáÙ &µü²¦ÖªÕárÍdù)§þ’—kµþw¦I×0¤ãètj üFœ†­fzVBÈÕˆB„¦ªaÀà¬d²W¾Á‘Œ`DC¡P¥\Oá0 +MWBú7¥ƒâùû×N%#äJDêÓaÀþƒ=sþˆI“pDØL6›CÉýö”4­™U`‚¦.Ï Èq\®§CDF<Í +Á:ëHÅ,&Šä@:“ ”N™üW/6`©áŒŒIô À¬ÔÉÙ#Ý›Äþú´€L—ÍXÁ .lÅ^é ø¤Aoc%Bz +Ã:XA1ßÀ>[>Þ{j[mž¸ºë¨-=c¡ñð–Žs[O}˜Ã}>N×ð¦"á~uÜêø1rÌ¡t$ì+¤äõSO‰rLÙ2ÖÖ^G“½ ½rŸlÖÅpbòŒKåímïil¿k^lIoò|ð£ûÓ;™çlë×Üãð«¨#E3koÞxù8/mcg¿ÙîKÈ}¨”’T~zÍ8ú¿wŠ¯LÜÁª1sÍ¥ù‰ûž:¿2SÛn÷¤Ý²7 + åR›ëFßsØtr “ÂÙŸ¶Ø[&X-Î^èu-ºÂ¬Þ÷u3Æúµ4‡I™=ØM ºßí‘ä–†ÆH¢F­tRÔ.Pû†ÔP­á†¶øVz¡ÐÒ°¶À)­¡‹ë[ÂIoÚC[—2þ’öë’3Ÿ$=Þ÷ìµÚú@‘ífåz|FŒ§÷~ÿLÏaz›j{õ3“[œ\õÅ]BäÚg·ÊЮù·ÿ@N˘Ä +®ç»Ü8ò™»™K¹'×ì­ø—4ÞóëfÓîD±ÎJwýp êáÏ[ û¹ÉÁ })g"oz^ªk<_ä\W83ÉÔ\½¤y6Ö;0ßÍÏy¡Ï\Q¢%¨vš/ôèŠï«Îæ8ñ&Æzèyá3ôCi”©iä°×¢<Û¡Í Òv2ïG.ÏöþÅæ\X]Š¾Ë»î„éûyËöB‘9Œµ{ÓŽÕ†ÕnÓè æì9*hxȱ©È9ûDÔü²/õaŸ.§·ÓÖ_®{D8G<¯JaâqþgZÛPµÏÎäžùh=Ï'1õUßáuk²wm|ðèæÊEÛ×S„v½ƒjºøÓÒ¼×[F{C´vŽâæŽ3z÷¨ñö÷ýˆ`póÙƒŽZwßد–úµRëÏÿglÕZ×Q™ÍVÇyYLР–*M r±\ +§z˜]MRço%O\QSKºa[0A;ôòDui4+Ïһꤗ±f¬JˆÊ–JN©—[͸=sìq©«å)¾éÀÕP~cÅNÈÿVeDühå„ïî m¾ó呢ΟN¯*¥¯d{Ræ+³ôº®yYÍÝe *t -§?ÊþœûÅ)CÓ&«yx¸$úÆZÕ±íšó•Ðh{ gsŒ@Ç}v$¶³ÀæÝÜ¢ÕTê'¨aiý˜n_}h™¥ÿÈŽ‹YQïšîxD»–‰K_YÇE×uX—'â +šM †ÝªJì?ŒVâe‘Šö[É›WKëï²ÛÎ9¨Ê)éž[Ø2káŽM?ºi§.#^¼J8¹Üåk}J1'¨Çð0¤uM„nÅ‚ìÃûšœÚý™ùù¢²€îë;GTÉ×ÊóB£dÔ‰öê}s8Qù,¿öYøbͬ{\‰ûô›”þàØyqkÒÕÞÏG×îà¿0'±èIÅ 9±ª‡7ϼáIVÄ¡‚jjÝûo.Êÿ üOP¨a9N`9žFù òŒ¢endstream endobj -1397 0 obj << +1442 0 obj << /Type /Font /Subtype /Type1 -/Encoding 2143 0 R +/Encoding 2708 0 R /FirstChar 60 /LastChar 62 -/Widths 2144 0 R -/BaseFont /UYGAJA+CMMI10 -/FontDescriptor 1395 0 R +/Widths 2709 0 R +/BaseFont /KPZHNG+CMMI10 +/FontDescriptor 1440 0 R >> endobj -1395 0 obj << +1440 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 -/FontName /UYGAJA+CMMI10 +/FontName /KPZHNG+CMMI10 /ItalicAngle -14.04 /StemV 72 /XHeight 431 /FontBBox [-32 -250 1048 750] /Flags 4 /CharSet (/less/greater) -/FontFile 1396 0 R +/FontFile 1441 0 R >> endobj -2144 0 obj +2709 0 obj [778 0 778 ] endobj -2143 0 obj << +2708 0 obj << /Type /Encoding /Differences [ 0 /.notdef 60/less 61/.notdef 62/greater 63/.notdef] >> endobj -1136 0 obj << +1430 0 obj << /Length1 1199 /Length2 2269 /Length3 544 -/Length 3057 +/Length 3056 /Filter /FlateDecode >> stream -xÚíWi<”k2ed_â!˳ØMe['ŒÆNeÌ<3†1Ã,–¬ÅÉV–É’#[Ñž%ÑbJ¡Ñž’(EY¢SïC§zO¯oï·÷÷>χ羯ÿuý¯ëúß×ýáÑTÃô­ÉÌ@ОÉàèch,àB ä² DÆVým •ëÄ!Ò0&Â55Ýi:¸¬ Ú²@"‡ÆdàˆÈÇ=ˆ 8Y€À ±h3¬Z£ ¿;2YXÏ¢…2wx²è4á˜$n(Èà¸aatHÞ²™\ dc -Táò™[fX4‹F âm^:ººz?-sss 0ú;à@6Ê´ EHg†-fƒ(@È‚ -'/úâ)D;2³Ø6€âp°(T…B6$›‚d€”T¬ƒlË ]$`ÃõÃÑX j,µœ†! f$#fYˆBc—Ú#sÃP Z8tÂý™à?mT£ Ðæh3 À(Rj1µ{t¸bÍD9.&ŒPˆt6G£€ÐÃ&F€‡ÅãbþøçŽÁd‰‚TèH~²CfòmïLä°hQ€‰Fcôâûcµ:\2“AþéîB ÎÇÇvÛÝåúÿáicÄhõ1¦f€¾™€Á@}šþÊúCïZ,YñDÚßµ¢R:1(LÀü[K–ßÛŠYlhVÄÒhëÿäwarh$@ü#´1š èƒYv¼þ/;d¿æ°çÒéKÊ ¾I@š°­À¢*tèâ,*C#ýG1”F^&îWG/ðÛ…ø›îWø»5ƒJ}ŒÁ7#mO‹Éx‡ômv¾ËM^º  žÉ¦-^q(Äó æD#…0@6:”%dIjÇ 1É4 p %²È? ‹0‰ËbA:-û}O¡A%‚`H‚ó˜¤{‚÷4ϲVŠÔyÇ°ÃÄcæ+WÕžAF -¶»(„œP2*6Ë+ÆáoYÔû­t^)š­d—abnÓ‚\-%"%蘦øyz“ víû5ˆžIt‡bÎ~…‚’׶Ñ×ß©ÕÌøhZØÞ–"¤2eÖÍù¾ w…)©Ô”× »Žè˜ËÍ'M¸:ÒãÝ°°{¼V:8ioÈ–Ëçî~ÒÞâ+rîͬt]‹T@ÿÀUQã„{©pNãû@%Ÿ¦ØÖÛ— 惪›(ó§xaåÆ[ ·‡=Ðë>í…Èx—Ôj£{Xæ÷Õ…dïÝ5êíqÕmUJoŸÕÑļÔR¹¿Ð¶·MTŠßÒ&$ ¨Ù×Oš+¼œ:RçlâpÆ›¬çm -„‚“Çý+QùXP W± -V+î²ïÌêÔ`_ðŒw8O /L(î³¼ªWÔûlÜ{óZÍiáË>™1us)6oá„é‡_¯Õ%…+‰¥TÞùÊ×v':8SMr‡Nï…¥‰’Õo5ž9ÜÖY¸kJ¡eÏé´qth¿ˆÇL²g{ÊÛû~›à_”²¼6¼Ykr /+ÁBîÁZ}˜Ã¥+cÈzITˆa]±O>ª…ÔÚAL-½Ú®Š1µQx;^æiÆ¿M,êÊü–u …ÕÑ!ìðvGÒ‹£½¸?Lìµj<Ò štÚ¾ïRuîyΫÝÓ²^ŸåµDgëNŽíñ¿þ†ÇêÞÇ÷Œ(¾ÔÜ¥‹;Ý )o°éK€·‘÷kËóùV/Ð -W»Gí'oÝ\%7rƾöö:¡ŠÊ¤©œ³?„b&TáüqD!Ï¡øtí).ÍñòÌû% -wV¶šØÍú6‰” ÜÜkì¨0 -Ön»Úd(Ážú…XjwTêÝÙFÙçþÀùñ€L´²ÁEÙ¼f} ¹H=±î…žàÕ¥êŠc ûy:W|Ôf"yÕ=Û{ØÚ¸—£ôpæ IE´˜ýæ|vb.›ûÂ[Û÷c<îõµ3‹0™p2hàª×*?÷Z˜Í>Ó(yF:þúÖþCêãñtÿ -)å?ÿTsr0ðõ—F›™VF×Ï9~Ðzèt#p¶¯‘ýEñ^Âjd0  |7•ˆ/®Îœø˜“ä+¶BÌ뼤:œVb61Ò’¬ühM÷®Âª0r<¾tþo/VŸ4,RtÈǘƒÇÓíéè[¾Y)Éy;àá„€C‰6{‡„ïÞzӌ؈èMWy° æ½/óÂ]†9Á+¤l¨ØŒÑûË$¯P2A>”šˆ‘˜l¶Ùår÷œuedÇhç%±¼`EP¼>8·E}Ç`Md@xº•hÌo#­–eëÄ»7Tÿͯ=ƒ¿\,sÒÒäÉÎÁa° _ÂÒO`sÚÃÓÙ¶ÔÂ×+¿Rv|Ö\öù%dÓR„ƒì±ybîQlk«@¦ª9â³ð#ÇC\F?Ÿ=à"0‹ÍcÞ,Øåu0ÏBssz¿Æ®ÃWì|úøòupSЖkúÛCA›‡½olF‡ ž€g¸u~îìº$Ù÷Ž¯ëÙQíz­-=ÕcÁþ¬>—yÒÂ*¹ë(ù#/¾ÊWûöü»ÊP$á`ûPéŠVV²ùýÛÒ/Ÿìžg¥\)9Ä ¼\›¦¶æ×;µJg;gQ‰šëºÓ -L[ô̸ iö±•b^=“¼täçÒRyéÍ}G®‹±a¥0á VšÚxGßûÇ[5DH›vlx®¡’qÂîM5·:{›Ví–Jì‚A[DùñÛ¨¦UˆeÞî,žÃý‚ÀȳÖcZÄ£*Márn“JVéÍ>œ£€|¼§øÄÒ »«âhÓ°¬ÚÛL­§ „c_Q®>³þ®âÆ"„B#0¯mWø"û¬úv>¼ë.@SÄP&v^îÌ52 -Ý5›õ‰·Çícüžf„„ËMÄöñ²Ü ‰ónƒ\ÿq•œA£×Q‚n׎Ýmæ­ž«ÌHSKÙ©abü"¸{ç°Î…ÄÚ1>âÉrq7ÌÅd„T3+ütªé÷çLѧl¯a‰o}á`Eì€ËYcØ“d—ï«ט›áýXïÞ”:/†Sö°ÛÇtõô,Ť!}gfë ?†}å™êÙaáæ”HW‡P“¯ðqÅÊ»µ¶®³¾p9ëœîÑÊ`n‰(k}±‡W˜ßø=-Ï”Ý-ßòtÖ"Úy>:)uw*ýúÊc>å@UšÇˆ Ï5Œq“ZÏÓªaØ^[D|xsyU\ïnÀOîâIsèÜÆOOîô±²3eö«¢2òÒU#¨†QµUÀ½ ¸ÉƒŒ•åœìÛW?×{d'hÊ¥>¿ðèh’LÅÙ²_ Þg(w3OÈ -E¯ÙÚÉŠ{}$³OÔ¯—X@|Y}ÓÈdLÜ\9a,]ÊÒ5‘,!¸¡˜Ý)¼.Ñ^¦„%§º)¦ÿþþm‰­ x›|wrŸCóÅQ‚£ØÜšž{—ׇH˜²«q+!¾ïfO¤—”É $ártÌX±õù¹±Î…® )ýõ¾+ܪ‚m‡7|(KÐ/¶²d(å¾7*c¥ÉÝ’xPjrè±FžêÞ R*3S/·Ù]ûNÔªdÎX–-Ï2ejßP(Ù­BÐ/mò~ÓÑyA!/÷º/ˆSšB~|£—d—:ùR¹ßšõº±Ÿ=Ëï8Hàm³O=Q«ôPö¡é¹>?j¿Ö¹2Q‹µðjîšõÙUÂgñ7Õ2…úK»äÑÿåÿ?Áÿ‰Yf(‘alè‡rñß þ/h‘@²endstream +xÚíWi<”k2e$²ÄC–ÆŒ²Ò £±S3ÏŒaÌ0‹}‹(N¶²”H–{¥Ý–h1!²†RQ*Z,Y¢SïC§zO¯oï·÷÷>χ羯ÿuý¯ëúß×ýáQ”ÃâÔ͈toЊNc©£‘(CÀŽâïÍfâð´½êû@2Û†…§ ƒ‡+*:RXTpM´`€x…NÃàY£°Å3M€F¢ô µQÐ¥õÝ‘Î0° Š?= À‚,A¥Ð C'°ýA Ç R@â>Ig3 Ó A®° „2(d€pÚ碢ªªöÓ‚600¼C¿#dRÈ4@ ZTzÀJ6ˆÂ¤ ¨pâŠ/–„·$RX+m+ÀPC#€„!’IBÒ@–† +T¬%hA÷_!`ÂWôÃP j,Tc- ýhô`Zøš‰B#®¶Gdh8Ñ(lÐówd‚ÿ´‘A ƒÒD ô0C>+©CÀU½bÆÓˆ‘áô€„§2ÁH + „>ðp&>X 6þïÀ?wp4 R,À$CGò“2ƒ¤o{[<‹A è5ÇëøšCök+6•ºª â›$¤ Ø ¬¨B….Ί2ÂDáý)ÔÐ5â~ut¿]ˆ¿é~…¿±›ÑÈTPGk~3R˜V”ˆ¥°>ßfç»ÜÄÕ +béLÊʇBtп`Ž>‚ d2¡CY…@ñ—¤–4H¡‘ Q<ƒøðØ ¤ÓêIA±ß÷$ +T"†€ø`?°ó°oÍáúÅ fRÁê/hµè:ÍeËjÓ©\cHîf; ¿2)í‚9ýÌ< ¶ÍǸÚc½íz®„4)Ëd½`?óäF!áx!î݉’o‘—vÙnžÚ„èšFµH¦“ÈÎczw÷¹Šy7Ec‹!\]4zÛ¢û«×ö0)™Š¢*^û×ý*bK±ïíwS£ a½œF Ê7öH6ßž›W~RÞãÎwõí‚pUƒW_ÿms~èÞk8«fÊ[Ê­LÏ°±ã¦æ’Oyié' HgÖþ€aµÎK.ˆä±æª§D.°_½•ˆs=T!ß\Y^ü¾©ôIAÇEôK%™GËMGšø…šxD¡ÕÿúIq«„MK¢y$Fg—Ù’y6R—}þœç9‰Ó2³óa2¦¾ryíV­©­ +ÌëÎQÖ×pÄå÷’GMn«åv?ŸtÝf»YqŽ÷¦NdB@×fÁ¦£ŒmÐ}𻕪„@©-ñ%mã_•ñÖ¶dÝŒ¡KG`‰üDù¶šË§šZsÂf$áîOœtCUñWxò9ÍÇ97Ç¿{ä± þE*ËeÇÛͺÇ3S£Å†7«Ã¬koO «·jøðiUå¹ei4û‚ð ·›e±|zæ/#& õ§öm 9­aÐÆCîo`4Õñzx½;;k|¦󇮕R…SRö Ÿ Ó6ûaíJ¯Ž¦¿:4÷$ õÍ•ÁÜf¯Ð4Õé‰Ãžwßr˜CGƒòjëÛe#0—.n×ÜõÅËUÛõɵ¬bÓ(‰Û¯­¦ïåÞß 6~Ùª²cOqIìñÖ²þymÂßËÂ'9ƒ‡ŸòD%)Ïèrµ+N¥<Ê—x°¾Q×rÁ½Ž¯°ÿþ«³Ÿ@‰×`®ÃÞ<ÕK +öÌÃÏD¹¥DíÁ>ÒQÇaÛ‘~‘PiÍYIÑÌzuc±`µ-Ë]¾ ä%'–qUn¹]”›æ”ÿõüÈ)3n–ÔãùË$Ñ ÿ›ímXÙb²aÆ We÷Qd¸Ë×>ôB÷½fZ£|³ô¨ËòBÚåš­—…ƒáo^ZÕÒ„>žKò,’îÿóO9Û!k},Û^ûz žnª}÷êîY•‰¡á›{Þ =5Ì/’½Ñ‘¾‚ôE@O0*¯.ó¼&çu2ÆüÈïö·õˆÁî$™áe9×£ÞèŽ"´à÷œÒŽb#ì¸Ú_º™9[£ÅýÉ1hÁézó0»‡WÍJ‚sYÚk·dúJr¥ƒjÄí¾ ò*‚½“LùÃÛl꬚DŸ)bíVhßPpM§Q|Ã.æ¹F”ÃÒK³Ù¢å>âÜòØOÁBsîžÄpɸê|š°6ðár·8Œ÷nÌãÛ>;Ó’Æ3P=¾û…BŸWÝ(J÷ÄU%y¼n¾BÇÝ:!}·TÈHâÔ.ŽìëfAÆúÜXŸ½õRo\¤'£6æhb|§Å¦›ïfßõž`Û4”Bñ¿ë^=@Pš—0ÂQÜì¥m`Ý4¸®n~^ch®¨Œoc9-†hµ»®÷Žðïo 0¹·ii¾y"Õ†Ó;T=‹¬¼Œ¼™'rÞD÷éÁ10;KÐăË(ñ±ß¥´?*áÛ¥_Ib :Z‹l¢›ð±]æSe‹O"¹RdyˆAŸyÿ?çg÷úó•ãv\ †™ôûÙa.'22QÇÂNݲt뉯‚ël½ßs›ï<åzÏå7POÍvhýÜÚ^»µçàªsK¹ý”²ðL—1ó³übÊycÓ¸ö3Äp¬Àw厥%þH܉桂uŒ8ƒ!«w_>YŽ¦äÆßÊ?Éöîð-„Í‘¼³ªm…ÓlSÉxÅmI'¸û猻ÌŽD«ˆ’-.]Óœ$äç‚qa£žÓw|˜°o‹ÂuSEeìn÷GçøÖ»ìUI.³b¿—@aÆõ˜%‡¶ç¤Lú€“ö› n‡;gÖs6.–$'ÊÅT0ñÓyáÛypLåzLåÄ âéb^'ÌNwœP±Àûl¦î÷Q:ÿ³ëw ñïÜá`qÄ[€ÁÚ¤Õk™å.Y“‘ì:¢Ö;#Ï g<îtÓÛ8·‹×½˜t°B±ñžͪärùÂo}|°=Ÿ›µ¿nË x‹€ä iïCJ{·™]¿™zÕ3ã‰/;ß5»ÑÅÉɪ™E͉ÓE‰÷i8Û*á-Ÿœz8“€š%¿rZŠ?^šè4ÎívG­S'×õ¬tL%¢ÛX_TÙ}ÈÉû“£@ì"ªŒ]óééÃìFZŠÈ1YëÌ$Ù ²VHe)Ðë×N^_ÄJë¸ý¹Ú)-ZQ,aôú“3±"}ÅW>Š~ÍÖüp&ÝI/å 9W±·•ùætJ¿G7>ÿ**¸ü¾¶î„€tôD’‰} Q{G³•w'\°¹PÊ8™à ™ôûÔ»| n&ñθëú¯q»·,nêê½¹ÝïlôŒÿD…C>~Êk²“9ן”_(Æ‹IWÑgDTgeDØæØ_Œï«v_çPêk1¶c¶0Z=ÏÔ„&•1¥]ÈHk.Ð=9¢‹%;^Tð+™¯Þiä¨ü dykúDª)%Ó$~æè?Ñ¡˜Û#qúQÝ™%nǪ/ˆ ŠO<ƒÚ/‰vUâbóîÛ“Uÿb>žÕrÇ1š°J8T)ãóXô±ÞÕrŸÒÕB~ãÍðrö¦íi¥¼W°÷äRxú +ÚÅQÿåÿ?Áÿ +â,º?žág€Lè‡råß þ/uÔ@³endstream endobj -1137 0 obj << +1431 0 obj << /Type /Font /Subtype /Type1 -/Encoding 2140 0 R +/Encoding 2705 0 R /FirstChar 97 /LastChar 110 -/Widths 2145 0 R -/BaseFont /DYYCRJ+NimbusSanL-ReguItal -/FontDescriptor 1135 0 R +/Widths 2710 0 R +/BaseFont /NYLICW+NimbusSanL-ReguItal +/FontDescriptor 1429 0 R >> endobj -1135 0 obj << +1429 0 obj << /Ascent 712 /CapHeight 712 /Descent -213 -/FontName /DYYCRJ+NimbusSanL-ReguItal +/FontName /NYLICW+NimbusSanL-ReguItal /ItalicAngle -12 /StemV 88 /XHeight 523 /FontBBox [-178 -284 1108 953] /Flags 4 /CharSet (/a/c/n) -/FontFile 1136 0 R +/FontFile 1430 0 R >> endobj -2145 0 obj +2710 0 obj [556 0 500 0 0 0 0 0 0 0 0 0 0 556 ] endobj -1064 0 obj << +1354 0 obj << /Length1 1608 /Length2 7939 /Length3 532 @@ -10693,7 +13316,7 @@ stream xÚívgPTݶ-HPPÉ™&çÐÉ™–œƒº–††î&K(HÎQÉH ’sÎ 9#$ˆ€øÐïžsn}ïüº÷üzõvÕ®ÚkιÆsŽ¹VmVF-]^Yª„p@óùž4`ö–Î(]°ƒ¯ÜEXYå‘P0†pP£¡O†P@jÅÄÄXòGw$ÌÆ àÐ×1ääææù—åwÀÒýžÛ(˜€íöà G8ÚCзÿãºP(m XÃàP€¼¦–1HCÀ¡¬¡P†:@‘`8@ËÙ³¨Á¬ (('ÀÀÿZ¬ØïÒP|·X²(€r„ZÁn·Aݬ Ž¿]<G(Ò†BÝ~`(€ 쀾í€9XÁ!¿ ÜÚ­9"·ö·¾[0- ²BÂÑ€Û¬Z -JñDÛ‚Ñ¿s£`·nÂú6‚°rþ]Òß-Ì­ †9 h¨úw.K(C9ÂÁî·¹oÁ‘°?4œQ0›1à ¡6`$E¡nan±wç_uþ[õ`GG¸ûŸÝˆ?QÿäC£ pk> àmN+ômn˜ÿïA9X#@¿ìgÇø\ È? âø=3œ·$À„ÜZðk з)ÿ3•ùþs"ÿ$þü‘÷'îß5úo‡ø{žÿ­ä ‡k€ío௠p{àj€ßwÌÿ ¶‡ÁÝÿMôß ¡1üw 4ø¶ ²6·Rð üe„¡”`nPˆ me °Ão{ôÇ®ï"á0è­–ÚàŠˆüͧg ³²søÝôÇb\PÈß™ßÊó‡7¿’¾†ŠŽ2÷ßoÓ?QZ·ª£õÜo‰ýWêÈ?¿1äänO^ ¨€WH@ôö° ĄżþM¾?@À­ÕÁh$Ì ðü¶hàŸÒÿëý×Êìo0ŠVÈï9ÑEƒ ·£õOÃo·•3y«èŸÓ~[ò?Ö† +JñDÛ‚Ñ¿s£`·nÂú6‚°rþ]Òß-Ì­ †9 h¨úw.K(C9ÂÁî·¹oÁ‘°?4œQ0›1à ¡6`$E¡nan±wç_uþ[õ`GG¸ûŸÝˆ?QÿäC£ pk> àmN+ômn˜ÿïA9X#@¿ìgÇø\ È? âø=3œ·$À„ÜZðk з)ÿ3•ùþs"ÿ$þü‘÷'îß5úo‡ø{žÿ­ä ‡k€ío௠p{àj€ßwÌÿ ¶‡ÁÝÿMôß ¡1üw 4ø¶ ²6·Rð üe„¡”`nPˆ me °Ão{ôÇ®ï"á0è­–ÚàŠˆüͧg ³²søÝôÇb\PÈß™ßÊó‡7¿²¬¾±œ÷ßoÓ?QZ·ª£õÜo‰ýWêÈ?¿1äänO^ ¨€WH@ôö° ĄżþM¾?@À­ÕÁh$Ì ðü¶hàŸÒÿëý×Êìo0ŠVÈï9ÑEƒ ·£õOÃo·•3y«èŸÓ~[ò?Ö† uƒZ|™BX‰¼LLIB—Qdt ( Ã?V1ñŸx£+w¿³^õ9’e‡Ð†ŠÚ¥ÍäÊu””7œœ¸äN­Ñ÷ˆ¨/ùŠõ.‹ú…'Ð)á0äPùÝÚ…ke ¸éÛR§ö ]8sô&sß±­|*åŸî#>cÕ¯‡‹úœ‚ œEëÑymeê÷AÆ€>8m„ 1œ4¬jõõr¦XÜâd8„²³¤¿V>M¼çÀ7ÁÜ&N\€*ÄJÒÜOµøï8•^Ýçôáö¼J%qõ‡ ‘®.µ&у;ìXBÒ0ÊÚcVKŸ0-SÛ·ߌG?óí·Eƒòñ(€(§¸Ëš’=´øô•ú+y\J6.æꔋ‚œÞ»ó^eúÞ‚·V„(õb*$Ã=AÁžéÌmEéïa9žoñ€Rý3™ÙÑS×!÷8ÎãÒ9‹ÅÕçÜrƒÅ£‘C™Äù\‹-ÕÕ²k±ò¡øáÃÍ8 @@ -10725,361 +13348,356 @@ QH; ‡á{__bçâ.°ßþºæó}<¯½kb¶Þý9\¥™àpDË\TL[\a·¿«NüÆW¨œµ>¿¥t®tÉQÀRD‚!$Dr£G¢1¸AÌý¾ ¥Y í–.ç#_©ØÉ#¬w¥Å¹ò«|Sþ?Z:è:”—fÆ×’¸ʵhúÏÈ×XaÛfÚœ¯Ú3™B¶“—£Ìü¤‡uቇôä·ÏÔϾʉltãp)’&ÿT+p•°e –íZ­M31I¡ÒÏL«êÈcýªG’«ô"Hx¾çS•ö$Û_Œ*[£n~OYgÚC¢ã® ø LóÃI8GU–¿Bã¡\‚–Ÿˆ{éõ´Sû›7M‹Š–…;ûÛ䃵h¹0GQœ&÷ <‹"œ_ý¼ÈAze‰ÀN2ÿPÜJ"u]©¶ÕLòs.}æQùü‰iõHö5¨ñ‹‚‘öqLðëƒýUj[’ =Á®…1Ñè²YÆHOŠåoq ’„!¿‡RÒ¯¸ð%ê«~u¯ ³¿0Š×·6î;>nE=m½aÔ\{\ÄcïQq”&T/bµ^þü‹}m“¹ò A’ü陈×O/ÍI>c×b%ÒÌ&ìýºªú· ¶mJ;û7žb{ª6eC‰Æô_è<@ÀbW’+Q'‘šäçÚU›‚ݧ/ˆ+ƒË°a*¦Ûåõú/5 JÔ†½ó'lï 0Kf›/Ð^‰ˆÖ½žO¼¡M [If§€ãC `æÔbï1}ÚU*÷i g#™HÓÄ+¸"î2X|F#êLq¶ÀØÙªþr#g <¤þdÑ _IÒõ.˜ê¢Ï\9¾§é-xÚÖ-9?›ìÐv_ wóý}¾éH`…Ñ'>Êß4¬>äŽT‹¬ÌÛúGäµGÔà…$Í ï‚7LI›u`žUJ2ì„΃79ç¯~f´lá­ÊΚìïW 5?|¸':U—.ûrJo ÇÓlÔË5áAÜçxE ³º×ا‰3Ç•ÚTñ#åKþtâ•.iKW@ö/É›ÔÑ÷ ûj&Q ¦Œ²È˜¥t°Èð§Äh-ؤ1íý b?e¾™F Š– ÉXrÙ/&Šjz©¨rAÁM°re.2Òe%ÉÍ£™6"5[¹(H4 :\mdb“™[i:ýP½2“¿Ýä÷ö0JÑ»pÕh¯QšQ¨ý±Qó_»Ã7;mþã«÷Aú^ÁÐ; Ó èvñ¡Õñ¥ã«*’Hóß¹,QëtT½}…ÁbWý€g”ùxÔ$Ó¬GÞ×™®'}¡uÞói õ´’D§ùõ; ¼xðÞÔ¡Æ°~. °öâ%ÅÅ4O”˜»ª¡ Þ»Bï­\ÿÆÈæ  -†ìvm…$t§³ÎLd?莑ˆ+í–«I&VñZ"-¿35MGöÊìä§7À Ñ4‰>ÅauA×W¯½r‚…`Hã×W{Ûw1Û®­¹E¥^["W¬%BŽ… >«íÜMÑ#nNCuy‹¼Hû %Tž,TÜþ0]4.ïdîžk0œPañœ„5ðY ÓëF–?ªU'?Õ‹«žäfü¸Š·Ö¤qCr®až1j,†º¿÷2Ó“=²õáÿ¶D4ÏØeÊÀ¿I Üóv¼vþ´b„dîÿ¼ø)xý)\+"oÜ´¦ÜD1å[|)h$úØûeGUeŸ?õ¾†Ó<åízznKB†Éd–¬ö…Àÿò!øÿÿOXÁ¡`$aFÚüð)æendstream +†ìvm…$t§³ÎLd?莑ˆ+í–«I&VñZ"-¿35MGöÊìä§7À Ñ4‰>ÅauA×W¯½r‚…`Hã×W{Ûw1Û®­¹E¥^["W¬%BŽ… >«íÜMÑ#nNCuy‹¼Hû %Tž,TÜþ0]4.ïdîžk0œPañœ„5ðY ÓëF–?ªU'?Õ‹«žäfü¸Š·Ö¤qCr®až1j,†º¿÷2Ó“=²õáÿ¶D4ÏØeÊÀ¿I Üóv¼vþ´b„dîÿ¼ø)xý)\+"oÜ´¦ÜD1å[|)h$úØûeGUeŸ?õ¾†Ó<åízznKB†Éd–¬ö…Àÿò!øÿÿOXÁ¡`$aFÚü3ü)èendstream endobj -1065 0 obj << +1355 0 obj << /Type /Font /Subtype /Type1 -/Encoding 2140 0 R +/Encoding 2705 0 R /FirstChar 36 /LastChar 121 -/Widths 2146 0 R -/BaseFont /FUNHRG+NimbusSanL-Bold -/FontDescriptor 1063 0 R +/Widths 2711 0 R +/BaseFont /GAUYBT+NimbusSanL-Bold +/FontDescriptor 1353 0 R >> endobj -1063 0 obj << +1353 0 obj << /Ascent 722 /CapHeight 722 /Descent -217 -/FontName /FUNHRG+NimbusSanL-Bold +/FontName /GAUYBT+NimbusSanL-Bold /ItalicAngle 0 /StemV 141 /XHeight 532 /FontBBox [-173 -307 1003 949] /Flags 4 /CharSet (/dollar/hyphen/semicolon/C/D/E/F/G/I/L/N/O/R/T/U/Y/a/c/d/e/f/g/h/i/l/m/n/o/p/q/r/s/t/u/w/y) -/FontFile 1064 0 R +/FontFile 1354 0 R >> endobj -2146 0 obj +2711 0 obj [556 0 0 0 0 0 0 0 0 333 0 0 0 0 0 0 0 0 0 0 0 0 0 333 0 0 0 0 0 0 0 722 722 667 611 778 0 278 0 0 611 0 722 778 0 0 722 0 611 722 0 0 0 667 0 0 0 0 0 0 0 556 0 556 611 556 333 611 611 278 0 0 278 889 611 611 611 611 389 556 333 611 0 778 0 556 ] endobj -1061 0 obj << +1351 0 obj << /Length1 1166 -/Length2 8686 +/Length2 8911 /Length3 544 -/Length 9500 -/Filter /FlateDecode ->> -stream -xÚízUX\[ÖmàÜ¡pww—à.…+ pªp‚— Á58„àN°àîî—‚ËåœþO÷íÓ}ŸîÛýîÞ{­1æsαæþê¥h)ÕµX%-ÌArNŽ®¬œlBU°ƒ¹TËÌQ™UdíxyÍPhiµÁ®ö ÿ _iÈÌìä(cæúÂkÛ¸TÌ .'‡‡€/çËšƒû¯@'ˆ@vpò¨ƒ\A{°ã %ãdáærtÕrsv¶ƒ,5AP'7ˆ*°z©ì?³¤œ½ `kWƒŽ¦#33Ë¿NAAA€¹×_ @[;è^î {'ç?2½HȃA—¢-ÿˆU·2“µ»þÑ.€ÁÆÕÕYˆÝÙÊ ô‚±A­ØA®ìŒ/…Ê:ZJ;9ü!EùÃ30dñÒ”ûß}³stòpôùØ -ìhùgK–nÎì:Ž`7Ð[™ÿ ~Pþ…Yƒ\¼\‚\ äiaÃþGJm/gП$ç°™£¥¯³“3ÀÊÌ -ò[^(>P3wÀâòõù߉ß¡pr,Á®sõË1üKýYýc¯bæ -{ 9Ø888Üÿ\¿¨¥“£½×¿ÂUÍ@v-5-æ¿÷þÏ())§IVN~+—ïˤ¼( -òrÿ]ñŸ^üåߨºøêäø—ä[G+'€à?Úyññ¯–ÜAèËlþcFÀ¿ë«:¹‚-@†Ž/ÇËÔ¼<8ÿëHýÿ_ëï9äÜìíÿt…áv^ü€”8boùp3°½×yáïz LÿÿAç­«™=ØBÒÑÚþŸ6¡r`O¥:ØÕÂæãò—Ë–~‡ u'(ø/ÀÊÉËù7NÛlaç‚B_ÎâO -ähù·”²ŽN–`Gk€–ëËTšA,ÿ üA[¸A /öüy@/ïþµ·¿y‚,Pçœ,„ƒmk‚[oª$I(™eÔ]Gþm!2¢ë!D -[D« “-Á'u™¯nòŽ<'Xð"Yeð&­ øc‘#Ñô,åKXÈm®_l™Y¢o׃GÐoR:©‡;Ѧ¯êJ³Š÷ѧ‰mŠoâºë•Bå‚n‚‘7Cj¹sD¼˜<îcØGÌàwÛlÞ—q+Z/½²Í"^Ø|$Go-ÅlêØTåPÛû2oT cÚÝŠùýüÌ yÚô~8!4}"–öj6ä äkÝ8x>9"¡EVj› Y -˜ñ)l¾ÍkU¾q¥DÚÌå¼S2³òOyÍR¥vHDShÛ!¤ÍÙaæÙþá¿U ¿ë-¿ku§zIúèçÝ ‰ŒPËi‹.7 -‹\÷+í°Zû²Æß5eEmüØyò£ ¿×Sewœ•õ‹k†­bטUÊA-”Šß »,ÎCz7†–#œ$%Ïɶ$¢Å*:ú8¬û¼!Ì·ì«%×ç[âÁÄeÂ[³6æÂîŠî×ÙšÀ³õðù‹Åôm›Ÿi8e>Hg33nlGº®3có€_ê0µihù¡gÊÀäxFnPê¤ëηk,4K§ͯ_MKíkû ß 6ÚÀx.a¾+íÌå”o·gKR™¥ Œ’H!ÚèE=é_–9ºã4? kûŒê‰Z*¬ wøŸOV#•3Ul# 2µÕ¾Aé£ßÚ¿d›K€–¤–g§$ýæªâ'ÚG÷nAüùuÊnûF¼‚›*ñƒ5_ /NŒšrþj{|í lÎC¤r è·Ív¢âr‡"¡þßù¦…µš6#qØFn²‹³9ôgåÉŠEg€+Á öÊL–¡ÀN,@‹%8]è:ÔÊñ»¤>$5o5Ò"“a£ø0ªÃ4v~Ý«¿~õðõ@÷܃3/qviùk'´-âzÞ<öë#n×wÍîü‘m•Gï%Εxó¿{àzK Ü(ý„÷’¡¦7IâA³ÑÁ8&ÕÑ¿u<é‘Ø”¹oe²ænrÎA4ZÞ ¶OÑ©Q?Ÿ&ºõJ=ÞÃ^…j´\!ÃûÖ—ÝpÁ±äÞ:ê íg|ˆ»}¾‹œœ -yíó»Ñ€:+ÅIÄA=ÁÅqÇR&…{Åšý ÈÉô\‘Ñ›ll„%Ós@÷j¢¥”¾ì{P¡-ùq¹§~AioMu“Yuæ4m¿ø.ãг޸ùûlÌÞÖ5ŽI£ÅÏ+Üïzê#–jˆÛÞ)2PÛµZü"{7&Iò ‹fÉìY§qxø6·-!{.t>ò1Êœ<›ËÅ‘w°ÿ;)¥ÕHfßO-`ÌÛžÅ"}Š¯ò¸t¨T1úä8 -“þ¡•Æí‰÷@@P‡‘»‹©ÝeÓ¸­ -ÜÜŒ”9rƒéÔ˜OÓ[¬™ï!)-oB€û³}‡rñ.ïÞ%¸ÂÙõ@ -º" "†9ûˆÄ«@ŽŠê&z -§/ÔÂŒV‚¦¢PŠ\Ký`a0Œ¸É0òç?æˆn8Ô&Òm†_Ž'{•ƒ -ÈxìúYxU‚Äb/Ö[áNŒe­pŠÞŽéPS{Dí÷æØ*÷¤ë½þ[@ìŠô`ŒJ´ÝŒ I¢ömu:¶>ÿC˹@â!±S „Á‚Å5ä!4ˆ •ï¯ÞÄü65ûö£¢M#·Dž^ëgœÒ–óÖp|Ø.õw®òž‚ö§E¨=z¥åÆU²ƒ¬]!áß9Ø)'ª’,4в¨XûrYuPÖJÙ35S1CKX{ûºE†å™ªwïÃ(aÁÛè|êÍ tþ MLªe±礨]´ClözÉÞÀÏ·?©ª_±ð3~‡³?®Üv-‰›qT·‘?Exqj›2± Ž %ÊŽ3m‘Ád™°IÍ»O‘ý—Ž›§Í)?ÉeGJ¨£w¿ýág§“fϯˆÀös¤È»I–û5-<‹o.S#Wb$Ø#ÝÊâ¿gt{öª«$~]šõñM˜Ò~=©ëÄÄ|_ÕLÈSE×»=¶\z°‚éÍÿªpe‡#˸æ•(‹êþ¤I>X,>¹k–!tvÏõŒˆ0€jƒu¼T†ŸbœºüíWfB¦ËÎNXB0êTª3½#“Ò²í¼%ÿÒY]¸r;%lÂóùéÆ^rÝ‚:LɆ¸×„ùõÁô”H4ª©vÆ“»ÍwÅà›MFog雲ã ZÏ„ 1˜ù (“­¶2}!¹ëïòúq56sžd -ÕS”Åzo¢É-Ê–¯‘®xg`ùÕ56b]¿¶Ù0-÷9§ä:Э4•/ú*å^X2Ô`”.ªHa|œ¸BgH,h/¾“û®RÍ<ß81ðf¤ØþkÁ{ŸËÛÞÍȧËÙ/[`¼† bYõ^]²­Ù§,€ŒÝ?]ñ[úûªˆ_ Ë2´nnB6+æ`±•L ZA1ùçàÈO–-–r³m)ìxŽ#ª3ã1Na5yK`k1Šoí_¶aÞi­$j(#ªD Œ~%²m©+3!Äû×:š4¡#÷+.Ň·uíèúš'7þ­ÑL2tlª>­ö?ÓÈepžî¸w¬)ÂëÅrï])RÄ9òDXø¿3)>?éSEÛ™§)»œ_l×wfˆá!MµçIZ§¿#áMݾh‰¯Ù[m2Š…¶Í_EŠÏùøy:ÃÐî+“E±MªhF‘¨Pж\6([‹™Ò«úÓHJº#}M”•è˜ôNÄjø‰®Hæ… ˆîÄ­™%°`WjÏsäìË…ýÜܱb-Ö9¨\t¨$ر&<Ç‘‡†gXp>Ûe5È7îç€WPèn÷ÑTÞ<Õt,Å.ã@©£ :ýDªÓŒ²™[9%þÁJî}< :¶¸O`ö$)ÿF9ØR'm=4Ú¸†ÃkÆ…¦3•”âYD —(C}whø{kx„¤G‹Ú<Ì|r‡Oõ3ÏbAl‚ý«R1¢ ”òz…õS¸ïªüõÏÓžŒûn8™Ãq4 á0 Ÿ¨Q¡°ñÁ­¾»âçxÊGú÷kÍd”™¯ˆ±0X–z#) A ÂÝ·¢°a+ Y::8ÂBõïe©Ž+Ë~‰‘ß\u„è‚M—®Ujèç>'¸…Yaïu:©Ô‡„ô -‹ÔÈN¨ÆÈ›ÚM„XÉåxÔʈ•xšê®c€‘˜ç$KÁT@üäÛk? ÎT˜þ‹[ìöÀØ”†©´ý²Û7Ç´c¿ÆäâÛê̈GŒŠÈ9ob»ÊŒ¡˜‚üDò÷à-:=N&”b¬Ö,áämŠJ-)¸‡0&Ù{Þ‹zîoHª¿^ûûqN:zá¹HÏâxFbq‡Ô›–wˆ­)ÔµîNØUOíãõ¿ÊwáõAKŒðÉõñL -ˆ°S‘bð(b¬Ùj›_äá~5BWg<÷7©TÑ_á-75ÓúX{´cE=Gc)| Y­¤h°—ÇùÐVüå‰g¡õaûÇÐvèiUX…DÿM¡m`Ižl½”›oaü %t§ò@Ìšÿ›3„O¦kų™4-šzIÏÀ·‚~½Ç›™'·&>86Ób)& ›xý\góŠN¶Ï“rˆ ¸öñ}ö—›OƒÍ±Êaoï<±Gº¨6DIjܹêDwtO)[\cpöI±v —Öž‹¿å÷w‘PæT'yñæyÑy[€©ŠÑ·UíDb2{x³eNb$ú'Â+X"„–1Ÿú{ˆ=…¢ó×·ž¦Å?Ç€VÝʶ°OºÁ QT«•ëòÞ¾_ÍÃG[tc—Ûzú ¯ pÜw+vx´c-² &ôæXØ^os>–%ê~þ:O¹<0P¼¤'‘ù&Zèç– §/ Ü/_;Ä샎 +{è„Å~~ò`1ïQ¢´¤6¡ç@$&ZÉçÓI›¹*zTHf–§Ì²Êcçvr~Åm}wdË77¸V×ÌÇQêúj›NB íË0É»£NZÎ÷îç+Œö -ú¡ÖMz*xù³Ù™Mœ%˃­ÚUºîCkÐQLn™“:OÆcüTº8з/ ²)¡>(÷ÀÍön÷©sz'­`04I¯ÁDWKÜNèOâý†÷tY$áÀÌ)Ø*L§ ‰ç};Jo[ÞEˆëä Ng²Ž8¸ll¿zd¶Üì˹¸DÍjÝsP´Ðæt¤c~þEûj$fã‡óOùS&ìóÌÇIÖÖÙ}ÉâÙ´î(a_Ñi'QÒS¼w°º”=_”‡´dMÐZÅ£ˆÔ|+£ÞÆ´ÅTÊ29¨ÅœÙ®"ø·¤#.bíâvÙ†ÆVõ/‘ƒIŸáqÍ>#œ÷j¥ûÛJ¼¨p©†ã¢*¾éN#ža"›ËŠ›½Þ ÕC|§‚¥X´#`²|£^Zë Å•›4E2öE ‡u-ý§æÄ*{`€õNÖ”xœ Ÿ -!›Ý RŽ_hJK`*twé½Âð!……܇î[ ‹–4  ÚohëðåŽF(]F< Æ©—G©_ -Äê~¢)cGB‹/U¸sP8®mØÇúÒ¢¶`¶Tø`M»"²€œéê¿ó(uÚ·´s´1~µc9&$†÷œzC×·yá8õkm -ó6-UNy"Œ‹4°™L;ù4±IKpVƒœÀÞ¤ºT ±ØâigÆ%^gÞg¢¹ÃXGÌs§v -å-òý0òe [¿½Uey Z ŠÜƒ‚¢½šý~Îƹ©Íëw·ï ‡rø;)¶loXë[–ˆ;<ªœ‰¦u†¸,‹#ˆ¯ ±Ê4#Æ–LkžE{èä" Þ{WMÅoão~ªJ(â¼þíÈ?ÙíÛqLºdØmM¢1ö?kæQáo•d‰e ùbÓ -mUm‡·Ã—ó»@}[ñ½óþw8u"n‰m´ýºß­>?¦ƒé\Wm ázCFàS©þ|í™1ú¦ eFµÉ£®ùÀ’ö±’©û$-dà¬þÍ}Óì‚'©xY¨ùE¿gâ´¸ÊtÁy®y^8'À³ë²O¡¥=ÁŒlèAJ1ês|ügäÊi”KÀƒÇ§%RzP_BÏ„%Švà}ÌÎì'Qö!‹ÛÈδb¦/"ÜLê°Fn6V¦âØœ9ëp”7ù>ëvâïÚ¯‘Ûºa)ÉÐB¸"ŒÚE-D¯„Nêl£/0´é6ÈG™)¶e½'‡[KzÐ0àGX'õÅ0ÎYàƒmÕÜïƒ1±q÷#Ü`ËEoT©Ç"Dí,4Ë_ ™Pã]‚‡vDL¬)7¯H£·>ÔZ»ÆJÌGåO&Z•¿VôžÞ“,žS½·tFŸ¹ùeúäºÊ9s>?{TÜXgÓ´ öv¦ÜóîH ôñÖÀU·¢ÇŒŠcB¥z©a´vNÒØW:Žx^…Hãh³ìUQG ³)½`‘wúðê•R¦Õ窅!…z=ùø¼HvQæüE.é º‡Äcè³Îí_{t<¹ga›ÜKº­òãwe ÊÔEÊQU‰ ð4Aj¾Œ¡‚Ú—á(yeÁæøD{Á*淋ŠVè>´§=ÂÏËòQº™mcW™³}±ù/Š‚U2­8`öÆ ¦RCrÙ:-XEª¤ö÷.çë%eë1‚&5 ÛáÏÕG¦â¬ÂoªÙŽbª9©MåÕaKl2È°}þˆ‰výhÙCjÄ熰lÖ¼Þ¾B¥)ìW²+¿`,.}‚;§7ð&´y‹‡‘¬›”ËŽÆ•¥õ §IÓ'ËpCy¦¸ûÉúœzä_i½¯—V àøPŒR ”ünòöµIâ -(ÿC–MsÕXAr^Ó17êLÙÌžlõ­$/xš®X;õi¢¥=bøŸ1_mb|L½dò¦Üw'>z²ò‹O¼#Ìÿ(€5¸ÒC¬Tpy½’kô:Fd‚yÛ¶±Þ4ÙÏi#¦ôâ^ÑpdѵˆÂú#¬áæË”CbëÁÃ%1“}`5^'\[v¬j ‰vý¿ÆÒ›Û'5\ë±IN"(Û D\ã 4˜Øa.O/;ç÷g™¥XêÄêÜŠ¡šWOWÈVå黤{ýg›ß¢‘ÕR÷w¶¦ô$Ÿ2Így0iƒCif0kgÓm0qÎS.Gp·Â‹' è§ûŒ”nÔ,=&‚,bœ”ËUƒ­üøèpß.Z®¨È À¼®¢O6àøŠÏtó¾I›¿Å˜ÑdGŒW ;VÞ`š#L†ÑšøòtÄ’Ö‰àŹ|Ì’ûÎëžµ¾H°gˆGEŒ²/l“9—w^e ™A]9|LÕX/öU)­;tT#é³/‹ñ«¨ƒ0\Í!ñO¼É|®Îiæ*¿ªV#”±Þ.g)óøá¬]Ú­Å„‹©(üŠý8zËÞ³e”R|6T…HP£l_›UÔbyv˜{²M6öJxEuÕ5½µlŸ!rl‘ĬïD+«<]á¶Z†«×ÇåmT 'j½‘3~jÇxݸç'3Úµ&ÒE…ˆ.š§.ÿ÷| Êu´Jë*‹Ä6·W, -mCC$³%ɺ¿¾rš³övž]%ØZ™r˜äkЄäªUºN %U+þ÷Š¶[÷þå°GgÍýÉçà¸çaÿ¬Q9®èB€¨¢â&vÚSóK‘\K™ p\n¶ ;÷#c Ì›š¨¡5÷5m"5ƒ[7Û¹æ©ùšHŒ’ýàh®-5‘T²V³d¸8âs³Ìµt~GEìõaD-‘Äë ³:EìÍ/-‹Æ§Œ‚Mˆ{ CaŠnÀîä‘þ‰ýs¾E]íw>³˜&Fn_™g­ ÎÇX¨ -­s3uÇ…u’Õõ ®]Ãý=rY˜NÊåGÔdÞi<Ô+ßoÆ‚’ôó"hßÇàÀ¿sUòrE© Ñ{zØÞkpO‰(b„ær >_e”iqÎÑ ipemë…¦Ôobæa-Ƹ±.Õ=ò’ó”èÐÅã?0Ábxºœ{ö¥]æÁèo‘êËä¯dŸtPÖ¢ ]Þ -½Ä»¹MmÎG“¯ä7ñ“Z4š-W!ׂçØù{Öe–”7ÁRš5\ÀÜQ^jRòR©éLYÐ9)˜ÀUnoꃶ:6Јàn!_¾]‹¨'­B xÒƒÅv{FWÚ„3¡jì¨cn$“@¼y\ D,B@nš¬ôÇÈpiÍèïï°FÙ|w‡4D<=Ãa§w&ª½GNsàã%¿nR>7=–¼J¿ï·>?OúØVÓf -,;.Q39œŸ£K÷Uʃ™/!Œ^¦n›˜x§]Sd¾2LÀŹœêxÊVLÒ •žÅöÍL² M ‚ÌÇõ}õY‡Á¨ù ¦{×Ôÿ„mÆâ Ul!Q‡"ߺÖÉê‡2ß\™ör­h”ôúÚ>™¯­ZŸÁ†åfÊ}Ôæh¾ú A‹¸ "UÂã@‹µÒ ^øZe5O§”=Ž+&qÁÜ—^B—ló¦Cµ%üð`M=0ÜMàvnßI}V×âGèZ2w²}ïïÌs§ð2Š(³Ƹ¿Ñ úªv¢R -j6ïàѲËY[M'㣩ëÓ3ëK)ÎdâˆE~=‰ÓÐâZ1ŠY±SÍçw¿ -à¿(žÃÙÁY>Pºjo¬ÎWï`wÇmDZ%/#KÇXš$8ˆJ¢¹–'R‹5ât~šë–¼oI’öz•Yz b©MªaÜíÒøÊ•Fp‹„÷‡.Ø—îÆ/,|•ÞH7ëäH;O¦Ž9¦üpÜ°Çâ®0äã-ÔtñÓ²6_G®¦'B®§¿×_YÍ*Ëû ±Ü„?Æ€ îdãí;ù¬ã¸Ý´&‹"ñB~<I#¡„‹6ØHxÂv›Üd-3&ƒÑÕx0rpëÓ»—Corý~éYš–Å]bæ¬Ù«Þîs‘Ú‘ŠfÈ)1‘j¾Ú‹8Í4ˆgùÙúµÇw9”BžëÕ%+š'4TU“¦ËÎøDµ°G¤çˆR°ßqsD± uµîçpék3(F•i% ¶lOà¨Ù˜zp~Öu­ 3|#OO˜gàIÙ:t™V&Ñ‚Õ6àﲺKk΂Âø’P’’¤¡ˆèYƒ¾Výì{-s4]¤5Wghú c! - Ã{Q”(õ¦ú`í|ª[]˜’·.YMðÉÆ–™“ƒ]ZÜ•[NgN»Ã‹¨×ê-Tt×n9ÑB{^Ù¤â¡?Á’#]ü–KÝcôƒvÖoÚS)ãPß7cï·Ž -_™v5Ìh­a6ÃŒmäs\mµ1;×Û,¤æ‚pVƒ?Qñ:7i‚ð,yK%Ô‰‚/²Þ4?à'…ÒpV¥ú®”ÊYøÖåw»:/û 0JpaäÒ´øm'v¼ÝŽ[#}é<‚ú$OY°ÒÃ^;W ‹ƒô < -3M©VÞM` €o³z˜ ™Z`¦›E?É÷c¤«?\ejÆö>îÆø°Ü·M• BöºI@;xl¨Sã0¨ ûŸFTWIƒìg#YNßÙð~+\ @O,¨­ ¦ñåiA7Th¡†QüÅö«a¿8ý ¥Ù¨ó³8Œ±g±ÂC…ì/¿õNìññáß$d×.†”Ó‘µ¡DÅ$!Œ˜%eÜ''¶¢ -ïË»6ä½ã¬#Q2Ï EèÈMmaYEÞêÆ´¼F_wKßûLãqq‡ÿeO-âùgk=þIh®.íéÖ9ûr‹ÕÑÅ)­µ–aJ_Ü’ÁæG&Sb÷~ã‡gŽÝoûé ·ÃAAWQLÆ|C¦Ä,hèÓ×Ê›'jý1ÃʱåwôF5ÿ낡ѼfbhœÕ¨V¤eÒoŸZoxLÓô$eàÿD ‡™3]@IâNHËæô-y©‹ñôÈ="²üL^ïçj‚»j:&ŠèenY?º9«ÿ—ÊÿøBÀÂdqur0ƒØ¡ø@@PW'ÈÿOCù_Ú?Î…endstream +/Length 9724 +/Filter /FlateDecode +>> +stream +xÚízU\\kö%‚»înA‚»»;PHî®!x 8 îîîîîÁƒ<$ýý¿ÝÓ·{žæm~Sõp¾o­}ÖÞ{}ûœz) +U 1Kˆ9Pveá`e(ƒÌÝ\4ÌÀŠ,ê@k7À+Èc†LC£ rµþýJH8Í\A°¤™ë+¯iãP2sp²8ØØß ðp¼®Ù¹þ +„8 TAo€*Ðèl¿R’ 7 ØUÃÍÑÑ´Tº@Üœ-€.«×Êþ3+@âèå ²¶qÐk©ë0011ÿ áàçç˜{ýÅ$. k0€öuá´‡8þ‘éUB:¿mùG¬ª•™”%Èõvô6®®ŽllŽVfÀWŒÕÅŠ tecx-T +l)qøCÀùÏ$AÎ@‹×¦¼Øþî›âöùØ +¶ü³%K7G6-0ÈÉ ('ù?Á¯ò¿0k +€‡“Ÿt=-lØþH©éåü“äø6[úù8BVfö.@?ðõ‚ìãbæ¸:»ý|þwâßwÈK…+Àhýz ÿR…VÿØ+™¹:ƒ<ì¬ììö?¾ÿ\½¨%lïõ¯pe3 €MVYQ]K—éï½ÿ3J\ò*ÉÂÁÇ `á|Çó:)¯Šü<\Wü§ùð'ªjúŸ:Ùÿ%)¶‚øÿÑΫµätvyMýŸcÌøw}eˆ+È ÿ×è²ó°¿NÍë…ã¿ŽÔ¿ñÿu°þžCÚÍÞþOWèÿaàÕ€"àGìÍœÿ#ÜÌdïõ_nø{ ðÓÿБs5³Yˆ­íÿiÈEä ´T¹ZØüc\þrÙòÏç¨ +qýñ$X8x8þÆiÚ€,ìÀ@—׳ø“‚-ÿ–R +l±­®¯SiælùOàÚÂÍÙùÕž?èõÞ¿öV ×@O òÊ"ÄB0Ô¶6´ý¡ZŒØƒe’«Wëî·97rŒ=ô7V˜^e»bîÜÛwŸ³$UÇl„+ `•`¡Ã㉥bø<ìøÅ;X°°Ã°`d#‰NYë„”P/駯Øûˆ¢ R¾Kx Ê^P”ÝéÑKL`i„CpHôœTà‰ÉÊò+TŽøñž‚ÏUdíýÕàçG:%Ùmƒ#RPä»géäõQOï±+:°LûÅÑxæÃe]k/͉õJø:'º8ŸlJÛ¬žªGóy乌טòQK6‡ Ñ+íLvþ˜ð‰Å16(ÎñkX„Éßš†+…¨pœº–QÄ´Ôß^î)RêÔ[W,,¨Þ‘õÉ»ãp%n×)iuGYÖǚπñZ¬Õˆv4¹›îµ:®uľõ­«GZýÖ:„<=Ÿ@‡ª˜yÝ—l:GBÎÚOAs½À:rÁUuiw™ª¨,w‘ʽVç±ÌwZ6ç]ºš½žWßÆe ͹„縤h£öÙ8âØYWÑtÔ¸c}ü5æ?°5&Jt”ùËÞ¨—OÉËÛòÁHÌîZ‚pr_‘\OœÅ±„4šß²~òIÝbâí‡y"ûÊ“¬4òŽZ¦¿;‚Àždz™RÑ t[^cíÆ=ðàæ÷Ÿ‘øÜÏ•ä =X}§^ÍóâÓÌ:Ë;}ß %[µ, ýÉЛ>µÞܱ^4AXç%ä#¬wÛ±W:eÅNã¥S¶SÈ“H f÷ÖϦŠKuP ·}.óF!Ö§•"k¯“/ågö«ÉФÁ + ê2³Õ°"Ý ÝkÇÃñJ +¬°PÙÜHyCOÍbñ¶ªß+óN)$Ñd®å]šU$浈—DÚ!΢ê퉆‘´dGGü4Éøp«lУ³LdÒîJ Ò-¹¢TÓÞœl-t=ª²ÃlÌš2iΊÚÞÝÿåOóáQDWX™ ¼ åßSͦ¶ ðå«xÂAÄ¢<ÄQ“IÔ/‚ŸÅe8XW…4XÞO¼ŒiÿÞä]óÓ̇ô+ö`dsaÄÝ´6âÄêÒú6këás‹ƒÉضÇÇ8–²"‹½ö6~r_¢¾;cç˜Oü$µytégÿ¬žñé¼ôˆøy! æ“_;ædx–Vªÿ`©«m%sÝ8Kçïˆ&êîvp§ ïfæZJÛãåªxfÉ°E#ƒb˜&Zazé{_¼ÚH☦τÎ{KÙu¤®€ë™IJSÆÊ=x4ÆŽ: äAºýá£,ñ‹iÃ01bT2l$qm®JþïiÏ`—Õü@;å³v{"•X”IAÖ¼Á~ر*ŠexATöxšÛX'ˆè.m;„E…ÛC·ù¦_ëÔmÆ㱠ݤV¾¨Ñ]V$Ë:\îøCت2™Gƒ»1­– dT4ûp+p˜®s,JÞÆG‹Lúí¢“¨.Ó¸¥-¯¡†“7Ã}‹?ñýˆ²K*Þ@P¿5ðä±Ýçr tWïËßSzy×SìX…»|Û;PRàFá/x˜ìbúðYM¤+#d!&»À¸&æ*I˶ ‘U‘ëQ2ÛañáË5Z#ЛÞöWLAjÔÙ¯é>@“"˜»põ‚Öã;$8¿†²NXæÜG°ìVFPüãï§3‹!ao|n›ôØ\–`Ä9Ù©¦Y"]°Ý1I`¡ØQ²¯ô9WfD$ë%bJ=ÓBM·–Еõ„|}GC¶;%ýkȃ_Â[]Õ¸QJ•)MÓ?¡×(ür ~é9[m;3l }“}Æp%gˤ¿!ríS-Q‡‰<=•]»Å©É¤LˆógψæÌþÍ)j‡Ÿm‹{¢R××ãÑQædÙœNæ<#C=$V㙃gú±rÃÜ+…>ºJäå28´(”ø±ºød•Ø²3/áUFIÏú€.Cw'S»Ռ۠ŽjXPK bæøÃ[HS>õ@‘z¾‡˜„Œ1>ÎYçÑ>ÅÊSÞ³Sh¥£#ʱ¸Ëú;!á· 0/xßydÉPPÜÞ_Àê$…´2¡V]Ò.)„îÅw™é "E2 øNÙ‡cO4 µ[àÖH¡¾ 2^zϾÞ#2%H²æ6 »aZË^à]w¾u¨­ûNåqj•{Þë«+ˆ[—‰UŠ±›7&NÒ|¬)CÃÒå¥o½~—t‚K v¦·àEqŽz,¿u‘ªÜyÛ6» -oÓÄ%š§Óžƒ]ÒzÝþ¦WÕÄUÆ“ßþ¢¥?C§¤Â¨Z*c„¥²7ìCO0;Åtõg 5Ô,Jð`.‹òf [¦zêÛðb–Á>¡1Æšƒç +Яªh 0/Dý-å€ÈŒcæ½]‡KºðÂý!¢½ž¿ ÎÐçê!ù‚nÝÇé½:b7£¨>Ã}fÁ•Ù=Š¤‚xFä(;Ž´xã5‚feTï\y¶+-7O› >â])µïÁÞCö'9ó&ÏrýÎkÄ ¤ƒÏ–Gµ­Ü+?R?®ÇŠ²}t“-KèÉè6œòšPUJ*_]ðñK{7«ùfFÂÈô\ÝBÀ]Mþ!~`o8m­äx3>_.{g‡-Å°â-‹êKT')™90˸|Jxæü?ŒbƒyºZ†—b”ºÖvÕñöS¦Óþ~½ð§P”ÙTG:;F…5Ûa8K¾ÕËúŠ0Ÿ~__l&׫Bo‹xM›ßÏÍ +Å øÓhaeÜ1ºÛôȇ>ì0x;J Û”†Ôáz©ò]É”çQÓ +Ëlå6¹hèÏû©Ü)sýüµéð´ÊçzïüR|Gz”ñEß@«M†!»0µç‘“þ¢Â5Ï;©Ó÷›|3Òáž4!Âð…ßÄo+Õ{w¸Šý\Wá )rtÏŠ“¡÷FŸ¯3]¾ Лù ËŸ’n´3–? ,õŽzíFÞMÎ_6uÑ‘—‰òµRçW¾J +}­ØüN²îé_ßDЄIxúÆfÛ´Âçš‚óX»ÊT¦`à§{cI_‹^²¢$Ž=}‡FŸTÐYô$Ý£TôÔ4= ðf ß뉳àyÎåéìcàÕæ†i€7Ú„W²¬öUëhñ) $e H—7qcM÷=¦Œ¼Z^“¤qs°Y7 ¯gê«‘å„~L´lµ”^èHaÃ+ÏOÅB"jóV‚¬…ÉÛ:K÷ M46ô’Ô”bB ßM”“X¿©*2Â'ԛцdJ䤨£1ˆ¡ñûx!ßãIEöY×{é[²ÚúdŽ6v¨'÷"ê ²'3ÇHØqR“†ÊÝüB ò',ºÄ¸­ZI®¹ÂÃÈ·e”u­>^  ¢3•/ðåãÉÕw¢éªŸ?8´Ç0JÒ²*û´ÛŸ¥‘!HbÿzâÚ·Öì®ÿÍfŽ—Dûµ¶ Aÿxš£UÛ°éu÷QÓ%íÒ縸¥S†3 ¸¶â¦Ç>¦¤70KÿºD$4ô@CjÎA6‡úØÁCÜÅÊ~†×Á6_Ÿï]Òæ$pÓOp†9¦ ŠF1ŽnϤd¡äo Áüñ-¡¶±cæº2V&«-7¸)‰¬på׋oHÄ'Q„ð‡¼È»PÍŽ…»þ®!ÔÊ€Þ;«s+_ñZ8¹ñ{ºJAþY‰`$(OmÆä.™\x•!qƒ"*¶À×à3dBŸ.ŠQ~0‹Oz‚bÌì7ôí’[ê¸Vü/S%.mÏàyþƾg®Ä³.'’K…9›‚ÓöJÈ Âתè!Œ¶}1êý_rç‡Ô岪j”Ϛ˟~‚¤$Ò[ײ%›5¤'ØqŠÇ ¬õt¸ÃQQ‹8˜Îo! +cú»â«Ì;ìãàc B$æàO|‡féã«îèB¹·öÅÓ¶6›$Xu %áIEœŸ·ºÉò%FÅÝd=²g[“'±&áJŸÄ½s ¡Ê6˜®fi#8ûÈ#àÐgeÌqñ ×ÉŸHüÖ¡d´ý^Žë« c4È.FTOi-ãU¨§µÔ¹‘™½Ï?“¤1ÄÕÕ„ëÖW¨ ÙB¨ØècK?*qŽ¼û\‚-÷P™®t¿…ïh?9X^9¬É±m|1æ&®Ê“–JòVF¾]LÜjÍ©üª2˾ ø`}DV*†eê l+ìnä ¥Z„IÀàgjY¥®ƒõÝxé±ÜÜ‚¼½Z¸ÃüÔ¹hbì6`? æô˜*š¦Ï­ït<×kØì6$¸ü7l>÷“åj‹q]a˜Ü ù‹m­Ø~~´¨ïçƳK~øpF¹-ÑË ×YkUDø+•’_ÑgÏÙzÁóþ»-/¡Øw+[¥™ÐIHÓ–Î!$-û„œ²Xb¼§‹@RŒ´¾ûh.ƒ +žP4a€ã¶VØ:!+¤»×¶×î‡ûl ´0j;¥÷oŽâVA[…Îá‰`‘Ú1dËíæ;Õ6áŸïÍ&6ò3ÅŽ Þí·³ÕíëJèþ:g×A6ÉÚ›Ò®œtјûSÓ­&‡£sO1Äõ7d% YIe*sÇ~ö]/ê¬nojÉw«ùèjh~í”®>ŒäXzÖ»Œ¼Q÷R©¬»’¶Å>%ÂHõ#æ­¹ÍcFd¡Q=i€?$P¬ð³V:F[Y“˜­]äk[€ ûzqùHw|×qž&2ß%4ƒüý^T~¥!Ypçh·û +)XOAlþ莻ªÇÁCžòšvšÈÊ—\mKéÂáçÞ7Œƒ;vAʼnš„}¢ûŒ–4Yä-ÅŸ³×{#+Hm ~±s8Ì9µp/¾{Ô.Ï9m«ŸÅ%²2궩xWEGÖg=Ñaœ‡ý‘*þ3ì[ã¼"EÉ<˜÷ðê¥pÉJâ‹Zô¹X¤.«‹fÛk V–séGk´#¸ß=ìk×O+n¨A%¶ ¶b§èôÊÆ;Šü$\Ž°èêÂD˜‰Î¸.Jñâ¬ïFÍ]‘\Jdì?QÞàÒ!—ÇÚó‰ý‹ùëvúžé¹Õ ·A˜É’Z-Ÿ„Ù¤^Ð+ØÓ‹¥õÕ È¬ —/èwŠ_ð4jF6 D=÷= ÜiY ¡¦=—%èû±Çn1Q[Q-µÇ=W¯4Õ2-wCýdä‹û}š“$¾]Á”v'¨ÿÔUÆh¤#ãCåTŒÙgé B#Ï$Åà×îûè^oÍv-Oó ;™a§(#…¤Ób¤Å,J‡rXÙKVd–g»[Cýx¯–6.øf{EkÇ7™»yÚé$ ˆ~ÂÊ%ç©k·­YWÌ‘cåËwP@@6BÇèHt'öqåÈâƒ[®Tþ{7†¨@×V@õî±9¥ú墑-7!¼çì«=pÕ0:Ý/s¼h 1(šïr’»&Çí4D +òÊ¢rÈY*caVøõÈ€ØV¤®M'êÞ1V>?®#n>¿ƒñ—þ«ÉÒ£!SÆ€j–©Nj5J6Dä„oÔ¨µ8廿J¨‡Õ+QiÛz¯éØä-³Ö³Uéh±«û +ÄU¼\4Èòá ÜÞ¯Jý¨»} +ûIøR1\ÏKÌj‚MM ÔÖ[èÛ ã`R°tžLIþÀbÀrgÎˬ!ÔÆ{qÒrÖðú3P†§œôêÓkë±Ñù›Ý #IM1<§²m%2?©Êš’.óE ]EÀ]-»us®(x†Í¥Šm#ðÝ)TÁ‚Ÿâ©©²QE¸uÝàÊ¿IÓ<„­E¿w…Z3×ËçT$Q[&héã$ÿhkVen|Äm§ {ä W R +÷&w?Øú&aÅ/ê?1ê0Öù½úر6é÷&Üþ0†£,Æu;m· uÚä‚úí&º‘ï^C“u"Ëe_(w´#øÕd5J, ;çaÌ3EßÁ,EÕ–¸™zèBeò³ æ:-ÀåøJÜë¥Óbb½¿j‡%Úˆ!í«û0ê®.>h~÷ycLWÜØɱ¢n©.È£sr´nÕVÆöÍZŒˬ‚²ÔÂUŠÀö|¥¿Î¥åÚþ ‹Ç=É7÷N„ V—|¡°ƒw¤¢&닱¿•Èè ñ}¯ö㳂ÌÅïø^ŽOu” Ï™r•‘¿½Lyk¬«P9~gë(ïòZð틆GªDöž;Nþ¬œo™ÍI¥âÉl᧢åЪ!ÔÞ˜ìb‚uh*²Òˆ&úË'cÔns®~Af=çRhÈâ2,š9tX¥Üä]œË1Â&Û'©AX™»ãp …-ζmmˆ¢ðÔýa¨òó=“d£q !³“Nγ߱ý„ta¬ä{La¯FH5¿[Þ{a˜šöǤp=Þ_«lä˜ñ¬#ub +>Íýøee‘þ„1~ž¹Lèdéק‰˜§òUPG;K‰SH9÷µóO9)ÖÃdøì)Só̇”ùdؾh€vå× ?9kèd¢^—Û1ÊÖ¤Gœ¯¯¢Ö —ü2@vùÈ}˜ÞIæ,h~‰:ߺ$HÖìgù@ÃÔîO¹Óp*@û8¼ÏÙ©zF64¡Ësó"î@­,íþždb©d\‰œ=ãhŸ#§ˆ‘øíÍ-”Un`ÌÔg­ñ3“HR\»q=éí­pȸ¤Šø(âög=:À£³¦Ä'ƒ}ÞXºÝ^ýb©¯-øo¸óÁ‘ +ÌÄŠvu +˜ȧ„P겄A• ]fv/‚Í–~H;ô„¾u oRùxoù}‰fí0æóÞÕj[+uñêN†Ã¶¤P!%8¼ÿH|›‘]@^Kl!@^) <8›Ž·n|,ÝyŠâOÉ6MýZîzq´:}1üä$?ÃÃJž<Žñ èix±ÿ«]×»+ é´ UÖzNYTm_ ~É­m.7,Db nuM±ŽÂϺaW! Ó‡gÒx 4*Hzé·<Ì04,%ÿ£ëzŠ¦ˆÕÔg”ó¹f÷é8¶Ñéî)¡¸<‚¤ðöù½ã™·t"ú_9ËÙ؉5|ó»9Ä ×Q§XÍþÔn{2θI™ÕŒg$=A.u‰÷›ÚjÁ†û…浉MO´÷ I~b $tdIî~AáB"Ð9ÍÙü97d'ŠÚ >Šªï7¡1 ¹Q\cHj?רQâX!ó¢KÌó= í Cä üë‡]¢U+(}µÌ}‚önB-ý²ä‡¥­pÖã‚–Ÿ8½5üÕ±]‚bɶ[Ò}ûs~3L±Xw’žrº_o=af—'œ=s‹¸à8Fag£Ð|ýæŸÛ†><¦¥ª˜œ:¨¡Ó”¦ iåSât)Ñ °¢$3ÕnÙþŠÞΖú•·_›GJí¤·Ž\ÑÂ¥T§h¯9´KÕª-ŸÝ²»ñu—©Óe¦IùFÆwòÅ'3½=ÊÿvŠfcuÇ0ŒQHãàšÙ,r6*\ƒP™Â*«Å*…`¹ÈEs} ü4{sâc*‘·äL*Ò¶ù‘Â_dîf*탴uÇ༕Nå£Û¤7‚eYÎ[¬ LÌ‚@Œ“»kæƒE´±dUÐîp¯Cú‡,4ëöt'ÑPi)Rð9]CêwÕªˆ’AtîÅœ“yb³IÇÅ­¾ ]4oýØõ[/ðtœ:áüú¸<öHM° $2OÞåÜ?çf>ØE¨}“„% ÃXiMÊ®iÖÆÐ¥­#o&Éþ÷ú¾„28\ŽÈ •Åüº`²tzþ¥LrÓfê­·-m8ºmîC⡬¶.£×^‡Æï/_˜ó¼soûqýœz³`¸ùÐiNWILä±Ðl;˜ì °õð}‚ßëR­Ó=¡/‰ ±8Eµ7é=;jš‹e§8ý¥ 3&˜eGᨵœ…A&Ü`6ö1Üû3#ï¯ýFö€gØüÑ:M·D´)2 àü¥™uÉ"tt®¸òí +™œzŸŠôÍ‚í ÌN†ÊŒ»*ž;+[åñ­ŸB–{Œ~g+bò¡zü*É =x¯Îc9GØý}]e ìq§ZŸµ`)¡µ-MêìÒ¯x5«9Ù©s‡(‰žObõÝ@wk›«`må¹£x!WOŸ§LÐ[óÔ4"–:ëêô—ƒ[°‘»g10Å«š5íÂssÌv³ïÈÌœ¤ObŽÐW½E´«iÚ^7êµÈA·ã,»ßô͘O”¥ÍœÓï[§9õÓf¶ô9°åÂ#Ÿ×–6l¦G“š˜Þ1ÊÓdQqÆÞË®sÀ¨„JÉøï}ˆ °Ü,€‘;`aÖ5!€bä¯àbÖl§ÍS*Köì„¢Gµ„ î’Ø̯üLXz¨ÈµÌAí!gßÚF÷¤Iè¢MnÞã?µ-§¹éÏʨNm*°ô²èîˆéE1ô+[çD•½Ì‰Ðö|® ”[t¬H‹Nôç‡\Ðë¬Ü»pÝ ‡=glßy#Íæ µ—ÖX×,Ê<¡m$Ýê +ÕÛŸX%`z¼Lõƒ™±î¤Þ1{È‘HÓ#ýEENð=’ôGž»‡.>iîS ®Eò€R‰ÁÞâ–ì–.£aÍIÖÛ^š}²iø/ÕÈ䆪wÅL~4?O¤#V΂öOØ”%';Ãê!“Üd·p²…q!oceZ³sbØàß +Ðú‡ä9¬PjK¢!zóÙ!ñHaŸ´Þãïÿ¼£êOß,?€úVÐz¾’¢Œ¤ñ¸gTW-Š«XÑèƒðN¨PÊ94X}chAc~‡^ÅûI8Y½-°Ji ¾á.˜<®¯ÇIâšo,¦ÙNì¥#ÊͽÊûÊàùk¤lùnýh2³ÒþÝu<Aíâ$FŒþ¦ÏD!þ:ƒêj%FDõŠ‚QúPÀ„´èÖ#מbG¡³°ï\ùe%mËf›‘g'CÕ䦨 Ñ)Ê$‰‡x`A%*›H«¶#Ì'å;…p‘ûÚ9ß/iÔ¤N…ï#‰yàE×Óz˜8ƒÄÛ¼êpXe€N®Ñ †µ§r%ç˜û7¯¼Çé&ï`Foùª’׬ó›}tW™ë',4Ó‘õÊ™‘8‘À`Z*\-šðú[Ü‚JåÕ®{i!Ux„T û•ˆ¼‘‡ômÙ85û)îÛ¼e¢ý¾KµÔÌ;¨žè{ÜÈ¡¾è{´Ñe¼Žò»~!–±l˜×R¡^n`žTG?ÂŽÎCMž—û[©s¬ ;ZWÀá¤ì`±3iSw-iUÉCW©%Lí®GcM¦ÕãÿªzâÊZ•*¨±…¿ +ÚVâ>xj„E‹ŒwêIo³}‚üH—ã +Örú ãkÑnT‚e¿S< ¢x K»«- 1…‹54ËÆa«÷-ÕÜ@ÚUóªîÐsL/}8ÀѶ›Ñl¡ò‰ó9È+ß©O¹È¨qD‹£RKˆ7hëÀûÚë,l³Ž[‹x³#‹³ÆÒ4 +¶ÿÚ®½–ZJS•ñ~´õÓp+S!¨yWC6Æjy.Lä“X5­ ^g˜Â£˜ýÿòƒüÿþŸ°°š9»BÌœí}œ.®ç?þ€‡ü¿8sendstream endobj -1062 0 obj << +1352 0 obj << /Type /Font /Subtype /Type1 -/Encoding 2140 0 R +/Encoding 2705 0 R /FirstChar 2 /LastChar 151 -/Widths 2147 0 R -/BaseFont /SYOHHS+NimbusSanL-Regu -/FontDescriptor 1060 0 R +/Widths 2712 0 R +/BaseFont /HNLRUX+NimbusSanL-Regu +/FontDescriptor 1350 0 R >> endobj -1060 0 obj << +1350 0 obj << /Ascent 712 /CapHeight 712 /Descent -213 -/FontName /SYOHHS+NimbusSanL-Regu +/FontName /HNLRUX+NimbusSanL-Regu /ItalicAngle 0 /StemV 85 /XHeight 523 /FontBBox [-174 -285 1001 953] /Flags 4 -/CharSet (/fi/quoteright/parenleft/parenright/comma/hyphen/period/slash/zero/one/two/three/five/seven/eight/nine/semicolon/A/B/C/D/E/F/H/I/L/N/O/P/R/S/T/U/W/Y/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/quotedblright/endash/emdash) -/FontFile 1061 0 R +/CharSet (/fi/quoteright/parenleft/parenright/comma/hyphen/period/slash/zero/one/two/three/five/seven/eight/nine/semicolon/A/B/C/D/E/F/G/H/I/L/M/N/O/P/R/S/T/U/W/Y/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/quotedblright/endash/emdash) +/FontFile 1351 0 R >> endobj -2147 0 obj -[500 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 222 333 333 0 0 278 333 278 278 556 556 556 556 0 556 0 556 556 556 0 278 0 0 0 0 0 667 667 722 722 667 611 0 722 278 0 0 556 0 722 778 667 0 722 667 611 722 0 944 0 667 0 0 0 0 0 0 222 556 556 500 556 556 278 556 556 222 222 500 222 833 556 556 556 556 333 500 278 556 500 722 500 500 500 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 333 0 556 1000 ] +2712 0 obj +[500 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 222 333 333 0 0 278 333 278 278 556 556 556 556 0 556 0 556 556 556 0 278 0 0 0 0 0 667 667 722 722 667 611 778 722 278 0 0 556 833 722 778 667 0 722 667 611 722 0 944 0 667 0 0 0 0 0 0 222 556 556 500 556 556 278 556 556 222 222 500 222 833 556 556 556 556 333 500 278 556 500 722 500 500 500 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 333 0 556 1000 ] endobj -1036 0 obj << +1310 0 obj << /Length1 1624 -/Length2 8579 +/Length2 9769 /Length3 532 -/Length 9445 -/Filter /FlateDecode ->> -stream -xÚíwePœë–.Npwkîî îNpo Fº¡iÜ‚ \Ü!Á îî4¸CȽï™3uîüš9¿nÝ®ê®ï]ÏZÏÒw}ÕLôÚ¯¸dl¡Ö E(ÎÅÇÍ+лX{¸k@!ê\²Pg[-kg0à Âdb’ƒ€p0"„ƒÄ† [€<ÈÀÏàÃdÈA]}``{8€U_׃ƒóŸ’?*kŸ O–î`{€ùéÁä uuAàOÿcÃW îØA9-mcM%«’¦>@ Á€Îm§Tlê`ÄÄ°ƒÂÎ6Pˆ-øOjîÜO\2î ÀÝd~2yÛ€\ÿ@œWÌìîþô »ìa@ü©p( ±qö°ýÀ“ÜúW@®0蓆ËöD¦ u‡»ÛÀÀ®pÀ“WmyÅ¿ã„;á|»ƒŸ`ÔîIÓjãñ'¥¿°'š'CÜp7ü/kÀìîê ôyòýDæ -ÿ†‡;bÿÏ80=fë rw¢yâþSæ ø/Ù]]}þ²†þ¥õŸ1€áî g;nL>þ'Ÿ6ð'ßö`&ÏŸaQØA|¼Ëm=\ÿy‚`ˆõÏÌ°=´…Bœ}¶ ;LM(üÉ%€õÖeî_“ÿ -þ·4øßÒÞÿ]sÿµGÿåÿoïó¿R+z8;k]žàï%xÚ2P€:àÏžüY4n ÿËèvöùo¬þUÑôw¤ÈþSŸÊ!±j ?7ïßb°»"Ød« †Û8ì€ÎOÕúK®±ÁœÁÐSWÿ*è“/ï¿`z`'ÈŸò ý ¶ÿûS£þŠœÇÀÀ@ÑXã¿Û­ij?Í\ÏÇø?n 5 ¶ÿyøÃ#+ õøq ó¸øED¢‚¼Q¾€ÿÆã_4|ÿ³ß]¶UÙwºHY:Ó@'ÔÏÙ¾¬2·‰pì„òX”àdÆùΨ¯£˜óìlŽèèZ|ø…F3Ö&{vzËüܳ0˜˜ñÆ7Ð&½þ I;~#amÑ÷Cæ”ýÛ–ÞÁ¯ý}ç¨_¶©8rß`0Ix¢à0Ç»åRI™èWøÅ0¾T&À2K‘cXöà ŒñC¤[ÔÉ¿&˜,£u®NKz½A„þßlH‹µc@™ê -qh<ë/=íq|ÜÞ>“f¾WV “Ž]m(;Íe J[<ÃaÃlœùb\¾¡ æúžè×}#-#ÈÉq©¾çeÏ[9Já¼ù¢_¸ØWaøáÖß -ié”ç-ÚX'ÕE1xãÕ^r%LSõ)çœ+眛 Ë -õÞÇÂ[&Zêy#ƒ0Xæ]&òCO#ÅÛ¤ø²¹2Eí úIlºgÌéÝ·akÃÎÇáòû¥Næ ´ÃöÚ™5ÍËÓV¾“/M,-±çDÇZÛ>Wk˜DCÏ7rRIÝŸ’¬ð1È‹diøÚ¿Sü€Ar%çÎ{*“AèÊôŽÙ.… ®mÏ«Í–ÐW®ýkD -ca¥ˆ:ÚŒás#ñ€îÀpolí›ò¾°ÍDŠNsíò2¸‚Ö#Œe -·&üÖ!Bë}àBA¨ÛÀΡXÐm|¢]æpvKºXKõ‹•‚Eí3MâɤáÝìdtÉa~´K_\ â4HÎý**iœ·É\Ìe:ŸHÄ6]«W•}]¿­ÑêS%S´w< Ü‹åîOìkkQ^¸ù‹Kû`ïJí¦¼W&MÕ½%)–›D6Bc<\ë¿ï’+8H„ -uŸ1Í‹K -|TúÁ.øó-x{dœñØZWäû¬eÙ—n¶R^v&ëgD& Ê&>2P&õ£±•_aG*Þëýï°`eNNAU{yßÅi\îÓÇê#‹0xðØï†×c¥•¾\ûõL$ü•ü¦ð·ÒæªØ,ªl'<]ÔLI½à†ž­Ñ¦°¥ú_Ûµtk2aÁŽ§ØÚC~4¶âµm1²¯I+ðí^a ¤Ft(†VP É Ç[è>C×ÿ:_!yà»uµ ÎVfVúôz–ÙÀOX¨{ëµW°{מQcVõª)ÝŠ…?÷dɱ8~EÎHo)3'ï÷*Ò]_™¾ÓÄÔ~Ÿ®vx¥ÞòÊ¡ÀØÕ&˜žØHHyÛbœ6ÅFÝM ÆèD,y5¨˜ ß~2‘{Yî ”±¥¥r¢­ãÉÕ>»8Ÿz“ –R…•RÒõÐò˜ç·ÇoÐÁÀTÊ]ÈÂD9îæìðêàkÎdߨ².pÔáò[ ¥`«Ë„‰ä9“2Cƒ‘i‡“žÆáWö.—6Æ™ÖE(}Ruã̱«˜10Ë _S0-ÏkH“¢JéG³ÂÌV³ßz/gѺÇ;Öö#ejö¨0Øt5¤^yE½mqÝ(X q(Ú2”*n#œ³tWtV¡èžã`Yõ±Á±º l/W¢Ù©kü:e·´\úö†K+=à7éë¥ý7§B´ÌYUÄØŒbTáœü"¡ o–ãú£ùwh rU ‡¾á%y›?qp©V«?e4¯Ue iPŽ—YFüF$Má…­s¥E>œŸ²G»ˆÏIÝ®6‰"t:Jí¿Sy“]Åá·IߠȼhåiÖ'«šÜÝ_Û¯Abí±šŒbuQç“:)õµÕÃR)Xß–j“rJ=Úð†6þÒË+ï«‹ jvð©´OÞ'”¥‰änÑ ›éí’Lp¤Xk²W:=KO$ÛÝó#VÅ­Ý Gèwua[¿ÍL5DIÊiÜ·Bj «½x[$K@"šà­ ’ìeÀ¸„^Y·5o`f^œñ2é…ÎXÐï•rN}þix—PÕÊ WõÀÍê݉ aä{âÕÃÄ¢%F'SÛI-ºàLÉž@«ò­Vê–¹Ö‹y+ƒM"º%ãÁÞ÷d¨Oª<ïË5F¸½‡·¨t'ù :rÕت}O¥nÌåðêsú|I5cd ô<™Çë,©ŽO¡ÏtûgM]O ááÓ÷ƒ™YÌzt/xßõk?ÖH¬¾·ç±SÅånÍT3‹št:°#ž'º -ýL?ë´êpUn¿TöùVnEÁê?Ø×_¾´pãúâ`(ý”b z@¾‡ínüºSw©õÙ,"ÃeçÝ4b‹x™-R†ÁÊÚî™â “”„üKKëšÄ¶´Ÿ­äü”Fõ.Ÿ1´c~¯U¹¯M]p¤)ûIoΰ2$Z`8+B5®Óµ³ÎJ}ô²?ä\ –³[¢›.ü ¤Æ°Yd¶SêZDh»¹áYºœü€~IÒG>\ {áxÊ/õÉ®[ávÅË/¡‡')Ù®oº«;ùqÄuj 4Ö„bùàgÈ•ÝçOñsÆJŠwí^ùÏõ £†þè©ÿj/(xý¬Úñõôó//]ÈÝÅüæOë~Ó×ʶ•àt`e/ûïè ãûcOû) …WU/“Ñ‚¯Í–Þ´Gù­ÙïÜwTîÏW.¼)ð—«{žÿE4%ŽxôÕ×ñO‰Ö¡ìѱüBú®^?² Ò7Ú‡6i–”“´šü»;ÈÂœ{Ô¯6-®dó7 -DŽãlÀŸ_¶—s@“Mú§„ây¬ödæº/ŠP‡}øe(x¿ÔR^¾ŠÎæ -5ËéZôO±N>%¨ˆ¹aâôOZ3)€å}íÖN¤§fQrÍ›d²~©d›Ã«°]µmä_—–õo‡öé´6š·§¯t`0ˆ'¬bXšz˜g­âA;Ìƺ‡:ÄŽ/0´ ³’YÍ“Ó^O¬œ.~èÿé“1 m«ð(¦Ìÿ#~+ÿÄ@è…†–1‡¬üþÖZš‡ÑÏMŽc…#ë,…põ «—½ ãQ›q„~ݶDwRÉ­±­ðç}ˆãêЀlqâÂmƒéN¡òºât»ÉÒy•qÝGŽó©6ƒïXd,7DýiF}/JáP*Z°ýƒ[ïÊñåx´NÞl¾d¯÷ÝêèïM‹Í¼:,ýdÅx#µÅøÇ—ÄæÂч7jèÜÛÓáöâ¡Ï˲¬¸x›·wê¾Â'_=Sz<Ï,NîË!É.öš«çY¢¬-j=-¨¦a”%m].'Û¦œ|ó+êçÞ Û!)Žoh\ð(~r£hc*o±q× q+fõ³ïóäÒå62†™·«ª vVij^×Lb‰—'ä¦ÜÌÖR8ˆ -à–¨ÞÏÙCãr±`Í1º'Þ3©$.GæEHÇçʚʗrhüúŸ·Òb¥éuž!&¨qΉ6öQnªÒ$:ZC}˜i%¹Ê­»ßàÅË]¡;J¤ü¥íÄáÈ¡¥æê?^0ß-±9,ƒÖ?¾oŠ¯*4ë™XÏ¢ÔVúåœó5Ë%`*fÝÓ áõ €¹Jx¬ŸÁ«|ÉÜ-MW¸Æ1–Máù*ȼRé¹!;vúŽËE”¨Km+F´ˆ´zç*ëئ‰å›«ŠÍ5¥êi¼Áa}4ÞU•Õü<4·ˆp2IÝb“I{Ù·¥ÙGL‡<‡¨)L™¼§6<{OÚ‰õJëù‡)=Ž`W Ti+Ô/ëy§Oul3`C¡Zª¬8Íçë)ƒz5f(mNnLe[C~‡HèÝ:«é3oî=vc"¾53b/Ba•Pâž‘Á©gtgºeغîõ`Έê;¶Õ$´T¨z‡Ró™Ú$F2æz__híÜže .#‡9Öžc蛫w¿YøIoÇÑÛ>;V;Íúå¥~$»Ï¨AÒIK(¢Û³@Õ0¦Ô£20¸Ê )$çÔ*í> Lª×5z(Ro,ÙõÝ#ÿ}àQàÉçÙÛy\1°Èöºc.FÚËcuÉÎÎý D­P”0Çj XS;ióé,¶hqPÞQ×I®y² Y%Ó&tÅú­;ôþþ ¹„ÙsQdÐ+-\yª×¹L&¯Ÿc݇)ùÈ69ëzTê|øÚÞo–ÖÕwÙY\9C -¹oú•ÿ™„WÀ ßóÇÓNV]UÅw¥Uf]F}å'Æ ~’Ò›Xœ#Ëçž¾cvB¯W/¤™iÐÂò:Èû°?¥Zï³ÚÜt!r¨±w(P¶¨^á ô Û}3e/¹N \J¡ñ¢ufý\˜‘ãLT(1 „™YÍdãºIé;o¤äú9oÒ>ÒçMªá8rCŒuÁÀ߉DL6¦ëÕŸ¦D¹í[v¿ 8½£ÉICxY'ž%¸)4ãl¤Ã!þ"2J)/E¼4²%º㉜Ɵ1gr P -×¢<Ð;’A m&%`»‹ý,]@QwÚÛ²R×jArÝ;Â9†¤q›~ c<Ÿ;–º¬#v·K÷ñI2`=Ìáä4 H™óÔ~÷ïAÀ–fZrëÆ)8UFžRÓT*¥¸¼ý  -b&c,±í™Ðò´6@ýMãÇlå‚¢Ý+§¤õþŠ´JX)Ò~Ú ®~_òŒ`|µ*ÊOw`à™]ÃtíÓ?³Ý…‰ÎZÖz¾xï¥ÝQøP&_DFáî?¸jÂÎóï¨Ùšø•À„¯çäHËlÅוäÀŸ/¢p«·ýj/ -¿¼I-*-]‚×X![0O²h¾µuí©±°njî¼Ùõˇix6·ÇüvàÁ~ó©O‘Àù‚˜lMT(Ûf™)Ea¡ -«f\‡Ð¦¡$ƒ±È=Ñ3{UvŽyo{VîÏë ù P`üñŒT¶Ve¤âZ­²<§EnÚâ)ÚQû´%¾ ¦¸7ïI¸tƒæ¹H)w)I¿¯r8Ú'‰uŠ‘VäaÊ^äZ¬Øy·ºÉ’ðô`ù³d^z¸)Æ6Â:F´lÙGNŒî;T“Aß<68açÛœ\Í„˜P&-‰*Tù–†‚û9n‰ƒMŠ.Ö _®¾˜ì»[tTç5u|e±ô(z¿‘1­ÄE¤m½9FGyü…Çݲýu %b«º&Ü“k®[“Jf—õvbè,úS0ëò£KvæOìÂT€l,Jc§wyÛezŠJ{ÍG¿+Ö¤²)¹¶Ú¯ã5ßõzÕ~^Ñ™,UËÜíj4¤fÒØÜÔ–Ÿ"^£Î|ÏvDÿpï2®ÀžDrng/ÿ¨F1}ël†±ùÝ/àíÀÈ/þ€%À!yjå—rG?v’ŠÁ÷ão¿1ÎÞVlJq§FÅã®|‰ú^òñ{¾°ì¤&>M†J|)§C'[¸@wÑ„¾»üë’N¨€‘ÇA,‰MÒ[PÊqu RÏëgì N™*>rˆÞÌþs“°Š¶ì×,¹v¸5½âz*¬Çsu€yÂ<·@t%'ºÎ)>þ÷k[1ÞyãçM–i‚Óµ»ùêÛ9ûÙhYéTŠDá]ô-$@auS¡s™ -wñÈ6úà ”mÕé²ÂþYTñ0¶ŠŠn˜ÄVûÄ*ª¾“z<ÓËåoœÈ-ÜÌ€9ð®Éü̸˭ojÊÁª&ÁU/ðޭ목;íNˆ"ç}%éÁ´ä}£‹>òΰLžž4^ùÂí°Ä`üÃ\½[s!ªÝÎLð.ó¦ŠÜlµ ò"±Úu -Ú匓$S¢’ 6CSûT ßé3çDIЩ49VTÑÞê_Eb:ÚÃæšúa,M[a¥1a=“Ûÿ³6]<·1Š\KŒŒjì…¹¯ònð /u Än锊ê&½7Sl x±*#Á ÆxpC‚yC[ >F=ÂT@Dæ©F ¨j`ŒT-Fbj ×t0ÿJ"Ã.c0@mY{PJ 5¤Ì'¶WŠô(æ -w:©ÿrŠ®­|¢©Â¸¦z$:S÷5ýe!Óné³úÇÈ‚®¥kîciqç`“&"Œ»ñ¯[’¿ +Þ^aæ’W~Þ¸‡ï¼¾L¥ [þ¼RB ¶¸¦ÓP?¸O/Kch™iÆìɶ69eý«Æñ0C¯zÚV»\€3ÓF6F’×PK(Â}<….õñG¢7uª–íöx?Q:¢/³«¡ÝUf7ù0ýÖgß´—-hyŽéT¤ÂpÕ äX´Ùð!Gf“$~°Úù‡A—ñÃ0¦é!Áy[—¬Ê™kØtó̸Ã[x-¬Vgûi æ_£,îiH0Ÿ9´>fDâ´¼µ¾éþ…¯P$ÞÏa$ùÁÌ È«×ÅØ¥p*7'ZtÐg;9N{9*Z—ê^‹Ã@jò£ -É]g¤ÌÒìÃ<¥)7‚Ñì¦aìnd0² ã‹ï»¡.{tm)«ÿÚ;ðÅû¥™¢ËÀOû&*‘8$nÎ ¢7ï A -/TÍ®vi6Ð9¸Í>4â|ßï½@G_C )$œôÀÁ¡S霿<+sK…¦–s5KÃóøêÄ寶Pþ}JýHgëeC÷ÁUf2‹ïU ¦(^9g­5Þ’‡®?¯¸ËÎïPrtAFžÕŸþzo…‡“Œ:¾æ$žýf¾ ÙéÝ›S”¦]¾‘õÉŒ·‡¶3­×žÂBR­Ì]þ -诮ñqÂmdàÔ`7nƒ¨RWºÓE[œ–™Ù6‘9¶?`ƒ=p®ç3Lã,oئDLß÷˜¯ÙTýŽ§Ý¯eW‘öîònQÆ—a)ähF%ö¤5ÙÍqXÒÜâDÍPá±S)ô|ÒÞôÔŽUYïÃÛ›ær¬f~0?rén#º«mH¼Ÿú„Âl#¦u¬…85ˆ#FìEeU§ ¼¹Ô_ k<ÿk¦°ÙbA%R7@"ÿÔ÷»Â2aë}ñó± Í„½![/©¬‡DpÙn/Éo ´=ý!"o×Ï¢ðœoâ}Nó’Ïúýk'´$ó ’;ŠTÅã8æWÌuTš+Èó1pT>×v€n -^õ,mÝ>µsªÇÍóQ™“™:…&ÚÞ0Å(ÛHj…`ÌðSòèí$¬=Ý3UÊõú”ûµ̒yæMŸ"¦*lÊKÓã)¯ý¼ð^lØb$vÖˆH 0癥l{< -ø_Ê'Œ.ÌGöª‹é–Q}é•.t(f2‰ûjéŲ¼[Õ -§m#dì^Àz#ÎHc3ŒÕA›Þ@4ýÆaù ÃM¸gGs´+l®ºhXÉ¿N5ÙbHË5toï<Ÿ¶¤UxÑ£(½¶§b^j -Ûó–ÊŠEVÛ*l‘(¯;Ä¢føqOóÊE½WÇçT(ÝkEfAó¼žýÂdù’†¸æ¦n®»Æ8ô¸©%ê XVŸP®Hè¥SûzëÈÑT5JÊ»khOiÅ©Sá[$#þÀ~yÖÓ àŠuq~»ty5ÈßZäë¸îE¡Í ƒ£ç<–õ?ž|¡ÿk7Iä¬óX‚Ö†¯¨Ãw¨JÀÆ!¶vŸ]@ŒÆ „˜ì¦{SL+SªÕT5ìÊnÂI’8˜$ØÛwk:P—zŸm”ñ¢7dTyïÍšVìL~åò0„­(ÕC‘¥H›â{*SniNƒ;о ¸î -rW²tˆjêÏéIœmyhžrñšxÓÍΔ{.2û˜Ö=2£&Gl þhÕuµÈ}«ƒË±GgYúô‚á1*ëlänȹ¹YEÒºOúʼÓ\/QÐ4Çê§ JLn%!ê‡-ÛêÑ–tzŒüâ!rÈ~¶Ç*¥ì”o‘‰šo6õÖÆe›DÈ7äð+÷&³áøÚsŽNvÊ0± -¼õ¥¦Ø[?°qI„Kõ⬟5~•)ž¢7StûŒ•_ÑባûŒÒOLû-ˆè•ÕóåÉú¹@¡dÉE’]_VJDù»ýõW……¿].²dt~ˆ˜ˆ ëM„í[z:ð1¼meãðÎW &If° ânË5èŒqJ ùHçq$?HÒàºN÷œ³ÄtÉÕ¶øhÎ=øi2Ó1\‡>ÆQºO€Iep3ó¡5_€lª§~—å6í×ðnþ4à ;h·M±VH½r4­ÊvV & ¯Ž¼ ml߇K€#×?xÇ”³îL3sÆ™¸Ö‹ô¥{Îcj+;ó÷ˆ™¢à#ÃZIü7£aÛG+ˆñøÝÔ›QEíÀ’¢#­ƒ™)­ìÕ¼`¤øÍíø´) ’J±4ŽL_$/Ö.,ÇÑYéácòwjÖlžvÉ[ÓáþhÉðþð‘æó|[×L.6y¾WLMèJÕ€¯ŒþØ;©>âÏ  ‘Y‰è4‚ïÓ+Å·®‚›m=Ø”°YXÓIp}å°ñ YÙ߉ŽqûN<Ëúæ=´ûÔg·>ÚܼŽq9ºT†¸ÃèGSyçm÷p0ðÞû[  ‡s‰³3 Éî%ø¥/ÝðúµnAi•wÖ,[é5SõˆcÜÕ°Öº×èÏÕÇFÍ,Œ;nòAï-´´€Ä߬ug¬À!ˆ <*’Ïã´ñ—Ü›£D•îÔO/ý-?*¹Ww×%sUc‚ö6a u¤´ƒ·¶ªVq«ù|4F;2¤¬«šßh1Î2éj˜ô÷8æºÚÀ¤¨Ä•½š:q‘— 8roBÎJìÞÉK<<æÓ?6tð4)=Oö¹nÝ úy33ç4ç«"s_ʯrXZœ´¿":¿y€Ø`eóúþèÇi™f*õÀdP[S Ú^D$24³ªSpÙçr«u +¯X£ð\½àá)™—Úùìû.¹ò‰¬vY·S‹È¸w´þÓÄœŸ£ãì/âìœb†Î#aÂ]ôG1ë-ñÒ8;iµ¡ø LÃ,c¥&]#¨£V¥¨wʈտ™f_ŒWi—²]Šã—â¬3—ÄGBßèòQB]Pö½!FUßs³Ó¨ú­™¼‘JÂÀFGí -†Þ[ÕñºòŽABjÙhaLMô\¸©·UÇ2lucJQ¹ô@!5@ç;*>ƒìïâ _\Hñà‹Ea{¢ê’7ÎV[ˆso'Ƈ.–¼{èãrœÇ<˜Ê¢©5û&/gý©~ò†…p´F7Û,‹™éÞ& ƒ–PvZœÆé<ÙX<Ç~ÚñDRx›±Î°mé¿,œÏxIÀBµüïgE/Hý£öÓçVB[1úüû¼×+,(ëÈj‘õ8¶DšÈ1éV%á*>ºÑÌÏ-ÉbW®V§…* ßcoÃÉ«Šx›B¶>GžÀ>­š-QFÜHÑÃâ•°8ð8—ÿTO¼VJ›Jfo!ŠËKÌ4,pB@<ɵŒhÛ*ô¬W¤ˆ¿™Ù³[¯6€œÚ§óªE:§…¼L¤åê•B¼¦aíe®7·víÀe™4U8Žm]èÝÜA±ÁYažr}‰Í#1ã™Ûµ*j”ÿ ÑŒáè+àu–L _#Ƶö»Ìñ˜S}­—qmm(›1öÑà kªuÊ}$ìL„_hH÷,½ÔtÚšw½álœADöâ‹Ctkôq¶ÁîV1)Òö" Ô»gFbØ_ p(xÿ—ÌÿOðÿ3ƒC]€0'ÌÿñG*?endstream +/Length 10632 +/Filter /FlateDecode +>> +stream +xÚíveP\í–.î xÒ¸»;ww4t5Æ5¸Á=×àÜÝ‚»k°>äûî™3uîüš9¿nÝ]Õ»ö»žµž¥ïª¦£ÒÐf“A-ÀrPG;§0@ â`áê¢ +uTa{µ©[ØCÏ´3ƒ@e€0°0@ È€-ÜÜ.!!! :€4ÔÉÓbm0êjé3±°°þSòG`áùäÙÒbí þpÛCÀŽ°gŠÿ±¡6 €Ù€V{0@Z]ÃPQMÀ(¯¦ ;‚ö ×çT,*K°£ ˜ `uØÿ}XBA?©¹°?sI¹€'°%äÙ ìa vú±œÀΗçoÄ`í t„=×@-í]Ax–[Aÿ +ÈÉú¬áðŒ=“i@]`.–Î'àÙ«†ŒÜßqÂl€°?¾] Ï0jõ¬ ‚ZºþIé/ì™æ…!Ž.ØöÇ—‚¸8Ù=Ÿ}?“99Cþ +ÃÕâhýÏXÎ`k 3ÈìâòLóÌý§:ÿÌð_²:9Ù{þe ýKë?c€À\ÀöVì\ÜÏ>-aϾ­!Ž†EÑÑ + +àâü[ruúævþ«@Œf†é9 êhï ­08Ô °g—ÆÿY—Ùÿ}Mþ7´øßÒàK{ÿwÍý×ý—Kü¿½ÏÿJ-çjo¯tx€¿— àyË@*€?{ðgѼsÿ_6@ˆ½çcõ¯Šúà¿#ýCö¯˜" ø\)Gëç–°qq³sþ-†¸ÈA<À ÌÒ`´®Ö_r]GØÙâ~îê_}6âäüLÇbiçø§ü|C`GпÆþܨ¿"çÐЕ1ÒPeùïvë_šÏ3Óñtþ}U(è?xÞ¼z¼Ùø¹lÜ‚A^N€ —ïãñ/®žU0gˆÀ˜“““ ðüþÇ·ÿB#ëh ý™mÐôaÿúŠ¡g°¿¯·ý¹s›œ%+NÄ ›>*à]¹„‘n©w­¸ìà0>¦I‚Ôõ’7¶_„›üë%^ÍœKüÉâWöIñ‘ë¨âx&CêŒm +ä¿àh×ñ€F3>ÒaáÓ®GÀÇíí3IúYbɘ¨•šâÓ,&ÿ$ˆ)66ï7¿ï†%ër¾Ê_îoj_Yüíl§¾v‹w'J‘ñwÛàÎ}¾ÇÁú„l±•÷êµÂœé7ƧøêjܪŸl±Óä½ +™ç +™zçFˆoxDÔŠ +’ÆýŸ ò¸K`º•ü~O3¶Û•Äd2.›ïÈ"oÓª›+sÅ¡9&˜qèLÄä÷,Ä”U´Æ—ÀÃâÂ.©éÔ–ÉâEƒ€"~ j´ xÙ +ÛrɱÐ×_[Ú)±£öô-bݸ= ñÍ —öˆÞXi†šÄʨ}— )Y§(ŽRìº0U²Î<©¨m.[*ÓÖ)EûšÆŽG±W_óâšîÅœ^sÆ•U*âCw-ib|Lñl±œt‚z•ìqz«ç£©•´:lÿ#Xæb¿ÈîmÍ«akÔÊÆ¥is¯Iq8?#33¬YÁ±æ–Ö +U£p¨íùz槗÷7§DË\Ô2éª^ €4¹œ¢Ë0i΃@©”NtiôV øÑ-{î- ^ÒßúCŠQRæ—?S„›P·Öh ÷DUÅ•ôm| m«QR¬Û|Œ¾ÄCún§¯yè…Å>p>7ðÝÀoì#O!ÿë˜V©Ã¥ ÉBMb˹ ëgj„“ñ¹ü·]Ìį?y¿ZìtpKqtŸáçí¨84Îd‹Syþ¾¬Ÿtv­´‰ß®U—^òȧò ²®4-íÌ’ÏŸDáYÜ›wöjt¿Âî}Ä{µóÉŸü^9ƒ›‚'¦Ežbõè>ÝL»âï¹8j¯(¸¿Ò10#·ŸÞy¨”¯_Q˜qÊýªRM­¶#_ì<Ð'Þ:^ìö³¾#ý½¨¡&QZz±ÆÓnš7€ÃyF~÷˜{ +0L_ÅÈ™a攣×w¾js¾ƒ¯kc‰ÓoÌòAoÔH”¾•Ým<ìè·WpÔ Ç>£E/óMæ¨ +¢Ãü)Ä‘‹™”!‚¬QMžZVçü£ÅÙ?f t˯f'+jÉ 2& Ÿí¬1~»3Ù]*¦eæPˆÁà +´(®×áú7¾õu³°XDsÎФ-ßæ ‚ä< ]¤UO_CÑ÷ßC}Þ„©Õ7ã«$³$~©T)*üſתŒ?p3Q©}ÇéÉ“h†Ì ?‡'²½KµƒgòëÎA¸t,´ïG—½Æ2ÕqJv¶"ùÄÓ/$zÀ¨Âo>Óxùå„?æe“`µl˜&eo^äkbMšn«Ä6-ý…ù.Ìúo$KÅž =_Í@Ÿq¿úܳ}ïð¾) î†QZ}GN޾Ȁ"Ÿ× k¾Åš{7&H¢ñ©5ÞbTü®ãÔw6”ˆø×g¬F¼×ØNF´b¸ú ¢L¥p1–Eñ‹ +[=@{TÌÏ à¹ä„á£úVBØW +e?«ïÀï9Ìüï†LßÓ;Rñ÷†yá ZEåÍ´% ¢ ÕÚeªÄ&Ù—dwàšÂ#ºŸ1X*Bè$XË5Qt*Ñ"ŽNÙ²”äÞÆx©º…”éÙ)Ÿà7,5Í<²wážÿð€¿($ò/ öý²ÉG¥bà'úîgµÛŸZ†í4µx BuïFrOŸFw´¡3¶¥Ù^t’ú‰¾ex;óÒI )-϶‹mžzSsE#½ºz‚9¦ý°ÁÛ²¯BœÄÔg ™—¯Oõ«7íwR2ãvp…MqÛÕ–@{ì l%lB—7ñ {¥9rAüÚ‚XfBótf*œ\Õ!16¿îv_˜ù‹]ú¬ÊvÅ£ ZÔdïƒÅJ+fJ‹q삈ù‡Vê?µz³ +©^0?J¹Þ%S0F½¹a[A3ª_NáÒŸ5VÿBÏ~5enjž‡½¸Úºê!ÀeêW¬Í0róš°PJ«»OX\•ؼæ“ýˆëoE[×}œÛßõ¤‰XPUòûrx÷ ‚ñ!G÷‡M˜7öÆ_Û)û(Ô—þ6\”¨îZ×íoËÝ–°Ã¹ÑÎès‘X^T¦K˜I£û-ªv;Œ*î‚¡ÁÁ\^ÇÊàY'½v¹ÓeX&³x¿íÞt,®áÀ"¶¿Õ·r O“‹ÿ´Uct–zÛŸÔœ,:k¢³‚d +þm!u‚±Ý.óû<¥X¸L-åÀ£~Næ;9äWh·¤ý/"Ù+‹bˆJú;ò®Ùf—ùMØÅÆ©ƒ’™Š”µÔ›ãÂYO±"X{6´¸8ÑO YÊd–`+…þµQ¦ÞáÍ–éŒÕae±ÁwmÚÉlSäæøFBîÕÛ‘GšR™Áëxù¯Ÿ<ýö‡é/ûR#¶*w ©"/@€P+JcÞ‹¯_¨L$¿mìS ©—áV瘛hòÈüÀÊ[†;{Øå\I±Ú>k¸ŸÍ6ò®LèWhÊÛ§d¨n%ôÛB%ÎK÷7­8äÇ© )ˆ¹S‘£ª/OjÛœSNÕ[7’•ªq®÷ç„ñ'Æ °88<ÉŽê Æóß>q`™“a Î*($}RÚTžPÐio £·f›oa?ÖxXž“`gôß%î;P»®ùÜ°R>)5Ë5)ÀÚPoX`¢ø`*7…ÛÄ»'´«®5ùÇ+Öúuïno¬ﮟ9`Ó<´»ÐÜëOÌÄpâ’ÞÀæO!&vœÝTéR~býî¤á’ŠWQ|Œ\!EÐ:¸ çB«eV>*EÔOþÂÁs º +µ‚ˆVžÍ¼Jæs=Q‹•]28m*~)„2…ß<òY§ó‘˜ +D츜£/3à¹LÜZ‚(1±»wéµM ÓyKMØjY,XpjuG£äŠ3UMx9½gèOl´zÛ~‰ïß4û/}è´÷tUj»^É0Ô.½¤ÄÍ6fø¨·ÏÇ´ÉöH¯ƒÔ³˜-«Eƒµ™6y]Î(.öˆCŒú› +þbXïýÖî——UçN âô7&#ú³yź)¤µ¤*›= A+Õ/µwªY|§î«Itô^¨œÞýøŠ kc!@Ìâ×Îoé–TÐÂKª¦ÅY&ÉŒåʹÃI +“Z#ω,VÚ(œ”MÕÛ‚apa®šR虶¡#ÖqW3¹©aþHï«Û‹P>koQÙYvÓ}y»´7ˆP%¤o&Ê5ëÉFpJX¿šG™sÈè’ºñÑ Ìã‹AøÖzŽcøáC ô5slì‹vRuÆê=|aOLÙ!ePÇyL­Ÿ< ïíïaàŠ)æ¥:K,…_îãþ+t2†:Šu’&½ïë‰ÚxÀCÒÄüTœîS$°#géDèxúl+ÍãÌÍqä]‡çÏsº÷=5¸Ù³˜–ŸÎÕ{À¥pYqBx;µ Dj/YØ—ý–3¿¯&„¬¥d±ìTâ”qÙ+W{|°[TNôƒñ—SÿP¶§Äh™ïE?ÐC–Êt#½l]gvÊoàôžo=‹ê!^~•óà@Dk¥úiÌ–ê" v%¬Sϧ»–Ñì "…t—ÑzgÖÚ6Ý/ŠÀ¤ÊQ'ìp…*YrE[#.˜ð-îqhÌEÃçŸÔ—j$u´!Ú‹¦0 Ò'tõÍÖ™5ý¹Ý­k‰#ªõ¨p]죗mñ2ýنš&ºÓ†òåܨzD¶›ë8¹à·m­WŽµ´î_Ê[· +Ëc$9h¼ ß~÷¤ÕY,›=–SID!ÇôKu²¼l·»³ëF10Âw ÖV{XÅõn‘¨hÌtñÏ^Ôþ(öG+;¸(:fkŠ ñ…·˜²z$t#³Ï+}åjŒ}×4ýŽSªÅ¸0 ‹–ƒ&œ*åQnÿs 9R̬ëœ?ê(ÂuuuÏ0¯eHr¿i^À&­.`Å:¡Äíy¶*9Âï¼s*q$x°ë®L˜L}ÍÏ3û„ýÆæ—Âo¼–N#Õ¨åc¸ „iÞY·S÷¡#ÕÎt@—aü,ÍÃK‡½îÏKm¡ôl¿Ù¦1…¬VJ_¦s¶s¢*;‘ Y™)ÿÂóÌÄ=%k »¢qëqÓ‡ã~{¢a" Bê'Åbg,®sOG›†nGzÿîæâüR8¹’ð½cÊåëqKS*o¸¿÷**‘ãUïžoy!"¿ýwë%q¢õž'4XËŒ@¦gu6 ÆÛå@ +æ@à§ÃÍ[tW a¦Oc³%r"|”É åoxªn‡8àÅ•Ô6úÞwuÉ^ oG„$®Ðè{9³IÈêÊ£¦9]ÏÛ/FVÊ,‡2§Kv¥mLA†Ü`£ùvÒÞä«ß>ìÌTF”‡OhÏ‹#¬É}D¡j«Ä>ÔwLæEUý•œSm×òm Õ˜_©C=D4É"Û†,QVJ;2IÖ 'ËÆ°jW?EçÆpë«iœŸëÔÊ(ŒlÉ—km?\æ ]«ü+ô»¯òOõRÑÜhImV‚ÜÖvÞžÓJ–¬«i†˜’®ü9~.Åò?AEWðZQ†ú2Šo]’˧Ž¦¯F$PEy¸>¦ëD’à€q’_Ï•o[¤KƒægK+Óq¥õ{MÁŸÚyª¡WÎT°ÞW +ÛÚy—ÚnvI]Íd¤L%úk(““¬Àj@bÙñó0µ§ÕŠ)'ýÇŒ³Rf•±åE*Ýç-å®}€)W ùR Wôœj»•ð±Cÿð81fôêôq®úø×'DÎßÃîÓ.©Â¹U´ûÅKmM™úŒÜÒ¹d¬âyd”„è™Y~¿ôÊ@=/jÉR½è¥ö.5SØGäšl‡e‘ÓŒm +ÈOâÙ~Ù'V«™S0‡xÓ™8C‰œ†d£Çýsûž"¯¸±]¸ê´î>œ³æÐ|ñ‡™ +Jünqèèרô§Ty½šƒÊ¿¥I·Aq—õá‹Z%9?)¥§üŠp¢#^lÌáŒðÖ„„I’³ÑÉ!´ðKˆ«åWü–¾UÇCÛ¹†’º‹×®z*®éhíç&îÝÔˆ¦ÒpXNƒéÁc¾ù."”ôÃmPU›AJÒàäÝ +Uf’å¤ ÏÒê(HvÏÆ-nÂíÌìä`Þ0DEâÌ +ð¥ªT Žºù&¡‰àëvHìÅÎø—â—¨|2#‹ÈûjàÍ­~ v ]_¤sË–¸÷£dLý¶‰¬óªl?@7~ÕìÁf/Ôý]ŒéB¾ˆúT-êS“H¾Zª[Ã,›ìÁD#wÛL­øÍ”PÀ68I…ûs—t5\œB¦Ïq G)fŠ…î ÇÂŒ}”ðª4,m¶Ï]ÍŒš£±éŽ@·Ç"4BËý˜ïÎ÷oŸ¿ˆ9uK…é‚V¨‹Q2dY’㇠•oÐXë\\ÁT7ôéL§ æ“Å=„«ßKì»×…ãåÞB^¼ïñ:e:ºûA¾ºÖˆ…Ø×%YäÜ´évJ÷\«æØYûùJV},6>Þšv½øÈÏi÷°6™’^¸OøM–!kÚ^Ù»V·.—< ÉŽ-± 7ºK|áÑ÷„öc5ef/÷K%è¡NÆ$R^ŸS0qÔ7mÇ]®¸JÍbÃZeÝmµº¼Z}”XÍÛ«±-¨ñËýúz/;ø}…]pTH‘Mn–Í8>à¿ò_9þX°|ù/X£õZMÛër×4}ué]ESsüt)Ô¬ÒË-˶x¹ ì÷•â ßMÿ’)‡¡;OGÊØ'ŒîD0÷R—¥û`]mÒ‡âyuªi~6mÕWîÄ/%pòEdÉÛÑj,™”H¨‘…GÆõyYgÛçkê#cË1ÀÁùæ“ÁøbükV~,´3Î&ð©Ñ+Tž˜IJñû²ÏJñüݤѠûÞeƒÒMÐ-¹v6ÖY#ÅŒ‘[Ž˜7)ïyÔgšèo”èT8ýËy‘D‘éooÙàä»[Bpëímˆ܇44[ÍU Ïw†Çg¥7…¬9æ¼ÜKæ-Šu9;ü·(ÃJ<§°JD†„Oò³ È"ùÝýìÇ]Ú!öfo¯+#ß< +ÒÜîªQè]‹*ðåVäIw8¶ñÂi›M‰œÌ¿$a| ÙòȱV¼ó i×6\…¼“Dýð¹¢\ý£¡J©ÔK•¹¡áXl¥ÝöVƒoÓÞ$âbÌegž#ñò¢ïF’pÌ ¯Úè‰Ñ^rÅxñë‹L6ZŽtjE?L-hú^NÐdžÃÈ”>&É}fýÅö¾ ˆO£arû£¦7Ÿñu£H¯Ÿ7÷# &6…š[w%´Ý€£e„×·—*GU@–p>uh,¶é ß8º§H I]’{ø#Ôî[b\Tç³CíýEÊŒúÍÐ[*Wck Æpâ{g&A ôÁeP×4É¢‰¶š(…·ƒÑ†¦‡vöÉÈ%­9†Ÿdeíû¬ÚÉLawË¡yô©g|ò O,Í %\°©øØ©ô©Þ¬jÌo~Ä¡yo©;b”.™#qÂrÝ” H&÷Ü°8^G(l +¥›S+YÊ;Ūìâ?¬_§IÅ>Ø7!ÒÇÏ£ûQ +aÑF"$²¯Ö­|3ß!i#ÌT<ÆK[tô p;w»Ô.Š[° + £M~Ñg<ÇÿšâNÜ~¬Š$’ýg¼þØþDz.“›¹·hån¸¯ÞL¿Ÿ€!Åo›h1í æ|Ѿì,«²éWlãñRÆ´„š—)Ø=¤Ñ^»â»b¼;» +œ\7±?·-ï¿ý÷¥“ MEo,ÖA„&±}â÷ÂE¥§Þ[:Ö¢•P’º‹qݼ¡©Ù¾u¾1b’0W—¦‡WG&Ù¼2ª¡t7· ,Îĸ—Áw¾Î”…uÑÎŽÕý9f8xºH]*ùY=ŤÔ\">_xÞä¾dB²a×/Ë—œ{íÓ›ã¾p‹Ä#åN³Œ„„×ÙZ¿5ð +‹¢T4ƒ %ŠÑÔfj ÂÅ4L7¹ág¿«“qàïÖÈ@¨DDF‰šO`„®vÓ(…dE^€É0Þ±½ß­O{_õÌ¢„Îú‡Rô¤ê quâat¼ÉXe²Ì¾ÎKä£^´¹î¯é,’Ôªy–„ø<œ§c9\`9[B½‹º‰¬ÍDªc£ø,̅ò=åÃÄ3ª"&‚Œ™ž :XKdÓNBl|ÂX y‘|$F¿¼EcL;×Sü¾g*›EHç8’‰¾óűŸôûNYµ]¿FiS_q³;¾‚AiœôÂÑÅúÈÝÃNÞ‹Üwæ¬J¯@Ï“¡–ËG±M· 3% ÍÀ·°XÄ óv¦18+M“wÉâý÷8K‡ó–ŒÀ:ÉÉ/Œ-y$"£âµ°S]{:‘)EÜYíkNÖþý½5c+›éjþ6Ó×”<ãñ ËK¿ROFbñŸüDMòx_ÅÎœ8µ¦aëþtt—ÄŠ³Ô¿¨ŸŸá¼Ó©ùybŒ5¶È~™5éÜIo>Øúèo}1”ÜÍA£oBV¢OÒîdÁ¸G&þüÃbZh“¡Š9Ì!ñ‹½ô#_7eµµn…–×ÃW•oøÔaç ÝSKþàj?!ÿ²ªugò«êʘ%Gå›5–×’aèöô ßÅÐYᆋ/ª{Á§É‰˜ö7J†äÌr0ÞW @LÂï’âCð'<+BÎ8~¼ÞKiÈ>ÀI +Ä¢ƒ7Ó*e¿§Ô¥Ä‚¦o‚¶n»éPà:m;Zd%«xc¥Nâ™aÔŸ?¥=€ýZuxçY+¤ó^¡Supã}ÏC£Õ,ô\r”xW)<çK qm’E+Ëç‘‘DÂó_ïŸÃñÆ@V7³îÒ³3›”a¤)dÚ?·Ý‰@xäÄÀc”´Ï0̓ºÏó"óâ½û™µrJóòZ˜JÅ›=2Ónñgkù"áz@éóa⵬å½µ?ÝæöP¤!}•-ҾфýG¨ÈVËs­Rñ²aTRïäËâ‚k\Ãb¿U¶.ÁãgößvQ¼h-aó•âœrfAÞ€ÊUÁèDZ$ù('€»¯LM£/hj¸ÒRöâfòg ¶ËŽ§ÝÞ»'ûêºn ³XÍw‡W×6>y~ëF—Æ”§üŽÓúÝ—HÒN•Ûë{Bk}ÒLþo†ô&‰¨¶ßgÎ~Á¼Ù„¨;¥rÁΑ½‚ãi?:±{Êc<ű26ÏÞSˆS¯ÉIy¸z/´Oœ*kYi‰ÙË6lRºQÜqà +8¾÷z³ž“pTÞC»e1—´}FyèAò%Ó¼&Té³ ÌPæsî'éÄÕH]†ÌBøÓõöa"unáQaÝ,«N”:FÝÑû£i'Ñ£1»Ö[¤$ëêj€þFuÙ¡dò–MÏ~Ÿõ½bœ¶¹k½žØMƒGµ*‰ÃG”0õé ™ØЀBBVÅBZ_Âë /y LæBÀkˆß–œ2}Â)<ª2{2nUb^=èΗx¨oDÒš6ž_›ÊXÒÙÜêÚÐ×x¢–ÌnM¢É'¦WÍäŽî$ 9Jœ )o¥ÇH—ð“ q\£ÍÃ/Ïîí3Ê&”ß^ßfn%5zÄêrÌV,qZ½ ¥™ÀöKןÝûˆAüV <³kù6~öœáeË8~y¿òWËBnÜõsnˆyý Ž€V9~ ŸŸÇà¤ëçGîYöÚ Í!÷¹¯sµ’)ñ•ïŽñÑ‚™õüZ>Jƒ"É7õdhNÞ¼@ÖèMK¸ãÑ£×½³]M‰kS 6ÅG‘,¢¸œ# ‡šS½À2¿A0à—‡3èý!SêÁ;¬ü¢¦xr{­ôÓ›Ç=\Ô_¢Ê;bêŽÈçp’®¼Ð™åu¤îè &Ê&¹B‰›‡ÇRIˆN 3ØÃb֨ь¼  ë}—ªm­qòq(væm—IÉùhj C¤9¯)I½W=d(‹ó¢‘ìÏÃvê|ñ)K’ÐJòáýSg +6DÄ[Z°!IÖú­çÙÇ+ÐÖÑІJŸdؽsFÔ£üÙubÙQ3*L+õ4í©·ÄI³t¤%‰pcÔMí{XØlùo,WãÆNË™”!6TyÏR»éKGK±è ×¥RLRÑ•ÙÙÃàâF§WG_œÙÎzð–:9Éx §ÙüÐjò´L³™åß‚!«³6{Ü?âú{ÄÉúÌÕ‰&Ž]bÑØ›Ë+jžÅýr¨gt2fÄêÚ+ÏÞ›í–j_€âY^ +ë1£äª .WÁPxjSÞI#Üʪ֊ çtûuiš!Çî½ÝSo·×íÓ8€+zqõSÈ¡,È!ë*T¶CÌ]ˆX­9v]&8S/¤ê`諺aÄcmHê–ELL.&Í·c_ƒ²ÍçˆSÈ<:~¦¹OÅ;E¥5Íq˜ÙŽà¶?ñv— nŽÓŽQ|oyèNÕïo磞YHºÜÈ÷”L¨·½ÛìC$?Màc¡"ÇN7ÎâbLnÙq: +§¬ì:9§ËY×ûM¹6­È"Ù~ÝßïJ™uz¢ƒÏCz ©aÞÉ!âÚª8µs¨•<Ä× Òð쳯†²Å³XcÄ*3å²›Ëj†Gˆ4£j2Æ÷Q@\}’Tyž¸¢i¼á8t‚ê·ý†ó`gh‡M£ïBD¸ëÙ›0Âp^*•-ºkjÚ·Z»æãÜd¨ ÅüîÇ&n»$q‡˜,[ijK„½½­%¡“îe6eS. âú˜ˆfÄ®ý>e¾î–â ¹¶« ŠØ£>;–¢‚/MòI”¡øi1-ƒ +¯‹3ÿ²]inÁàÞËDÒ>{ÓЈ dx—v³©lò9 ‰N‰+¶¦zöÍñÔ#é)ó\M£[s@Z›ÉR'õRÇ}ËAÕNQ¹IuÒ.8þÌÀˆ‚;a?ú“‡ö8ζÜ8ùx ÐxoAy橵"wðõçÆÛƒã)ï¼àì…ŒÞ Ί@ÌcKÚ_Ù¼Z‚{+ˆ•\£\hr‹v·ñjÉæǸ((%Õn¹ð· V•BòÃ{9y¦gN°œ fµv*Ûï›s**o™^þ(Ú‘r)`lV3°ð‘öTÇãèή hYmš´0”ÚÊ÷8K¯6ù€›§vóÉy“Æ 7D倷»ò§1 \eÌ}¯ø§5ˆòþ[%fvÄÕ'œbÛ©ö¦&©"ò­ƒõ4ìË*Ã5[Dô`1käý¶Õ•Ï ê`•rM<4{áôUC÷­øwݲðãT5cï¨ûët©„U0í ¶»©kµG#G”Ä~}±yôd¹üÄI!ß©¬ÐGÀEîn‡NOí¬PË$‰šÍµÃ‡WgÞú©é!q@¥{ß®ê7ö$¹UÔî¸ò¡Pšè¾Ð›ÍA©a•bg¿fD(s ¥ùv®gZÙZP€=NÕòä9èÕ&çýw…$H›Àì×Eg—ó¹-}>LÁ•Ó¦4üF¸pâX•*À¢„ƒ0¸LM­+ª[‹Àãco®OóbÖŽÓ% Hé.. Ê X;éôN~'R‘`&‹¤­óH–$Ѹ½¤[*¶–›< ZG„‹m8Blà ‚`•‰ +& ùf¾±<£>W†2<퀔ã*õˆ¦¸ïÞºÑbï)£(]|Ͳ7.ÅBêOo_™íí—I>Ĺ=à[väÍ$ø¸ºBÎk[œ y¸;ª$Ô¶VÔ¶¨ì+Qý †$·fø‰AÙu­õ€•ô퇚|ÄS)¬ß©ãb +ÞëÇáØ(>§"´Ô?"¸ÔvÂj“øÓ‹©OïDkº§«wèKêfhÔu­ÐàÕ–®L~vsÜLðw~ùŽø›f÷ÀGY¯y²™)¿ÓbOú©ogɺeÁ]ñ¡—êÅÇêá0 ·H—c<ØÔrZ :ÁÀ]>Ùã‚!ååÅÈؤüð¹‘c›€ù«ð#®QÆÂùOsYŽ\$yÓ&ˆ³±Ò„} ÏK÷ØÈó¢ä(ä&&¶¬SÊŠ¡ÊÛË4öË(d®NÏpT¸ #;®±õæü_>ÿŸàÿ K{0Ðu:Ûaü‘€?endstream endobj -1037 0 obj << +1311 0 obj << /Type /Font /Subtype /Type1 -/Encoding 2140 0 R +/Encoding 2705 0 R /FirstChar 35 /LastChar 122 -/Widths 2148 0 R -/BaseFont /VVVFYL+NimbusMonL-BoldObli -/FontDescriptor 1035 0 R +/Widths 2713 0 R +/BaseFont /PUDZPM+NimbusMonL-BoldObli +/FontDescriptor 1309 0 R >> endobj -1035 0 obj << +1309 0 obj << /Ascent 624 /CapHeight 552 /Descent -126 -/FontName /VVVFYL+NimbusMonL-BoldObli +/FontName /PUDZPM+NimbusMonL-BoldObli /ItalicAngle -12 /StemV 103 /XHeight 439 /FontBBox [-61 -278 840 871] /Flags 4 -/CharSet (/numbersign/hyphen/period/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/r/s/t/u/v/w/x/y/z) -/FontFile 1036 0 R +/CharSet (/numbersign/hyphen/period/slash/A/C/D/I/P/R/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/r/s/t/u/v/w/x/y/z) +/FontFile 1310 0 R >> endobj -2148 0 obj -[600 0 0 0 0 0 0 0 0 0 600 600 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 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 0 600 600 600 600 600 600 600 600 600 ] +2713 0 obj +[600 0 0 0 0 0 0 0 0 0 600 600 600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 600 0 600 600 0 0 0 0 600 0 0 0 0 0 0 600 0 600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 0 600 600 600 600 600 600 600 600 600 ] endobj -1028 0 obj << +1302 0 obj << /Length1 1630 -/Length2 10814 +/Length2 10888 /Length3 532 -/Length 11687 -/Filter /FlateDecode ->> -stream -xÚíteT\ë–-w‚-Ü ®ÁÝ-h h…KáîîÜ¡p'H ¸;—àÜýqÎíîÛã¾þÕÝ¿Þx5Æ®±¿5ךKæÚ5¹Š:³¨©1PÊÎÌÌÆÂÊPÙ;;)ÚÙ*0«Í•­A€7€ ™šZÜhÙÙJü- )@h`g°ñññ!SÄíìÝAæ`†š=##Ó?-¹ŒÝÿy‹t™ÛhÞ^\€Övö6@[ðÅ;P€-€35 ®¬¢#«$  “VÒHmŽFÖç·VL -  ­`fç°þÇ`bgk -ú«5'–7.Q'€ÀÉhz º™íÿ‚˜ö@G“ÓÛ;ä0w4²¿ÍlÙšX;›þUÀ›ÝÌîï‚ìíÞÿ©{#{{k÷¿£íþöú@`' µ 2û[Nð[ns-òÇ¿–EÖÖÌÀÆú»©³ý¿c.@Ç¿D÷×Îпadjgkí0š!T²¿¥Ðý÷TfùßùAâÿÿWäýŸ‰û¯ý§øú=ÿ+µ”³µµ’‘ÍÛüã’¼Ý2vÀ_÷Œµ‘#௻ÆÁø…Ù€¬Ýÿ‹ÀuÔþ£ØãûWXlô6Q[ó7a˜ÙØYXÿa9IÜ€¦* °‰ÀÌÈúmfÛ5lMŽÖ [à›¶õ-ˆ•õ_°Ï +Û¿Dàú´5ý×òßäú»øjjŠZºjŒÿÕ û·§ÊÛ&€?»Ûÿ–FKÑÎô?ñˆ‰Ù¹<™¹ÙÌì<N/›÷‘ño¶žÀŽ 7ÀVVV6ÀÛÿ¿?ÿ<éÿ ¤­‰é_›£6²5}[¶ÿ0ü›8;:¾iü÷÷ÿÖô¿Ÿÿ^{ Ð h‚¼8gg"d™š‘®ÁÏé•øÒÝÉÓl_\ÿ¹0߯ʮÃ75l¯Üð©:˜¥aœÿ¥Å}öÐþy[Žag°Ïš¶ãð$Ø›’¾+ÿý*M+ãNÀǯÅhiGZQž§3 -k°ºÜ¬š;£ªj_!Oð$ã­Žˆ§·ô~”.ù~8T7öè>&)u±¸m˜ PX5‡G4‰û·7´½Cý}çp]ÛDŒÙ±HÔ.°h4‘~ÙDºåžáŒ[ïjwÈbºr¸°ÌN¤î“ƒðÆüSgÊrUm4>_pû´e{eÊóÀ@’ªí!B¾^gYâ¶fˆ^FT{ônRçz[âœ5Zóì3ŠìŒ—*J–># -sÁx§¼*o.á_g}wýœñl^îkÝŠÔ'Ø’(Mô{Ä'’WuçÙ>`·pòdèŸoR[ÌÒö! íë&XôÕFZü¦½ê>ì%Ü}g·û[˽æb6J¸uq ÖDP»}"ßžo«/2åKžxÊ$©ü&Ú6|I²k¢QᲪÖÒß(Fà"A=PÎ2íܘ??ý@²å·‡•Hki–óº‚i¦¢'¦ãfü¯êäœíe'×ijÞ ^ú«úò!,lÌ@Q“àx¹ ªy—3µ€ÖßDáµîÂôÄ©;bi¾©õZä7ôÛf]q?Žlcß?‹}…U´YFVg½\BšÃfÁOAœ¾Ý=ðÑP†>b*˜ª¦ ‰¯írß[îEÍÀo]æ7hÍO#Á]ö aOp£Ñ’ݬyÝGÜéÁK² ´dÝŽ½6[ -Û#Ò¾ç‚u¨Öåºp³àž\¢4hS ©–Eéf< ¢sj`ß®›ÌFpï(üÊæú|k-è=‹ãEâï°ü‹üTvalÝ´X\0X¿Ù¦?˜|ew…­K£KòÉäÃïÚجäÊŠíŒ]Ý: %¢˜~¡¨ç7GÊÎÉÃÄ} .Íâº$ÉvŽÏÊ~{ÞÏ>ÐQµßS°Ââ¡v»Út`{æÙ°¨ï•›( wJÝ$ÒTùœÖ’F™yˆç·é›Öõ¸ÇÐv‰øoµBï:>ï2ýôK-ó»}—®ÒÁ//Ä€fHÓªQÒBÉÈÏâÏñIW]1NúX˜ðCk“L2 Ö¸V2ûØ/‰.®#G`1¼6ü~fÔ R–|Imd¬²ôðh„{üÑš¤‚™Ë»äË´ÿeÓ.ÿ…Kµla°. -‹jm“Ÿ˜=~ͼ”øh0IzÖ¦ú·O%_Ã% óa:¢hšP³ -S¹ÏÉÝÌŸÜü¾ØœQlq¸†=žà~pFÛÝÓ³0Ú=î,ùƒ272ï‘,n&£#:$Š¯JÚ0ˆ/ŠRžåe\ßoeEÄ`µ^×!Üæª-î¶ÿš¼îKÜ¥8ÈT?ß÷£G§Ö‰ƒf}a² nÄN’H”ûkëYwõ¤.<¥‡‰Kµ¢©mëŒy´˜M/a#EEjþ >Q fÀº¢Í.RU¶Í舽ݕ–ôºtó¯Uq¦SÜe«Ù+Ú-åòëhŸÛÞR5ùò` †’Ôg³Ð•ßNf@ÒEAÉD—ÐÖËå^-ùkõqß½¨}cÇ`ª‚h¾_¨óAËŒ‡ŽAPÐúBM<]Ü÷ MD Ñ:F¡u¿\å¼”ÖÑ„Ã`hy!¯ß1'O—©.[°é$¬k½,]sMʇG¡¬3ª&%ìõ¥íw0í1¼¬}ö´($ë‘ÊSBŠ· Žë̳§ª3¾·†DþIG—'Øa¤T¨M§ùƒœ.ã|AÆ6Q5¿3ËÞêŸÕ#¤­ì?@ÝeȾ‰BŽTÜscueûû%Ç‚,3Ôª?’ÌQ\û³ë;eŒŸ†<¸7ç—Ü×)Óyi›ú8Ëk×4$qEÝ:9œeŠîG<æ÷_àˆ/tàz'Nët­ÉxÜ -÷glü2®® O!ÝèCÖ½93ìôÙÆ_*©a …õD¼3»–èâ/ˆ’Ö®¼à–tõÊC¼z]îú¾¢(ñÏ~½ŸM¹ã±ÿ.#à:ônÓJÆê|ošAb%¬Äiªê3 M°úá]@’œïjoj'õÙ{˜D—ÚëF*‹/‡?Éå'Å!\˜ˆeÄ£Ýó5ئ;– ¤ÓÌî[f=O¼ótï«?=ê[("1AŠ“K£IÖOÅ»C¶+·àŠ3 U VkÍqˆWš–tpêþÌ1N«[„©Ë¦”cþpëY7ª|Rù³d<¶øiü7ÑL³¦%Mt1ÓÛ‚˜†ºĶÐÓ!E§ç¸ý$>ó*€€~0i÷ÄXÕÀÃg`ÈsFÃѸZ *%šHò± w),M,Ä~J¹9ç S-ÿc5 É•’w¶Ú#µÑ»ç¢áY¦:‘s‹{hh}ž>76 |Œ¹›U)y×R~L H€Ê좮!DG íM†2¸Ó9ýröþ<2‚Yqñ‚pÉr‡>Ÿ‹YV¡HHààCò˜O}÷x¡æŸm;>¯\>j$Ç9Jv=»7ØŒBW:ÜÚÛ\~ôm]<-h2ŒVòbÒGR&ÓÎjÎ@p°HRþtЉü1Á[ì #®W@S~õÇ’l°ú­á«b'ùÙáÜVS[E ºtz“ÕØ~%Mˆ¼²(51f–L›$°ÿ™Î¤/¨Ü}ù•{°¶&3M€}rÝX6¸ð€/@@t“±µûIñZ -ëŽ,/µs¡*/m¥$±¸§Þ˜¾§Û›§pnBÌHé”S*û0uœd²Â©èyÁ„Sçx"ŽšÓð§ÍïB½þôÁü{Y‹ð"ÂÏ1·¾Ú½IRA®ÙÜà‘=$Aê[ž„ÍŸþ媓D¸“§B1·ø ¼•"Höû÷Åj·Â¡Tˆû\ÑiÀ´G¿åG»xÿtÊí|ú?Ã4fÓmƒŒŠ% 2ôÝLTW¦‹Å&wË…j•¯?CÈÆ6X™-ù» "zQ׶Ó6å[g#Yóñäúd[†’°‘ã‹’È®óÐË" 6Ç”wue# ¬ MË%òG¦ìü) T sbw^˜¯ž«TMZ‰âK_5¤÷ýÈ¿“ÕÌß/ëâ¸|cÐùò{ý†VðÌSÛ¯Ã9rFòâý±6„ëhˆ·u^òö´g?›õ¡çxu) ìEºéµ5B=]× ;¥Â’Ë0¶§s7ÁjèSƒè‰#Jws¬Á¦ôE`"¨€:¾2̯sû6Œ¹cÌy!¤¬èb‘߸¬ÉZæc¼`ãû”mÍ—áM*ÛM&½{Rù³®óL–/ìœËG¬¤Á‰ß/é0™'_D¸ÑîWÛ­¹ð°cQþò¬-a ˜,EY(5JÉ4Nœè¦jEh]?L;x"üùÚ‡5Ï^Å8~AT©n2T³Tœ±¿A¿wÝWINîjK˜z¼Ú{jÈj9c¨(Mll‘_Œ‡Äñ›¿7^2êjNéÊzŠðë? œ™ãâ°bòY- 3cjåaŠ|Œ8í•»è‹p¹•2N¥€¨Z(Ó÷:c½JÈúMÈî¾vN›êè¥û}pÕ¿À kCn-,xŒ‰á¯Y®UÛ” ãç‘O(¥ÙýÎø'ó–CEƒºªëØeŠ ÿ€O¡•ÎýáÜ!ÄÕ³0ŽÿÙ™2"s¬o£w²;ÜëA¦{J(…5 ¡YlYÏšÈÚíi®Óâœûhå5ÄÊótZÉ“MÁ¡}—ágøN¬ cÝ ‘?ÃûÕ/Zy?aáj‹‡kÒ7}€*¨(5ߊßã1¶PhžÀt3íù¥@—I'•ÃB>1•GÚk:[„Pè{Ç$ÇZºô£ n[ý‘|¸aÏž³ ³{ÎÔ(ÂöTo°|кÂ@@%Ö˜·§X „¹=VA3ìB8Mä%dÿÀ·¦Û™~´FK3¨t_èl¿i'pw^ߊ¶÷?­Ö¦ˆ%•áæRaÏ„ápŒ{ÿÀ@´Z=GD'jqÜ7NØ#þjpþ;JxvVÔïÝô°˜ÛHhW ­Ô>oqd"y“¬CrîdÒm‚ÿÓú¶sÔ|I»î5lExYeW[{ßÌU“3¤à0Òp·åÍ…Mœ{áX¿à¤©Ø‰¼ƒaíHݨ*M(„%~çTßõÎ60CÈVî³Yû~©­ƒ?>æaßCX¾ydD`0+ù½ÎÞEŠ‹ÌFD‹ còKó­1zØãÿ Õš+çµP(¹§ 7c«¨ ½õÿž¯ôÓÞ÷²Àya];ço¿©ÿ -ϲiSÛz´­õ…¡I§ `~œm5é—ÀyyB‘Áƒ"[{ÁûqâoÓÐåºïªðRBøœ -;Øw3øGæüõù¤…Þì€E -ªõVÖ>ß"‰Ï“Br{´5ë¼â@u´@a¬Ö“saô| y\qÊýÛþÔ*¾Ï|ffi&Qå -žzÊ6âÄ:gÒ¬?yéM|â(¦‰RÕùr ði­æp2¤ˆp(â 1¤¸£œ¡æ1Rᨅ 59©ðÏ~J{ÖÜñÙôu³Y+ÂJàå)$Müà¹kMˆz,ª.hÚU ñ…1FÑÖÅ*§, /+CÅe+ÅàãïG›},{S&›1ê’™l8ÈÏ›òIø°°€¸¤•·©x€*Ú§wH™^kŽ6ìÔZ$Hq¼Æ!Ü Oý#$*%UˆÜGP õi±}&ÌKá6ºÙÍ(ô@€ØuzZ Ý^ˆà>ªR|­ fö*9 Ÿ}&R°ýgFÝ^å†áÞõ°(|õA~øo,"ÊŠöjes>@vôfK=²ŸßýÄý¥¹£ì“ã§.WòÞNBtÎáÂLå*B±Æ5“¢MÔ®øÙûè¡Cž)øð nßúB¦€×~µ_ƒ8c“Îãš(‚×'ÏÙ¿²6¬iÓкõ°T«¥‰;kÔ4¥ÒªÐÞ™bä® 5˜Ò´íEXŠC†q)6ôfWº‘d0¥àl‚$8ç< -Ì“ ¦Nó”-ü¨(Û–7 .\2Q0¼[ã>ÞÞc¼9&‹+LÄ@¸J°aiÆ—23Äoâ+Åçu%•!·îÐ èä™G—!WùIŽ‰ó¢fÌŒp V[ºÁ);A Ž+Pc¹ÚY¨N7ÓfH¡RÜõªv¸¯Î_ÛüdE…Ð鼦‰ˆzèže.7-„ê½NϨ?iœ¢}U'ÓÁ¦çÿ -Úóž¨e6[x5±IœG·6ünñ>ìlu ¬YØÐâBZ *7VU?Átr T1[¸™w¯ËÖj6Ó”äê#ŒSÔ\D¾y¶¢yÂw” k7ÏC¤Î‹ b‡døé’|7ÝÖè¯:9so³h2ûñ¸î–¾ÈUªû—rl’9å'sÙ°Q@ýBîå6Õ:íkX‹(­ió¼·õUðW¼ÕÂîcŠ˜-¹¤ƒ¾-Nyˆ®:RjQ4KàŒTÇc—ûÜœï¥&)ëdQb¼‘– ˜hïáœ#±»¬žS£`KXÓK5S°]Ħ~ WUðã?É g7ÚX¿~p™ÑðÎu=*•ÝGK;t·Ú›iC¢­Õc‘n6=‡˜ñtÄY9ÉæU¹¿«õ¸² êvæão?32y ÊÂEò^‚iYk»QD}ÔÓp>ÌÔ>¨[ÑeØØÙÎGuncáTçÊÅGP½L`.عjÝVͳ…U16–!]!•PN‘âñ³ª^{[T´^Þ•tBÅ.‘¿˜ç‡n\¾„a ªáàïëðõGn‡ ÜÌÂí?¨‘‘å²cýP'}¿ô51iå0¦Tz4½‹Úç=Á‹º£ë°½„ª&koMæ!ø\ß"g*ãÐu»r £6„ŽÑm­³šÞRAàÐ,H¶ëUõ@=ÒØೞTÄ2–‰ÆŽ÷ã3él~ éÅ»{ º;j•ÜvÓœ:Ý×I“ª]:³Í~ÿòYŒ“o4|l‘E½&$è0¼¾Mi4p˜òÈK]Pào½Ö§Y[5¯…ˆDEì¬h.«POýéµû’%.71&x—Ïèó+xgŒÓ`*”¥n*04üøý±@Ó]ì ײ»«Q½»;(s†'FTkhÃ…û53èÞT?>·:ïðI^Ä&¯ñª¹˜SùÂysð&Ú‚œŸÊ¿–<㈮¹_½<ýrz@go*aÄM½ù Uß¹õÊ&ÑQù™ÉS€AéÝa’S2N—‚ÃÖT¾ÎÁ²Ûä!µVEýn×?ÃDI%q(P{<·ëÑÊÏ1ÉT_§ åíæ8UON„·:°#‰©_R;×|öwˆåoxr¡9ÂÃ8smª¾F¶¦%ÄM‡(è99ÄòîúÄc˜†Å‘¼öJj¬ªÅ2¦<¤®nt [.K©Ã`-›]ì†ý0HýÍþ©.l7ƤSÄBîÆ\+õ;ŽÑ®Bs…ÈþöÕ¦ÙG•..vè»6ˆ_RÙ]¿Åâž¹AÿNh¼ãšc A4Ì×Ùrí¼Ülwƒ ]ÇL`©xNªe–eé;ø»¯çnðœB622ݧ1‡n7ú½+n¶ôHàû:/øå%5†}ÎœÐüÇ*cK[\µ)/0Zõ:Tx ×WÇ`G,96\=k°ß¼0 ô¸z{—Už I[ë‹p†¨`ûq … T¶dp½”z2¶º£H5³SÿæGPýŽÌ.\Œ¸p3àzW‘‡~Qh¥ÞNLè¾\‘YŸnÕ­^o…Œ)Èó”å~vûL·Îò‡*´Ž¦9u#ü=]KÝÅ7:l1ãž(oìÅc'ç1tB¨® ií<‹½n°ÖÚGT¼8 Z-á{#Ý_H7©2!j·´$PˆïBë*ÇÛ¿˜øÀ3¹ø Ûꦶ §Al(,8(ëC=»Òt(Ø‹®=8û~b¶ˆ†Ð¡~á§=\õvÉ' AG+‘¤¯Ûœ’Æ—߆%{R ;Ò毲íS~0²L…r”èã«3qû¹$¸^Ï„Ò4VÔRJ»Ã׶J™~rë/×a«)G²:Vê„ ò ÛªzVm|Ç·ªnZCÆuP½5þjBoËþ•‰{º.u½HÐ8¦ýáÑ»BI¯ïöÁå¼9ö˻ò®ÔŸV9N‡-z(~ÎzÜ”œ¿‡eÌ?‹÷¯¸™Ø?ÎÝS“íHþÀi¹OB*jám<ÕœZ–[’‹và™±lcxf‹hâ&^2$w -ÎÒOVYrX¢ïàwJŒSôm‡¯)&`WfXñï³’Ò‚‰oRâ­‘cƒ'ò­–c^ÎlïŽOF–õ×Ùgäëf>MÅ·+(çÑ£ø½fM•ÝiïJÍ+lÉÎ$›©Øȧi‹ Kº¢»»þYÆa´á+“Ðã)ÕÕ;{¶ -{郎£¼Ã/ô‰ï-˨–ÞëijNg°ÐMë"@þ0ƒ[ ®xžd/mý€p @{ m·bÊ3ö£±™W€¯>š‰øç_ìŒïyž"ÿÜßXvܺ†FŽ• -+›5Æô™6ì{ˆñéŽzÔOBz>1%Α}}mBl*î Èà+’?îÍ6 ±3™þ™^\É;<·ør ø»(YËV¼5,{n½@Ø`2Ÿ<Þ#‡æé6~p/Ø t+—¢44bOT§UŸPʲÁ%Ï™Ý×êmŠ¿¶kš¹ÒÍ»¿^Q6R|Vœ=¡ÒÝ03ÉX­®/Õ¨îmˆÔ-gNGŒT=(k÷m‘mÏòæôB"VžŽ”õhs>ƒ²ß€ ¦|–¼,–¹g,Tà³wÐ Dt:‚vmœ¿[ñ²ìþ‰hï:©AãÓ>ȼK}êPJL¶¦¥;“_ªÞ!Ëѯô¢ßn³1VÕöe¬W¿FèÇHKi(ã%WQŒK>÷K ÜDV¾ˆšƒ(•‡õ-¡•¡¯Ô¼a†¸$E@Q‡¼Â(‹gÏ#'%‹¸\¡íͷ¡P‰Õs÷úëC¶•Rä,wœ©¹äÔº1¶wЕ@®ñút„À—ª|­écho>àW{ÿ»Ì6+(RÝÇ ]\Ä2ÖZ!M; Ly–whÊDDëÊ¿£êDœâŸ€ylÊð–Syûwzcc”S©Ä’QÄÍ&Ó(füaÍ+uà³þ{ýîTÄ3[ÜaÔ -^Á?g½Ç[eœ[T.¸;8Ëñ1S¢ÒŠs¹£ìãíÃ.õy‡¸MnÕ\v¡.Tü©Ä%ñõdaÑÉ•%úh¡æÍ".‰„%{O÷0+íøHæ¢D!‹fäYvç׺X¿R+b-Ý°M&ã\ †Úç¾5 -7³”rÁ©£håIËC3L—ÏÝ| á`õ|,bÂd¨VŸŠFsbðdQãØ*Y„ÒË×Úó2ξäÑø~Ð@HÿtyYÓ%ô@웸xœ×­j)œL‘S b(€hãûÜs ­âMß?j«%ÔpVjÖD²Þ}Ä ož)?·ŽLH{ï"£ñgð>ž¢^¤?¼#™G¶|gF˜5¹ÒoPûæ*Ï›:åC²fn°±\ÜEÞ'µ1[™Ðý-î…ƒ€ª^J€•†h$>rþ]™4Q¶â@/;¸€’ÅJRlºl,HŠœi¢~Æ»ü›ŸïÁeé^v×eatÀ cI~ž¿o=•¦œ÷²U?¦¢)‚QÃ-Ò…{ˆbú'2)Û™”²ÿóe6Å ²›6©U5Ã;ßðþ4(é@ñ㬃´nž­ÂøZáNÐp»‘$!¢ã½e“JŽV-õ¬·xØ«ôz-o¾óá@%³hL 21F+—t"±£ŽÚ1N eá!q…cÉM¬¹J÷AÝ}²m‘”Ðn.~,r%UŸtg€|d4N[¯]rÖUöì!—q4Ì™§M†éýx¼¼°z4ÉÜVzv‚5+=rCMõÂ}@Þrþ‚ó!bàS_ä6ýŸ—µÆw¬‰«+FE€ô¼f‰ðPµNªéö~yÚ½VƒL½Ä«ÅcÈòæqA‘ ‹$‹@BÊñ0oþ<ÓörÖq@‹¼Ìj=ù†Øz­X©Ö»à⣣ÙVæTâYMi£ÒÓK¨×l´—틧¡{¥»¬ëe˜R™ÏJñ­j}Ú§ÝoìU¿ë à{™ä–\©†õ6Ü:ƒ·¬ct5I/« €,¸Eð=÷ Â8i¢+~[‰2ðL~¿%˽ΨEdµÄ3C}®éX…VÇÝ?àëV!CŽä‚à`D2Òé4Û%‘çÖ9¿×õH„)¥ð„ÁúO”P7tt1iU~½&=I¾òèÏF}=шû\XUêÅá[&¹î3=ûŠ†ž2¦8Š¼á"GĘ›À[pClC½ÆXÊÉÍÿQi¶Qk bºmj‹df$Àw =õ´åƒ‡”]·¨¼þÑØŸKƒ©ÄøÄ[¨žúÝðq*ø!y›%Å…øØLÏ?×-+Ù‚õ´RGÒX I†ÿI±`dìÚhZN¹Í"VÛ‡ûô2_®ËâÈ«Rßó!«r -2¯å²vƒêõj:¨¿Q<¯%C/õ±c“I+úI~ŠøwØc`µÝµýƒ§¡þŽ¤ûJâ˜ô ]8 SÆ/¸÷E.ƒa©4Íî¢gb‹òéž7î;‹f"pçìÏðB]u±¿‘ßó‡èãb·4îžiÀ[.þB&Òva­¬7*l?TГ„ræÝÜnàœ`á'r¬Ó¦Ló1&9¿å8ƒÓG§~p…QxcÃÒ=´Z‘ðŽ±Ä5ä‡Ø×n™ù VbY§©àùÏ"§Ñœ}úþZ–§75’¿@-[Ë›œ1=u˜Oÿa"&¦u¶|Êê;ÏõåÅÆŸ'?Hl4ëE\³Üà#ï<Æ— -¹`†\ÿ¥¨ª1¡Õ–£ªø«¤\Å'GË'²RSƒbzûÀ…´ãé‘!©¼?ôdFÕ±EÜ%üÝtk'õð‹äpNA‹Ûº†‘ã«óµýñÙyõ)¶'Þ¸$—( ºI‰fÞê¢*) -£ÖöQðŠ,$ªõ@˜Ôáö%Õóø*(lŒl>9h¼à˜áxJ¹öÅþãn ˆï§šxíWE¦º²Úa2”b÷^+BBF¶-c¬>À‡ ïç ›Ô„üR¸²ý³áìKE±®èÕ'¥Åq5/ÃÊÛËÑ»ï-ï'{+Z‚"Ìô”{9…Öñ›‰ò¥YnY’8ùUú³­^dËÈæõqàÝÝÚJÌ7C)[yðîñïÆ^3>@–cÉã1ùéóRŒ€Í}hH˸À ÒlÛu…ûÎ÷e]“$;eÑFøUo¡â_õ÷[±S}•ùÉ%=4qEãå.\ïÚ4ãòoðá#;íC•ßw®îÊñáq–Ó ’òS„Uóë$׈ÉÌ‚Ëç«0Ã&q¾å¤üPàÄ´ø´€D g+m„• OÑ v÷ù#¹r”üœ¿yÁ(›‚9MÌ ¶1;–/ņ޺úàËÓ=’8s(ÀÐgŽúá„©¨­¦ -NaãLïñ˾œ[{Uy<-Þ€-§Žà@÷ÎG{|Ñâ'ú*&MËDß×°‚ÚKÆí¹W!¡ÏN¤µ‘ÖÅe<Ò}øÖÐÇÞfnÑ»…³µêmºŽ5Y ’8&€ù³js¬†]ea^å(Þ¦14üŒ`pË{B/{ã“ÜŘÊgþ6<ÔÆGE§Iwuy³¯<¡= 7…ýÉ̸¶ä3…}€ÉüR4{Ò^ø<zN‚‚!y™ÃÛíÃáxVRο0,¹V‡}’Op7A7!ÐTÑQP˜ùT™ÜÞl,P½ÙTE™>>™åÝ°^ûþR›„»¸8'n¤-ìJk®²QC - ¦Ô"ZñwOòï™»ÏöP÷ê¨.ÐJî~&Ö>zm^B¦[s°'òYøš×Y­D˜¾ -¨ÿKuß!å"|ÐÙEÆVÌð}†ô¡¿ O'®ÖÎþ€å&-¸ùhì8ö²0ËüÀëèæy€ôõ«`o­$‡Rš´y?…|¨ç>K/µ^¸°«l/J¿í§öÙÄ¿Ñ׶ݶëÒ“<‰âïŒçî*O©ÍTK?5;º(›o³ÇUJN¤P3 -øÍæ6?ÅÖ%X<²˜6˜ü” èýÇÓ·55ιbÏ(L853ïáˆÕë¡›íÐêº/ÂÐ7q‹^¿_5 -r•ŽQ¾¹42"ÒQyܽ…8[E~*ï\ºÊYòÃå«&R½n<NÁŽ¨ÎŒóöÀ8mÈpf0 <«±Ìœ/Fµ{ —·î9ýöÝ„PœÒÄ@cÅÿ4¦; ™«×”¯ü¨K­ À$çdLÎð©»$?ÊCîYÇF¢á‰á&Ø,ØÏ<Ú#@Ë%® ]g‰hƦÌäÒ†F`{&(]ž·/iÇÕÜ\p±"Ëbö>¸M¸  ý¡$úu}ÞÕ*äW˹ÑwçQ -®ŽW_hi+yñ¸âÅ‹…† -ë‰f m…ÚÐJï¬ùÏ¥‹û ´¤ešÌiûFt& ß–³´Ó²ë“´›>Y`™å³{ëéÄ2 û“°dõ>sf gz s‘žI Ï¡¡Æá÷”êK“VeùÞÉÄ;NIN² -ÅêàÒ[xŽø?‹¬ !¼Ž”xí°åJ¦v> +stream +xÚíteT\ë–mpw÷‚àÜÝÝ-@€ +(\ +www4Xp×àNp×à®yœs»ûö¸¯u÷¯7^±kìo͵撹öGC©¦É"nî` +’q°‡°°³² TÀv¦®.ÊöJ, KWUS[0à àF¦¡‘t!`{) $Й¤@f;???2 @ÒÁÑÓliÐkkè2011ÿÓò— ÀÔóß‘·H°¥=€öíÅ dëàh²‡¼Qü·5A Ä +°Û‚’ªjåUdô²*ÚY=Èh Ps}kÅ  6Ù»€ÎÛföæà¿Zsa}ãw.Ž 3ð[Èà äøÄ p9Û]\ÞÞ`€¥3Ðò6ˆlofëjþWov ‡¿ rtvxó°{ÃÞÈÔ\ .fÎ`Gà-«š”Ì?ê„X!åv¿Á‹7Os3׿Zú{£yC!@°½ ò€ü•Ë0»8Ú=ßr¿‘9:ƒÿ.ÃÕloùÏ +˜Î K ³¹-ÈÅåæû¯éü³OÀêèèhëùw´Ãß^ÿQâ²µ`EfçxËiyËm ¶GþðײÈÛ[8ØÙþa7wuüwÌ äü÷€èÿÚ†·"€æö¶žsòÈ[JýOeÖÿ=‘ÿ$þ_øEÞÿ™¸ÿªÑúˆÿ§ßó¿R˸ÚÚªíÞà— àí–q(þºgl΀¿î'WÐÿ´Ûzþÿê¨ úG±ÿÆ÷¯°<ø6q{Ë7aXØ9XÙþa»È€=@æj`ˆ™Àhû6³¿íÚöæ g[°=èMÛ¿ÇúÄÆö/˜–ØÌÆþ/¸ÿìÍÿµü7¹þ.þƒ¢¸’¦š,ÓuÃþí©ö¶ -OGàßÒè*;˜ÿÇá/ €7 ;€…ƒ“ÀËËàcg÷ý/2þMÃþϳ2â ö°±²±±ÞþÿýùçéÓ¿ÐHÛ›9˜ÿµ9š ½ùÛ²ý‡á/ØÌÕÙùMã¿¿ÿ·¦ÿýü÷Úƒ@ 3ä_óf‚!ÖÙ™oy£R=]ì0¡Ž¥õZE…Õþü&Ï5¡¬ 㯭žsGŽ/; +Œ»C]ø¶ti ÓRß÷ Ý…X«´m¼L»AŒJÑ2uc¼Ïf•ÖaõyØtv7GÕ5ŒJžáÉÆÛ8ÏîÞ»àRß:¢û™¥×Åãµc6¼Ãþöåè˜6ùàî–®oxp ¿ó®{‡„)7‰FÐ 6:À)—DT_»Â;’iºv—"®;)ˆmq*ó‚?˜1û5_ÝN[ë’ǯ=×ç³"/LIê}Ä£›k¼¶lBñ«¨¯¾-š|oRkÜó&[Þ&±ÝñreéòDQnßô?ª[K79Ð7/Ù/–_!ýmÛÑŸ ·¥Ê“žHÕ]Çy÷A8­\¼ÙŸ.¶h¬æèú†ô“­Bj£­Öè®{ŽúÈ£÷ öÖt=¿ !æ¢DÚ–¶bO„t8&óïû·ù#¿-L.Ii§¼µ\’îžhRºª® xïNŒ¼LÒ V°Î¼0È'È:”n]ó’¢k+ÏQbÙP2ÿ,ˆè鼕8S“š·³ìâ>mLÃÂÇp]_1Œƒ,Žbš¨ðM›zÁí\#¨m-˜$²¶Ó“S”4cW"Ó?£^—ò–aÇ¢;áû±ÝP<Ö‹„¬²Ý2²&‡øÕÒ<³A–dâôÝÞ¡Ÿ¶*Ô1ó—)‘º°ÄÚnÏýå>ð,üöUaƒîùÂ4ÜU/ÎÏ ÅíºÏCÔ½!¼L0ûBkÎÝØŸfRkSGD:,þaX§}îK+žÉ¥÷ÆíÊa5òb=L§A!ô. ;õ“¹žEFìÎ`­;[aß9\²@§å~Ê3ùű óRIáPE‚»PÊ•!¼ö.líblÃ!3¢µÚøœÔªÊì=ý°:5¢Ä§"/pïgúîéãÄÃ7<Ú_ Ĥ(LF•žR.Ø31s[’\(œ‚®¤'¾t;ßw&YÒM’Žª?ºcmbU‹Š¶*´XÞ/‹ÿ2ä±I €¡y—Öë^‚TûþÒAªHAmfŠ É9ï§Û‘a_Ë®ÀÔa÷r;ôzp=§æ¬@[>`S÷µWøªNt°óäËa7&%êìXÕåÒÎ’Ñ{ î›òwß1 $t®L+í÷âQzŸº4ðm_ÈaêBkzK‡H‚Ï©-M_„÷œp:º¤õ4 1°îNŒYIzÍWƒ‰Ûyì ©÷ù3TÃÛu&ÌÀ„†6Ó¦0¥ÇmŒBw‰éÛQ¯èIR´Së‚òj>ËŧÒ—‚øˆQ—Šæ†ßF™bp5S±7ìuŽ½§±ÔlI*ÖÃ(>Úñ¨$®ßi w­i!œQ4±±¨äÀÌÂ…vU|Ð÷üÇ’Y›¾ wûuNWdtä[KÙm8~=¶iš5¾Íû]SMÖÑj.¾ ˆÁ±üqÉÒõƒÙøyÑ¿Z6k’ÅŸZåzÊIæ ù»:N=•´qo¯õ¹+¥„B™¡dì¡AÙÝÕÏYgOþ†¥tãµN•¶‚.“Ÿ„ŒE¤¥ïmvž÷ç]4Ú}Ò°'~ªRÉfv5cêÙ‰¯Ó‡)ë8jÒès°;C­L‡’~œ‹Ãò%¸ëP"¸ÞUÉì^ª¤6PçÚ'% ðãÔ' Nurp~Q Ø÷}ñƒ:|Š©½lLÇŽH|·—ÜÝþ¶w›æAµù½ ân¹‡T¦:¿ËzÊ( ï!ɯÄú_͆vEÂëÁ|Ž¹Eʯ#«îu€U•ý9å™x¼.­dávÈ!ý:8ò¾€Ù€;pñJ#WT ¢Âª^Ûà'áHðmAFr4”,=gK3M¨Ì(R +ª¦S0†¶5§(ƒç•ÒÃòÙ#ÀÀîœj›Ó=âéÈmoßÐ +¸wÛõeä7ÊüÈ‚Wª¤I„ÜGñaquÂŒ†!q”ŠÂÓúF›ºNÑvw=É€ˆ ø?©þ¤ÝÊCÌõ ýß{?~µCâ¤ÝXœì†q&ç1j;¯ãI¢™Ô§U$´ö2s«Q6·oÛ†±Œ•°ëãä'n¢ªÌ(" iÅ ÚPV Ý£BªÎµqt¸Ö•Ým™Y•d>Ã[¶‰’¿¦ÛV­¸‰õ»ë+WÓP¬Å`,kE}±_Ys™°‘/Îþ’Jre»\áÓZ¸^˜ÐèCcê?SBk@z©É{ %7y44V‚ꪄ֯næíæ¹ßTd&…Ö9ª ¥opøZ^G ƒ¡ëƒDºqÏ’:]¢¾lÅþñKêà†îëÒ 7pR!42eƒI=%yøp¬?ó “yŸåðu]ËÛªˆ¢W¦@)Ñ>4F¢«À‘ºÎôÁö0òzú¬áN RJ‘½ÎwJúì‹ V9ûdõ®DlG"~›§’ö¯·AšnÃŽÍT +ä’Þ›«+;Wœ‹ò,ïV‘äîIº9^Ü¡U½0~˜ðâÝ^ ^ñܤOgn}Â]^¿¡%K(îù˜§½ÉõUÙó˜×òÁîôò#!\ßÄY¾-¯GÑÁ¬]@öõuÉsXú‡° _®l§Oìã¯U40&¢†b¾Ÿ»—è/IRÖ¯}à–ô +Â|úÜ‚îûÓÎPTæŒæÒïy#Eâ݇¡·läl.ö§¥V²!*\æê~ÓP„«D‚Ò”ü×ûS»/æ8?Éôi|nerøóRÜ~PÁEˆYG= Ò¿Ü@ìjpâ¹Á[8ü¿Ú.îþ?øšõ/“š Çͧա æÛ¥ØSXtÇ”ù"QkËy„_ž™rx +îÑâ§Ó/ÆÔ€P +°-¼ÝyתžVý(/}_#™mѱ¦€*¥f~[ópÏ8V†ÉÑ8ï„$gÿ" N:<3Uwñò›ðžÂp6­Ö‚ËI&Rü¬ÜŠÊ“‹pžÓo/8)Ô+~Û Js§\¢­öÊlöí»i{UŸÈ»Ã»4´½ÌM_˜š?Å]FÌ©•A·Ö_\"Óƒ‚’Þ}#FG ïK}g|ÿñÌàë":ŠEù×%ñ’õ.C!+6‹¼R±ˆà!Qê˜_};¼È#Ëö]¿?Ü~d'My*½{·8¿á+ínßû·/ŸuG«ø0¢ß§ÒÍéÌ–àb“'¥ÿî¤ûm>‚ÿ«?‚´Q õÞ([ºÁfMÛÿŠƒ´–?Â…?¬Žžš.Tùô+ª©ãJ¦eUq8jrÜ…Yp?Á ½Y~H…#úò=*Ïqí·Ï™‚T蓦ò¡E‡üA‚⫘Lm=ÏÊ72Ø÷]‹Õ™+eÉ¥½õ¦ ½=¾¼Eó@•3.¹w¹Gãd“•.Å/‹f\OFJ$Qó:ÑâTá…ݨ7BЖ_[E!üóèóªÝŸ$æžË 3D¦¹ã]DØùø#°¢R}’o²ä£K‘„Gâ%þJqI.Ö7Ï_5EÃ%óÅgAÓ^Ö³Þï2üúIk1Ý>Ĥ\V™$ÇÐÓÉL}mþ«Ôì~¹H£ŠêOð0Š1„M6kîwQ}¨ë;™[ŠmsÑ‚Èl…„ +ýò­Ã)8ȉÅ)7è_£Œ·ÆT÷ô壌mMÌœ+¤ +G¦©J¨ç­$î}0ÿx¯R7ë&K.iËP6RÔ.<,ë㺥1~4XÛ¸¥>÷Æ ètž•>¢Â:Ñ#)á>æk[¾»ïÛ'Îåõž¬Ž"¥à P¼Ê!B5ÿi‹ÒÌÒ÷ÀI¯´æ6‰ïíÚK²j?uFéi‰W!Ü’½ NÒ.TEtmúÖF°tŽ¹.†}-¾ü%`úµÙVîC¢p?VúŽÎëÏ-jû-fÃrÅó$î‹Ï„¬\AËÇlä¡NÉWô˜,ñ¡ït5맼À÷3Þµåb쑳¥+•æQ¹¦iÂSý Ý(Ý›Çi'o„ßFýØ ÕLã—$Ušfƒ)ß–J³6öoú«H ©ÝíISO×ûÏM§«ËS¥LLñ~ŸÅZcDòóJTIEsZÏYKÔT&6·)/ÇÃ,±L—,†»‡[Ò»sž£Ž‚gç¹9m˜½FVË",˜Ûx™£Ÿ¢Îúäç/û£ÜîdL3¨JÔ­Tú\±ÿHÉLÈïa…ºfNuöѯ&],rÁEÂÚ1DÚÇŠ +Ÿ`bêTèÖ6çCÅx+Äèô@›þ`ÙvªlÐTw»J·ô+²ùøp4Tâî]” ðâú>êóXÿfßdO¤Ï£\Ï”H:[PC‹Ä²¡-‰­Çó|—ÕÏñÊŸ0ï³iov%§Ž=Æ‘»ñfLu³$ŒX«Dm|BØxz’‘: ÍDï¾T–[&n'îóšZ) ¶L`z˜÷Î(1ܦ—Éc¥œ˜*`ï3Ÿ+F(ò¿gVà/_JcÄh‡ÛÑ|¢Üm:rGæ-Ãì]07‰±?×›­‡¶­0RK4åÀí+—‚`îŽDÕÐLºÎ’ùˆ9>ñ¯ëwe£¯ÓÑ©<Ôº:n;=]7¶cm$Ïjô¨âÉåx¸Õ8>Ãp:'`=2’¬~'¡·:é'î•üc|±#úvN<z꧄ÇHxw+Ì­it2e³¼SjþdÊ]Ràwó£ºö ÔBBBi‡žuexyUw5{GÿÏ«fçH¡ä‘Ë[‹ß›¹ö#±gàe©9H|CaÈ=¨«Ì¨D¥×òjî†æXJ(VrÙúg4€O8%¬i^ÙQ,*æî£%ÅgM¢b%D1dù×M¼ ¾“ëÎWðY)•=¼´`¯¬ ¿ l,TùáèõÅuqC'ïþDï7¼¤O¯·Äštéþ"Ìs¾Á%ÞÌø-".#S„ÚOXõNèWÇl„Ò]8T‹0üPÔ}zZÝ^„ð!¦Jr½fî:5…€c6Z¸ãGvÝ~Õ¦ÉþÍOqøÛÃÂÈ5Bl’÷eÆT5ª–ü€ÜØ­Özä€üÛ W–ÎòÏÎBÝî”}]Äè»vµ}V­&–h Ô0;5#ÙB탟{ˆ>â‚ éñ¯/bú3 13„;6é:®ƒ"|sjü”;“ã´iK—‰Öcˆ­^#kJÚ•üMCG&³ Ú#©Áœ¶}äe-Yò +iÓpn¥ISÖÎ.DŠkÞë‹eªñÔY’ªUÍwUûŠÔÅ+f*Fèuž“}¦ÛŠ„¢d „ë$;Ö ‚öaþr>wr9ÊDÛNý .Þt9J±”¨Ñ¸¯¦,'%PK·¸_OÑB¾h°^ï.ÖdYè1¦S+ïy‹Ô8=Ô®o Yzàƒ+GQKè AÈ>Ó$$½ôÏOòÇW[OV"õ>gç4BÚghFšdzج™}?щZ‹Å?fvÉ è¶&Àߣ®Žp÷ào‹›ºÜH¿B*LÕ5ƒ$O1BœÞ«Y,Þ.8KÖåê ·XèHs÷'(ýB¾}±¡ +{&p–è°ÌO@¤)ˆ +á(ÉÐ'k‚ï¾}ZuqåÙaÕa àuß+•?®Ò ,ç<Ü¢p)Lå¶c§z7ƒÜÇc®{Öß°Uþ­ÝûÁÞ_)Pùîã0Nh_4SÌbÉ- Œ”²:ã%¹îL¯EÑ)ƒªÇ7D.÷{¸>ÈL¾¯“G‰óEZ:|ÇL÷çÓmó’‹XÆ–U®“Ž€ã®$15ó³ºúP€àYqL4·ÉÎö‘Û¬¶o¾ûùp¹ü²D摧Íþl;Ux­!«l‹ùE‰og‚‹qAµ't­×µÃ u+¿@Ç9ÐìOH’÷ÏU„®‰­¶EÜO3—h¶ö‘LÓ†>ÛÎÁ~!ôñ.N}¾BrÕÇ æ’ƒ»ÖcÕ2WTcs¹¤;¬êK´d✺Ïþ6õ¥o=¡H©[ô ËÂð­›Aö&—ààÓ!ÿ@ôN¤ðàíÜÁ£E>&ð»&¡8Ö’QrÊÊQ\¹ìhV7᫦³ûOG)u¶¾oŸ 3pý¿@¼SÙGî;Uc›µaôLëí\ ô¨èP ÖJ‚G!òÝÔ5£Î(Jµ e¢–±Í´w}Ÿ^Êç +ƒÉ/¡¤èïiÔò;ÌóêôÿLšUïÑ[læQÎaœ¦Ñ>ñ³G÷™=}!C‡áóoΤ…ÃTD^ê~÷Yñ5l{ž³×(᳓* ŠŸÏgé­?»ñ\²Àå'Ç…îñµþ@vǸŒ‡¨óÀ9šæ‚Ã?ŸŸ¾èxŠBœZ÷ö´köö†dqÏ‘"$!ˆ íxðÿ"` £þmÍÓK›ë.¿ôe|ê:Ÿ†›%u@éœo('_ +¸=Äõ¹Â¨ìW|ÝóúõyÆ壹Œ O<ã–H¦¾kû»TCT•3SQú˜8EŠ9·[Éi{ªðãá²Çäve=§ûïŸ$)e Ù(ïöyï6bU_>`R¨ÿ™2Qt˜çR?=ÝIêbĉ& ¦yÍèZ÷;Ø%U¼å͇⌌àÊ·«6ŠnËLJ˜S2tqŠç+ÚóKÄ0H ûÓ'­½ª~Ï”aLø˜±ºÙ‰l½,£ ;ˆ$ùubq¹ñÝ8cC¨.b /άKÌJáÖR7£¸§ôŵRì`çzËb“³Z'º½$ éëý€Õ÷ÒÞù¡À.(?ü<Óo' ÂX£¹ +½‚ü\Oãl}çÏ rÉ^Ü ëcërhÁÄ{£ x.;9¹ž³¸#ÛO}+ö H‡Gzøå% Æ®¼ð§AjS2kí;<)Ÿ@ZÍÆ»È`n#çPglvçxž–HhÑo°þ¦¯£mÉ،Ģo­»L£ÇQ“0íñÅùuâ#ø2†Nü®{Q[V¯Àj¿¢»þ?ƒNWô¨?ƒt›á%¦qGGö:¼®*x¼ÃÀÌžÙÍÙ^?£õgf‰•çûúpïîLÂTÅ7^\ý?0[ÅÃèQÄè$†À×}ÝŠIÃP±ªÇdYvgä‰e¦w©Þ$àŒ¢_™ ×¹Žéß™†Ø'DÂ9ËŒ?h2ó¸%¹ß̆Ó6UÖ¾—õ„¯m“±(ò¨øÈþ­ÉæD¥«‘÷§½ºwõ¦$MMó:2ž“ú©‘ƒ=‡3Ït]ÆF±°i\Çã“%N¥ŠaÿÝ£ÛEK¼ôÑ×îŒ6y.G­†(®AM†<ï¹Ö~Êyõ.‹ï—²À.õ8'_e#åBâ[7Q:¿žßämø"mƒbìS ƒŽÆZá 4¨YŒ•{t¿Op¡Æ¨à‹!| ‘õj—/™§ÐLve§eŸ(ú]<Žqž(Á¨ð칄…ÏÀßù¨;ïAJGZ0ý7ùˈ¾†[(-®P+Uìp¤ëñ|\—;ïùÝ27r¤v¨x©t¯½ <¢íæVþ–(ù’]”Û­®ÂãBB²ßâ ïE›Üä ?•ïd +ž¥ ̺”k®ÖPú-F3{^.|àƒM],¿Òck&Ïý"§^{9D_o·äË•ÄgDwŸÇ>B_6õ¦F§zJ­ïf¬E§9åGÆŠ(IK6na mü¹¢äßúta\‘±+O|oÛn™ÔĺàÙ_ $üÔ>­Šäkës±7¡{^´2ÐX úñ©ã³¼€¥=Š&I×}µîäØsU5u¨ÿ’àï"VB”—~²rön‰Ã/A“¯>k]苬’)ŽÄìÂèÌ?vYèäF8ìúš®GFܧŠX$ã‡ÔbÐ¥åž_¤M2`c5ã&ÊÌ%R JÇϘáVqóÒä8Q8¬ÉÓ3·Õ"×ya䱈òòÚ9¹2äÈ6†KuÙÔtiA\d±þáf’wÃAé@To^¼¢*¤Ë€™Rö%̃°£üú‰Gë÷'xGJIÀ´‡P9 uÍ„ÒQÆ"òg…L*+cl4— æ…¬9rv*š0–4Û±Œt¦¾‘ÑÝIÕ:š»”IšWYøûè èNg+Qü¼v-Vê~Ã4"å4}/üÇ—’W'ŽÉŸŒrOá¿<·3Ül6¦//¦«Žw ú–ƒNb©«þÄ2Y4·aG^¢11ýÎgœÅÖ¿£’,„0ˆÜËûîÛ·j˜pÔwS±¨W¨¯¹j¼~OÖÒÜÒh¨Ð÷p I•æ‘¹È{z^½3q½ ä9ƯLh>íïYæÇ(ì$%É †m]"’)_]VfíÁ[á›Æäæ1‰¿òŒ\³.ô1T•]âGö{ˆ¤V.¸/Sïd`´.òUuÚ‹î©>ŒÇ¥÷S?iI®9Ãq-Ý%áÌKõÞÉê(?:LÛ-·R†ÐAáç6=¥šp•3È)®²º/–}Ì?A\ÓžÎxŠ;­ŽZ›hðJ•ò¡žŠÔœjó\áÊ8ORø±ØÞþÚ‰«£%e +M,b?Sœ†è‚-\ ì‰ûdVwÑIôœúá~Ö7ŽÄkeAø€›ÂG9”¬™C:¶œ<_}9TïrTÒ^%M…íŒC,[E +tÓÎ@½*¯g :_‹»o]Ÿ°’cü‰·ÑcM +}­+^ÂÂí¯e‚³é)À+-[‚fß7 j5$‡=á›®bÖ;tZsa¹rz—xž,ÿ °Â,ZAË°z˜wÃV‰”]AVrÉ|RMc:ù~pŽêˆ°Æ¸œÎõb².<„âÓ?øÕMÌlH~6ŽäÓl: Íx²_$j)ÊWA¼ëhEBuµ²¹ù%Gx —iSÅ Ê—Ž²ÅÄ© 2'BæÈ °ç®¦Q 0h< ´ó’ ÿž·§£Q-önµ‚q¡òS‡!»l˜ìÙŽSö£'ºN–³º,ÇTéW¦“ð¸Ç­gÈ‘²Ëê³ä‰#¡,Gd›äô‰ðýl$HÀûa—>7f»‚Z%ýÙS•²Ú@G÷Ø/RÝŠŠ¤`· ê²8f½ó¨ª»üqÄÎdX Gû¤g¹Ë˜ »„_qvw3ƒ9T ÛáÏúmœ”@n¹aOJ‰ …yu†çêfÙ=Õú{ÝÓFÎLfN‹GäÔi"?þÖ}醊ÛUœ—_š›iN„z²ròÃõ3 +uÎÂüÕÏÍ{1T¨—t+jªNìpC4ç@ÖîÅfÙä:)0ýôðtòuwô›§`âèÃJ_Âåfò²¤p¡Éý@ ë¤åcùC¡î—rj¿ÁRµP“ÜüQ[öºC›¨˜2Jí¹~?„.ìpÞ»ÂVXz%˜©­^ŒºÎµ†×þ'R¹ÊxE˜•ú½Æ#´ÂETíö`…TÆ*‘Æ4d¹ ÆÔÊô;é¯QÍ·ìe¿Éŵ§Ú-Œ™–¾~jͶœÅ`k(vï¯ûa¤æ ‰öឆ…ö*„þlØNÙçfr²ÇŠ1³|/0î4ÑÉÇýžjÈ¿>VùEƒ" OáZ¨zßû,q!¿å]3„*Øœì>ÀŽÅ­ˆ‘{+$v¤fx[VÿÁ§ðaXïòÞòÃݸ´îÖæ#¬OÆ fe­Ž¨€Ägs·BÌgtíD·°¦1?éBmbvø¶—9¢¯'2S☟—øø/Ð]Å`œÎækâ$:DKØ$žr°[[/o•‡á‡¦„ô¨ÜëÏ~fwHý¥ÈC¸¯É½ßn +ê÷E6K¿­í‹zv $àg¨¡Ñ8qx!]ü`b6#2•›PÖŠ>)ЦšôʈQІ)C(Õƒ}R~­­‡_¯˜>{š·u9;ƃn¡“íó'\ =…i{,Áe“b««=µÅ¹ÛˆÎÝ6ß®ãÑÜ€AŃšlôϺΛv6Úì 5ÕÍRjå8äò¬Úèpõh. ÒÛþ1«,Sd¢Ïì^5 ö¢ ÚOèˆ „iᔚ8Ž¨á§ˆCî¤M¾»ÙIrúdöÿÃß#58ƒ8øìꯦ‘c‡9<œÔ?Xé(õ£ƒÙFkcˆÊU#´gƒ–ŸA>fâÃ穬-mDñ{nÊ¢,B‘dKÝ*ÞFΑt0¸ß28°ê!Û™h—Ÿ"à}8Bò˜á"¥f]™M<"$‡[ÕënwYÅ—ÛuÌ6ÎG¹óê=¦™¨ˆG(fjwfÐÜÄÃú£Ù_Y×Òm¨õPø²—'MWußÛKjÓ\·EE}‚Sy识cÔPÞc U»¿WÎ…{gÎV©)ûðqBÐPègõ‚ »€‘j´µJ¡!ýÌÇO^â®=ÓôÑF~÷H×¥[ñ²Õ É»yè¦<€]¯©RE›x†{r.¸õSz÷N®rÍcOdùñ6“ôíFƒ ZÅ»µp±êLÛll™ÞÔòÓž¾h¾s,ü×Ã"TqÂÝ^–Oãrç,ÙÅŸ¨ÅEò/*f’”Ž€˜›…#ê–úJ8Š\ÐTH6ÄÄëêVäùã§q_(7QÐNàQK¸7VÓ¯¾«v…!YԫΓ²QŠÚ—>÷m‚«“мNØY©ŽJÉèÀê5—I«^ê‘ËT3Ey+fèÏÛ¥ý¯Ô° €H7Û³k ‡9ùÔá?b& =eÖ–›ÆÓG"ÎkM•å­•ø‚ÚXaI\ßmhû]½“T†·8ŸNÀÝKmpæéðí”?Qã·°U[˜Éä”y­¤®|ïöZíµ§&”A¶ùLðÕ(ãðÎ^X&¿*HðÌ·lØgÔõ"‘‡³oÆÿ ×aáTž'zûû¹®^u?%Àtc ¶èÁÁVuA†|£¸ÅÍ×”6>1Å'¨¥Ô2¼oòg ’o›Ê KâúÂTðÝö3r bBWnêPÑÕƒÕZì)dž¡ÌBT«Í´Añ5¾S5£æ̦¥ÐTU¢¯:Üê‹°¡À†zBnüm`L ô“š!±ÂH¾¤å–+Ž«I¾†ïSªùqS”Ñ&bFœ °–gVÁYòÌÒb‰‰(ôŽÜÄø¦XãÂ]¿ã>€)­—¨°ÇFÓ<äGFÝ«bºD•Š £nw…|œpg¾0ª“•MPü,‚›E˜ž±Y™ü§Û¢bÎl·×Ø‚³èÏl¨¡~æ!È¥ÔS.šÈåwò©‚h€9ƒÔU¨7w¾¤9“Ü‹”‰ór‘¤òá[ÊKâìÜX¯÷ÓÝn\t“Ó~¿ÔlOöü8Å’ëÝBj”Nf{橆uö{!^æ’™Y«‡w댰1Ù$M­,ÑgZÒƒŒÈ&“É‚FS´Ã§·…¥wlü4w ƒ#F.°Ëc’¼uÔi´íòE¿·Y±uÌÑrÂåäÎ3J2ý9}°ÃÒX¬søwéª0ÜwP1®¤Tv=gvM¢Ç6igU›÷* ¸WŽˆ%Ñú¦ó¡VÆÊ`Â/½Ù#»ÏÃâÒß¾!õÈŽb>"Ä*200œ7¬ÏT} èó fT÷¡·MEfº>³¼5qÖ€m®)½—ú~ètL‘×(æ{ŒùCõá¢^m„çÇ'y؈~ +EªÊqÓëTéCòâ¯yÇõ•+«ûv©FZpÇZòU1ì´‚îâD¨4ùÓ£Bªg9Œ¤ÁÆ{¾Púé™S›vÑ$ ‡¾\ñxllË5çÍiéõ$éTlFÚ—}GÈØf<ü È -ü%ë2bh{açògôCÿ£ÜïW{e1¯éF¾'GŠ)Æa.¨³BG=(”ˆüªCÞÛjHk_×iêPtkºé7ïze›¶ý“tå9¬)U1M¯ž6¾¬ 4*k?¦‘<ꮢ±²àN|×P’.n¹||£ÜU+¶3F”MhÆœ ¡¦9Ÿ?hHû›ç—nr Þ-ä0±Å‡ÝÖà’U·¢PA7ÄÜFwæ°'ŽÁìÓÖ‘–º@çPú)B²àFpéœ=ç(®é…àÎÂL„N·Í-þÄYØÒ.ŽF¹ÏîÀ1­ÇN4.ì—{œH¶/ªB¥0¿N­æ%@»&ZëÑ»BhÙœæ¹áí„WèºÑ$Kí[Êit9œßë;*ø¢FÜíƒPk—×xøOyŒüøŠ¼ÂÛ/¯OwÙóp»B"6àl:ˆ›ŠÕ‚U‘eP +Ç^; áµ³†˜¸ÔÕñXðÞŸÀ»b’¨®k€*G/·O3(|ýhÉ›ÐÅØ%§Yæ6ÈËM‘~OŽ¿Æñÿü ½}»—%Kƒï¦|º9W¼ø+[Xìè¤P˸—úòbhê~ƒÐT¥:J‹ìÛÔM,ŠÔšf4énhØ~Ÿûâè1çäí›}“ïÞ®ì”[/0ûË,¹Ø1¤ù…Ž 4E]MIw1Ÿx}ÿØ€®°ý`”dt.¨«]í»¬çŸ÷^²ÎبH¼â(kæOýGɯ¿Q"g‚ÏŸuú·­Añh{fº{iŒv®Ù¦=ò9Û)ÐÔ•#ùîÒé–KTå+§"»dåXïkø’S.ð„›÷]lÿÃòÿ'ø‚ÀÌt†8ØmÿZFÐGendstream endobj -1029 0 obj << +1303 0 obj << /Type /Font /Subtype /Type1 -/Encoding 2140 0 R +/Encoding 2705 0 R /FirstChar 34 /LastChar 122 -/Widths 2149 0 R -/BaseFont /RRMWZR+NimbusMonL-ReguObli -/FontDescriptor 1027 0 R +/Widths 2714 0 R +/BaseFont /KALSPG+NimbusMonL-ReguObli +/FontDescriptor 1301 0 R >> endobj -1027 0 obj << +1301 0 obj << /Ascent 625 /CapHeight 557 /Descent -147 -/FontName /RRMWZR+NimbusMonL-ReguObli +/FontName /KALSPG+NimbusMonL-ReguObli /ItalicAngle -12 /StemV 43 /XHeight 426 /FontBBox [-61 -237 774 811] /Flags 4 -/CharSet (/quotedbl/numbersign/parenleft/parenright/plus/hyphen/period/four/six/colon/B/C/D/F/I/N/O/R/T/bracketleft/bracketright/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z) -/FontFile 1028 0 R +/CharSet (/quotedbl/numbersign/parenleft/parenright/plus/hyphen/period/slash/four/six/colon/B/C/D/F/I/N/O/R/T/bracketleft/bracketright/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z) +/FontFile 1302 0 R >> endobj -2149 0 obj -[600 600 0 0 0 0 600 600 0 600 0 600 600 0 0 0 0 0 600 0 600 0 0 0 600 0 0 0 0 0 0 0 600 600 600 0 600 0 0 600 0 0 0 0 600 600 0 0 600 0 600 0 0 0 0 0 0 600 0 600 0 0 0 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 ] +2714 0 obj +[600 600 0 0 0 0 600 600 0 600 0 600 600 600 0 0 0 0 600 0 600 0 0 0 600 0 0 0 0 0 0 0 600 600 600 0 600 0 0 600 0 0 0 0 600 600 0 0 600 0 600 0 0 0 0 0 0 600 0 600 0 0 0 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 ] endobj -952 0 obj << +1227 0 obj << /Length1 1606 -/Length2 17112 +/Length2 17262 /Length3 532 -/Length 18022 -/Filter /FlateDecode ->> -stream -xÚ¬µct¦ÝÖ%ÛvîضY1+¶mÛ¶Y±mÛIŶm[õÕsNw¿=Î׿ºß×מ síµÉˆ”è„Œí MÄìlé˜è¹r6†.N²v¶2tÂvÖÆ€¿J622Gg ;[Qgn€š‰1@ÔÄÀÌ `âââ‚!ˆØÙ{8Z˜™;(U~ªQÑÐÐþ—怡Çÿ´ü=édaf ÿûãjbmgocbëüâÿú ’‰ ÀÙÜ`jam‘WДPŠË©ÄMlM ¬ -.†ÖF #['*€©#ÀúßÀÈÎÖØâŸÒœèÿb 9 Nö&F™¸™Øÿc¢Ø›8ÚX89ýýX8Ì lÿöÀÙ`akdíbüOõ¦vÿJÈÞÑÍ_Û_0;'g'#G {gÀߨ -¢bÿÎÓÙÜÀùŸØNÍ;Ó¿žÆvF.ÿ”ô/Û_˜¿Vg ['€³‰»ó?± MÆNöÖcÿ³w´øW.N¶fÿ•-ÀÑÄÌÀÑØÚÄÉé/Ì_ìºó_uþ·ê ìí­=þuÚî_^ÿ+ g'kSz&æ¿1œÿÆ6³°…aøgP$mMíLŒÿÖ»ØÿO›«‰ã¿DùÏÌPýMÂÀØÎÖÚ`lb -à gçü7$€òÿŽeúÿ>’ÿ(þo!ø¿…Þÿ7rÿ“£ÿíÿ¿Þçÿ„s±¶–3°ù;ÿ^0€¿Æ øgÇüÿ| l,¬=þÞÿé¨fòï ÿO ’ÎÛ dkö— -FzÆ+-œÄ,ÜMŒ,œÌ¦Ö{ô/½Š­±‰£µ…­É_.ÿÕF#ãØ”Í-Œ¬lÿi:Û¿M&¶Æÿ™ù_zþ•7ƒ°œˆ²†,ÍnÓy)üeÝYÙÃþobÿ£Y;ãÿ%üƒ!,lçð¢ceÐ1spØ9™œL>ÿ‡hÿ‚aú/YÖÀÙÑ õ·dF¦þ?¾ÿ’tþ懭‘ñ?S¢äl`küw°þ—ⳑ‹£ã_>ÿu×ÿü?帉‰»‰ÌÚ²O°eú¯ ç:ÌÜ‘IQ­>&БûÒFå¢ÿ»^¿ôð]®JýÏÚú¦iîïv¥sû¯C)꣱> kŠÞT“ë|<ªþä-òNš£@ÝRøŒ µh¯›E™0MvFÕ£½IÅŸº%ŸøÓ,ŽP7/Tþ$®þh¤Ïö¾Fi qè]HM@(u…çäI§/ÏC¿GG†{ïÀûqirâ Éx\ÁàÉ£ürp4U*½"¨—Ž3Ç'­1/ÍzG$91Ø7™Ây¶*GÜ|®1ïOåñ•`GíGˆ\.­=û“æúüq†;÷šLÉ»‰î«;¿ÐÄ“n\¤ÎõðÖYNùÜóÒ1àL—ëFb$]#b²ûób€aOžcxwK÷ ‘„%&B™‚ºo"ä¾²’UÏìU(­Ñdù?ç ‘îj\I‘näQÒ÷í9~5\ýYsÈ 4Õ;¯>ꪅª®c`r *§Ž¾í1I>T -Ð÷ª-KCºæì¢]•ß@e›‡á±Í R©e7ãÝ8æ¥X¼Ý ú^¯bª¿fiWã¦Ç6hé("ôæ?ü…$ØVS̓÷â¹-Àõæ}DJš2½œœ$~T’D™ˆ‡…:Nq®ó#5ßì" 󧈼ˆÎQჶL–­Èµðc“Êç؉/WöýîŸX2ŸÈÈðxª©-“[¿F7žsWÆ{4B -pÇ€úâLV›‰¨ÛE°¼õ`K«Vá½Öž\ºÍªk:K?>1ÁÆy9ãd™5 @P2ƒ÷Í°]öþ6Í(9Ð`®¦ ~ Ì¢ß +¹9y´Æ¢]’ˆåþJ¿*ú¨ gÒöK“]?e’CÌ(m -D\ïN¤Ô´|˜Ǧ¡‹Uf¥—øŒÉïÀúÒáè -ûÙ £)¨Ž&‹"º–Qª86Æ…‡â9xV6jƒxlˆÊù†º’2–^ù -|Ò Ä;c g¯lt_´û•jP°– ¼ãT³mê=-ŽÙ - ËÖ /¨é?&§ Ã­¤oø -%Ñ]µÃ³V‹Éµ‡†#hižrX£2¾K±²Å?²©Ç‹t3V<«×üHl'}µ“œ7ÂnhJ권buKÉ)O^Œ Z5‰OßöÚÖ?ý<ÿs88z™l­; %ÔVæ ËŒõ”ððßEôÌH«íjÚ ~öÖ´Öb}ë­MùñÍê+GÝq’Yµ£[N¢+C1¸Ë¯öýµgî;ƒBµÖcæ4vP“"d×sžåxñ^ÚÁ9O^jŒŸ»e: £$‰µåf~)Z–Tz=a“2¨ÕæSÐÞ»V›áçp"êcýK¹Wåã»/Íx=‹ -RÚ8Ýw>SÓ¯S®A˜Ç©ó-×;%¾À˜úeiH—faP$÷Då€ãCã&¢A†C ѾB&eQ/MN¯µÊQg¿NÊèÑ8o©­?²ËˆR(iæŽO¿Œz‹~€èßöØ°ŸŸÊ€ù#!Î4uðÏU¤ KqŸV!rÉœt„Èä´n"/«åâPH<8±Ìà%!*áÂÇbhO‰†o‹›Cd¨· †Q>ÎN{©’ÑòíÀkÕÍ=ý.8}"Æî™Ux§ñ~Ê©jG¤SY¹Ÿc[kÑ‘pœr)h‹xŽ7ó—Š›Æ]BöTx¿0¬ÝcàÏ}0p²¢A17y,óUø‚‚¢·…ø¿K,ZS¥VÇìóK—Àd=ˆúÓ‡j €Ÿ;¢’Ÿ×¡ôã+J‘RPl3ï˜ùÆïy4¬Ôx_½´oõƒŠHÅÔ·vS_ü AåÒg˜Î_Ý„õ’~w?@’4ýQîï(á"[Eq¬ã si5׳¬ÄÈ—D|ÌŸ|çå¸K¬m@e½)ÿø’– -ß$TAÂrü—ÇDUËx,¬mCFË„vh”V¬èæÝod%·Ýͼc‹ò¡R´©kð97Aa¸ö<ër Ñ¿5{ßîRÖÀª—Öì6 °¿ÒÅŽð.Îe“ž¿|€³ÉŒÎ¤Àa;ó›c ø1憀^Ñå݈2ð#"ÎúÎøYkK?¤ãž4rIt\IIÛaë°†;ÒD™øÃW=ü÷œ÷YÅ+˜©rM‘!ˆÑ'ëâ§λ‡Þl è‡ÕŽ¿MZaÆ©wO/ˆ¤ÿä‘¿<y±Ç-û"å{a«Øçé¹WÑs<¨ðÀ%ìÝH(*ævØÃíý¢_õ¦fŽÏZ5X¥¥6­›Þj<ßó±/¹ç*£ÅJÏ“o“¾™ˆÒ¼¬¡µ6"£Í·@¼çÂKtÛF3c‰¬#«;¾HõOR¹éGA½qW/}gTHLŠ‡Ö-'¾ŸÔkí2„}ÆÅ6ðû {î56Ë!l<À-€èÇUq;=t}ÃY)¬8Ýø3yìáœ9oÙìF€s#MSþ‘»Ží®@§$Ùýû(§îºÑ¶±ý¯ë È>loD‚K{à[ì1_s©–¤ ÑLâ”Z|µÙÿ‡L§/:OMz}ÈÔïKHï~-ð_Åt¦¶Ÿ ë­‹­åÁüW“Ý$ýAƘ¹ß3¯œl×âr,ëâ€y¥&0•²jmÚqý[„ìÑL6Qb~´+¹PÄ-sÙø¿µ$ÈÑ*ªï ¥ ðÈOÓ…¦JûèY[éýSækŒ¹©[üm}ÿ˜Ð6L÷èO³[²ò½¼ƒëÆÐNOp:„ùHïä7CĬ“ü]½yî´¶ïïÃ>Õ“·aý'×M½®qê äîbà_w– ž]4ðÚÀˆ²öÒøÞó¬n +: § Ìô 8û›cÑJR[2£mXÅw‹}y7ˆ×ÅLeD$ç,?Yh{³ÛÆBÅΙki¿ŽøК¿ Ø1ò°ºŸ;eó‚T›n|˜)94µ9uæÐ¥x´ ƒã½R ->ç³]æoM%„£¬ÎG)³‘4°ký‡ïbZ~ø ¼`_[hã»8ë<¾4²}$.îÁ³ÖÄ‚(¥ªæu†&ÿaÜÀ™y£Û2¤³‹Ô»¹T+ªJÀҙçÍÁØØJJ,šëò¾v\TP‚Êü´iÚõ pÃsùâäFáã!ÌnT)^”"²À±R'ºƒÀ q)J‡4`¿s]¼ÉZGâï”œÒ Òœƒ(BÖqˆú(““v&ø­3UÏ‚Bþñè› ™Œb‹Zˆüù Ir2Ÿվ ¾îÄ›7ïX)c¼5&•‚OϺ÷•—2nµÏÄGýÓ¯?74¥Ü׳ Ž²Å­Tj(–Eãs‹ &‰Rð³ÐѵL‘ˆÁ3²pæuy6©Ì7k‰¨‘}¤TêÄoÊ"´wÂñls ò­Eâë2¦'jQ®,ßéàHˆ]í„äÛct? ÁÕÑÊ,Ga³ýý¥­Ý2^¤d0•NUx¤$"e`à%~7*ýþ¬Ø挭©Ÿˆ{cÃl³?hZFCH7U£*´Ü‹Ç‚Ìy|±°8ô.šÎXAÐufóË ".Ä-_Z “MÄâë뙤—¡¹Â‡Ý÷í[áÉ\DZQR÷¡ x“à¼K)Ý)‚pÊåDÃ’«¼m“­HÁ• <¨üˆ´Ÿ_Ä1ÉðkH/·)(_|ýû2ª,B³i‡Ðñ4V®ÌCøY¹5õB2Ey»…yö47£h¬Bù\=m‡r94ÚOäjùãwiºð_w ÎvMíð¬òüò[°4ê©—Tÿ³š™\Ó¯r»N1†c-8!âΤұtzžK,בZÅ5…ÍCÅg€„ »öˆÍÐJÎÑ=–|üËÊ,u‘,Yƒغù‹ÑîÇôBÞ¬ƒé\¦SM„ L¿ÐÛºp`i5U])ÖìUæt™PÚŸhlA¨6`¦ãqµ"~g2è2êþ6d`{#Cn³W!Ïw¦I¼Lwdk J)ýK‡"™¬ô&¶ºV0ÀfÓ¡?þr83)J‚$È4?$ àE•´Åì²›¯:Ÿ -Œ(iýŽà-º 7~õSLcüýkÅ!.0Yü:7— `hPêoˆÜä¦ójÂlƒG¥v‚j»8Ç«Á¨›ÕäÅÆ6nÂN'éú3ÑX®ÐH¨Ïü%›zl½ ýƒ©´T~Ú}ÂwlzŒ(D:ooV¯Ãúe@Xrݪ#ç‡ d4C:«G‚nxŠôÒ¤Xç©þƒê¢dÑ^øÎg’´k½›Ú}Áîí{åÅÄõW·F°;ª¬ë§Â×òh`7d H—”µNº’7G«5–-™¥Ïà 1‹†d ®\É(¸¬®&Á€%þg› R¤q[â’ÖÀ.Ê¡\ÔýÔG&ùƒÔä1Gô!ríØŽHÀÊÏôØD¾!eeÈ2¯ª ­òûôÅ![é@8Í1J©áRJËÁE·¤]wú³{D1Â_¤ Ó¿’²\ýz¯ö §D‚ßìñ¯Ìd$!ÉÝ–#/û$ÅVrþlAŒÕ„ž­·:@¬RÏhV‡ƒTW÷ði¼&ßVQžb‘¦°$Í?^ªøŠJj ¹vQÕ±:³´FRƒK«}ÏGL©ôÐ÷±ûûAÜ8€)dä±”Z®N¨æîuQÕw_ ºLã®páý±•¯ŽÄ—¢9Qök¼`EËih[úª•³Á5?M”õÝãõû ØÃ)’'¸Q·*ó4yΊìðüC[I&«Ýrx”/Ø`x0…oÝûsËÙsïsìêƒø—弫Œ诗´% \˜Ò„-qBÏÐá¹ †^ n u^CE ’¡ù‰ÝĶAµXþ¤@á¼ömÿÒ’JÀf)Ë‹MÞÈRÁëVSi•#w6VBÐù£®QŒßk¨£1#ð9‚ïq?ô¥VAØAÿו° ¶ì.Ü5.óQøw¿­'zÁ7°…#|ÝX#c½r"ëòUt™îÖÔRìáϳ—åd—ã0Â{)ÒuŒÉô˜t’’•û6°Aêõvƒz»§ö»`~LÑ%óÌ·«š™,"QW½^CDDûa.˜ª¨ƒµ ÜöBŒvUÛaÀvæƒ~ç÷%ƒ#™D@¬Êž±H •e—„7tà›¹¬6–O_pãÊÑŸÀ)ÏÐ÷#lžtñôË.jLt•¤ÍÊv)nè>¡á˜T‚nü%´öª•K]^sõ'lÙ²k2]¿÷þ5#Ä®j@o^'Å|³ÂÎp?èÅyIß»7ç ¶ÞJ\pA·F¾#Û÷jYó\a@D‚Y>›‘Sa? -)‡¿ ÕÖÏéÛNÄD]*¾ÔŸæ›õ· ­‡.kÙõ£a ü:ræ\e·ûá&ÈÉDŽ¿Œ™%_$$3}9šü• Š8$½¬€È¢þàÎg×™„¿ZuÎÚ8רË=~³a#›L]gŽyiðÎ+.ÐÇå‹6{™jšSksÀ›ø¥qéD¾ ~Èͯõ{Ó·Æm'¤v;?«A%qÐ7ú"úpM°!(ïx[„Ô]Ä,…u‹0~‘—Ý›°ùot…ÿ‘vm¸oŸÓÔ/˜àyÝSÝñ}Ó"‡ÍÿImñ@üñ¥Çýawú™¿9Zôèý öI„÷,`¯ImJ /¿!UÕ†[ƒÒni$%µÖwjÂíÏ÷•y†’Úª? ü¸Ôî¿¥8«?—ÇÍá4êµq5‡g7¶}E¹l“lRŒg{ ©Ò2±°Ÿ. nÇL^ªJéˆYç¹¾‡(Š©?fÔ2ciÛŒ<¦É¥¼""—@ƒ Èí•Ú!kŽ 5+V=ÑÅQA+žß͸ÒË;vƒô% ÎFº+s*)¼Xs9NÛß™üÑ¥˜L¦ºÿ[YÛyt¼ÿ²ô„ xÚ:tés®` [Öx³(³û¥šrvrÓ vÝW+—ºù.myÙï=Ÿ†Ì†Q54ÕxÑîÊa•Ÿ‚T`ò—`È „^3¥>5¥UºaÝH‚c™'x‚.löÓ°g™~»uFˆÄÈ8ˆò€ b ÿ.¸%Û »ðPâ*¡L;.w_÷<Ê/¸‚óŸ‡o£ ov£~8ù8‘ïV¶qãf -åÚ`qÈoa’:Üà}ÒË’àóI¡ Å¡H±`í ¾‹¢R¯u²Í3}›’«˜Œ(-ž ŒßDÇîwëôêé‚t­»Ìt«Ã¯W¹4#UâRwXPƯY“4ìg·FRß vßû<ÔxP>†uÂËe&+W-\O+NcÓÈ«¦ˆdÉÊç°Ÿuµ‚^¸Îö%oH¦£¾]ü¨G,ïjçís”'Ù#~3’âø‘JÝ’J¯E«N²A»‘_l ØÙ1U¶c3  ˆ¾G»m+–¦VÙû©|¬-íÛ`»õ¿lf³$Ú«ôŒóÌžÕÅ›±Ëšûvy7ÅtU¯Z¥lÂÙñÏ,¿ Nªä@Ëäþ‡¼%NRs¦P†[¼‰P?ß”ÛI¤eo Õ wö¹¥@´!è&/Ä8Ù×öÐŒëÝñ‡þî…l<œ%š.Ò™{A•£@lŸA µÆ? wR,»SQ,H›ÀuQÚå¯>¡UAﻵÔ/£²­™Ï&/Ö…JVíù9@(üˆõ›œÏt\ F;éœt­Ha|þ­ZÇ)Ýb®4¶H„¸îbtÜ©. -Dì2Çüߢ¿¢‚IÔnèEYÒÒÇe)ü²:V ùUš>иɚúq:…mɲ¶þUñNžY±B§Ýêƒ&³Ã¼]Rý*ÃŽûý=*n…ѽKv„hf0ó;!ØÅ .&f«RÚ„ Ï‹ë&e¤ãe}|“x$Ó½ââ;£kgž=çyÅg©Þ+a…¶’û.Î)†Ú`NËiߜʼnW«Uäç*i¼/W 6æø>±§“ t6ó –p2/ÉõÚzî„øÑ=h>±` -n5TÁšëÑ”’ÐX"GEÉ.4–ú&µ¼ ØØ…'Àú|€PÜLêar ¾0N1fo÷í¼Á¶Uå" ‹*0âù$]s¨>ÓΆ”'â¾ÞÑØèÝf6qì©)¡}mZ€šÍûIÄN§ -Îþ@PD # V{¿Ö%þVõ|3ùÈ”JE3)&Níð{_’ Ê m3™Î1 oåñ S“•/bì~O«¸8/*™Œ²éëíZφä(.Pÿ§žÏdÔö¤¾X<é§îrî9YJÛ)E抰z6Ø/v0 ¡ ªD °¾T㹋˜€7ýP“Ú¡ûµ¿^¶û°iDØF…ṳ̈9Ô\ðØDˆ“Ï%Ë;¥Ø—qëŒà2ß œNý.¶8bWÉI0Uy®ƒÎÈfPw³‘ Õ8ŒÌ" Çsäs -ZmØFÐÃʶÞïPhzI÷™ð€*qaBrÒ·Ø^ðƒMâÝàí-Õ¨ô¡À˜å®™ÂÞžÑÉö>u¼ ‰ŠÏãonŒ{óæâ<ŠéU¿˜f);›Íp±OË,¾†ª™ŸÔL~‡(ÂJšWQû¨ -`þ* ÎŒÔÀh0±ì$(]J+?!uR[LGÓOÁ ->DGÓyØ}—(l ø &‰åSß}fÄ †ù©»7«ôÖÞ •ŸÑ;!)îüP_©cEìì_Ï“Á’TYj¥àê§ïS({ çÑd -± éÇ¥µ¨ÿ‹0Ò±«ö¡`¢/³I Ph¦€ZhtDįcÅxBkô¹õ¾z힢Uˆ1áû-C^­î@\’ž¶Ê#f„†µ]òOÍÕ5 Ñôh‚˜CGÚc(hƼ<@žðŒe/ºˆ¾]úyèŸãgT —–B„W‹:ƒÅ‹"p+EŒŒûE|ë7p<*6~¾R—”{N f.]Æ&‡•è…MÀNsr'=d/UMzW¿¨8ûÎ=ªŽ´n¸ÚvDôÓM=×ArY8sœ‹ªf(ú²"’å®êvj×;¥ôŠË7/“æÖö¹]Ë\Ù”7Ùë•azgòá¶gÌ)RàÞ%H}!³¡i°Re<Ñ 7¡%ý¿¹a¢d:£gteµIˆ­¨*’ -‡–oü‘éO' °xd"뙂T¯·3z ^‡ø~LËÿ¡IÖBcP/giй.^ÿâ×úÔ¡/jƒX©ÛQÕ ­€ÒÆ-Ô¦4Ê{Ù·hïgZ¼'ªF§ó.²$2ÈÙB Æúž07êÅÌJFØ “|Àmv®å·Ìù´"Ëæn0jª8xB¯QÎïïˆþ”âÞþÐßÙ«À|˜­jiu›¡lQæ5ý%ßzÅŒãÎv¥ú…>GïÀ•Nv.óY‹=Šð ðô"¦k ¿E)û›™,$i{;vÓSë œ†œSW¿BPPúËj…+ýá{ÛÏáûg¬ššLœ/ -¹,6:üâƒ^ÔX'€å9U¿œ‹fkM6¼¿tî˜è^‚(Ò2g¡I›yÕ²˜RôÓ(.ãcÃÿBM¶SaÓv¨‚/uø¹!&jìdR¥ *ÿ!´BSJ‡ã !DË¢FT=B–žýÏm+›ä’…0Ñ¢­½ãmëIÆ}ÈATZS¾Ø ûú=óÀrèƒ!÷v§} ‚ü |8âìñ,¼ - ’¦ž~o8LÃć4»DÜ϶ÒlÊô‰'´:Y'ϵ:X–¹ȃKKÖr97…ü dé2 -{¡„Fuœ·3žÍÇoÕ‹Ü2C7§jy¸-Í@Šæ,dL//¢„KàôÌ°FYîÊ„³Ýþ9Å™êVþ©\ªGôZמL6ú3‹:—g›:‹¡RB£–†‘ž/Îç»v­KH©—Ôï[¾­mÁò¥®S%{ D4ÌuBÞ…ø,&ñ~‰‚F?Âì–\WöÉ¡r€ägµUê—ÚqqÜ6Mgy0#Ï•`¯Ô&Â~Œ[¢é°ŒnÒ#u"%`£–ŠžÏr­çgäeùÝy£ç#HZ@#‰F•Xý”ÚèíTÃl’Ä’2”XÇQ[ľN1’ÔD͸©ØÎbÜÙ{òdEÿÍžó¦˜ßTŸß¯£Y4v̪ߔcƒ>´ã¦´ŸÆ½;åø³U>.Y'²–¹.NŸöLM-©Í•åÂ߈¾x6·w\uÂTõ *ÁtÛ©X„ø6‡{AFi íDñËèŒ}âýì¬pK?N2%-MK2{%¾,æ)ÝPÍh5WtK¼˜/ä%‹(ü¦„¶â VÝ?Èþ¾uôÎEšwž]“¨Jb $Ùd+¦_wZ+MVÇ3”Fíh¹ÝG{>ôº0 ¬{ðÀ“ [^Ž O0~öãÊô`1õYû -*–÷oz ×PýÚúŽÇä–G”30¢ ò ¡€?Žê)^¿)’£Êw8:B-sìFDò±û¹Õ.¯ýaËmwñ¶ÀBUôz8sš3&¥JÎ|ñ$¡9ê -¿’ƒ½[žBš´¾™Kåd H*ž±yÈ"ýƒß ýzêXê>ªµÌWÕŽ“Ѥi$&N“yu°BIsŒŒÓoLª¸IòD·»ñŸ’ÆãÇ•ÑlèE)÷—¡OŠÌ:˜¶O-h/_cÂ:u* ý ‚(ÖÛõî9ç}y}F)ß×]>9]¾¬šæù%†­Ž8[pµŠ Úˆììˆ4eAäÙoÀÄÜ# Ò¹äY¼I©[ˆˆu÷Ìp•)ÁæDÚøõ l¡ù})¼ºjoÌa %h1•l­õíP”Eöd¡‹#ò!Œí±Y‡q4NaB¢#@÷3ÁÜ´*ìåFÖ‡ù–[>¼üózëþ2‰ØMÌDn…Þ ÜwKØ¢Y(i£X‹ßüƒd¤ú9ò ¯L,ÿì“^^ñëàö­ÂóY%)µ4ÙZ\ÔötôÕW¯ù­i ¢7,qK“ñâ”-Ç?ÑúE@•àë#¼‰&+ƒÄ0¸Ø¡¸04ºœ5Ö–›ÿë“WåÔ/¶fLƉèß‹›¥0³Å¡u±yØ°Ðu:¯Û{®[’ĸ2Ï}’ cu¶Þ÷²' )¦Z`‡`\… c¬—ÖÙ±{OÑØD°Çré ám;€¸LÐl} JÜ„Ž6 ‘nþ‹‚>°§nºxŽPc=‰6pÊè)L[‡+»†%ª}'¿P°aŽ‘45¨lG½>(ÅûE&-#Èkií·jEüÅ×Ö "ŸûmUó˜SvL „„§=ªA2Ÿ¶_5J¶Ôø¿ÒU‹‡_O·V°mîl= -æ7ÒÁÒq3‚`¦ t.Ó„c‰Nä•×wíÝZKGº¦Ô›.(ðÔà^æÕ—w[.,ÕZåŒ -cGM}!;4šÍCnœ®2'ÖÊïìù®? Œå¯@9ÖË'Ñ®æp]CÖ-C¼Dû]QPÓ-}yhÎëzqã©Ýcô‚®ËÚ+›ß™A;tocšn’Éæ¤-O‹ÛÃWÓ•ºžÛóÛž:]‚é#Â_fbÈ°g‘øÌÇ õPŠ€Ú†ÑPÅŽO£ªõdU “ï6dÍpŒ‹bçÆ©\¦©Þ÷Œ­;£&{"ÿÚé,–ŒO_»ÔÇÐ9V¼47M=ÍaÍ]:mÎïGAã›P.4”ªþ3€ãd—&•É–è*HfÅ„÷‚¼M:ÞÌk(g -4–·öÈZýjH sóG··»èV üY).üjcPÌ¥’»nÞÝtïw¼RÓTÔBÇA4MÚgw†çsI2½¾C®æÀɳ/™CŸÈ<€µƒòðð½·J'“8.}äjðg$Y[ì3úØ“ü=¸ ŒdÇäRŸ\4˜Y^ ßZóÖãD`LŒ³8äûX‡¸xã-·òú:Õ]PUˆo3‚¡©q¢ÎÈí¯¸âçü%­F~Ÿd¡Ü17br'ÓP¯Ú.~ÈFôêg´ªš’í2\x%ÃE…§é[#ùÍ[8‘çðÞÞª'Õª{±ôV2ZâvWùS×ve?sL¾d5׬¨sôßaJý.–óÌê0Í›øñ(#­FÎv}MD"]˜2?µfÕ_kÜ͇±MÞí'–‘nÇ[ gÞi×ê¨SÖ—¬€ðp:ªÌð/šEù3/ùkÑÍ Û1Æ•U -ŠéÑ:kÅÖ ›r}’õéŽVbbérªïHÎ7Õã³ßêí¥‹_©¼“×2[ëAõ°çô­JCRz!»‘<ùq3mÔ¢W[M0hÒ VÊíaL¦3zb¥ÿÐCNãú?O“lVŠšßÍÒ4Øë>Rj•·•ÛéD[÷87ž9(ÎÔ ëR„Ç?Jáf±;V¬32Ýy‚¢ÈÚ«òßü2ž°é: ;QU–8Ííx„µt¾n -vÚÑKâåÅíÍÓ¿½Í~¬?קS§ÎªôÉžµè6.¤K±“H?R‡yþnv8Âax9™:¯¼&ýµêo<çßb%ðórÿDí;Ú%§1M–UΗUÈÁXÒ6G«NJ"€Ùíì£â%Àì”w¶ðtý—_7×¾`!—ø§‰×o>v²|îÁÈç™±ÈBu:ºXXv9’nn*Ç÷ÝŽ#*%)½—-“u¸3ôž¶ú¯?N ` -;ÜÆŠF¸*Cb&Znf]C¡ÈN‹×6Á.þÂÑ, èW91£ðà«iK;m+úbTèSpïGsÊuÊkÏ&ALH^Ö™FV{ð$ ÝkúÝMbxáñå6ÿa˜ƒØÅYå›a¹5°þ¦J0Ëšëö“©¾é™ý¡ -Ó†©"S—Ïz_¥¬Sþ@Î lÀ£ì†D/®¨÷þ¹B­c0ˆb( º -ƒËsˆŸ.ÍÏxP£þþ\ næèJµõN*·ƒ7A—^…¯f£èïnò˜Øc#ï|<ÐŒ¹a=íÂèœL¹Çt}N9@œí2ò“º¬ð;ŒÔ’`Ÿš瘓gÛ–» “(kw“Hˆ«fz# ü«TU5aQW.;ì§øtÁTK!bñ6Û¨Ú±A2®Èü„è-£þ|âáŒMÍU5j2~áúˆ^]i‘åe-·¨^žÿWeoÙ~äèžÞÊ„×Cô®ïw= ý² {ì}Åï÷šNå)àÒ„½\Š*‹Jò|±WŽMí¡±Òøòo- kÈ“èZ±Õ6"Ù™þ\W7ϧGÂ}VÁc§Úª4ØXoM7ùwÂá›P«cþÕ’Ûl{lY B‰©Ù/šÌÝÖíü¾ì–­˜T¡ÁÜ?ï°êšš+‰¾Å’Ñs­êŠGô†äv5¶ÈÍÌ?ÈÖ§éBÄ<wsÕÆصŸ×ŒD¦¤9 ߥKòã_Ý»›’«á`Ž]} ‰µñnÃáhDÜÀÂ\É&*NNk…¤û0œ†»™¥ ›ýÔº˜Å9}­Q}lêœDª0ŸœÛj2wü“¯µJ÷‹¡œéÃvµvz¬,Æ}úè"öìijƒŠyñý›·î ’±¼cæOˆq¸Ìpãd:3ö¬Õ¹$c¿_W#ò4ºÑ1¬ç¥†Á z,8ÚÈÕD-æ h•’ö5Cº ͧáƒ_%wÒªu¿ â#¤Ç”g!]7¾ô/BŒ]eh©IKôŠ2¦WTŸuÊÊŒk84æÍ¥0Ç‚AÞÈ;b•1b°mÍH;í>nôÏ¢ÖR /#NìqHºà0gÚ…>tí°§Vûa¶ ˜/æöŸñü |¥sçYà¨q³Ý,ÙŽÆ™(®” ¿œ^õÏ‚~¢­Ö>ʧÐÃwHv«;ø´þâÎMÌÿ$ìe ™´´_ÚژтX–KµÆZåÀËÎ)\uñ–Ã2îvKËý XåEÛÒ7ÉG’”¡":1£ëV G½°â”ÀÑ&–Ê(è1ó›Û9‡?³3˜FÛRâåGcM-,‘kÖ!í¯±òÎuÈþ7æ;r…½VÌ+r“l«á¢ü” ³˜¿4{k{#í"øKMaëb³y÷ý©ÐØ l/W^ïo<9[<˜W(§H‚I§,âkíŒ{·)G<«ªfÉÝqIbÙÈKá«J-p_¶×&,xÖú~Ã!C‘FŠ‘Aã”Vh0–à¼ùMeœ·È¾„B‰?MÓQNqXA÷žŒ#´wøÏ4æm¼ðS"u^5^á1vÛv"®3P£ÂîƒÃ Âù^Ú&5ÄùïzFƒ@PD‹oŽ+'.ë²Üãa9…@4uÝlXÃÇ1ߟ¡X3Žª‡µ?c(µNn¢--0žà1ò†´Ñžácó—W¬¼ˆÉâL¦â™w ·9 -Ú…W¨•fI•M@ï±–KÉ­7‹û)Cc¢ïS`…,8'Îl[stÂ<¡\nc«¡T&8Ñew‹¹ƒã'}'ÅrW÷ ŸMì7#X1nfœ÷ ~¸ŒÓ2Û*¡U§ %›ˆÁÇ:èDMÂ|Ò.Ž«ªˆàc:š®)IËü*ŠÎ¿žê³Â:rê2:Ò©iWLÁÎ=¢wßÎÙàì­J5 d'XZ;UïÑ[ˆÉô+j£"dgO5!nYÙÚõmÒ/‡`ÈÛZ¦  Ã9LcZp)©Ê›ÓQ$7ÐâänX튌X,ðO“˜£Òâ'ؾe6\0˜`À2ÊâL— ÁøÁbÂrQu -ºâreA5n!Ñ…êì]Œ¨ÁºØ»‚õOWìõHƒ:Ô…—‡uÀÏk2Q:ú†Édf¬š¢ µ‡$EÏÐï8f±æ™€âNØÔ@Gœ¹}\=ñõ°¨öˆ¨‹¼_W/nÀÄbÛíÿ¸¯ß0^8U¤>¾û=O?°g›¾U̧[aý;óþÓSX¦ä”gÚLÁ´·¹‹.võ@/Ò&ÿ”i:dÏk0G£u¨ð“rÏBž7gO‚w üúàü•–”À‰KY&j øœ7¼r 2–á°WNÎxëh“õÒ¿Í7§LŽ„×VC@]ÒÖóºÁ*óë-Å ÃA;}üvñïiCU…—.úZl¬ õå?²ŠcHÕ¸´Ôu½ö!» »†ó±œW‚Ñ/ðó\Hvq•bf€úOÕy3¹;¾Ð¤ ² ÜŒ°š'ÿˆêIܯE|Ÿ¹ š­p:ÔC9èc!¦²VûCÕ7òÿ2]„2ø²âª³ç½ã,}Êø%(ê’r‡ɆfQþÏÈéª{ÃÅ3’u7õ(;†>Dî`…°éö'xN°?1jaóXDOÄOTÕYe¸S;&bïæ„Ÿ"=_ƒÕL+Æe)ëõP -gŽ}“ú£qÍòÛ¨ù›ÂN•¥•îÉ/­„¼Ÿ¿¨ÎwýéN­ъ”⃞êöÉ(ú˜i.ŽJÓY{Ê…ë߃ˆêo&ãX -Ë|åT¬N!{¶ L•„«a` K=ETBÔSEÐATMb§œ -Q‡Æ~ËJlQ‹Rü¶×ZB§©{g¯ ^x™‡¾m€ï¨LŽ1p%õïø×ké\¤~}ôO½Ü8Ûu·×çqÏÜV»ì*æGj¸ÙÛ9ýèOâ÷Žû’VuûtñCv.¯ÉÞ¯²”ì U=Ú·rèöI3 Í¢¹ØO7( S~ãÈ”‡ «ÒÛšt”š®`½öÈl/ÅY¦37›„Û¦š ;ŠôÑ à<‹ÆN–T‘Z.!`ßêã…”´I¼M%0,(`Y³¡mm¡ §&ymr¦-åɽ.§æo·œ¢ŒEŸ¼B91Œâƒ!ÈD4B\\ò.½ Ÿ†‡b.ô¾=ƒq™“s,|Ö?¼´~8£»»³­ -Ñÿž¶l ÷ö" •äjÓ`Zo…hbµÌ}åÏ0—ŸùoÎ*˯µŸÞµöñæ/~ úÕ'Kü@Tƒ¯k5{<‹i»ö—ROBz@-+µyÚª«1èûŒÂ·–µZë¿ÊnòEp7âPi«ú€pV¢;g.Oã­pÈTA3V.ÀÙòV…I’]UAÍÊ&¯æwú{¥,¿f -ý’OP\h{†!Ë/:9*ÁþNª‘À„y†Ý¢›¼~¸®<rÍ¥Ø.k¹áR\ÄKÀõ=™Ê³ô¤µéšàš)É  -Ìó¬¤^©êzX-Ta’•éÔUÚjLØ–‡ÁPϲ ‘ Ú €,j%‚‹Bè_|³yŒß]¶to7ɹ¿"Á¡ÒW¾7ÉÔ9NÙbdÌ÷Î2s—O‹D"—MêÓ†l›Ñc,Å=Æ/¿ÎWDk¿þ-ţø¬‰tF%ÿÐjwÕïS;ù^É£ ñšo?ñ -ÆQ'?ßœ†*×3;ùQhþà“R¿«A±FÌb<\gÜÝ@ƒ×oìfg,ÙS¿´íw*0=a{ æŽ!Ù5"OBŃð4ûbü[ïR«r‰2Ó'VìÖĵv\PjÐÝh «»Œd ­ªÌ'3çÜŸ¬ô£uªü”.ø¡×cšÎO -DSmÝ÷dU«TòȨr7)z¡mYÅÀX˜Ä5ê¦[Ø÷ËÅŸ"f ‰@êéqD„ç™Õ'~ñHA[€‹Vû¤“õ^C -ݓ׀-xú€°šNceŸ[å˥ߺŽ1½é˜Ê®aYÝ«ÀF5PYåaÉ|3ãä¡ïbøM@©Nyav.åh­nî×ņ®ô²¡RŠÅ—ȬŒWyŸ¦Þtƒ7×ÔÀOkB¬œC@ƒž©êo´dÏ “I¿ü“Z©þä}\žÅ’gÎBT…bM+5êõHzJžìfy®âq -C¸ÎÞ•¡‡›û/ìë aLãdU±Å,[g¯úWСÖX·V7~æQÈ¢%+ð?éצµ!ùUè³Êk5ãø&Z£Q‚É [äxŽ-b÷uP…#Ïñ¾†E@qIÀ$ä;®ŽVçæ$#ÜíkôëtJ€\¶p5žr„º‘¢€$|H{U¡øæòƒK]N}¬ò†Ÿ€E×D° -FÏ-¶ 6© †Â ߸ŒçânVä^… ]šMg\ÔKÇ·ä 9·/£‡õü7o¼¾¾Ð¼­ÎÉSö'ž”Q®¬þ´òB†‡Òe|°ià”¸[‹_Ý‘†6ùŒë.'¸cä½M½åÕr\S>‚K䃔t§C稶h5uREæ‹LU§­Òƒ˜Oôz VÇ‹;¬¤'áS™ÇOXñË€¿®›¦™;µWEƒeÔ #:0츜BøUª,ØÞèb -Òó…2pÈ^Ù†:0|&e¦Õ,?‚HFkJæU'ý!qÆYµwß³HžÿÔ«œ;…ª»ž–3ª[œé@—hžÏuãrnL‘;®ˆ=bªy7¥E>°áíîä=HøŠõzŒ³šâs|Ó߶ª`KA -Œõ_P-ç'„HS -Л¨'ÁÚæãy¿ˆ Re†êi[‘¯²2Ê2ýQ%™ÒZâû®žm-c¢‰LPe³o“=ÒÜi:èÑ'Ðr^ùÑ­ßÔ{?z$É&aM%*Æð®iÞ ïÚ‹š%4Üôí#6¼± -´!;h¾þGáÁj2Á|O¸D ‡?ûµ“îw¹´`ªÓ¢¿¸‚’cçÅò¢†‰‡Î·¤ÌaŸŒÄÆ툗62A»wÆÕ(†“Øs/A'viÙ.Ü]Á‰µ‚7*‹4¥'O ¢ °vŒ÷øF34§¡Æág¢O¿u¬.t¼“®rõ–s}/¸šä”ôÛºö˜#=ÕdrõÔVL­WVŒªÙÄKã‰éS.“ (Õ;ãh"’€}R>•lÏs¯ì³²Ô!¶‹lAËE:ßy&ôœh»Æ2©×Äë2+Ù®HѳÁŸ¨0An´ë‡Lš@°ƒy‡ß[q8^:ZËÄc hjð-¦B _¦–¨ñº€ÛJT§ûš5j9È«>Ú)¢Û»nSÑj=³ÕXër÷Hl_—rß:¯0)]F: ”Ùtë,,pQ£î÷s²•õÒœúåx.Þ!ª±…» šMdÙŽ%󌥢À>­×בtÍýh;ÑN}ÅO™~ìx[ôÒ[ ô)Ò`Ç™[z€Ð¥Ç;ÿµbä¸ ý· ZÛ±ýW=mVùD×®9, «Ÿ³e,ëKj}Ü üï J¼,®bðýÂò3Þ2¼ ­h=Á‰U,jï% -ìé×¾ Ä92¯kƒG`µÕÂKþ{|*Œ”)ÎêÒˆÁÄRéAîCêD´Ó®ïÒ‰svѬµ>cj -6müÍpHr£\Ik[xi×$¼šÉH$S<ÂÐ]­H;"þÏ] …h!ÎK Ùç wœÙƒaƒ!Wo§têQ‘21¸¦e}œDó—ýªM¢Ê&ëÅ"þçÍÜ1IpÅQè—{ØAÛ»kJ‡³÷4°6ŒíîO«Ö*“YŒÝ*³A"Õ±«Ì Õ r¤eKãùŒ©$a^Hœ›Œ×ý‰ÞFïNûé)•7µ»‹i?¦: ¤®ý§"×ñ—á -¦y¼5âéx Î?8€†,ÄÙ%š¼ø*%q$GÐ]È%\íðÀ¸¯±ÆLÆø¤z*­Ë"7›U0ž$¥¨ ×”€ïøq*櫸×\~ghL[ü ¢rñY{âkây9‘ä¹_­-¡„­“ߣ|ÒœZ¿€ë˜û.†zžÜbé>1aNÓßø–à—ÒK!5hI¾?K3²< áŸ,ÞÅÁ¸²Ü$j:=úzåmÈ_N4ƒ˜Fäûq -°’胱«T«þÃ5jíaƒ"¯‹¬Î×Эô'7kˆ]ú†A§òuSà‰epÀƒZ˜%ÆÅ…¹­Â¬¾=úð¤´~¸Pù*€üÕÝ+àŒVd˜¥ódqɈÎEX—dÓJHÁ+°:ƒÊ}Ð)#ôø@ײ!R»ÿ©€£ì–ù -;\ùˆ¹¥e7ÍHÖx³¡l½ [sÉHù[êƒáëXôËUNÑõ¢i X–Ø«c4ë7û\Aº0«<{ Evg]8xp[lZщ5õè¹r÷ûGâÈm*Nêê:Q+|‡gµ}ÁÞ\d„äO¾>hžDä¡GXnöº +b¸¬óÇ;½tÛÓÆŒ£6lÄ”Å>4ÌÑÑ0a=‡ˆ …˜Øà zb¸»6û€x{³IÝ)KÞí­[×î÷7ÑÙ€ ï²jP8b*æñÛGŒŠw4£V³ü2ÎŒfu3^üL9OOW3èPq½*z5la:ÏÆ> ?Òæ3zîÔL¢Ãùïú÷~¾­ÔŠŸ+qqj²„îÌoƒ¤ 2^›6Mäck~·H‡Ogi$q5|©/̾®¿îÁÛë3úï.7ÿ”,—síÃ[|EØ9 ®+Á -ÐQk|/Û9¾ÑxÜÜúÙP7˜ªl©¼å© 敱<ý6œÍ¶Â=Ÿù …3ñTI‡@TƒÌ07ƒI`5¼áô‡lcoƒ|áþü]¤ãÏ(^¡¥µºÈÕ6ÿCÞŒ Ú롾—lšÒÚ´ë÷aµ1Óþÿ×Îœÿ3¡¹—çÈÊ–#Ɔå‘yLî£æhm+÷U¹bó±'ñ˜#GÒ,Ga<ç,÷s¤„9a§¥|I@µ>¬Ó ‘ŸÂînÞñ ±mŒ¼?Áá¼ÃñqJ˜.áC{¸Ús oÐþƒ–B•(­dfá¹È|ÄÕñÂï„Ó84šÁç2ˆ¥(phëž7ÓŽd5ÈìDÀµ€ÛæIl]Bå'IÑ¥ôFÛ܊ꨤ!šFó…L`0\ÁàÛ˜‰¾Q¹u3!skA$TˆBØó“É°`¬ âŒéúŠƒŠ–%¹Î× Aä÷öoŽûŸ»­w‡¾ÙºïÁ° bCL?í<:Ú _Þi 8eT)ŠD¨á~ÑH½ØÏ7ceÐès6µ™Â$ï|ûŘ‘ùË âæIPÈkfåöVÔBÓ(ü -šþˆ/KnèEKØ(xÆÈìƒww¦\3¥kÔ!›ùÑÆlð›Qe8‚nÛh’8¯tãær|BUw•Q“)€gÏ£ŽWºè¥@Pñ„¥¾‡LZð7×(fÐlç9¬Œ bf r·Ñá·šPæ}p -øš*›íßyýá“ãûB/1;Aì2ÕÙ3ÕSs±‘woÃñÕ“VÝÝíßv¼¯å¹ÜÆ{¯’XcÇú9'*:ÞÒˆVÂ)BSzŠ)Xý_ƒÓŠÖpm{§z¼¸—±u±)ôc¹ÿÕ)€+H2Qi·'Âڱ׉×b@akÊE¿¢vÉÃBakR‡å:›ñ†‡Fˆ~¨êÈ’Ìm®g4šv~\œI©¸ -^ýì¶<[7Û-ú%çq´Å5mââËÊž¶t“Bdc;|WÝÚú7–xSyåÈ4ØÇÖv´¦×Åõ Q«´˜„2ã¹Rwr\Œ¨ÇÂCÀVD -­`Ú5øy÷»é@k"¢™5)Ï1·ØRù-DÒH Ö»¼ÍDdM†o3w»5Gv`LÐ2îä¯uÈoêb—r›[ˆv^Ð^P€ó]üQ¨‹ÔS^?¨Ïóè_û³£ 'C2T5ÍyÅ [<;ËÛÜ}‹hLé4mMmÖéҎ/À}"ÑçB0%’éVE~µb(e’ ”峕UòïiN“ýië€ëÜ„{X#Œ=dÓ[娽 ÿÆOƒHð”£Vê ªëvGJMGÚêåÄLX^9ymiZPpù˜B5«¬Âø#…sW+* ¨)¨OñD¾Ë_*Ïøy81¢ÎsY×/NI„8wÖ¦.¶v.rþ÷¥äïûˆÍžá¹ˆ“¤;éë7¤{®ÈEÕîÄìø‘VYƒÉïÌ|ÝWN`ÄþÅW‡Ù¾—›º‚ÔÂâsh™ËúÊIÆ(ˆxó^m¸ƒž²Ê+»O':QGrçÉ×æ[XFRž;j¸±·ùI•šà5A0 {Ab8A²T†’QmO@ i©Vél³¤Ó¸£CX;䆔¢$ŸaP÷ga†kq*Õ{²…nøglƒ’¼2GÞ Y•.ß“­õSlôŽß-%-½¯·e—ppÔW³8©×‘fÅ¡Ú=ΆþKbÿÿ‰À/$À'ê,öÌ¥÷¥endstream +/Length 18167 +/Filter /FlateDecode +>> +stream +xÚ¬µc”¦ÍÒ%\¶»Ì»ªË¶mÛ¶m]¶­.vÙ¶mÛ¶ñõsÎ̼³Î7¿fÞ×ZWFDîØ;2“„P^‰FÀØÎÐDÔÎÖ™†–ž kacèâ$cg+M#hgm økd!!r41p¶°³6p6ᨙ„MŒŒŒ€½‡£…™¹3€\EQ‚ŠŠú¿,ÿ„ =þ§çïN' 3[éßWk;{[ç¿ÿוLLÎæ&S k€œ¼†„¬€\LV fbkâh` w1´¶0H[™Ø:™PLíÖÿ^Œìl-þ)͉ö/–€Ààdobdñw›‰»‘‰ý?.j€½‰£…“Ó߀…ÀÌÑÀÖùoœí¶FÖ.Æÿøk7µû!{G»¿6}Áä휜Œ-ì³Ê ‹þ›§³¹ó?¹,þºv¦#íŒ\þ)é_¾¿0½Î¶NgwçršŒ-œì­ <þæþ fïhñ/.N¶fÿÅ€àhbfàhlmâäôæ/ö?Ýù¯:ÿ[õööÖÿÚm÷¯¨ÿÅÁÂÙÉÄÚ”†ñoN#翹Í,laèþ [S;ý¿íÆ.öÿÓçjâø¯‘ÿ33IÛÙZ{ŒMLaèdíœÿ¦ÿß©Lûß'òƒÄÿ-ÿ·Èûÿ&îjô¿âÿ×óüŸÐ¢.ÖÖ²6àß àï cüsÇüÿb l,¬=þÑÿ¨fòo†ÿ' gƒ¿m°5û+=-ý¿N¢î&ÆòÎFæSë¿=ú—]ÅÖØÄÑÚÂÖ䯖ÿj#€†žþ?|ÊæFV¶ÿ4åß.[ãÿdþWžñ¦S‘•–¡úÏÛô_QòUwVö°ÿKìÔ!cgü¿ÿ` +Ú¹¼h˜™4ŒlìVv;ƒÏÿ!Û¿`þk-càìháÐú[2=ÿ +ÿß­tþFÄÖÈÎøŸ)Qr6°5þ;XÿËðÛÈÅÑñ¯žÿ:ë þŸë¸‰‰»‰Ìê’W°eZfºs FîЄ°V_èPˆ}I½rQ•]·_Ú¯Ž +ýêÚ†)ίVÅ3ûÏIÊÑtk²î“«|\ŸŸ½È›¤ílT‡tº%ðéçjQ^× ÒÛ`š¬ôª‡» +Šº¿? ð¦Ú™¡®Ÿ)üºø£?Ù#ø¥ÖÅ¢u 5¡Ôž“&ž!¸£C}²§ªM‡×Žì ÀòYÞx°¤þQá¾ÒžX¸Éªi8M;:6ÂÂ~>egš1 âCP2ƒ÷M·]òþ2Mÿ½ Áø‡Œò!0‹v'¬tHèúøÁ“zQ<†ó3í²è½*샶_Z¬ÌòØ ƒ,bzLC âZˆ`R u„¦åý´ØMŒ23­øGt~æ§Æ[G˜bCŒ¦8¢:f˜8,Šðjze¨ÂÈ.ŠCFÿ9Xé°ÍÀ#Ãì¯?–@FÒ*^€ë¸§­áì•îŠv>S +Vs£€·Ý‚ª M½§Ä0š!a9QÛáù5ýGdõ÷u8•ô _ Ä;+·¹V«18önQ±ù-Í“ªT†ã~í-oò„lèq#]Ïè5>ÙI]n'„ç ±š»-¡ØÃF޳ˑ#¨VFFàѶ|Â0§öN=Í}åÌ_$[ëöI +t•úÂ2"ÄB=Ž‡Ãýw=ÓS«;vbƒŸ¼5­µX@_»«“E¾˜}e)Û.B2*·µcÊ~êJ“õïðªÝG}îšûN£P¬¶Á˜9ì—cg' Øue9ž¿•´…³Ï‘–XãånšöI+I`nB¹™_—&–\Û$÷kµø´v¯V§û9 ûXg*w«¼õ¤Ï¡eQ@J™dzúÎehúµËÖ r9µ¿æz‡£ÄÓC?÷a# èRÍ÷ å«ì³½k\‡×I“£ó%Ø—K'!ê¥ÊêUÿ¨tÔÙQ÷×Iþ†ž†ó–Üü–YB”DI5w|Ì4ê.ÁÑÿºé²a=;‘ó12 BBœnhã-O”d7>©Dä>n Å—ÆÏiÞ@^RËÅ&“z¿w bÝŸ=ÆMD&PÂAמþµ,ll‘®Þô#Œ,ðafÊ H•”ˆšg^«föñïpÁéÒ‹¸gTâžÄù)§¨!Ofå~Œl®FEÀ};å’Qq6ò–ˆ™Æ½“\@v•{¿ЭÞaàϾӱ3£B16x,ñ”û‚‚¢¶x¿~[4§ÐKØç—ìó/‚Éxô§Ô@ŠÛåÂW¡´cËJ’P,ïÓoùÆoyTÌ÷”¸ŸÝÔ¯µý +HÅ”7dv“Ÿ¼uAeR§Οµ~·" ‰š~(w·äpÍÂØV±Ð¹ÔškYòV¢¤‹|B>æ¾s²œ¿­m@e¼É¿ý†‰K¯ã+ aØFÁå0~¨¥?V· £f@;ÔK)”wrïÕ3“ÚîdܲDúP(ØÔÔøœ™ Ð]yžv8Pé¿]Ú½ýÚêPÖÀ¨Ôl6À·¿ÔÅ ÷.Îe‘š»¸‡³ÉˆÎà'Ãf9õ›e qà @+ïð®Gé O‚³¾5~ÒÅÜÀÔOûÙvG±(<¦¤¤íŽ°yPÅ™ Hn OñUÿ5:ë}Zþf*‰\U$`âFøÁ¼ð!„ýæá†;SDúnµío‰ZÀA~âÝÕ "á?qè/Ç[Vìqú@ÞÇZØ,úqrfÀQô*Øw{;Ê¥Š±vs·àWC¹¡™ã³ú¬ÂR“ÚMo% žçéÈ—ÔŽ}…Þb¹kŸÁÆ·ÁÏLHiNÆÐZ›7ÞæË Öõ-?ÏTݲÞHÿ[Æ‘ÙOè"±ìÔ¿Þ˜«—¾3ÄH ²û6æM'EÊÕVi‚ãbø½ùÝ@÷*›¥.à&@Ôʘ¿Œš¾áŒ$f¬nÜ©Ö`ά·Lv=À¹ª!ÿÐÝÛv‡¯]‚äîm˜]wÍhËØ>ó*²Ë‘ +ÿÂøkÄ×\²)1]8ƒ‹h¥OmfÈßaÃé“ÆS“Vò ùëRç«W <³˜&ДÏÖád­y¡¹,˜÷r¢ógoº1Fî×ô ;Ë•˜,ÓÚ»W,¦j?úÑsvÕàÚž.fê"Sp/2²+hÁä.èö ú¤ õ´ÙUÏÕŠêîì–‘PÑS~†þjêÏCÔÆ…O(Vô|:ÌΧ¶™¼ Õ†kFr6MmvY4I.m‚à8¯ä‚Yúl—¹SqÁH«³a²þìz$ ¬jÿÁÛè&”—¬+ ­3<g‡güz–÷„Â…]x&‚*`ƒ¥Õ¼öФoú>ìéWšMC2Y»½ë µ¢ÊxLY<êôõm Ä„¢Ùï+Çy%¨Œ›Æ Ï7\—OvN\*‚ìz•âIB l+uÂ[ôPÁ—¢4HÖ[×…ë¬5$ÞvÀ -?íЈd ›°2)q`{¼ÑßPÈožé‰H–ÈùÅ{‰ŸÇC¼Y­{ÁàkNÜysŽÒÆ›#R‰PÉx´< »¯q‘yÉÿ¬ö8óƒx(ýzsC“Ë|=[àð!›ÜJ$b˜Q4>6ñ£Éù? +]Ké<# +ç©^–v©K}³ÆëY‡ŠA%E FÉ‹PßƲÍDäÖ›‹ÄÖ¤ÓMÕ"]™¾ÒÀ‘;Z H·Fh ÀÕQK-‡a³ýý¥¬ÝÒŸ%¥1”NTæ¹$Å#¤aîáÅ3Áë•F?Ê·ØcªjÇc_Y0Zì÷–PÒLÕÃ( +-wã0!sž-,¼‹¦Ò—t]§Xü²Eùh€ˆ +ñ~–Ä-®ŽÈ$`òôtMÐJS]âÁîâÙö,se, -+©ûцò½Šs`Ü&—lÁ8å²£âDÊVÜ´È”'ãÈŒžTFû"ìçÀp‡LÒýêÒÊl +Ê^þ¾Œ* Ð,Ú!4\õËs¾‡Vn Ý ‘^gnaž](+P>—[¡õöã¹Z¾Áxš.¼—Gü3“Û\+\™~ó–F]µêß+IU½*7»àd#ØÖbãBî *m‹'g¹D²m)•SA‘X¬0Ñ<HX°‹aXtͤlýaIG™V~¼#) $IœÀÖŸôv"Sóy3¦³NUáÒ0鼯k‚%(jJ0g.3¦JR¿£°ø¡Z€®ûÆÔŠxI t¢J){CXí 9Í^<ß&p3Ü5’¬*|$õ/Š¤³†ÐXjšÁ"Œ¦ßþ²ØÓÉJü?‘©DÄ¡Ep#·Dï°š¯8Ÿð )i†s÷‘¿ø)¤Òf.;Ä&‰]Åáä² Jüã ‘Üt>£CMmp)ÔŽØ.ÌrkÐëæ@5x±°Œ™°ÒH¸*&Ë)õ˜?gSŽ¬•¢½3”€ÊM¹ûŽL†HåíÎèµY?÷ J¬Yµåˆ¸IDÑ¥1{ÄëþJ–Zœm?Ñ¿ý± Q´‹Æûkû£7QʵÖM픶àçæ­â|üê³S#Øý‡Œó‡üçÒp`'äoIkr4%o¶fkL[KŸstºg"&7t‰*ÙßÃà2ºšø}–x-V?‘"ŒcYºµúv Pdk î&ß3Hï%'ŽØ¢«G¶…–Óbx”•!«H¼*×µÊîÒl¥ýá4GÈA&KÈ-ûÜwÜiOïE 2‰A¦2³\yt_îBO +¿ÑÙã]šÑI‹óC’(¸-E\ôHˆ.çÎoBŒT…ž®5:@¬PNkþùò§r¬‹G³ï%馒ü“8™¹/qî1ðBÅWXBÕ½¿ý¢†Ùј©µ?‚\Jík.ê}êS¥Ë€¶‡ÕØâÚL> $©Ärå`\í ww¤ƒ¢¶óŠŸÀe +p‰ïå¬tpy(¶ÅŽ²Wå+\FEÝÔóG9 _AóÃDYß=N¿×€õÙ]EÒ8çÍŠ£…†ð<î>Õj Úhá:â—À–Ü;Æ¤ß ïáî¶ô„¯²Óyú6±¯ê«¤­—e\>‹.Ò¼Ãz@Š=ü¹v³œ¬àr†¸/„:΂1“³r_ûÖ‰½^oa~sïªÌ(¸dœúvüa$ OÐU¯Õ’ѾŸ ¦(jcn·=¥ü¡í0`9õA»õû”Æ–HÄ'ReM_ ƒ…ʲ‹ÂØ÷ÍXÒŠBɧ-¸vekâ§Ë£ë ›#^8ù´‹œ'Q]ùÙbå@½;t_wD,N3öÚ {ÙÌ¡.§¿±¢[ºä¤LÓë½wE±£Ð×N6×(¿=XÀ z~ö»çÍ›½Ko96¸ S#ß‘åk¥´q¶0 <Þ,ÅÈÀ©°…_…˜Íß…„bSqê¦1AZ—‚'EÑ|£vßâ¦î¡ùÀe5 »v8,”·^GÖœ£ôfï— òø}¡c¦1£Ä³¸D†/[ƒ¿T»‘„—Iä7Î\vIø‹Uû4±s•ºìà ²ÉäUƈw‘÷œÂ‹ÿzǯo)׺»ÖYMý‚q®—]ÕmßW-RØü1EJ‹{Bà{ˆO=Îw»“üáê ï°B„ž%>{MJSj x¹uÉÊœ*”VK#IþÈÕžNžÏŒS””fý>å‡ÅVÿM…ÀýÙ<æ(6§‘P¯õËY\»‘­Kò%›$“‚|d\Û˜•¦ñù½4Ap 8FÒUrGŒÏÝ_»ˆÂú#FMÓ–¶]ÀÈ#štYÊËB²ñTüœÎ‘)m2iP3¢Æ;ØʉcÄò;é—»¹cF®‘>¥ÀYˆw¤A%ª.ƨ[ãÚ“Þ;’¨ÃT7ãF¥µ‡Çz/JÞAX€§ì óˆ—‘>f ±dŒ7Šâ0:ŸÿÐBÎL¬aT¯ùjåR6Þ¦.-ù½åS‘Ø0 ªãüM1^°»tXáÁ##æ›Èä9†ÐkD 7£$·J3¬Šw,õ×…Í~d˜ö,Õoµ.ÂEƒQîó‚AŒæÄ·déwHXa#nÅÇáìéœÃEÉ„+8SË4g¬?™<[*Yµæç¡Ôó: Ön°?Ñp€m§±Ó4#…ñø7k%wŠºRÙ"ซÒp¦¸È²Jñ~½ gF‡)]ÏÓ +3¤î§Æ¦ÊgZÉSe–¤õÕo0§Œ"N%¢.ZV×¾(ÜÊ1*”ë´Z½Se´™·Jè¢]¦Ûq¾½EÆ.Ó»wÈ N÷§`|Å»x¡ÃEGoVH™à÷˜brÂ$µ=¯m ec¸—Ÿ¥wlÏÓ²æ<-û,ÖzÅ/SwCþĺuŠ¦4˜U…ÇtÚ3grâÖjR\!ŽóãâhÂÂÛ#²3ðtâ‡çe… *‹ÍãQÈ8òù)ñ&Õxô€Ä ŸcŒDTyÔ€ùkÞÒd8ÁE Ñ`Š:›±ŸS°J™ûçÕêZî¸Øáh2Ψ‚U×ÃI%‘¶òß;Иꘔrü¢#çžë³>13Éû‰EøÂX…èÝ׳:Ûf•ó,LN¨Àð§ã4aŒÚ ;b®ðo}½Ã‘áKšX,¢˜kSSûêÔ5›Öãðívì½¾ ð@z&ÌÖ6^­ ¼ÍʹFÒ¡I•²Fb ìêÁ·žD~”gêF#@Ïò â~†&ў𽑻Y\­ÞÁâ¼È$ò†Ï×J=›Ÿ‡±úŠzv\‘[Ûú¢qĺK¹g$É-'dŸ¨(‚êÙ`™¬`:tuè `=)†‡³çѯLú¡&Õw«M~Ý,waSˆ°õòù‰³?¦qÀc Ž¯=-o•búžÇL¬ÓƒK±ý}ƒ°Û}|ô;„Xb‰\%&ÀTå8öÛ#AÝ͆‚VbÑ£1Š4°ÏÏȨµaëA*Zº¿B¡h%lܧTŠ ¿Ætƒïoí×ioªF¦ F/mwLvw‰D%ÙûÔðqÏ'(<<½ºÑï®Ï™ÇzÓª~2Ì·7šá`”Z|Tò3>ª™Œ†á+ÀJ˜—Qú¨óóad–gDh ×™X¶ã‹‚.¦–;©-$Ž¡êLJ` ¡jÝ)Ö ¼SþŒáQßy¢Ç†QÔÝQzmí†ÊƒOï—s¾¯­P‚ƒ±"rv‰«åJgJ¬(1”wõÓ‡÷)”¹€óh0…Ø‚ÇðãPŽ\ÐŒAiÛQ{—7Ñ—Þ È7ÒöA­„7ÚÂc‹×0£=¡5zܺ_ú½vŽùQOÊEðü– /W¶!.ˆOšå³ BÃZ.x'gk꨺4AÌ¡#úíÑå5£Ÿï!¹F²\„_.½\´OqÓª…K÷K|!‚Ë ÀEíÁbEá8BÆƽB¾µëØûëŠ/”¿Ë<Ç3/b’Â~ë…M‚ÀN}±s&Þg/VNxÿyVqö}Pj"Xwµm 陵|ª"ä°pf;VMWðeF$É]Ñm×®u2Jî”nœ7&Î7¬!èq»’¾´)k°×+ÅðÎàÁi͘“%ÃÍ¿‰ÿì÷…Ì>€^ ÂrJ‘ ð@F…Þ€–ðÿ℉”nwŒDžÖ ”Él]VU  ý-¸þ-Ý›†OfñÀEÒ5 ©>V3fgô¼ñõšÿB•¤…J§^ÆT§sU¼ö âÛüئ/lƒX¡ÛVÙ -ÒÂ)Т4Ì}ѳ`ïgZ¼+¬F£ó&´(ÔÏÞDÆü–07èÆÈJBØ “¸Çit®æµÌù°"Éæ¬3j(ßD«RÎïm‹úäÜz×ÛÞ-Çx雩ljv›&oQæ6Í”k¾dÄvg¹TýD›¥uàH#¹ø%ýQ5ŒpÏ÷ô,ªk ¿I.#ò‹‘$$qk ++fÃS뜊”]W¿œŸ_êÓj™#íþkËÏáK±7FMM:Ö— +ß\ ~á^/r$ŒÀô”¢_ÆAµ¹*ó«·töˆðNœ0Â2g¾I›qŲ˜\øÃ(6ý}Ýÿ\M¦]~Ãv œ'eð©.&räxR¥*ÿ>´BSR‡í¿.DË¢JX=\†–õû¦™EbÑB°_ÁÖÞñ¦ù8ý.d?2µ!_´Ÿõ펱o)t•Îs«Ý>P^îþâÌÑ%,œ +’†ž~÷/˜ºñwhVñTÞp8Åx–’lò´ñGÔ'ÏÕX¦ÙeÈý KæpRY7ùüsd©R2{øzuì×S®‡/Õß¹Ç$†nN×”rp›šdYÈ6^^„ñÀiaõ2œñ§;½³ +Ó”ͼ“¹hÕ®û\,´§É4.O65%FMuCC\ŸìO·­:›’Ï)_7><›[ü}e‹'\Jöè@Lˆ¨kÜóqY b½âõ~ÙM¹®¬e|IóÎj+”ÏÕcb8-šÎr`FžËÁnÉ „½h·ÓAi3œÄÊHDrÀz5-;®åj—bÄEÙíY½ûHj@oýOJÑÚIÿrÔá›Éº™Dñ$e(ѶÖð=c$Éñxª1SÑí…ØÓ·¤‰rL ²Þë]ç Q¿É¿ÌÃTVŒÊQò‘~ê1Sêãîí2¼ÈJ—¬cË\—z§{†¦”ÆŠ2Á/D_Ü>››[ŽAŠZP•`š­€”L<›ƒÝ £ÔºV¸ñ%´ú±^Vf¸E‘ã KÓºŒnñO‹9r·f|Ôš+}º%}^ŒçrŇd~“›±È+îï$ß:Zç¢t Í[ÏŽ‰J¢ñ?ѳH–M?oµ–¬Þ¦:ÉõÚQ²;öY¾¨œâÊÅRGœ)¸\A®GövDš´ ôì5`Cbì’i_ô,Þ ×-Dļ}¢»†Ê gq"®ÿÌ›o|[ŒBÁ›‚ÿS¹;b‹Ð׉´B²Úüú (Ê¢bY´ÐʼnzÄòبA?#3ù©ÃG£onZö|-ëÃxÊ%÷«üãjóî"‘ÈMÔDv™wÎ ÜwSТQ q½X‹×üýçП§ˆýž0°(¼ÓZ9…Ïý›;ÔrÏ'•Ä”’$k1aÛ“á_½Æ׆Uˆî°„M Äó–?¼dD#ègy|UüÏ÷_ TY¹è? ƒ‹Š C£Ê˜cl9y?E¼*&3Y1èÇ£F6J`f¸[u·’ˆÒ7i4|ŠCkbò° `Ï¡ktê_¶v]7%ˆp¤Ÿz$@Fjl½ïdŽA’M-´ÀÀ8 +AÙF˜/¬³cv ¢ +°adÓ@µl¯b3@³õ5ÈqâÛZÐ…DÜöýø}`OÜtq¡FºlàÐ’6!–wÈ «ög¢ÈcÁ!ÅkjòQØ{½“‹õ +MX†“VSÛoV ù‹­®áG<>ôÚªæ1&×m›NyüÉxÜz®×ø½©Æû™@ Z<ør²¹Œ‰HoskëQ0·ž–v€“3…¯»‘ê ðCx,§¼¶cïÖü»~¨cR½áœ W-îyN}i§éÜR­YÖ¨P!fØÔ²M£Ñ<äÚé2c|µìÉž7àòàÊXî4Ó±V.‘z%‡ã +²f â9Êï’Œ’f1èÓCsî\׋Wí¦½tM.Ð^ÙüÖÌÚ¡xÃÃtƒD&'íÈx`iêHÌþM‰ë™=¯í‰Ó˜>"üEº4kÖOŸ¹Ø.r!PÛ0*J ˜± øj]YåȤ;uYÓlcÂX¹±*©§ªw]#kÎ?úÀ=‘3·;û %âÒV/ôÑuŽ. äLSN„󅆘sOó{QA~ÄòŒ+JþùîÃv²ÇM•Ì`Ipå'±b@{FÞ"kä6”5š Ë[{`þóbHsý­ÛÝÙJx£ +þ¤ûër½ŸÌ©‚³fÎÝtw4N©á*r¾‹m€ œ* í³3Íõ±(‘V[‹.[³ïäÙ“ÄƇGhÀÜF~pðmï­ÒÎ ŽCeG±üAÒó¤>ò(wnB#Ñ6±Ø#fV‰è·Ú¸ù0 e/ù:Ò!î^Í­A[£¸ ª ñmD04µ3NDԺɌ-~zÏ_ÔªçõIÈq#"u2íõªîð¸ç…¬Gûó„ZY5ÿs«^ÉpAþqêÆè§ÜÆ œÐÓxwwå£jåhZ3 5Q««Ü‰k«²Ÿ9O8²škVä™Úh˜R¯‹åã *LãBÊP³‘³]OA¡P†´¢ÖŒúK•»ù –É›ýøR ÒÍXäôõ*B ÅCòýÚbŸ.v[¥Þy#½0oÆo}5št+zÀ˜²³JA1-Z_{µè*DBC®O’>Íárt MΟ;#âø³ õ¸ì×Z{©â +ï¤ÕŒæZP=¬Y}«’änzÈN$OÞzœ Ûyµ¨•f“ytªT¨å2û“©ô®©oZÈ)ß৩Ÿ›§ Âæ·3TuöºäZ¥T^--Ýú£ÛzµI8çu`##Pô9ðQ£¦‰*²J3ŒøoÙÛjûÜ÷øË ¹{ ¥ïÑómÕå}j*$ õž$Ó;¶£B +·K=‚'h²@ßóh‹•ÊŒ7¯µŽà8X€› šÞÇvÐkÊ]àŸSü=Η]äÖ¥ajË+*¤¾o²ë”¤0K>ûÊV$öåÄgÞ·y[ФÈèYW5")JÍì!h¼¿di|!6]$ÄÕXT}| +È›`”¸5² å!4/VqT,ù’ºÄ÷·Ýg¡»Ý?€¸Ò?FE£tK´²uÀü,…LÁ‹VoùÅöÔ©:Ë\ݯÓ&§¶*á—sÉB½hšYiÉÐlóƽ"΢N +ióÜG4ƒ˜Y8åË +²á²‰Š.²%§:‹™»‰A{okÂÏM›—ßçB/Èñé”ïÓ²fOk¬ù]ìŸá©Ú$UGÏ y›j‰Âx0NùSîg3V8BCúZqœh‘à­ÃÜ8#ìêLÂÃ-]ñ0OŠÕMærÏø¸MÉ“h Z&ÙÒ¬­¦Qõ5eJí"oëÙ¤è ]yƒ³ÏãRÒu?åþ>®Ó(žR‘²LŽA†»vÐnØz²)‰Ä "’xœìd‚W[f¸$àµF]ˆl,1 ‚Y_jžæ$Rå›:ˆGlå)^ÕÈÓ;3ò šã«ÔJ˜+͘ŸVlkˆšu‰ýÍA¼ fO""©íˆ&&L}sjÖü¢|åõI™m)ýïÃkDÒ…~@XpY>+À8cæ¾8©=_£Öý‘Dbws»÷³KøbíBw§ªi†#sXꇈz¶Óe¹M„[ÎûÑzjÇT¦o𨉱Wr§'Kýeö<¥„v³;¼(§ŠÝ™]‚ ª‹Ÿ/Öt2O„¿ ËØÕ}ò;.‘‰|€y-%ûXXd‡`` æôÎ'hæHºàõ#Y¢ö×FF¼E…ÌÇ.¥tzÉ® ðæ«9r:Y¸&¡Å £77P³ú\é&겆sIÉ&¥ßïH'}VÆ`AQE°Áñ‰ÊïASþö„ +Gzߦ@ª9L惣}r#f9£¬÷B/o´þç~B3l?9uB¢˜”ìÎé‡v’ëƒó¢²‚»ß02=·2IL./4í ²ã…±>…SùÇÕðý|žO`s}ëë ˆ“yúóŽzè7§@„¹‡ÊòÙ ntæÌYv‹\¡¸Î&Ê™º4¼XObæŽ{´N¢ý)­< ‡¨ï ûß‹TºA|夯¾Ø†ôak×J¥0 SPÆÐ>*®á7—æµTå`ƒ_j¿iþ <ßB +,«ÁË&^“V—[*% +LãDÉæú5š³YèûÜw'Dà†<ÖP²?iȯb2‘sÓ'Þ»ÈDcûˈ‹b˜\]ƒgLâ1Ú÷sâÖ³þé|Í+Gæxïô’RÉÝ8V³-ÑiÉJëÑbÄq5¸kr‡¾éÃø}$ªÎaunj”M*qœsÎàFi7pîßp¥ŠF2çØÀOªAŠv’/|(¹ï~ g$dß¼¡ïñâG*†ètÛ*»_xö«|l‡|¤¯<ÒQ’…µ·BÏÒbˆÈçSæ|UX¥¤³ƒö‡kmƒK.¢^>^XK¶Z“–—õ"Ùj‰\O__y¿U2N3•ÆúÁÝùæ²v3©aþêâVùóìM $EÆs^+îÉ%ºœ¶ÉP.LY…Ätï'FøHÜvq¡ÉoV'¬ûˆÇÕÝ3Òm¹Sì¾ÀÌÅEKð'í~Þ*žÓñžÒ­CȶvZÕJ^õA4m²\ƒKýa Ž³7_‰ˆþÚÁvdª®”ÄÇ0=£m"=®b."nÈ_§XŒH/zþóÕ›Uí MígOV,¤yU—.* ±™\QšcÀü˲²>^å„ ÀüÏvÁbÀ ï q[QFÐhXô.q±îõ_=B’¿Bƒ0qù™àú9Ã@ß\1É2Xü¡öaã4réZ¿¬î…ý`$Wü‡ž††˜ño§Iì¹÷ZŠfåmñÕwû‡òk%¥g©Á®j¢´ç¿¢Dù¥ÐÐÈáFyßÄOt‡á¾<1‹©Mq.Ú¼}-æöáA*zw*üË3{È%äè‘x¢¢ÒÉe)õµ–—òð€ÃŒÎ~£'ÜÜ$Ëÿ¾±†å‘?`âÕa+ºéòw¢äp¨3ÒÍVèe=å’vˆó\pSìy÷X²ud;oª7Ím²óù+÷góuÆ'â«‚â´d|ÇÕÝ S>ÿ>\í8âUö¼­´Œ¶G=Ù\ݘîÂqX¢¨ +œ_ðÀ,9°(öhgû¡o¯jÌÖ o4çþ‚‰f…]Ó좙žÅm)ÜUþµÞíQSßïקãW m‚dôåvqMàÙkN‹u¶üû‚‰L£R©i nAÝt]«¬9éT±fNûh}¼#ô ÃHNº *Tñ³WÅ.}*ZùöA0ô‡©Áše¶`v¢ °ªC <Î<š”¯Šì6-MÂÁr¹Èhݾ’ÎHR=­/«ƒ<öí€i"@[®/“pR¯óùwUëz¡••zÌÌ%»Æq +ÁoP! ~}(™ü5ÌÅ9Æ;Õ±Û´[H.¯Ÿ³ìdÔÑ`“ ÍÙJ¦S1<šH ë¸ÙìÛ ¼°Å˺Ì}Fµó¢¨(*XÎò~¸‚„Ø€gؤqÀìSUhyxZœª.%Á{ +YwBæ­‘03ÐÞŒ}NÔ‚‹hÀWºœÌ+wßÑl“1Ë’CQС6]áÐw\‘’¦…Sqpi& â?sv«=ë¨zøÅ£ðí½;Ω\º c=EB/›´™ý‘“5eª~D§ãƒŽ&Þ)^LQézåÚÈ»„` ¼'8ÌçvŠ ÔPææV•Ìz(ÞjrHOZªî,ôÏz­Ã7í,₸ t!>Õ¸¢¯Ò»ûÄ&MÌ6ª!ÛaÏãJñ¼oÖ{aA¡ÈÃæ‰#mX €üÜ€0ùÔZei°T]s^‡¹ÒJÛÿPÇP øHȈnïß Š7ç—w=K˜ÛzuâÐAÇ]Px; +XúoLaùÐÚt¦@a³Ð"—„S ½ÍϹÎóSß©×C¬ÞML[IÁÄL¢Jð>¥lg¼‚v›ddÆ0¬Åü!½ÈœKis÷ŽúÃ’bk\¿È†€ŒsF +ˆ;övû.Õæzi”Áí¹œä`f “s(éA¶R¼¨2á^: Ä!=Žfý¾‰;ŽW§c~µÁïnS¿‡ï9âÉLšß<Úφ¹Rëä0Gc­vѽ I±¦€¥('§q 9õŒËj1&0k„j0ÅÆ<Ëër­Ø:NÖ;{ä|`*ŒM4Lj…»·0V6ØdÞ¥¦Q€mmÚS +ªþ® æ¶Â´]›†fŸÔd:šþ‡|B<ƒ?X2¾6ñIãpËxCCMS?ILÑE[¤Ÿï9 _ýïNòsª¿pÜÜ E²A™µ,¦/ŽAd-ÝÌ¥®T[c—[Œ”ƒAN‘í녻ͅOXUÅÑã¾3ýªõwåߣ ¨çïSR ™¶µTJ]íy©:­ˆÍsÆ[@¥*sÑÓSyKÃOhÏ»E'”ˆÛ?ˆf’‹¶2楄pL’ +»BÕ=Hv1eÛ¦š¤ÎûÂÊt Û>–¶,úÅÌÞ$¬Ü¸éì}-160ŠðÿàÏ“t¶û»i$¶ñ@]¥4‹µyñahïwn +F×Ë0Gn‹ÄŽÕmâ믔õÜ“T^-ú 9]5pšzxë½!‘ PÊ Ü§`;¿¼TŽÌN®aÒŽà C›½/Qð +¤}V£×ÑÈv®_`Î…,$ ò£3¶â[ Þ¦¶J,‰Ìߺ‡ÃFŸ°¾ÖÀªÄ‘˜qhíÖ Ö˜5/$æD*ÔU›Þ‹]áÙ´*Ìz6£¹©2Êõs+ÈÓ#'R”±(d…ã½ït"-HúGÏ\!j´çzóPêû7žœF´Áë¼&·æ›Á™\} 6tê¿ØÎ9Ðe4¨Í´ô• ±B’}¿O„,/±²X1Én·ñ8o'’¤¾5Ð-±„'j#^)\ ³¼ÃŠ–Ì?äNªŸ²$+ïц Žñê…‚Ýxš™C>b1¯):ÉÃÐ]|¾ÇÊìóÂý=(eѼmoL=Ë ÈŒžÙíÏÕ*9Jö–à7J’GKé/cLò L>[úHAÆÞª©µÄŒ'°‰i5b¸ «‚ݧß=ˆ†ÅïJŒ"J¥É±K¢>Úûˆ_1]@hünH%|Ñ:²¸ew·ý¸90ôBK&×åw5Bzh¦’æ¸YdÜóæg}D +V;Ü#R™'Ž5ž%g|!@1žG½Gø†aU!Ðs…R÷+‰µ\[€gÙ]gÑŒ:)ùñf‚ù‹¢ù#5/³…%à•ìgÇd¾Z>r„˹o—»+I¢lþ$E”¶½%\Ï/é¹wPßï\C6ñXÍA0«ïiÇg¦5lR¤?:ç­Æ@Svɤýâ°ØID<~°µƒ™F1fžq7&Ÿ€N› døj8ô°ÊDgFÈÎÆ6’`ú·³HB)Á?A#1ˆs™™\lŸ‹üÌ‹>ÓTý›íä1¥º.½µëHU½;`å@t—L:°/°4Š®ÏØBlVgXÙL(Ñ¢!›^ñ×vBQZECJásf¿à¤w ª( CdN<ï4o :òÍXE6/´ÿ,æð«Ìí«‹²šiÐÔXÓb$߀PL+Þ¦?!ƒ†·Az.¾¨L§õüÄ\#V¥õí•äºo‰…jF5 ¶4…áQQsXÊAû—©45Še¥ð*sàïñÏG‰éÏÃ,¼ŽÇÕŠiK»cQ4Å×?epîlzJü¨ÆÏÞˆ®'C!pl‘,®-ØÈØ…Ò± +Ô‘LN¤@ÉÌh"OîD½’(ko]¬cúÔ=Òü¸…&TΨD´mÊE%JƒÉÞ›’~9Dªô˜21xBou×,ÚÔ ™Q +Z®ËoÛ4ëŠ*s³°ütg†©NeÔú#‡ßìF¹¤¹K¸]C•f/ZЪ}¿@ôFêbM̼¦K´ØËJ®?L›^ëåɼo¬àÜ^Såõš¾qD¬E¨ÁOÙC¦ª†#¢HGd ·ó¡Æ‰APHöʬãÒ_Içb®YX†¦÷Q"¥¤œN¾*I#ëÞO¼YM›㫼)³òÕ…d^°Mø(ÕŒIên³H­ßŸR‘ÎÕ^78Ï£`ÒÕ-Ô>=#ñn®®•jfúÛ©Ùü‡WYlhî»î|F]ti!œ 'Dª|ú%¡éï4GYö=!È?PÀ +Þ°S, LqÎ*™C •–ëüðÓ¨Ájl>ækøƒó +þ„ÑŸœ¥*´ƒÃÜ! Àr™27lÛNâøò,% @/üùjÇëf­„@´RÛÛ¹Õ:#Dô­N tAÊ_‹+fQ$'ß“_­9ËW„~cŒ“üŠ¶aÀ-Í<Õçxî~)Bfvd%¦Zýd4Â*Œ^ÓÐÎõ(“nÖ•Á7†Îr{S¦æ”‹ÏF/h8“¤s$ÁN…t´æzi› +¡â¸0Çø$øÖ;¬šƒyëMŸžü tý LïXºªA- ø]·ö•9£ö˜À[æË#­oÏ}ô<°F—ŸA¤Ì Èúë…¾KUÇÅÎ}Žøv^¸úͺÛá´„W…Qo;,@o˜ùQ@&×_}=. š×Š˜c¯(¬t\™z±g¹8§Ú±ŽŽÞ¦LiR™‘KÇ>\*kuqzÁZfËáq—›J`X‡¤\TÂuZöc÷ò!ç³yuB«Dn~ ÉÜÀþ.†Ò ”á—NËL3%áoñó½&Z5á”"~V‘; …ˆ"´F&Uß½ãïö@µ¸!ÙTä‹f*§àLs壪чv¾tQê¼,ßANŠKøÏÒC+«kžˆ7DÊîA霋熻ò+ ÝNóÌâa’XœÒ±SK4 4ÖÌ͵4xÉwJµ#i­ç˜D“ÎOep¡rÓ@\ŽÆ[åâì¿›áÑ5ÝÿÂç=[-¦skÊóñàè»ÜÛ±ŠUþK›kÚ³œ<Çv†UÕbƒñlq£Çy1nð~üñ&:µéÿ¸TÌlúëøàÓ&ÍG ï:®!4sõ€½YOǶà“*júJìÔõ1aâž~©~þ@89¡ nÉOX¾€²–3ŠzµÎ— $uú1¼òÓ7º¥hÈxsB$ˆ&î*ùCÆeÙ:ÄÍ«˜H¸só H¡t—C±1ñP[Û—†üÒÒCÑŒ›ñ»—ZÏùµÓ^òº>ñ‰¬ÊÝ“LÛŠtG?‹wÇN„GõÕ={Ë MFhÝÎÑÓH:“LÄn‰1h¼wrÏofû2@„®?÷Ó`C;ìyÒÑÝtÓb$…’P±š;Òµ•X¿8ЖL¦9$:ÞŽ9"8¯^.¢Ç0¤ŒŒÒ àöžü1ÆP¸$@Öû¸iͦ"‘~|}ËUÑ}ü%ðPw¥Šlm—‘R™Ü¯Êý ®Sµ§Áé·Ê—ÂyëÑ]7ö{Ä—f'TBð¦ßi먵<|lüÙãaÖK °.Pª™úsëÙûØÈlSÐq8eg…S QYÂh¹•:ó„,!õ'ñ´z}xùWîúˆPÔ‡ÓÏàͳÄò JêMwÑé/[Nl«§ìµ=È»ªÔëj,¹8¢›&Ã~«sêŽÕU=¨cÄú‚‚?"R‘nöý¶œÇ9Ôuõ¨+-¸Pê0eí†íkE.BÄãós !\pæsÃú1Q¶$èëéÉ4šðw Ðïšc‰p(.),K?õ×ø52¿»ú'„ütC|4ŠÕ]¡¯+¡ŽÛsÛâ¸RäÍë‚èÔÅEB¥7™6†í?ÎÖ¥÷«èˆ_ïãf2µÌP ÇÆ5Ð_ÇrýÒ«°‚*è¼.Wj&g+¸ã7Ïß©<Ö ¡‡€n±0ŽÂAõÚôZ˜zµQƒÌ¹Ùž€ùE´'còÜÆÅ2ÓÜ hqsù|0C^[òC«Ó_ª†r"\‡Íøoû&g”(ÖÌÈÙùÝÅ´5&ïSRVí¯ûØP08²P$®Z¿—otb¥U gÁg-`-0ì½\açÆ쨖[Š¶Ç@zG+*ÀBM–"v½¡ÏY†Ia72±Œœv·Z=¥ãíî嬪óPcèˆ Ó¡K"ëÌ\üa¡×ìÝÏ<€nên¶ÇXiîòÎÔP5Ûõ駘c&[WZøKïÑ´Á.VwùBƒÄ%‹¬Õ“7ùCq#OÙÖ…L?À5„ß… ül‡WCÎ(°ùð|JÇÜõ$!Í»×&{Ï -–F7”ÒTâeGsörFu»Ža­QZ;€Ýš)ãºZnBýlðmC¨öý£»ÉJrÓü½ŽÄXãýÝC«Â¬¥»<9ìLœ@“|¾ ì5ˆ°[зcôÅæć<å“g„ŸÛ‡ˆ1L®Q#ª½˜“á ÒK¦P @V+£N·Ð©1ªœÌ˜RiçÓ'aªÅäyÈÔ£?‘@á´>s12O=9)B‘k{ÙÀ&eªÁÕGHr‡ëÚËÐ*AÛ_sWMÞýL0~ù´G’؈èz´ú½.ä¡À’G¶„â,uÇNm1ßèÙàÕ2ÐR ‡„ø‰ô·3€Åðª$iØ*£êóšðxÀóúW!äUá¡s-Ú°‰{Þ<éöþíÌù? +p¢0Ê6¬¹¯0·ÊzÂÐØÌ\‰÷HfdÑP4sGV9Z>Ê=4$Ì +“;·!iÍ1w4!Iõþˆ÷Ûû¼ïðy¤’2¶ +¼–I㊙•oh†ÿ9œ¡–Îí°Å`û>C¼]ûÖ ãP[iéº5o™òS·ÍÚ¦b¸ùP7xÊp]_x+Rl¥Ã×z/CUO² âRÀ¨lX ;² +VÍ]êAy³XH±ÔŒèyÒLåýkoù"-Õ6_XŸs(GÕjØwOÎÃIÕÕ\‘›"NÚGvBÓˆŽ…¤Yô·ØfàÄØ(ßÁx‰!´à‰%žM>¯Z)gþ•ÂEO“< Œáû_’W3ƒëLmJÍvD%Hv~Ð^¢bAXpÐÍ +å"UØð;z¯Ãg«Ô«¼L’"¤Ú-Û‚ Ÿ‚xwÒ×~ e]bþL‚¸=V›Ïóð¨-ÁÅû”Cª³;ÓÖoä®Í ¨ÐÒ&CdÊÜÞ<_}9Ížsßú–M©’£ê˜Eä‡S+ø{ðåÅ1Kg¥V£2¾ÒÁ5«È–­eéýê õÏŠ½SÅöÁ…®ÙK¼TùГ®°zc†\wír,Ö™yÆTôfDÇãF^±–ýtÚ|¶«w]’ÂйP 1dEi‰R—Ü@í ëH#É‘º#$ÞJƒµ€u!ê&äË+;YŠµM§æ.¸TinÖKÄæ“ÉZ1pk£|šYÌ™ÕxŒvâ³àõð1íÀtô^‡)9"ßb°Y¦ÇÐG}²ÿtƒVR=߇V²âߚР?V믱fì+¯†&cuOn”ˆÑcCì%LK”¤ðÁɟֺ娉䟇÷ ªú8çô»0±»A_ߛ¬ÄQø +¿,:Fp\îŽr|0`Ï!ÛÍéy¾.Nïè^(%×½ñ>Ü0Ø]^ÒC ‘$®Çž5~<ðrpÊÃz>ŠPãuÍx{¿šècAÊûß·™ÍZÆ~œe·9^|Ø™ª´:öÛ9½0 *ÿ}ôõW'¼D>½³}=à -zžûcêÈ^‡õsa`ÔúþçBº&¿¯ÈÀ}Ü–#üÝ×õ,¶…ð€5nXœ`KÃ|Úªup´ëqª£¦Ws•³Fþ»‰ûë»ÕnË·+1§!NqM;Ú¦”+1Åôä@2Z œXÞ%ÉŠû:bj…Ä UC¾·'èÈVõ ”ß½Eð©°ñn7I”ȕ䦑£¼"o~ô$¾ÇííD`i +XãÙS9´½ AÄŠ›˜ì \¿j‹Gq‘ñ YÔ4Ûûª2x"…þ€¦Æ">5IåñOù¼Ðù)þþbZòZj÷Ö›ŒEŒ×©8Œ†–BY‡tç÷]Ü þ×™¢Ë€9£ýd%ut o¥tÃØ_‹Òs¼#Žp9Ä RsˆNóÊ Aα›‘my_êB[öéNU9Wɶ¿~›ê?霨˜–’"¿²¾ê ³/8 ©Ž‡6Ý!Rëú;„9jº‰‹$:·ß³ï{ÇwBí`#Œ…Üä$Õgš³ŽmDÇØ<& P”»¯hpTÒ¢IëWZ²å–[ä§ÏL Øgî{]íCÇ|ÞªLkRíyÌ.ƒ·çý uÑdgÙ'Õ·ôNY•XJ A!O¸0Ëž9v(H§"lðp> endobj -951 0 obj << +1226 0 obj << /Ascent 624 /CapHeight 552 /Descent -126 -/FontName /BNCTYM+NimbusMonL-Bold +/FontName /TENLLE+NimbusMonL-Bold /ItalicAngle 0 /StemV 101 /XHeight 439 /FontBBox [-43 -278 681 871] /Flags 4 -/CharSet (/quotedbl/numbersign/plus/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/semicolon/equal/at/A/B/C/D/E/F/G/H/I/K/M/N/O/R/S/T/W/Z/bracketleft/bracketright/a/b/c/d/e/f/g/h/i/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright) -/FontFile 952 0 R +/CharSet (/quotedbl/numbersign/quoteright/plus/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/equal/at/A/B/C/D/E/F/G/H/I/K/M/N/O/R/S/T/W/Z/bracketleft/bracketright/a/b/c/d/e/f/g/h/i/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright) +/FontFile 1227 0 R >> endobj -2150 0 obj -[600 600 0 0 0 0 0 0 0 600 0 600 600 600 600 600 600 600 600 600 600 600 600 600 0 600 0 600 0 0 600 600 600 600 600 600 600 600 600 600 0 600 0 600 600 600 0 0 600 600 600 0 0 600 0 0 600 600 0 600 0 0 0 600 600 600 600 600 600 600 600 600 0 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 ] +2715 0 obj +[600 600 0 0 0 600 0 0 0 600 0 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 0 600 0 0 600 600 600 600 600 600 600 600 600 600 0 600 0 600 600 600 0 0 600 600 600 0 0 600 0 0 600 600 0 600 0 0 0 600 600 600 600 600 600 600 600 600 0 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 ] endobj -938 0 obj << +1207 0 obj << /Length1 1612 /Length2 18760 /Length3 532 @@ -11088,7 +13706,7 @@ endobj >> stream xÚ¬·ctåßÖ&›£’Û¶mWœT²cÛ¶m§bÛ¶]±*¶­[ÿsºûíqnß/}ß{Œßšxæ3ç3×c“)ªÐ ÛþŠÛÚ8Ñ1Ñ3räÍ­:;ÊÙÚÈÒ)Mlpdd"@C's[QC' 7@h ˜™L\\\pd[;wsS3'¥š² íYþ ütÿŸž¿™Žæ¦6ò¿.@+[;k Ó_ˆÿëD àd˜˜[" -ŠšRòJ y5€Ðè`hPtþien57Ú8©&¶«F¶6Ææÿ´æHÿKÈ`p´™ÿMºíþqÑì€Ö掎¿æŽSC§¿3p²˜ÛY9ÿCà¯ÝÄö_„ìlÿFXÿõýS´utr4r0·sü­ª(*þožNf†NÿÔv4ÿëØšü4¶5rþ§¥ùþÂüõ:šÛ8œ€nNÿÔú ›;ÚYºÿ­ýÌÎÁü_4œÍmLÿ‹-Àhjè`lttü óûŸéüWŸ€ÿ­{C;;+÷eÛþ+êq0wrZ™ÐÃ11ÿ­iäô·¶©¹ Ã?‹"ecb `bü·ÝØÙîú\€ÿå?;Cõ—„¡±­•;ÀhÇ oëô·$€òÿNeúÿ>‘ÿ$þoø¿EÞÿâþ§FÿÛ%þÿ{ŸÿZÜÙÊJÞÐúïüûü}al²€Þ+C‡ÿW¸¡µ¹•ûÿ!á?5€ÿ&ùÿ#ådøwB6¦a¤gü·ÑÜQÜÜ h¬hîdd01´ú;©ÙÕlŒVæ6À¿Šþk˜:&FÆÿð©š™YÚü3z¶»€6ÆÿIþ¯Hÿ¢Î ##¬¬$KóŸoê¿¢ÿjï¤ên÷—ØÿhEÎÖøþÁ¶uxÒý½tÌ,ö¿9™˜¼ÿÕþÃô_g9C's7€öß–™þÕøÿøý×I÷?`ÄlŒlÿÙ'Cã¿ëõ¿ ÿ¸œþªú¯ÿ·áÿyþ×¢n@#¸Õ߶F‘ÿ$þoø¿EÞÿâþ§FÿÛ%þÿ{ŸÿZÜÙÊJÞÐúïüûü}al²€Þ+C‡ÿW¸¡µ¹•ûÿ!á?5€ÿ&ùÿ#ådøwB6¦a¤gü·ÑÜQÜÜ h¬hîdd01´ú;©ÙÕlŒVæ6À¿Šþk˜:&FÆÿð©š™YÚü3z¶»€6ÆÿIþ¯Hÿ¢Î ¡)+¥(AóŸoê¿¢ÿjï¤ên÷—ØÿhEÎÖøþÁ¶uxÒý½tÌ,ö¿9™˜¼ÿÕþÃô_g9C's7€öß–™þÕøÿøý×I÷?`ÄlŒlÿÙ'Cã¿ëõ¿ ÿ¸œþªú¯ÿ·áÿyþ×¢n@#¸Õ߶Fö¥©F{1­(zR€—ùøÞ$T}¨›ä4 z%ˆégQžW‹²ÛZìŒê»“JÊzÅïPߧ;X`®ž¨üH\ üÐIí|ŒRëc1:QA¾Õžž‘'?=R Ž õÜ@öíãÑäÄÂ’ñ¸@ ’GúÙçà h©Ux†SA¥7!àÝ´_}jt{êå‘‘â’FX˾*šæ¯Ù´Ë¾'A¦· ð&Ê9H¶îWþÀ¼žŸŽäJœæšËýZw&sÄâmŸ 쿵$ œÉ„®'~»¦ìw 󬵮¦~íCÊ]™Qê,©wmÚ'c¤ w®Diµs$óÐY–1¾—f‡ÙÄ&>.jüäë賬9“5ÎÕu¨ÍÄV¤?m=Á8ib/4l¼˜’lºÖ’Ÿ$):Srïð¹ŒtéÇ#/sƒydŠü¡ _•vÏÐX¢ÖÙ"» ú”4Ú]Ô†Üf†·”-FêÕˆFG‚„ùs!kt> @@ -11169,35 +13787,35 @@ i ^hâŒð·¹ œ£“hZ™Í/øÅ_à7œÀ+P¸¸&&êåî$+Nȶp®Ô ~I(–»c¹ÚŸYªÓÅg¶%ø¥p%ö>­’H¾iL¿\ÚõÐß(¦µâ_«8Cƒ—R{‹ Žµrð¦ëØíû‹0Ê{‡˜ÊQê¸2‰«Zœa‰ƒ†*7Äc¹äJî„I›ÏüìÒ]©æÁ 1=Š¡å©òñS€MX¡¥GMøªéþP¢‹:*½ÙOT9†ÜD¨*ÀzÞÃ*Úž“¬ÿ°Ë_hg ‚œ«ê9ŸjˆŠ"J7Þ®(ðhT(ìâ ª¦¼ÜðÊ™§Ä‹V¬áÝq -oò]ç }£¯9B‘7õ· öœH{È­’ëæi`T&éVÇãs"¹‡‡ªÃßÛçVMo¼iá÷׈â{C„^×;¿_g¿`,·÷þ2 Ún“ R ɫǶ]ÅjÍuib°ƒãÏV!QÏÆ>²¦aO<ö”ñOÁxƒªH²$áófe°§Åû›ê¥úКxÇÑiêÅà>ò$­–Ìy"-Ú-ŵ ôý‰¤Ëq ¸ŠÖˆÕ"™[Ø m¥cA¸¶¹"t8Q+PK¥ìó÷Ñ”¶ëÛãh_“ ®$+ƒº‡¼S¾ÎúÜþµ$áØ™éezv~7EhÅZÞ‚¥ÓªãHÝåûm®Ý‘(ãŸÄ"Þïòwnúê›»ÉÕ”^«¦y$3î3i=+iÿWuÈæÔmâ’<£Ⱥ][±÷QgShSÝ»¤SñºïX±wû@`z>ÍÛòÈëB¶"Æ®.(ñôAàN¥Ã|³w®3¬ín1eqÞ¸XäL%­1;¹MÊ®¦*Åÿ^OìU©‘yo•½§ìRùùÑ© lå™Õº©RéÓåú’ØyšQÝÅêØÌ·XçY2‹†¸Ä¾ŒPñ+«Ö$ßo¼7SæDEÏ–GÙËËGªvË.¼–Õ£ª¾PH^ ÍuòñjzZ+3àÆ´¤Nc<ÃÃe™åGKB.þ/Qü?øŸÜ|Ý]ƒà~.>ÿêQÞÿendstream +oò]ç }£¯9B‘7õ· öœH{È­’ëæi`T&éVÇãs"¹‡‡ªÃßÛçVMo¼iá÷׈â{C„^×;¿_g¿`,·÷þ2 Ún“ R ɫǶ]ÅjÍuib°ƒãÏV!QÏÆ>²¦aO<ö”ñOÁxƒªH²$áófe°§Åû›ê¥úКxÇÑiêÅà>ò$­–Ìy"-Ú-ŵ ôý‰¤Ëq ¸ŠÖˆÕ"™[Ø m¥cA¸¶¹"t8Q+PK¥ìó÷Ñ”¶ëÛãh_“ ®$+ƒº‡¼S¾ÎúÜþµ$áØ™éezv~7EhÅZÞ‚¥ÓªãHÝåûm®Ý‘(ãŸÄ"Þïòwnúê›»ÉÕ”^«¦y$3î3i=+iÿWuÈæÔmâ’<£Ⱥ][±÷QgShSÝ»¤SñºïX±wû@`z>ÍÛòÈëB¶"Æ®.(ñôAàN¥Ã|³w®3¬ín1eqÞ¸XäL%­1;¹MÊ®¦*Åÿ^OìU©‘yo•½§ìRùùÑ© lå™Õº©RéÓåú’ØyšQÝÅêØÌ·XçY2‹†¸Ä¾ŒPñ+«Ö$ßo¼7SæDEÏ–GÙËËGªvË.¼–Õ£ª¾PH^ ÍuòñjzZ+3àÆ´¤Nc<ÃÃe™åGKB.þ/Qü?øŸÜ|Ý]ƒà~.>ÿ,£ßendstream endobj -939 0 obj << +1208 0 obj << /Type /Font /Subtype /Type1 -/Encoding 2140 0 R +/Encoding 2705 0 R /FirstChar 33 /LastChar 125 -/Widths 2151 0 R -/BaseFont /KKBRQL+NimbusMonL-Regu -/FontDescriptor 937 0 R +/Widths 2716 0 R +/BaseFont /WYLIPG+NimbusMonL-Regu +/FontDescriptor 1206 0 R >> endobj -937 0 obj << +1206 0 obj << /Ascent 625 /CapHeight 557 /Descent -147 -/FontName /KKBRQL+NimbusMonL-Regu +/FontName /WYLIPG+NimbusMonL-Regu /ItalicAngle 0 /StemV 41 /XHeight 426 /FontBBox [-12 -237 650 811] /Flags 4 /CharSet (/exclam/quotedbl/numbersign/dollar/percent/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/underscore/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright) -/FontFile 938 0 R +/FontFile 1207 0 R >> endobj -2151 0 obj +2716 0 obj [600 600 600 600 600 0 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 0 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 0 600 0 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 ] endobj -898 0 obj << +1150 0 obj << /Length1 1620 /Length2 20127 /Length3 532 @@ -11205,7 +13823,7 @@ endobj /Filter /FlateDecode >> stream -xÚ¬ºct¤]·.Ûv*I§cul'[£b§bÛ¶mÛ¶­Ží¤cwý¼ï·÷>cŸóëœý£jÜk^s^×Zë5FQ’)ª0›Ø%ìlA ,ŒÌ<5e ECkkC ;Y)¡5௙’RÔh²°³3y@€Ðð퀅›› jgïîhafPÿå ¡££ÿ/Ë?.#÷ÿ@þF:Y˜Ù¾þ}pZÛÙÛmA)þ¯U€@È0µ°Dµ¤ä%Ô’òjI -ÐñoŠÎFÖÆY c ­`jç°þ÷`lgkbñOkNŒ¹„†'{ ±Åß0 ›1Ðþˆ`t´±prúû °p˜9Ú‚þÎd°°5¶v6ù§€¿vS»dïh÷×Ãæ/ö—LÑÎ ädìhaüͪ(&ñï:A憠r;Yü…v¦=MìŒÿié_Ø_š¿(ÈÐÂÖ ºþÉe˜X8Ù[ºÿÍý—ÌÞÑâ_e8;YØšýWôG ™¡£‰5ÐÉé/Í_î¦ó_}þ—î íí­Ýÿm÷/¯ÿ¬Áä´6eD`ùö7§1èon3 [¦¶Š”­©€…ùßvgûÿÀ\€Žÿõ?{†æo†&v¶Öî )“¼èoJõÿÊŒÿs"ÿHü?"ðÿˆ¼ÿoâþwþ—Cüÿzžÿ;µ„³µµ¼¡ ð_A€ÿ¸c²€. ãÿÍÝÐÆÂÚýÿðß=5€ÿ®RhælmèøßáÓ ÛšýU„›‘ýßV ' 7 ‰¢ÈØ`jhýwVÿ²«Ùš­-l5ý×8 ,ÌÌÿ S5·0¶²ýgøìÿ†€¶&ÿ½ü¿2ý«x&Iuºÿý^ý—Ÿâ_ýAªîö@ÀÿŸDCÎÎä?ÿ°ˆˆØ¹<X8™ ¬ÌìÝ߃ÇÍÆâýÈø/"–ÿZË‚-ÜÚÌŒÌÌ,€¿ßÿñù¯•î£·5¶3ùgǨ€ mMþn²ÿ4ü;;:þÕö_çþoÓÿ±þ×vÝ€Æë+vƼA–i™é :ÜÜ‘)1í>È‘`ûÒFÕ¢¿»^ß´°]îJƒÚ`ƦžßíîËçöŸ‡Ò´Gc}8ÖT½)Àë|"o +xÚ¬ºct¤]·.Ûv*I§cul'[£b§bÛ¶mÛ¶­Ží¤cwý¼ï·÷>cŸóëœý£jÜk^s^×Zë5FQ’)ª0›Ø%ìlA ,ŒÌ<5e ECkkC ;Y)¡5௙’RÔh²°³3y@€Ðð퀅›› jgïîhafPÿå ¡££ÿ/Ë?.#÷ÿ@þF:Y˜Ù¾þ}pZÛÙÛmA)þ¯U€@È0µ°Dµ¤ä%Ô’òjI -ÐñoŠÎFÖÆY c ­`jç°þ÷`lgkbñOkNŒ¹„†'{ ±Åß0 ›1Ðþˆ`t´±prúû °p˜9Ú‚þÎd°°5¶v6ù§€¿vS»dïh÷×Ãæ/ö—LÑÎ ädìhaüͪ(&ñï:A憠r;Yü…v¦=MìŒÿié_Ø_š¿(ÈÐÂÖ ºþÉe˜X8Ù[ºÿÍý—ÌÞÑâ_e8;YØšýWôG ™¡£‰5ÐÉé/Í_î¦ó_}þ—î íí­Ýÿm÷/¯ÿ¬Áä´6eD`ùö7§1èon3 [¦¶Š”­©€…ùßvgûÿÀ\€Žÿõ?{†æo†&v¶Öî )“¼èoJõÿÊŒÿs"ÿHü?"ðÿˆ¼ÿoâþwþ—Cüÿzžÿ;µ„³µµ¼¡ ð_A€ÿ¸c²€. ãÿÍÝÐÆÂÚýÿðß=5€ÿ®RhælmèøßáÓ ÛšýU„›‘ýßV ' 7 ‰¢ÈØ`jhýwVÿ²«Ùš­-l5ý×8 ,ÌÌÿ S5·0¶²ýgøìÿ†€¶&ÿ½ü¿2ý«x& )UuIºÿý^ý—Ÿâ_ýAªîö@ÀÿŸDCÎÎä?ÿ°ˆˆØ¹<X8™ ¬ÌìÝ߃ÇÍÆâýÈø/"–ÿZË‚-ÜÚÌŒÌÌ,€¿ßÿñù¯•î£·5¶3ùgǨ€ mMþn²ÿ4ü;;:þÕö_çþoÓÿ±þ×vÝ€Æë+vƼA–i™é :ÜÜ‘)1í>È‘`ûÒFÕ¢¿»^ß´°]îJƒÚ`ƦžßíîËçöŸ‡Ò´Gc}8ÖT½)Àë|"o šþô­¯œtGLz¥ÈéQž7K²;P?8˜Õö¦””õJ>`ˆg:Yánžiü(\ ü°¾<Ù£ø§6Äbw¡5aÔž_|M<}~¢î½…î?$¤Ë‰…§äuBþéçC(øC­B¼ªùÕi{Ju ¡glŸÏÏìC(»ƒ¢ÈbÓËZÁçjð§fÌÁpC@¶VBjä+s^"ò“£œŸpÖj×Ñm¡HNZ¬¹Šù—;Ão{ô«OŠ—©š}¾ŽÈïqM gÀÁõ@‰Î @@ -11279,136 +13897,130 @@ K p÷†ÓºùáXk)iÇÝKqkùÈüÙ²ú´{Ô°!¢1µçsßÚ3‘à æý“B òÐ2t¦£ƒ% ]–Aþu²"ÉÜß2åº.Ó “ñx•s,õ)®k¾óÒ>hœýbyZÃ÷-ý$ËbÇ;¨´²* #Œ6^ÿ´Œ‹Ä*jj¾}5™üÊ­tÿg ›­ûá=)ìGõ™;RVÛÚ½wV*îM\ˆšhßn`ÇPÙºzÇ'I~©VŽ;&븙i—w âc3:™S‹åa¥40ÏZ: Moè¥Ø~ƒÐ#YcÑV„³IF^¸Övú¾&ÕÍBoªzôåÒ½¢šºˆ<è@Õ Ž!ÄVo£Cé·³s~íAãŸ)4°jsY™ÖÑÁ¤¤Òøɉ cxg4Hc=‰‚­|(—æ3§‘»Ñô¯ðÑqr1¥~tÓ™²süçŸVý;Ë}I†õ„=*š½Â!³ ®8¸²ù ¢Ÿ{J½ÅhJ$‘¹Í2ÕtKcÇZ=P¶)»ûøÔÂwË,û«øƒˆcÌm#ãdxÐu!^ Ú9ûi7ŸÙJcÔŒ]+µ jÆ»Ò_€[hI£YÉì0…òÇ*껪¦úݳj€í¨ž¨ß`Ù?8sGx9g3ÎîèñÙt÷:n:—SúluHx‹œ›ÍÉPo·«ÃJAüÕh€ß¾ÅW'ˆÃô´B ¶q…¡Jˆ`“ý kaæ®´bg>–MO”¶æB8uk—ÄþÙ7)Çê®Ü¿5GVQ(ë¿P­m-FG*åTA¸¡WK2z)· Ž×?3Ì›QOl s¹xŽ5WË–§zGϺß?ÁyËÇDóÛ8Þ6<,óyÊœ³%ɾŠaîjôër¤ôç ³L.¸!åeÖ&A—¯y!qíµ¸`Û®8 &ƒûCá°ˆ×P·KÄMZQƒñˆR“!»V¸x3ËßÀÃ'£l{…x|#”ÄÒ,ò9r&tã|¼ a¥ïéæ3sawÄø² Ã××ÿuåÝ™×Ãùv¦&R®É;Ƴo©5$rÇâ¯%ì»iÕav·4Ë EìØÔ;E6'µ…¹ïh;ž7\oqkÙñ*¯u¾+ÍNcýàÿOÃõÿû‚ÿ -¹ƒ%ÔÕÝÙêjý2öáýendstream +¹ƒ%ÔÕÝÙêjý'óâendstream endobj -899 0 obj << +1151 0 obj << /Type /Font /Subtype /Type1 -/Encoding 2140 0 R +/Encoding 2705 0 R /FirstChar 2 /LastChar 151 -/Widths 2152 0 R -/BaseFont /BGSVOO+URWPalladioL-Ital -/FontDescriptor 897 0 R +/Widths 2717 0 R +/BaseFont /FITVGS+URWPalladioL-Ital +/FontDescriptor 1149 0 R >> endobj -897 0 obj << +1149 0 obj << /Ascent 722 /CapHeight 693 /Descent -261 -/FontName /BGSVOO+URWPalladioL-Ital +/FontName /FITVGS+URWPalladioL-Ital /ItalicAngle -9.5 /StemV 78 /XHeight 482 /FontBBox [-170 -305 1010 941] /Flags 4 /CharSet (/fi/fl/parenleft/parenright/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/A/B/C/D/E/F/G/H/I/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/a/b/c/d/e/f/g/h/i/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/emdash) -/FontFile 898 0 R +/FontFile 1150 0 R >> endobj -2152 0 obj +2717 0 obj [528 545 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 333 333 0 0 250 333 250 296 500 500 500 500 500 500 500 500 500 500 250 0 0 0 0 0 0 722 611 667 778 611 556 722 778 333 0 667 556 944 778 778 611 778 667 556 611 778 722 944 722 667 667 0 0 0 0 0 0 444 463 407 500 389 278 500 500 278 0 444 278 778 556 444 500 463 389 389 333 556 500 722 500 500 444 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 1000 ] endobj -801 0 obj << +1017 0 obj << /Length1 1630 -/Length2 15892 +/Length2 16214 /Length3 532 -/Length 16775 -/Filter /FlateDecode ->> -stream -xÚ¬¹cx¥]³-Ûv¯ØfǶm¯$+6:ìض“Žm;éØè°culãëç}ÏÞû\ûœ_çÛ¿Ö=kTªY£æ¼îûZ”¤ÊjŒ"æ¦@I{WFV&^€†ª–²‰­­‰9ÈAžQÕÁÎð×̉@I)æ 4q9Ø‹›¸yZ@s€8Ð ÀÆ`ýúõ+%@ÌÁÑËdiå - ùËAKOÏð_–\¦^ÿütYÚ¨þ>¸mí€ö®)þŸÕ€@€«`²Ä””ud¥4RŠ) =ÐÙÄ ìfj 2ȃ̀ö.@Z€…ƒ3Àöß €™ƒ½9蟭¹0ýåq˜\f ¿a@O3 ã?Àèlrqùû ¹,Mì]ÿöÀÕ²7³u3ÿ§€¿v ‡äèìð×Ãî/ö—LÙÁÅÕÅÌäè -ø›UY\òßuºZ™¸þ“Ûô8Xüõ4w0sûgKÿÂþÒüE]M@ö.W §ë?¹Ls‹£­‰×ßÜÉAÿ*ÃÍdoù_0œ–&Îæ¶@—¿4¹ÿéÎíð¿íÞÄÑÑÖë_ÑÿòúÏ@®.@[ &V¶¿9Í\ÿæ¶Ù#0ÿ3*2öV–ÛÍÝÿs:ÿ«A4ÿÌ íß"LÌìm½æ@ fE׿)4ÿo*3ýωü? ñÿˆÀÿ#òþÿ÷¿kô¿âÿ¿çù¿SKºÙÚ*šØÿø; øç’±ÿ?¼Mì@¶^ÿ7ÿÿî©üw‘ÿWW“¿­±·ü+ãW&–¯ÿ@.’ O ¹2ÈÕÌ -`abû·Wÿ²kØ›mAöÀ¿šþ«FV–ÿ†©[Ìlìÿi>ç¿! ½ù¯ÿ¯LÿªžY[GK\Y”þÿ¸WÕlÿΗ+÷¿#”ÿN‚«º—#ð¿Òi)8˜ÿçâ>QQO€7#+€‘‡ýïdc|å`÷ý¿äþë­L\Až=&Ö¿¤ÿü²ü“û? ƒÿF#aoæ`þÏ쨹šØ›ÿ·ÿ4ü›¹9;ÿUù_7ÀßíÿÇú_ƒzÍV9˜ñ[§ge¸Öáæ OŠë ô±B‡8–6ªÔ8ôú§‡o­4~« ajšæýh÷Z:q|ß—¥;íñ¥îM^ù’Óö¢ÿ¦êä¦?d6,EÎ8ÕŠö¾\”ß‚ÒåbÑ<Ø™TQ5,yƒ!žîdw†»|¤ w/ À¢xpDñ3KkˆÃîBkèûqrJ•tüø@=462ü³÷ºŸ>7ž’Ï -™**À)—PHW£B¢ªU³m·WÛÔOrí]VÉ• $«ùqyĤ"õÂzŒf<0ëûë£Îðf}/Ÿí¤>bêFè,VØUd‹ÕƒæÔJlNÍo’©+¬OXÏ1Ï-¼§c-NÂ1ipÝ›í\AÖµ?ªª…¹{G.ž'Þ½µ$5õü^oDÌÒ’j8Á¬R/ë‰yÝ࣑<Ì`½^ -úêì`uvdé,RHžê$žkK‚>&Y ¤ºÛ”OØ&â„o™kâÆœm§Ù WëÙÉ -¨œ/û«Ð[BÒó´`Ûtä¯äÍN¿GfáĈHªýmVéDÇÏ“Ÿ”Ä÷¦Y_kÉóÍ+èü1pÇÒ¨åÁ³ñÂjD•jÊ -Ga1Ã8‘¯YÛ«Ÿãн>½l•ê!¾™Ç”œ±Rš¶?àW'‡Ù_NÄåƒÆY4!aÔ„ø‰¥– -/ÓLòFºVÕa¥¹òÞ+sTe˜1‘G·G]<ÖlI¯7E³±+’Ò=‚,Cš«OÒØor.¹kÕ /ÁÓŒ’ÍU±Hi~|ŒÖwÚkµqš‡~ƒ¸Ö£7ö³"ÄÇYæ…ÅO k_ã1fo4,ëIoböm5¹‹²O½k‚uÒ¥2ƒÞ¡úd‹j¨7W})“Þ‹¤ÐϾÑdT¥wÇ„{•ü¦ÒfËç«Ø™#K˜€Nƒh çuÏÏ%¢>ÞØXñÿàÛñÝ%rá§_&ωbksà£uÂÑj£«ÓEŸ -ö:çkØ¥»ãÆðòvÏ5ÅΰÂÜ0p!.ZÍ2§.•`Õé;ûòÒŸ¾´E 'ôòL‹~­'"Bδ •RÛ…ê뚀ÄÌË1ú€Þ‚`0ýzл»-õ®‰ÑÆöø$·«|Â9˜ ühˆô`´6GÞ£h‹º¢:"ÎÙ;¾M¯_­µJ%îo%ÒÌnck—ý'y¾‘ýαšm¡‹¦ƒ”õíÞ*{ iwQ[™¤kžç Ë tîF!cö8äÞŠNßãÇx´ ’Ü!Ä’¥¼Ö¢¦¥Š—Î~_ó©àH¶ýÛ±1%Š–±Ú¹ Ͼº¦á¢Õ>ÝMÐAŸdZ˜Ê51Ýb1ܤɬUð/ -‡ØRŠ#ÿ>w@ÿyXõCulŽ+Œ†ÌA馹°\¾ç­ÚÔ¢bjdT9äú¶’¥«×zbzÎK÷÷§©¿”fí*õ }æiEÔAž[ÙI ßý¹+¬C ƒœí4IX¹˜z²rw}ô‰öRj÷yÉX@È[ªiË fó„zyuôtT5åú4B›I—”ÉK0Ë>oIqÖÛoß™KØgv † -Š…â!^ÊÄ,õˆ¨òæ–áë,…â­X˜È(q"=Ã/šëø4ßß2ku¢Ã§oÈ\ɘPTø$á9¶#=¼.ª…ªI$¹ Å“‹Îšø©™ˆûz·Êp^‹T6ÞmyD¨g=_¤.Ó Ê—ÜÌOcVP‡¤.â³ù{:²|GÂT˜Žë¿·Bo¦w·øÐõï:j‘´åêÿ€Z uHT©—btcý½B.÷IØÒå~¨2Ò7*Qõ>;³2û ÃP“\³uŸ;k¦«Œ¥3b@òÑ©6­ZKî#C\òËT2ÜhŒµ`{ÕÅAîK岦G«³_ÄZ¥öc¤Ü>ÜÈÀâ¤k÷égq}2Ïþ=¬«E(Š¿'Ž - օݧ{ÌæßÖRáï›I“¬ïØÃ4†ºéd`ðe'¢ò›KþÈé•ëÀ0 xö¯´ØQ¤Î]åhÓJ;ZL½"7Ò–ñà|êTñÌãço2R°×%‚¬Xs­üòc–>`pȸÔ¢D…Üo½I[«4uÉG ‡äÇ]F?bo÷ ¦"1I[#– x%‡x‹¹žÆɬ²×Á>Эs*´Ïühd&Cîx3Ôà9‹œkMŒ™"SàÈÕÍŠL€''ƒ™C¦eòœÿ@ËÞÀ4:%½BÔ‡?Ö´OH6c{h¦5/çÕ -5’QÄ„Qƒœqó™0=l­\αç -¥×$á_~Т:ò›l -Û…úMÚ„m>ô‹'Á†ž§MýO³qÎCÄ]´5CXá*\•MN£dtWî -BJ!•l!~X‡’Õ É•aó’1Ë"/°E©ø!Jü÷™oó§KDMk§Èéw“F±§Ûˆ{¹g,˜6Q4²«lía¤WÈw©4q’7_úU0"¾B` Ï"ø?(±*ë2­³G€ ¡fÓêQXŽŠJ5úºîÚ ñ%èÐäíb¡Ê¡ÓYÉ_c¸p'vÿЮ/]·mÐøD‘ /³îwòŸÙ|&æ>¡®GSÜ° ¯d9{¶£IóJŠK÷9fã¢éŠ ©þäÁõ@ñ¼9xŒi,P¾*=cùüà‰µNm6O—^ E› ªÖž©ÁôЮº -M2tÉ»bqJCgª`AjI@vr]Ú@Ö *Ó ä½è¼‰_‰ä”/ú¼æ/ -¨á"R’´‰öÆ$ä ÚU W=ŽgY·'æýÕ ±M‘‚‡{}•ÜÿöA®ô5±ò½UKмÎf6ÞÎ'2¦g¯,5ƒŽh­óçü¨6à«ÈÇ -g!ò)#îLI•eÇO~,EbÛà ¢.ÈÁî=íõÙL(Bćơ=²a~¡Ž LÌjSȤk²5ž€ŸH½ºFŒ§WiWམXøwÖýï… \#A†%ñ³‘Ë2‘j Ç´½Û¡õ´„P2’åíC¶²‹’³o K,\QÛ²ÔŽ‹¼Ü3WÚ ‰SÁ™Û3èF#ëšlËñ°ÁºÌ¬§T{ô?êu5DZ—b!⺂Æn9Š#M‘y^Qi$ë\Êo#£ :“ÐÇÏq`{‹!ˆC%oÝË|°¢’N½`^¾VÄ:z´ßÂØÚ˜Å,Žž”\uyFÌOàø6ëÞÀ…?z†t+A×ÜéEî>VµÝ´çröt'ˇÅ<Ë9¶]ÄöýÞCðò—|fŒK¨ª£µ®ß( ­Â‹%SrÜ3ÀðYÙ%ŸTu3×dhtéõn&ƒà)pMþ¬'Ö]ÛPB4ÿA÷ÃID€à·GPDŠ¸U\%%2à!¬ÂúKÄÖ£Ée”Ø“ê6,Ù:'Û((í,ïÌ»DÜBó¦úƒˆ®õI›™½a'=I˼\ùKrå.;_ ŠRP,¦èÜ J¥0Ÿ(„Ï ÂmÃ*¨ù}‹ZP¼>iI*ëz¦á-µŽdy áäQ‡~zò,!Ÿ«ËöHéqŠûˆ\óD#k4I6ðsÝö:ïBéã Îö'è$Ë/©ŸìöU]€’’ƒLWF: KEÑx.A?C;ù'CvãR§S=ËÀÝ•jX( “ûµÏ~&/H«¼‚‡6œÀ#Žz„˜»»Jýx0ëÖ0MÞu J£ Ä’¹)AË©GOûØ+VôývŸsÉŠJǾYNaú»È[sûË#…ù«YñÙ/%AœrºWó¾B¬ÕDTi;þä$wÐy.×oöiÉÕÙªne\½þ„1Xï§Áõˆ_°ˆÔ‹ i‰}]hœ‘DÉF•X8)RŒ(êe+QBöìøYýú$ø𙨗wš4ÉAÑåFç[/Ìï(=Š|ú11ǹÌYfFã–s»Ø'ú[þµwù|¼ŽÇÛ,ë¢39i¯æ¼Žõšm!¸«uEÖê†î .>Pr˜áËóOªbeå£/Ï”£à?cÛ^0ô²³Ë«Lâ9}IÍv#VSgzºŽÙÑ‘ðîàê)˜¶©£p.´ÊI*ðwgÚË&)ƒâ²oUÌäšH€+ßÞÉ¥al‘BéiWŽÎG^ç˜ÀØl8„¬~ÇH/«æ5Àc/ý -q,‘ô¡ÇúGåKco IÛ³ø©‚Ž Nv#j»£)Ÿ—“Ì·‘¶ý¤C±Œmm§ -ÄáÛì‡VJ@ÂyÜ4A“ß(9,”÷-mZË)é‹ò8ÕªÇ+“lvÕcÊž|:"Ú!ý XjñÕ,NÛO¤y|¯aëŸÚaƒ™zßÀæÚ:µfm¦M?3r»’~°OƒïäɈö…‡«Ê2´Xñ#L9¡!&ySzDØõvÿæIp o<Èk`Ð S“˜ó¬º=âp¬ Y1'&ŒDŸpªT„¥‡˜VôëÿD·Xø}ÓË%0“{ Üò<‡·Ë|¬ôùØ8¯¿¦‘‰ÿ¨Ý.‚hƒÍ¢Ij9ì¤AææÕþpƒjFÓ›¯ +ôhЗ$™-ëM š:ËpYÒRYýæQ®îCš¯pc[`÷ÜñYÎþ^b}oï¿-æ‡qTBäò÷ÎõÀ”¸x•½ªµÏÜ«i HL›´,H÷RQf.úYaáVx þ&ѼzkK.|×{ih—W¦ˆvJwÂmà@Ãt i» ß–ü¸Ç.ö• £ˆ¢&ExìÓªúp6î#_8?¥œÕ”#ȹFøØËò4xITëèŸU¤l&€rùÞc—ßÜ°ÕÝ«C°*¿÷›Ãq(E–ðŸ2㾿Gµ:Í>‘ùÎâ>ỹ†o÷S¨æ÷yoúšíUCôM-&7qD¥jüãR…ñKs30¿¾»eçψѦ[óÚâ/×ÓI–<÷ÉgÓAiÐfþÃ.|ùž÷F?—$àvGQyuº‡ÚwòÄ@ÕTˆ•MU‰ѵEf|ähÝÖ̘®8 äiÌ‘D=_ND¹½aŸˆ?Æ)þVELK‹ÎR—èp-´ÇhÆÓDºøZXFÛ!¹àºYû,£ùðŒtó×ìX·¿Ñ¬7$ Ž»¤©„,óYch÷Ç›#—s³™&úÞ Ä¯Ã4~Œ•5-ò~Çc½ëweAdð)9Æ’6Éò‘Ðo¿Ý¥Ä3'ÄjhD(ÅêÁëi¾­!ÕrßÙÃpp¹g¼pä¹&<¸$LÎ}’²OÏÆ1™3Ñi Ê®0®©Ü•.;Y£34wçP×äU%± ` 6=ñfÛ8ÅT…Gç+\TÔ³7½ú¿üš«²ò³k“eNµLXQt0‡îÀÕÒ:_‡YšÉéxOmY|AÀ×^ÙZY Ò|4’ø†â·à:Ê>²Å)ZaYñ7¬Ö›ÅìiYyG×ì—'R>PìÕÕ™ùòrÖ¹š°[}Vì Ãr1¨ £É¢iÔUi©D¯ lu2CR.’ÉQtUÌä¡8ÆÍm+½Dø"‚Tq_…„p/×Ù^$Àw,säÞÚÁ­Á„¬±Ð%çͧÇŠŒÚ·7Öaeýì³^›)ô,ˆò]tïéÍþ²IäúœH¨õ4öM‚…QˆŽ+¶”/ #lífä±³Ëb!^sKQ5UúL0tŒØ…=0ØæåkZŒÜ‚û°ðâ>õ™^éÐÍJD&kÅkL=úïˆãÔá?OdG’’Ž“" æ™·?à37Î[-‰ç¤˜ô6ÀŒi,ÌÃ#‰ Ä‘£2¦‚ìDM(ª­ÂbYäGGÑw²Î¤‡ ¾Ó€v|uËÛ³aŒþÖÝF>d’çJy½þTf'X3i2]JÞé‘N»P¹ SwE©º3‹Pfèáüq9èºñ#kñ|?öèØô"’ÙY0(Æf·%‹ µòÂÐÇÎs>SŸE¢ö&*Âßš ²mÌIy’&ϾxÇÜ€~™~V XxDÑ:ÏbŒÕ©ê¥Ä4ávü\è<‰BÕ„0ÙTÄQ)9BÙHq9ætñÊê`í86[vƒ¡×\ø‹×«/…'YqZX«ÇSüýŠja axäa° ¨'m6q¬§Ï¢óÌzÉODB<ïô{†Ð/ºa#²Ü ªÐ©¦õ‰ô& ПÏL%ýÒÏmØ’NMQ_æ]¤Êåà‡~–zÞóÙ8Ñ\ë W@¿íÜ®¹pá]±ú¶}”òŠTGjf&ÓâÉèÃúVìûÙÄÕaɆ’¨5n 'Å4E“Œ¤CàÌùVˆw¤Ów"ýúx{Ê*X2&~䯯QP.Ì×ðRÚ•{kccÐe˜7ñÀ:¸‡_Va%±©â5G+£\÷t(§@évx©Jø™îñví,·WG Û KbýœÉ¢ðj:lêò‚.Gwé"oœúäÆL¬5“íÜÕÊï0CCŒú¿OéSyÌ!¨Þö&ü/=MÔ‹m?Ú|;uÓPö¥Zž°j[¿ÄU ;=aµ¯a`®îÈß}\ßöœ¯ç·xÂÚHÒ¶E‚ IDQ¸¿çÍõ‡Y­¤)„t®=°^Ùd•†{ 媒Sΰ];S ]“[^&PÁÙAÔ›qcàÊÞækt5ñt -"q‚x”Ad€Äœˆ®wÒ4°ÈJÙ¼­Ì8ø¿Wöwm B\ëê ìáQïÞÌæºÙ2çŠ'=|J¸^Ö{~ %ÒffÞ2*„ÿ¹UU£î[œRnÖûÎ ç äà/︊»æÕµ±úøÖ[²@“¬½¡Í—5NCCOQ~Ù/N»ùÞq¾!ê ‚„ÙHÔÚä5Ôû3õíya÷UTE‡3BŒýóGN½Ü‡ÄlXþÔGõ“) Âå§aow;é5’-Vy3Å„§J%™èvsQ¾ó\¥Æ0wW˜jS4ÂÒlêWbØ9z%ò¶;,_*EéÃŒ¯ïw1wÙ=ò^D%IßïÿèÀ ‘´ÃΉ™ûÆk¸ß‰y(@ÞqH·DêÇÊQsfT+Û©Õ©s>ÁK@BªB¥¦¤¹já»AÙSg(c¯Ì^¹ŸˆˆÄ>Ò k]5¾`®³ŸFU÷ÚI4û†˜0–—ûcw~¸øTàëö÷Kìµ/ØÐS ^¶KÃðàø¶úN†.é*fQÃïÊÛ…¸SÚK>2 -«°;‡5Î9ø%ÏçL¿ôw_†hÝ¥‰’ 6°V… -^”ØD>#û|ïzïÔ>Œ_ƈP‰ÌäFY„“ðÉQ[ÜȾo £zsT¸8ŽZv?=ªÅHAÓB[LÒÒâvl.èÆí“ÚGÆv‹7"E‰†O¥Ojn(`²¯—½Wb°¡vs÷;îù+®{¿ÈýÀX°«§º½[ŽÓì1˜'½Û6ˆUÊYø“÷dÌe`3ºæç³¼6àHÅ©ÜÁ­ ¾ØÅú(n°ƒù‹"uY»¦·[F’¼3  J -ÓdŠ®ÂlÀZ(”ŸRO¹Œ»“69Û€Ìà†ûŽDQäìUJE5ý*rÍ@¥”Ê~2ÉèeS2N˜ôBÔéø½S[©P°öÐ}—Ìjùjª¨Ÿ´ôÛíýc‚I‰ží õëš(ñÍß>‰/ÜagªœÁáµãº¸›þƒàà出ÅÛó,TúG–-N­ê½Pó5ø¯­ 4hi!Öøß|tÄ:/tô—nx•²åÕüÇßC)7µd|%çC§/;üÿœ/zm’.ØD×ÿa•¸·†iýAæØÚPƒ1.<-¿å¯ö”¶Ð¢›ÉWVž@£ÄUGà†áûÔËÍÖ* -(§[$$Òè,ŠÕ%%yÔ »´Æ”V°ß{Ó(±3· Z„Ö= (0ÜHnƒ«%1œÍBz;¦ßŽÚsÌ9û=u›UÛþígàÑv±Ú9Ž{â’®0ÝùÙ7ý#÷í¡J ÐF¦pß.Ð4·HóRØ°hÀ+;™ëŠÿjHj´JìÛ}Œ¹Úã /x|fðÙµcs|“úúa SNwX¨ÁCWú±Î~\ƒ6›Ðpr;h±8R÷>by;yÛÍálÈ0#e©Ðu?¼¥tMÕ€ž^g¯ªòn$Nß_ävSìêõíX?áûL•†ä³s«¡¡÷ Wþ¤Rââ5G5ºŸ~–²@í—OöŒ¬vË1¤ Š@ ÈÅÎt·»·¾Ãþߺš£pÊjUˆÂØÙ©®¼ú€5ëïžþôè+ -ø%IÆãа¬"£H_|B -DÈôZ¨K~¡ºy±'§«š—˜Â2ZSŸÄ*_Žs°¬¿áüy­•4á’DˆìG„V!3ÆÓä.¦ŸõÒÀ~Yx²ÚQ3æ0ËÉ*À‚äêJÛnïPýúúx ëW11u‚:Ow aA” ^†’ÃÆ„fÚÒRW—Ø(˜¾àBß|d9™eŸÇì x¹|nzç¥üí’]áÍOúåð;={É—êž/Ý„x_ ?à^ÊÃxVòWû‚¼%uÅ ºs+§iTO˜²ýôˆí^êÓqFÆï;ëá[1IÑÇ@ÑIÍEÃÎXq{tUå½ÊZ$ÊÈ/.·Ë3¨-Î ï_ßa?›@ñÅPlTÁLþŒ?iy1s•ÂyK°€[å>su ñ-UXr§m;¨:ª•Kó£*gò¤Åú‰᪠Y&–Ì1Z°ÏÚ¬½ÙQ‘~r"¬JÅÌ`\Š}‰rí&–¡[@²¦Ú»Eû($:¥ºøeÖÌÈ|½C¾Ö(ß~™„¡0¹ª‘ÉË]ô¢/áÉÈÂÜmúüpxQ[kñPÝVÙE·T+†L|­¢D©¦hèGR †.QÎ^Ïs)P>¸õ”.y•y=Oª\î­Ê¹¥ÕȤèGµÓà8þp·—¢®*7”:^&-fVl®ª¬.è<€:T`c…’`'×+mi£HÄÁÏÊ™³9E”ÓNÄJù>ÉVŽu“”=ÜÓ‡“Äòq|1,¬évÅDÒžZä-û4X…»´üÒhÓ%…¥!1ÑÙ:ՠãz&çkÙ> GžŸsêEL¢yeiªlŒþ[Mà Ô({§>¨)âNäþXP¤¨¯owÜô¼.⯠Š–4ãÞEUmVÏ“bD‰;Yª¿TÂíG¹=6ä’-Œ¿Ç@^» ‡¹OSä™aä]Çeiˆ)Vª´û~†Î•¢‡¡j¹×¦Ð;ûvÓ~$ÂV”¸ÃeEÛE³.£2§|Õ_ƒ ‰€G­™uè‘1—ñ½‰æ—DV‡„+j -ö99'(ÜÛG(#?‚iÎä²qßÇɲZ®[ÛÂääßýIbËw‚Õi™£KÝQSûž)VøÒŸ6+Ηݓà Æ8,LýA娒¤ÈåàãÍP9?¬CÚ+|…ëÍÁ^óøúÒ¼²Í·rôjÅ6À¹Ž‹ßuæ -[(†ºÍ öt bÚ[·ö- -HÉU -’7ø“’ðüÅšŽ,<ëÀ¢ Ò½è ¥;KY±7¨n’7qÍþL3Œ8Œ@×SÿCŠtv‰jáY²Ž¶bb»¸iS -ÕL;&ÜÚ社Q²;»UjNN{)òèÈù¥@Ã:è0>nOG"ýya,.ÉàÙ zi™TÄë:q!$*nK\Â)÷.¬’í8>‹ –Éîu¾J~&Õ†»M[oȳ©žJ´2Ëxy˜3Ÿ‰“ýÖ.¿”©tü.ó–5”Ï8Až «Z¦´´òÏn‘Kœ'‘[àõ•úV‡54›»Ü,eW~o§5X9mó‹jœkÑ$'<àYœ@ªùA-G-_ÚmVó ` «ú„£ù”Ó¹×”Šó“$È»²™©CÕr1¹"ÄÃ$AŠíŽ)й¦?¤Í0HÝÅŸàcËÉ&kžm,¡¿j%‘z´Üt/DÅ2—ð£xD*íÒú`s1VKó߉wAwcuÇ$aD_Û*_? -.g4“Mâ'M¦ï(ŠMÑ|éÖˆð…õ²›ÓĘ#5Ç´=È•ò~u¦5Vê£R¯/®£­óHÄ®f§ŒŠN¿:¿lŒTmoú_ ˆ[O»1Â̤§ké&èIN†‹v@‹þH,€tŒt¦á>Õ'R¥•K.zgóJ˜ë(+Á5¯2ìkÚ Ý϶¨Â[ú3Änè^ þ^×ÌæQ¡T d`v+f<ñ'yжj~›q)ž\k,°ý”škQí—½`µ‰OÒ«cìÔ\,& šîJ -íiW‡ fÈ“$#Ò±"÷qHÀŠJ\èWxZ'dô•ÿŽç[œÀþ‰Rèyý©ƒäHñ'þŽŸr9Ø®cpøÝ…uÑ{cBíÙ‹Ü$Ÿâë ŽX -'î»ìØ•Ë#>¼ºê£Z*¶ ?fôÑ1sm%$¥ž -aþ2rž¯Y"`¿/Éü -E¢Ì®_Q²HL‰@Zá~fNS^ÿœí^®<+9;ÚyÜúMtéÔtßæN9ïJAñÀئ{½ùMÌJXQ—DÎ+vûÔÕ†|bs”F-Ë•§EJ òó8}]ÕzÙeRéÀd.Ly’ö|ÿDl>Åõ]Ãh­W[®!ûÄT‡‡ÞuýÝ!"ƒgúˆ.’FHD•‘õÝÖÚšgì$Ð6MNâjpx#2ì,y]®“ê™ _ŽwrÀ% Oqp¶,Ô†´}–úy.Ì0ØÖ³pßãOS*³ã‡ïwâE †ó0m‘¨ü…YiEµ ‹X‚EiyÂ’“ F/ɪô¶­‚´J´ž—‡@%aHøèÕ?7ôÝŽ¨Â'’J‡ˆ2LäÍÝDœŒŸh¸Ì¢±·,Žh¶è„CYö]Ñß´­úgmkôfÆ#ÔíÈä¡J¸Umßý¶ªæö1ãïÕâ•Æ»Å†-eQCÕsoŸ½Ø‰ Í™ªLlmwÓšÞ—Jš¶9¾!&5#é»~kÃÓ•±9wX§Mk‘ŠHg¥éÌÐ6ÓÂx̱Ùõr>%Cçñ#ñ“(ž¢Rm|™$×B\µÉ AvV7Áû¯…00À(ä1˵ÕÝÝK¦Ü¹Ù~éo»T9z˜~Yã{òÑ=Mq0ûJA «ø}/£1Äí«e—Ѧn/*ómF¿Äxù q¬äyJS*\€d­-†:¯Ø]yÜÔåTƒ‡¿øƒØE@ÍfvTü6íÁ2~lW=_xãSeþ<ùBÐÊÒm"¿‹g|£žŽ/>¡„ïn‡œ0'OK_5b«F¾ìؽ°`‚ýÔš´ú&¯Ï¸?`;ãõð æzâŠ×=k-"c ª)k¡@2×Ül SÕs'tÜ«f€p!Ó«‡¢¤H|ö‘¾×Á[ú 4ô‹ê9_¹ªÒSGUPâI%¸5– -¯ò\†¦ U¥ÙˆŠ G (Õc˜Ã -qQ)[‡ŸäW=Òлe~ÙŒB‘»ëó´#âý mω;y»Š%üŽ@D$zfªéA%OÕtØ9ø»«óu 6’RáÞŠxƒ„ï”…íãÄg“Aý; Ã^ËŸæ‹ÜlÏÀc¸_!. ¹À2ÇŒaj¸ Öl§i»fâ^Ù'µÓ<3`¡. `oØNÖ˜©4kÄ®+ÉϺþô.×Zá4ñk Ãi‚" ·æÃDÙ»úˆ›§7æ¹í„ Ó³WæÃW¹i±1àüS ë™ §yBžÖ'ö^2V“j7¶Åˆºi³õ _“¹5·pDÆâwŽK/h,WÐU›4Ä:Ó~¸\+HÂÜ­$”¸ÃˆC»…ŽMŽ­ù•e–â.¥pzÝ?$f‚Y¦ &º2>4ÿ~j‡}áW(í ˜‹·¢ÓÕŠ£‘(kC°JS!ÛšgjäÈ&Em½õDeÏQz›ñ„ûá^–öŽ‘ámªºú$‹ª/ù^T@n®XEò´i#9äšÅ0x»M›×õio‚qÆ;aà̓µ!( ~ÚÀz,˜;ß@å3=7ƒ8L‰¸²±=_òóÏr~“ì”{÷Þ5#©7ûôÄU”Y]ôÇÚØû“ÂV¤íb‰; —Ëæ¨Iæ—‘ª@àQâü)ý4"«Šöâv=<èy9ãÀ+q Q® ð>-ÕOÆ©®@A¤K® m²v$i0KƒÏÛg•m‡D•g<’o9iTÎ’cÕ&™Û¤2)¢'ap¸—È–7 E›§kw†ÚSçšò¶8&drM )I% -2:RÒ]š¡¸\•´²DÊ™º´^-;nðÇY~þ0Ÿ1Í»PÒø¤0«¬}¦“?f0­úÙq†cŒ¶[ú¾;¶96Ø/çCð¶ aF nð¦Å;gF—´þàøåÒçNŸ†UçæÆ»ÚÜŸúDíÌꇺÿįõi›nWƒ¤Å…ß ËY»³»¶v»:ûBXW9aÇá‘ïíYÞ·+Kþ%ýY&ÕûÌÚ3.û×ö€4‚0åe3Â_C¸{½n™rn*6Âܒįì–ž?d&Æ å3²Èp]Í"å™:jW"w…¤ýÈò›ù;Õ+†éY/¯RËB ? -P„ é*Ë~fûiöðÐÁ± y;§‹¸Ãà’ßÐpù<3A, -HG€BÊ!´q<6õûœp—-HM¶Ýu'¯ýôhË)&)|àÞšÙbÎÇU$¨™4ªC‹äCQW -Ûs'&ÞHË¥Á§õŒñ¾QNç—‰Ÿ8[/»'ÚýtÐMs¾Z!Å7ÃFjA¡;Pì;ÎÓ<Ø:ô‹hX[ÇñxWÓ·MéxWÕòћӼaç~ݯJürÎÇû®³`ù²ÏÉF™m¨1£áú§U, Å€ÎÌ÷;:ÖÇ9½èyÄÂ1žìPUºÝS‹QRUib3íWëA(W×â“ÙÅ€µ†„äõ6ú¡Q{I–àÆ/Š†#¿I¨ -RW¥Ï -Òd<—ñ*õ/^›žˆu“ ”Ö†´06f¾Dx>É3ÓÐ6 $cºŽ~{V -´.ÎlTÖ±ð`­çÐÖátžë¾±ÉŸÜÖR)z’ºª^ Å}bû»Îd7 -Á~‡+Ò«‡´¬©Bcá#šUQˆµ»ž2ßÓ5:a]C>+×­ 7ø×B -lwÏÍ ¤Á;e£“/~Å©ô6€bDPö€Àì5 ßhàdÓ'±1ãŽÔH®—äI¯Ãz£íFR… R꿧ù‰´Ôö~ZB‹µü|†šïs>vŽ(B¯)ˆä<µ¢+þ‰>wÓ*>‰v»P°ÈÒÕìn݇32B‰;¾}0ñ\d3í•©Þlýöu>Ø5¹¿ å'Všµ«7ŽìòÂn@ÐŒ_÷ u,c!Üy&iÏ6I¿ÓpǾ -I3qn»#q.¢+j¨lx¥šÏw$àmE8L/ëÄŸ4Æ‹ jìhz:¼‡“nÚé(åw‚ -i}ü8c©+V\‚ØH}Hȧ¿`$¾³O4Waˆ©þ«ùůµbâbõê¿Þ™þz[›aó¬^QÅç¿o¹59ô>Ÿ%{q‡óx§òêÕ/ ìŸ)¨1£7i-ɉ<ô–Îy×`áÌ~)/B,ÔŒÄ ’$¯üÈà‡Š} Ðqƒq\­¸Ôä9XÇÊ&Y Ä~ÛÙ?FÑ«âÖ7AhnzräÍç$"wÅ:XÞ#uq^ß>\xb1Ò»Ïtá6J•ßOõ;‹ŽÉ–a¨Ûß„f {âe# zP$ü®)И'´³ýyòÓûÕn&såÚd´‘ôòh0×Qš>™ÒsA”>2Ì„8¹º—£q}ªé·Lm¯‚Ódx¯N›GQðLÚþ‡Yô2V÷«½ 1±ÅµXè*ýõ ÷q¦69+ÛÞ¥Ÿá0ë8õ¯Ü§Xî´ÏÚæs>Þ¡v5js+¹¢ˆ´Qaïe÷|* û½*$!ÿ½ËI ̽n(9Jºd`t=:™bڃĞ€»¡môÅñNqÖr¾¶Ù¿LÌ¿öåÊ`T0ÐElbiâPŠélº¤Ã¨:îi…wZ’„A[ž–áÇõVm#Ù®©ÂãôCÐÉ/‰ïF6r¨.]ª^|\¤†ÕḔ ¦k)–:õקàX9LÈí¾)b[ôŸSÕG¯Ê"2ƱµJѸRMxÝ]ÙrÿÅ:K¥ÓS%œx&Á¥€¢[bÜlñ™]Œ ·ðØ&T¡Tœ(j!Í'^‰1ýž¸Žƒû7îIÕäÁzes P©.—6Lb"Ž£“k2áKøvxxo¾ô Î@èô*sJc†*¢Zr»“”€—l§^c‹ÓœÌ¤¥øÅú2ÉÒq™ÍŸ8Ð 3?9Fõ<}UíçUr\°V -æ¨5-lçÖwŠ?v¹Í“!‰P£C´é¹2üÇ6$í.ªM¬—¿òÔöž8ü¨=Cî<:6¤Ò*À8€Ëi¾‚’¬ˆ§eœxÁ7gSL¥]ü÷MÁl϶É_LÎ[¯>7‘~KÔC¿ bÖ¡ùMÙDSG„l,Ô±ÿ…ô4¨·ÕõvOój˜ývXÚ‹>N]'#èØÌ×!óþÇ7îð*xîG™õñÌþÀ!%aóЦ_èõ\{¸®qf__ÌjävU“j3ùêEo/ž4 16ìž-AXðIŸsþã¹ßZI‚–>ÛýNA¸­s´Kp‹²ê˜"ÏGx ™?þ³Kl\jß»¬“aÒۗ샜+€uÊtC—hÇîá• -¿n$rÝ XðD˜t ÎõÓ…”2§—n„sÞmOÆ„ ˆ;²ÃßshuåU9ñÖ&;y-sõP~K*ªÅz4rnp´}ª÷œõ)RB—+«å—>¢cI£Ž¹w× éhz€Ì\mm £MúHþ×<×|Ìï­&‰ Ÿw³s£Üë+\?VË´<=yò‹ØH»M'²ñÑ67Cøoí+A5x5½·x¯'_Ë -c!vÜ~óÓ4¶bIpµP]ãH^ŒúÀnkLßYßÙ„æÀ,•‰)tCœrÀ‘ Çi†Ï±m$hýÈn.ÿ¶»öO¿ªWÂ[–{OFChÓ'žWùÆ*6L‡1±’g^H]u Ââa3ð¸g@—TÕL_1@d7¾ùÁ“†µ‹Œ:…‘XF.ÿ§Òfb1\ÄñSÙ£Ö®TÁIS ÒŽã{9.´ v´ôPš_$ ƒºÃ™.T€Áj”¤RÚ.zàÂiXÎ^;-”ûkwå0HMKyÃûSc-‘tkâôk'a.*bí Û¶4ŠdÇ&ž*qÉŸX‡ÒÝÓä"c°4 *+9‚3£ -cáE¢Lg%ãŸïÁó§KíÚï©=ëg‡~Q)œu‘Še7@ô`­¥¡c˜„s2¬ìe/ï´Ã÷5ØI*·[ÔrHîD4;"«hntRÉ´c¬¥ŸýÝ„u å{ÿÁØ }hë …x;³°çlqf—š “d79˜R€2õ¨)iµ†–Gö»€ê&‚—ÜÞ¨CšùŸeVò]ÏÓ~„ð¡T}îY¸dë`XÕìéÎ<òe JË»1ÒXê¤QáÀ#÷gX¹;«ÜÉà{}¤* ½lÈ»€~.ž©kÜõVÅÇ®þÒ€§ú‘7ã$o—#€àkص <Éâ{ -¯41¶{ºQµÚâl·Pãg;‹($@QQ~:ú4¥ /麞e„¼æª't“Ê>~œÍÆTÂ={š÷ÈcW ä­ë6Å͆ÇIjË‚¶{Al ¸¸ ²œís è¹”Lª £ÈàýÞùqœöÇ=*Y€þKTØ&§Ð9æ2ös³Ìü±×îªÊ›õäõ§=ìÌÉIx=ãç7åv[¿Céhw›«Ó(îl*ø®Ÿq ‰Ëb“ÛfÜèY àûYÚÿßRŸåÆ |)¶U-*ª[rᇻ……øw8me-PÍsóQîñúW™N‡vé¸î²”š{e³ã=öEëe>*­xQÿuò_­Rñ„çÒ˜ ¢þ«Iïç?d¯Y¹Æa½/Kz†Âc™›gZ6qæåØöì—3 p0, HÎIM,*ÉÏM,ÊæQ8f®endstream +/Length 17112 +/Filter /FlateDecode +>> +stream +xÚ¬¹eTœm“-Œ»kðÆÝ‚{pw×Æ¥qwwwBpwwwwn‚÷/Ïûž™9kÎùu¾ùÕ÷U»jW]µë®^½š’TI•QÄÌÁÄ\ÒÁÄÈÊÄÂPWÑT2¶µ56:È1ª8Øþš9()ÅœÍA@{qc9@ÓÜ nn +`c°òòò"PÄ=–V Í_Zzz†ÿ²üã0ñüäo¤ ÐÒ@õ÷ÁÍÜÖÁÑÎÜô—âÿ9PÕܲ2XmÍbŠJÚ2 +R)u€”¹½¹³±-@ÉÕÄh +ššÛ»˜Ó,œ¶ÿ>LìÍ€ÿ\Í…é/—ˆ Ààâhn +üfîajîøÄp4w¶º¸ü}]–ÎÆö ¿=9€ö¦¶®fÿð×náð¯‚þzØýÅþ’)9¸€\LŽ À߬Jâ’ÿ®de ú'· ð/ p°øëiæ`êúÏ•þ…ý¥ù‹‚Œö.¹èŸ\&æ3 ‹£­±çßÜÉÿ*ÃÕhoù_0œÍ-ÍlÍ]\þÒüåþ§;ÿuOÀÿv{cGG[ÏE;üËë?k‚\Ìm-˜XÙþæ4ýÍm ´G`þgTdì-¬,ÿ¶›¹:þæfîü¯Ñü33´‹06s°·õ˜™[ 0+8€þ¦Ðü¿©Ìô?'òÿ€Äÿ#ÿÈûÿOÜÿ®Ñÿöÿÿ}Ÿÿ;µ¤«­­‚±ù¿‚ÿ±cr€–Œýÿáml´õü¿ùÿwOMóù¥‘ÿm…ˆ½å_9y™8xXxÿ ]$æfJ@©ÀÂØöo¯þeW·73w¶Ú›ÿÕô_í0²²°ü7LÍ +hjcÿOó9ÿ ™Û›ý÷úÿÊô¯ê™åU¤eµ5èÿ½Ê¨jûw¾ Y¹¸ÿ¡ôw@jžŽæ€ÿ•NSÞÁì?ÿð‰Š:x¼Y¹¸Œl<ì_@6V/»ïÿ%÷¿ˆXÿë,o rztY˜XXXÿ’þóÉòOîÿ4ôÿ„½©ƒÙ?³£ +2¶7û;nÿiø6uuvþ«ò¿6ÀßëÿÇù_ƒonîanŠ°¾â`Êb‘ ªÃÍ™×èc… u,mT+* ¨qèõψØå­4z« ejšáûh÷\>s|?üFw4Ö‡cKÝ›f~ùЗœ¶¿ý'U'7ýQ³A)ræ¹fŒ÷Õ’Ü”‹ÆÑÞ”²ŠAÉ ÑL'»3ÜÕ#m¹[aŃ#ŠŸizC<¬úQt©Æ7áh,rç"ò k{µß8t¯O/;¥ºˆof±ú%¬”&íxÕ)FáöW“ñ¹äÀ õ HU¡¯DRË…WéÆù£]ëjA°Ò\ù*2̘Hƒc»c.7Û¢9ØÉîá!F†–¡ÍÕgélr¯¸’jU ®NÁÓ SÌTœ±Hi~|ŒÕwÛk¶qš‡~¹6c¶³#Å'X‡óæ…~kÝ|aÌÙjXÕ•lbñm6 ŠEÙ§ß5À:éÒYÁïPýߊj¨·×})“Þ‹¤Ð/¼h2«2ºc#}?è\¨a—îŽÿ’¿ÿ[CìB>+Üâ²Õ4k:àJV¾³/?㉤Ÿ0r$±—gF”·ž9Ë&LJuª¯k^3?×ê:d‚Á„$ì¨wWê]%*²1œ!ü18¯«|ö …s~ÄÉéÑ pcž¼-VÁuM/lTœ³wb?†^¯Zs?[Ü%ÁJ8´™ÝÆÖ.çWÊB#ûc5ÛbM#0Ûë˜Þ*giIK‰¸k‡„ƒe:o«1{rúË$Švß/£Ç´-â¼!Ä’DÅüÖT¦劗ïœý¾úfÓ!Ql£øz¡¶ããŠ-㵡²Áî8}uM#Eë}:ÛÀ£>Éôpå"º¥b¸)ã9« +‡ØRŠÿ>7@ÿyXõCu\.è ŒºÌQ鶙°6\Ç­êÔ’BZTt9ä殢%Ès3)#÷¥ûûÓÄ_J£ö •úŒ>kš´"ú(ߵ쬆ÿþ7Ö!ˆAÎv†8¼\L-E©»>æLk9­ûwÙX@è[šIË fó¤ZyuÌLt5åæ B›ñwO)ã—–C¾’âì·Ÿ¾³W°Ïì [š‹ÅC|”IÙj‘Ñåͱ,#7Ùò5D;q0QÑ℺$G›xú4oYµÚ13È@dL¨ÊGü’ðœ;ŒQîÞò—ÕBÕÄ’Üâ)EM_©™ˆúzwÊp^‹”·Þmùn|a„¨=$RWƒúåË®fç±k¨CRÃKxlþŽ,H˜ò3ñý÷V(Íôn:sþ]'-£’¶\ýPkaIÊõ2PŒNã¬?×Èe? ZºÜŽ•'BûÆ$ªÞÇãf×æ¼0 4È5Z×ð¸³g»ÊXJ1#$jÓ«5e?2Å%I¦SàÆb­Û«.ò^*Wí4ÜXý"÷Ð*µ£d9àF–$uY»Ï?‹³éìSxïaµY-¢¡€Ñ_{â©b]Ø}*‘¸§lþm-õ Ÿ¸,š=ǦqÔm'}ã’½ÈJ/W–‚ÑqÒkÐÀ xöJzÜRç¾R´I¥-¦n‘û iK¨xH6ušxÖésƒ7)Øë2~v ¬™fAù)KŸyHè„)Ô’D…,Ü/oÝEI[«t5ÉGsÉ»Ì~ÄÞîYL"â¶F,cð`Kñ3]õ³9udÏ£Cs´Ì!¨°>³“ÑÙLÙÓí0g€;ärž5EfªÌw§HD®nVdü/rp2˜©±dš¡Ïù¡ ´ì LcÓÒk„}xãM‡øATᳶǦšC ²ž­P£™5ðHL5È‘>gF¬•Ê9@PºMþåG-*£?ɦ±]¨ß$ ÙÂH<ðïôÕu=l²é‡M'8C÷Ñ6 `…«p•·9 SÐAÜ?ä…C+ÙBý°Ž%«5’k#4f%ã–Eòž`KR C”x£n©2^ çË„MçÈwS†q终y,˜6Ñ4ßÖÙÚÃI+®‘ïÒhâ%ÿô+cDzA` Ï!ø?(²*é0n²G¡¡æÒëQXNŠJ5ûºîŽÚ ñ$hÓäïc¡Ê¢ÑYÉÝ`¸q'uÿЪ/‚Ý´mÑøD“ ¯²v~¹°ùLÊ{BÝŒ¡øÃ6²–íìÑŽ&Í').Ý瘃‹¦#‚¦2̃ëŽâq'rôÛø]éºHô‚åóƒ'Î:­MØ,Cz) m>¸Zk¶Ó]«>ø:,ÙÀ%ÿšÅ) ©‚©%AØy´¼=€¬NX¦ÄvÙù'a-ŠSR¼èó6†o¡( †‹4ZQÒ&Æ“€'x_!Bå4 +œQdÓžˆo¥j›*÷ú*yèõA®È›ŠØùÞ*9Ö¤û¸·ÂÃmÈŒ¿Åû ×táú9ÂÌ¿×jŒîuÊOà7¬ä'½£[»÷HsHs¢4xÅÈé ývÞh÷»&N™3ï²,ä¯òàÞ¼«»PøÛÖ……Ì\!nÊ—Iž‘Ýù™,dsa‹™2,ÉÜïéÏé›_Ôn8Zr烹ªv{ˆW1óLN¡¦‹JD¼¥"eéUMäãëj“µB‹ND·ó›^ÖåÓܦÙv‰çxD‹ú)MènÁ Œ;Õ×`xÞý¤ŒAhàI%Üú áG`¦‡SØÉň,ø,^‡QXÒ<5µ[OtÂ×{ù…Žö„F×Ï+N•W¾¤Tær U Œ€´q^¾tÆ^?Ø|%uÂŽ¯B_µ÷Åás-™^±`Ö¹Ðü|ñ.ù½„õœÏ¡-eýËÅÌ…£×ïO©èOÕRÁ]k¯þ)¿ÒÃú çøbU'þ÷˜ÀÁ±CŽÊ|Øo‹VÀ,÷QYáŽeƒTÅ€4ù`hõhÃÌ"ÎÕ +¾•Qÿfí2FZ Ys“^É2ç1›èŒ}´x•oøLÅ~êú¼Sr6Ã,f“Å$ÖÁ~¸!’Åu£Ã¾¹fu[¨½$|8GŠ XP&k©:Ä0[gIJõ„ç)C‘ ŒÄ«é3TûÂü‘ë8‹( Ù‚.àu6s v>ñ±=ei™t„à cþ9^O ÎbÔSfü….’ +ËžŸÜxªÄ®»~dÿ|°ƒÝ{ú볩P¤ˆC{TÃÂb ~3˜˜ Ô¶q-ÖTkþWBµRè1 +œ^Å}÷b"áŸÙ÷?'q ‰–Å/F?®ÊD¨%·ŽÐrm‡6ÓÃȈWw[ ØÊ.K.¼€–X¸¢¶ei—ùy¦ ÚI‰sÁÙÛ èFCëšˉ°Áº¬Âì§4{ô_ju5§qWb¡â:‚F®¹‘ +£MQùžÑéÄ›—\Jo£c ÚSAЧÏñ`K¡ˆC%oÝ«ü°¢’N½`ž¾VDÚº‘´^álmÌb'OŠ žQS‚sxCþíº7pážÄ!Jà wF‘›UíG7íoY{º³ÕãbžÕ\Û."{Š~ï!x¹Î+~SÆeT•±ZЯÆ7 +«ˆbÉ4‡\·L0xi_Ö\kµ¦äf´5¾~Œ"%î}…|ë +›ˆu61j&všQÌ/‚·bénx;Á8G̾ +Xþ®qp…rÆm`‘ /Iï¨ë‚‘;ýR¨•å)’Ô`m ^f©>¬OÛÎ3[~½›ÍÄŠÜ?ëŠu×ö”.|Ðñb8‰àÿ´sÏ6Q‚"jWŽB‰ +x¯°&ù.±óh|-ö¤² K¶ÉÉ6 N¿È¿ð.·ÐøSýAH×ú¤ÅÌÞ°—‘,ŠeV®D’R¹ÏÎ_ƒ¢‡):?¨\)Ì/ +ásÆ#ûÝaØü¾C-(^Ÿ¼,•}3Ûð–VG¼:Žˆpöø ‡~fê"¡€«ËöDñqšû„\ãL={,Y6èsÓö&ÿRžéã ÎvøüÆ’ ©—2[<Â]*ŽUÍö~Fº*Äe¤A¬­âÒÐ{q÷¡Tjá¯r*DQ–Ðn8Ö±üÇ×^êî5 ¢Ú]KM¬dŒt¬êür–Ò›8»(B:ó1OCò£P^xž¶¼ƒ z¨V5]ª»r +‰&$_׉<%@v©Ç1‰4~å¢få¶_±Eû´½ó*`,ÇÂÍ“)‡D7^[#¨eNÄî]›Ä|ccÌ.g‰æRuõ~êP„¨ö­þ²øwâ¯Ú ¬9ˆÆo Dà{éøk JPÔ箫¾<àØ¡{ÒŽƒ£H ˆš9Û¾>,v§ßÚˆ37ïegiZØÃÎ’~92ïc¾q`¼„¹WËmÞ/ŸªÈ"Ëùtþù¡Î T¼ 1¨3(K$/U@ÔTÊ.5,6f!-ÌxFhÌÁó‚NnrÚzë¦wÇOïaóNô%0I[—Áƒ½ìê¯záíZpiøélò"`+Wüü‡Îù½(ü-]X7om_ìæž?Óo 褭c.Þ¥Ž: ÷tƒS3ÿ䤽0÷Ov¤u™g&¦qìI,Ù5Svú™¨ÿoxˆð9±¦Í¯1cüù.Ðe ' }Òß”ïˆ"Þˆæ#ÉoæW›Ÿî¦³ÄHM‚˜7/ —f2"ÏðGb iú_Câפ,øAµw˜1¹BÒ¦"S?‡EÿÑ0L‹²½ÜDCö2ÆÀ-ƒ€x¥!š™'O’¨O<—Ý®ÒaoõÒµwÏÔÖ¤;àkKˆêzäoqm‡šÒkï4³ã¥d··6@TS$T·ã²­×j2HÇ‘#úûƒ‡âi]¼¾_ØÑš#Tf£~:¹÷ 3²+þÓ ÃˆC5¢)„Yÿ^.»x·Që(Aä‡òIaèdFìß;ÓpÖÇÂ÷=r†m΢j{#¶VœNC°ÏB¼è‘÷ë—†£Z†V!’ÒòŠâYõ¤‹D¡T™ëœ7(8Ö&ÃÞ(ü‡*t]¯jTê_è¨Ôu/ýñNU:¦#ûPüLçß öÔ¬3§ C5«8N»,rÃ_=^U¢AºÊ7NåÆ4l[ÚÙrcw˜›%Ðo»ÆÕžÙú9ªR¤wã{EÕ[»\©_½zøtÏÎn• ‰ÚtP¶³ãh´¼OÄHççí".ëµ6¾ÚöW5ÔÞ‡ºd¨¦èmüq$:Yø +ŸáG®o4± ÖQÓo$øµì;ÑbV!ûykAžÔ^¶ª¡/©ƒÁ7ÙÈS÷ƒœÔdíMèSAˆ2xî^vΨÊXdºo{g@½ËZǃ¤ÃMp¦|€…¤}øí«š%%™ŽŒt@¶²‚Ñ|¢^¦VÊ0CNãr§S=ËÀµjX(s'·ŸÃ,> fym¾{<õ(w/v•Úé`ö­AºhJ½ È’ +¹˜%AÇ©OOûØ+VÄ‹~{HŠ¹l…¥mß,+?(òÖÜþòHaöjZ|êÕCJpL¹áïæw”­~½ØØÓ< +ælSŒNà Ëù}ì3½ÿÚ»~¾-ÇÓ]–Í +ÑÙÜôW3>Çz¶P\üõº"kw5·D +(ÙüՅ'•±²ò±—gÊ1HðḶ Ýœœò*ãN_RÓýÈõ´Ùž®Svt¤/wpõL;AÔÑ8—šåÄx{K³íeS”Áñ9UMe›ŽˆÍ×ßÉ¥al‘Âèi×N~¾Î3±ÙpYbdÕŽðéa/å…8•H þÐeý%‚BÒØdÎö¬/~.¯mŒ“Óø5­ÝÑ„ßÓIÆk´í0ùX,ãHKKÙ©qä6ç¡•ø;~¿Éo Šœç”÷-mzË9é‹.òÕºû+Ó·œª7ÆÔ¹ D´!úÅA±´âë9œ¶a¤<Ïë­á_í°Á‚L=€@°ù¶NM¹•íô™gFNó®äìS!à{ù²gâA}*ßZ¬¾"L;¡!&{SºGÚõvÿáIt˜h<Êo`Ð W•˜÷¨º=áp¬ ]3#"ŒBŸtª”‚¥‡˜QðëÿDŸ°Xüù§—K`!6ïH©/ôyþËZ»ùc¥ÏÇÖ™„ÚÝ"ØÑ6Ølšä–ãNdn>‘W¨f4Ý…ÊðB÷=Iâ¹²ÞDŠ¡éóñL—eMåu/÷r5ÒÄØù?¶ßíž;> #ØŸ#J¬ïíýwÅ\á0NJ]þî\wL‰ËW) á«jû콪:‚ÄŒq˾t/eÖ’Ÿn…‡þàObë·¶tóÅ@Ý—†v9p%Z§ P4n¦khÛ%ý®äÇ=v±¯l8E45)ÂcŸfÕ‡³QùâïsÊ9 YbÜ„ƒlï^ë)ý—$ÕŽþ9%AÊf|(—À»‚††î^müu¹ƒŸŽC©¢p°°ð(3ïû{TªÓýᓘï,îÍÔ}»ŸÇ4¼ékv× Ð·5™\Å«ñNKå'®ÌhüMÁüúîVµü~¦@Œ1ÙYЯx¹éœI¶ä¹O¹˜ N‡6õqéà/ð¸7^–@€OÜslDåÓîjßËVS!V6U%áÇÔaDšò“£u»7Z3c‚8p€È3˜£Iº¾œˆ²#>‘¿ŒRý­Š˜–—œ-¤®ÐáZhOÑŒfuð4± wCóÀ:t²YÆ +àé nرn¢YoIêŸ1Â4׋bƒ¤ôŽe&€Ü[;˜ ¤ÕŸüf$tÅùçS‚cMFÕkÔ•uDI/ç»i¯‹Í4z6Dù>º÷ÌvÿÙrè€}n,$Ôf:û6þâDÇ5[* ð[«ùLìâªXÈÏÌRTU…>  Ý#nñ ¶yO^éF½#ï{‰}xDqŸÚl¯tØv¥6"“µÂ ¦.}àwÄ êˆá³o£ÉɧɑD³¬ÛðY[¿[-‰æ¥˜t·ÀŒh,Ì"" õÅ‘¢³¦ƒíD)ª­ÂãXäÆÆÐ÷²'JA¿Ó€vðºæØ0Æxu·‘烢n6ŸÊìk¦Œg¾Söz¤Ó/•ïèÔ@2Uw¦‘J =œ?®ýüÈZ<ÞOÝ;¶= eöõ‹±ÙmÉâ¬<1ô°óÍŸ©/¢P{Ž“àoQÙ¶æ¥+¬Ü£éœç0ÆëTtSc›p;†;€¢P5¡L6ñTŠŽP6R\!EŽ¹]|ß´±öÛ-û!Ð._‹7«¯„§XqZX«ƒ&RýýŠja `xä`° ¨§l¶q¬g.bòM{ÉÏDB=îôz†Ð/»a#³]õ«Ð©fô u' П/L$ý2.ŽmØ“ÏMQ_\¤ÊeᇆKÝ îùmœhntG* ßön7\¸¾\³ú¶}”òŠTGid%Ó~‘уõ­8ô³‰¯ÃúF¬Ú¸3’ÛC<š3kè[!Þ‘A߉´òñö”ý}Ùˆèñk}¼Raº·â¾\ü XƒÂé¨;ÖÑ8üš°2+±M7°9F±妧C)J§ÃSEÂÏäŽÈ koµ½:ÙfDkx6›Â³éd°©Cʺݥ‹¼qÞÜ'/vr£™lï®VnbÌßè}ZªÈ}A™à¶7àç1Û`…ñD1‹ÍÂ#å‹ÐÊW3â?ù‘_È1ãTiiš×—uRŽáŠÄBT•Âa•T˜4¦ßË !ôÿCÓ’G um§‡"DÑľºAb*m¾ao°ªLü%úwd¬•…Â7’‹P?PyX€L0_„ +_… Q×G×züù²žxZ5„3&° S&áŠT›D«HÎÓMn@gl"º7÷qÔEÔÓÔ´´¥!e†j³7·_ßÛ* +«4èÑ?jú9‘`¸âQ[è)µF¬j,>.¡ÿžByù˜únŸ‚)L©uwŽ6 f +(ëI0r/*•6#ˆ,º¨YCYæɧàIfðcWζ{À`Œ" ίí+¸6¶qÔ…Æ*zcÑêZ ô, +keFüŸÒùß×Щ?Ÿ•4oJ¬1½8â%1¯ Vå81BÖ ^†D51ÓK˜œ½;ÐOÓfk…-$=ÛBÆk^è®ß+c稲8Èœ$çdôšX¼"»²0;•Š;dBÌßעؒ¿½^t…R—rïû½§Yºn†ŠetdÔÖŒ+Á” -{ðð6·M¬Á‚>Úši±|óºqóòÑ95¥ãfaòþLÏpúŽLNïvù1ˆjf (Ƙ@·%|â9?ñÓZ,ñÀ¾ófWüˆDQLÝ(ˆèÊ~ÌAe6ÐbHLSºFV„®¦·Cýã„z¯;þ¾Øp¢1bêînßÑð ÿº£T7._\äîà±rÖ‚*Á,ËAÞŽ²b5< ‡¯ýç³:^Rµ§H Îì9:Fw(2Ý!RkË÷"*3wÀôE\Ä$lÏãéd_™JKGÔ†Ej \Äíuvü÷<ž~â¥èÆƲU*€?›–ß\\8 …îçVÉ»tÐæhG_%éVŠÏ‹ÀGOõRÛ6ßNtÔ£C©–'l§ÚV’ø +d§'¬ö ¬Âõ=¹»+¢Ûžß›-°6Ç´mQ@hbQîÀ@¾<˜õJšBHçJÑ#ëµmVi¸×0®*YEáœÛ yÚ ÙÕU|eœ=DÝYW®œ]þF±‡S0±Ä£ šð $ædL½“†¾Evêömeæ)Àÿ½²/¤kg âF×@åà øþŸ¹<B[æ<ñä‡O Ðea½o¡3ËÈŽa!¼lÔNUšoqP©Y7+*ÎלãkiBÇuü ŸŽ¹o½% 4ñÆÚBypsá 4ô4%ÉaqúH`äï-QùT$ÌFÂÖ&Ï¡Þá´·çÅýWQemÎH50öϹõ²òsáPwÕO&d0WŸ½Ýí¤7H¶Xå͜ʕd¢»ÌE]HxÎó•ê#Ü]á*M1Hs}¨¼D°óôŠämgvX¾T +ÒÇ™¼ïw±w9=rž„%É÷¿´á …ˆÛaçE„Ì|ÔÝîÄOÜå!ƒî8$á[¢ôbIe©93«•ìƒUëÔ8Ÿà% !U ÒRÓAšx®PöÔ™JØkóÇ×ng"¼Ð+7tF|…;þí|PvùçÆg/CD?Aæ`CFF9€”’Ò󮋇ùã9#H…Kà{p”¦§ó×XzƒÐhÃƧ ×´;{ØÉ…OÅY“óç"÷ +ãÊÅF_ÕXƒÖw_¡ØKèJVDËXcïEhÛ‹Ô— –ÙR¡pŠÔ€V§éêÆÎ~'%œjeö¯´!ç˜ö: cf f(æ’"äËèÁØ\ûÖôùiÁ<„îvÔÏ:¥•F²,ÎÒ$£ÞzvbsÓÚqÂQ V-/°í-2vŃäƒHì£ ß¬«&ÍÀµÓ©ê^; çÞÇóó~ì/ŒŸ ðþh¿ÂÞ Á†ž^tW÷´]þ¿À·Õw2tIW1‹*íàNk-ûÈȯÃîoÕ8çâ•<ÿfZÑÛu1¤u“&LÑßÂZ*4|Qdù ˆêó½ë½Sý0z'D%4•cŠHÆ#Gmqu ÜFu7â¨pq³ì~zS•>¦…¶˜¢¥‡EíØ^þ®Hj×-Þˆ-11e ±%ɾYö^‰Á†ÚÍÝïx௰éý"ûcÑ®žêön=F8^£GônW?&L1wñWþ“—¾Í؆ŸÏêÆ€#§R·¼ÚR룸þæ +EÚªVMo·Œ$yg@;”¦ñ4] „逵PØWJ]¥0îNÚ”}0ý?ÜwüÄ +"¯RÊ*×Qú(­À4ö³)FO›’ ‚äêàþ(ÇÀN-ÅBÁÚc·}2«Õëé¢~ÒR¯ÛûÇDã]ÛÁ›75ÑâÛ?}’^¸Ã/T89B"j':up·ýÁÀËuŠwX¨ôN,[œZÕz¡jð^[éÐÒÊB¬ ?ùéˆ&µ_8èè¯\¿T~+¯þzF¹­õ ã+¹6sÕétäïøë÷’ç6é¢MLqý/V‰{k˜ÖtᎭ 5Â3r;þªOé‹-ò°Yüeå‰4Š\uÔ®¾O½ÜlMÀ¢€rº%bABõ΢8ò1âGÝð+kLiyûƒ7õ;3»à%h#üï[)ÍápµÄsÙHObgÐô»ÑŽ¹?§Çe×ĵ{ ì«þ&ÄqKZÖ¦ ¿ðÒ;qÛª47·‘)<´ 2‰Ç-Ò¸6,éó}›‰Êá]Â?…®ù6Çœb„5ÂxÀ ž^èvíÙœþÉ ã…~È’Õ*Epב~솳ŸP§Í!ðœÚ ^*ŽÒ¹\ÝMÙàvu¸2ÈL].ÍàE´”NDJösö–êä*\Ðqeùšß±œ²ƒ¯êrýrxÍ!¸ï%ծΟÖòÄͱœ·qšZ%ªæé»V7äÌ¿%þ_ÿVš*Ý\„ÊÒ$ǬÇ™Va ÖÃVáÙàYú#gXõÜ¿Œ²ÕÞ·èêµÁ),|d œ¢Û¶†ñ;îìSJh"¬t§?ßyiKYLÚ´pØŠG?'â{âÁ:ì&~&¨*Ir‰OŽŠÜô«þaÀäOÀÝ 0ØÔ››Uñ@t°'Âÿ}û¨ÃšA0IùúL{—p.ðZ¦{xyYOÛ–©Äï´+Ü sHuOŒ¨ÎU G£–@¬Èo`ñý"qà‘±îø•¢†>MÅ€žQg¯¦ün(Nß_äz[ òô:ÕK œ­²S—|vîc50ð>rá*˜RLZr§±æ¨F÷ÓËÅRè¯%ùdÏÌnw°GAš¤’€\êÌp½{ë;îÿ©£1ö§¤Z…(Œ£ŸâÓlXzøÓ£g®éË7âE–$M@òŠŒ!‘ø„~!Óm¡.YAuõdOÉP)$0+17`´¦>‹Sºšà`Ù|ÃùõZ+iÌ%‰Õ-Ž­Lf„1®Á]L?ç©Žý²ødµ§jÄaš›ý ’«+}W¸½C…÷ .ìñHÖ¯b sú =l!î‚0Q­ %— ̤¥¥®.©Q0cÑ…2¡ùÄr*Û>ŸÙ8ðrõÜôÎGùÓ%'§Â5æ+)Éñ;wF$ö’/=Ô=†1Ñ¡*^À½”»ÑœäJû¢œ%uÅ,ºs+§ItO¸’ýôí^êÓqVÆ/õø­˜¸èc è¬æ²ao¼¸=¦ªò^y#et…Ëõêj‡sKÆÝ{%&é³ ˜P ÅFU1ÂäÿÈ8Lˇ™§”ÁW‚e¾Sî3_×ÐR…%«~Þ¶‡ª­R¹¼0Ö¡|!GZ¬7™D¡ÂmlÉ« û¬ÅÚ›å'û!ªXÌ Æ¥Ð‡Ÿ$Ûn¬ßi¶cNÖT{·d­ìD§Xw¿§ÄšU ~pÌßíÛ/“8&[•+2uµ@H‘‚,Ì݆¡÷µîKôÎFT@·UNÑ-ÕšÁ%«(aš Ú#ú‰TƒKc´³çó|*”n=¥K~e~Ï“ +—[«R^i52)úIí 8Ž?œðí•(Hù%‚¶§q‹©[&H…U½3È’PǃjÞX¡(ìÁõJ[Ú(y4\9{1¯€kÒ‰X)×'Ùʱiüƒ²{æxŠH.ž?–… Ý®CÚS‹|¦iŸÎ+—^Pcª(¿œ($&:W§||RÏä|ó­„Ñgx^­ˆI4¿,]…ѧ <‘å ãÜ5u@܉Ü Š4õõ펛ƒ¯ÑEÿ5qKÁ’æû„wQU›Õó”aRG³o¶ÊŠr„ý·û–lŠ…Q`ÜwÈWáp·Š|SŒü›ølu1…Šc5|–b¿ÂÏ°ùRôð"TM·Út|zgßn‚$ØŠr}7¸ì»ÖUTæT^½ ¸ÐHxÔš™1‡3ß?1_%‘Õ áŠšB|Î~ãn‰"”‘ŸÀ4gqÙŒ:€âd[­Ömì`r +î~%³€8Áj·ÌÓ¥í©ªf‰¾„ö§Ï‰óçô$zƒ1Ž¤PP9*'+p9øx3T.Œh“öJ™¿Âõæbo¸ó¾4¯íò¯ý ~µbàÜÄÆÅëºÁJ‡£î2ƒ=Ý™vÁ6­}‹Róƒ¥ÁõIbSŸI¬éÈ"²ÿX´€Z£°×=¡ g)+ö•mò&®¹át3À¨Ã(t½—Ú/R¤‹+T ’M´5c»¸ m›R¨fÚùp äÖ>'µ­’ý¹R3rÚ+‘GGN’ïêÖÁÇ 9pÚÏ‹ãñ¤HúÏú3Ë«¤:_ˆ=o2C£ãwÄ%œòîÂ(ÙN²™`ì^ªäfÓÜ`¸{ÑD±u÷P¡Íy¶ÕÒÌ­Ló^æÍ&eâ¿yµË-g)ž¾Ë¼åDb 0NRgäÁª”).¯=°[äåKä}÷䥾ÕfMÎå­6KÙ•ßÛiVÎجÐ@Mp-çF<ë’ãKõ##¨æªf|•vÓ¸èSy‘ÏzÊíÚèæø®-ßìŒ`9î3yÉeŒ¢¡rã6éôÒÈâ&êêÙxY½#‹…4.'!â“߸•ËÏç×}¾ àÒmÆh²G:­v5ß¾>¹è¬I¤R¬ó%í®I2"m)pŸ†¬)LJ-sE¤wBÆ\ûàx¼uÁ ìàà)†ý®?w-þÄÛóS*‡Û×wün>òîº佇1©úìIn\@Áû‚#–ÊI£óþmü€Êå^MåQ5Û†ì+fÌÉ)sm%$¥®2AÁ*r¾¯i`ƒÿë÷/Éf×(’eŽpý +’EbŠøÒò÷³órrx¿Ùî…Ía"”æ$çÆ:O[½D—ÏMmî”ó¯åŽŒlº7›ßÔÁ¬„dp‰e=ãvÏA6ä“Ûc4ªÙ ž)ÊÏÓŒMëU—)Å#ãùp¥)~Ø߇gºte © wuÃ^-Ù†œ3m6vxÐ.ú»Cd&ÏÌ ]ˆ +%"ë»­µ 4-ÎøYmº¬<ÄÕàÈVTøEʦl'‡U3ž,3îÔ€K6:á…Á ز0ÒöuXêçùpƒ$ó¶žÅûšR™=?ì¿3OZ0œ‡‹œ$%fÅ5•.," ÅÕIKfL&Ýd«ÒÛ¶ +Ò*Ñz>~|åÄ!á“;Tÿ¼°wc8 +Ÿ(*mBÊp‘77cq²¯„#eµˆ½eñ”æ¦KN84e +þ&mÕõ­1Û™P·£SÓ<òÊVµ}÷Zê§@ÞMë€<€¬åË&ûqÝA_ÁXRz½–¬X;w3ª¹BË?#,d?¥®‹#{œhï1»D‰LÄшÔ]Lª0‹G€~8îK‹žo H]¤äë®ü²þ“’Bö¾w€Ö:8Y2Ÿo¸È£Ç}ÜÕV%$Á½ôK”t³ 15^@$N5k›¿W²àéîJXɺÝh‡ŒqÇ^èð ^—ÛÁîHú¸5<ºL~_ÜOùoÝ#ãP ÷C(oqZo~„Øq}·wy™søÈDûXp¡E²Y‡NDƒh®kÛþÂΦ@ÈË¿_Ÿ¿ô²çH¿Ëî|‘¥ ãP[µ!^OƒÆÆrá1ÔÑ­vÏ ´ßïŠedì°ÊC²Ö'Ó˜„çÀè¯u9Ôd89»} ©œoXÑdÇŽÜÐPSŠ7íÀ…¨><¤PÈ1|¹7ßVyŲ½ééá%ÏÚ”òÇ'Y¤Ôñ;˜8¥N¢Äï µ#®]«¸Hggªþ¢Ó‘‰Ü|tÿH°M)¦R¥ ¶N­Æݪíšòƒ‰R í{ø¹éL€¹ÎĶçüDG‡„*ç(¤áP£ðâë-î犌ã )@Å(?¾c~¾âhà,RýÝFî½3ˆ¼m–æq5<,0~öK[XÔ­PI¦ÛÏó\­b£ß~À!&{@Ý÷¼‰N–Þ&H€ÚÔµ©Ì22Ï”)IÑB\È¥=qÎ\‰æç´Ñà¥ß ¢b‘óøìå÷§iŽN-¸D&ˆ5)ßã­ó3.ÿdn# +Îs!V •ãrMLñ<'šP¾ÔŸ@¸WYÒ‘wçÿò¾Òç–Ö–V.wÚº7qËw ¾y2obW}ËÐë£ ~W·Àg¸sbj„ȳBMt èi(\­ùê“í&×ÙzzÁð4#C®­x@åHCK‚[ÐÚ¤[Þ#Ç©rÖ{°“ÈÕ84S’cmáË“áôÚ¤È*§6MM*sËY$:_Îñ¤C“Ø“›Ó¬ªc¾ìi'õs1z³vØhæ:¬—µ¼ÙùÆLå†Ò–³i]¨W@†–M˶ڧ‰I܉U¡€G‡• +ª'>Ûf4C¸MvtrZnàyTÉZÕ$KËýaGåEìÝ¿krÀ‡~fµŽúî„ÙGé¦éåGa5ÜÓ1ƒÌZ[\ U¶…\Ðר·ü¥ÀæêÛ‚Rèmà>ñº4ëµ÷VyG~ü½m4ø0QÍÏ<5&6,Å*Ô" €öºàÏ`]M$¥¹¼$ûË«>Sîy +i¢§£ !㺲”ÐÙmPžY1áÈU—¬h…øƒß'p¿X²0«Åû×N¿”UVÀzÔvƒÜšýâ„å®ðÕæjæ–Ä9Þr`òٷ…Zî¢ôÃ5†Q¯„ÿÖež&Zç:€âÜ3ùO7î•r+B«(ô]gþÒ¦ÈÑH=Fˆez u±!DÓÆQfl³C%q§Kõ¯ÏÖZ®^®¹Nˆ;–¤ßÀ¨ZÕS¡…ÄñÎ_\‘닼‹óDo®Fø>¦R°ÝÍj‘~É÷¯[÷oìÄæò n?[Œá)m’@©—‘Œ1´bÖ9Í­n8-MŠÝšá_jÂå­êÀ:BÝ{8J4 4q†ea: ý>F‘-¼ªø¬Oð…àŽóMA1bÒvBŽ0{«i~n"É(ãUeAqò`Z(سRl8ì|–½v:øŸ”‚'Š’^ÄÏlÇ7…·}¡…4íKœç:©ú,X…¥­­¡bt‡~Wî¥öÕcE«ÃÝS‹†=@å ´Ê×æåóÞ=hj3áRe*ý¸ +Cà ê8ÎÉ]Özá·}6ù\ø*ø1B%[3DŽGV.C#•kÔî F’)Ò›¹zäýWݱAKyIZùþr…ùÆ3cÍÄæÚH–V*›ñ +ŸH¡ó5q¤Ã·i±‚”p³×S“š¡¬p£“ ¿ EûÙc¡ó,ßlÁ5Á²È¬íŽÏl©-fͿ궘SOpø¼5Sy˃øú¶(û +.3Ÿ– §ï¢Uí,?H-ýÖÒzÆ¥¨>#uQ4ŸÕÃJE,°NN•SONãó‚©;0ãb°^‰Uåª<& ²Nåð I[•Æ«çº´ÉQì\ïåºÞïñ8+ìNH‰\¶¥S‰)½0@ÌJ,yßÙ ?3FçÐi®“© +X%Ž…¾‡¸ÝëÄìk|ßâðmbØ|¶®¶LïÄì†Ùû¸ä¡›¿å4žUt§Í-Ú'ÏxñwÓƒhÜ£¬N¦ú€·$:–©<©?æÌ"7{•åQιv – YRÀ¯Téœ'Ob­²)7_ùÖÊ$ùÐGDËky—Ý·¢ÉŠ†Ý¡í¸ sx¸ ìqŽ#cßê©Ê±•góf©õÏ)mé¼³_«´`—¦„j?ùÁ“³Û)„„)F'ÏÔJL%%›«Éw‚¦¤‰¡g¸ ¢̪Bé±¢W>"BYÉ:VS=e=X|ùÁ±¨Þw ö¼Ž”ò°=èäÚD¢z*•(J":“–ÝæÜ\ÒËâ¦òUàñ+º¡îîñ,XbAeL¼Ásg]ÔPŠûÕ!‘I´+SdDÞÀð®¼b–ŠÇêqüÆŽ·ß0º¯¬÷Y®M»®¡J±˜|‡à6RBÃðšÍØøæU÷¹¨E— 9Ò­êÿ„l™– ÅÚÎÔƒ™­GÝê™ "âX[zq3H³Üé[‹ãq»©¦-ÚÞ,ÈŒ3:I{r¼â:Ü?#©+²÷%g² X6F~“K0'Òöé½0r=ŸËH“¢“éÞiŒúR7a´Böj»å¸’CêOm‹FE „m&V”'TKõœ +焉p')ósó1ì¯z£ùß²›ÔÕŽÙÍd•¾JãàõgûP²öÎÁùiÑr +¿*,‰Hç[`öR{w…ÝƸ5¹¾ŠÇŸÉz¼ÃWDgãX°+>BÃ]‹BámƒéIÜ_<©œ+V§UžÌGT Æ‚(ø‡Þv9N{ Óü +Óúš"ýSz×âת 2\Ö´ÝõØŽHhKÌ´¥sšùíio=¶ïÇ·‡¾Ü⪧–AL!¾ëø ãt¾tblkMÀé¹7AÑ|e·šáfa$|”?²Å0ËvœÁ×°(Õ‚î)=í†þ ±T1ß<” î³ PÔÚƒÞzçäu™»Óƶ»]÷so›w~ª°äƒ]ÛG…,¡ñó!XúÆ‘ŽÝo-*d~}áóÖö2 §Cv¿*ìiëÕÎøˆIXrg]é‡ ³Yèîã`"ùÞW×·sÔ¿A^nÒÕùIÖÇZˆ‹ÕúMºpnc1à€ôC…M¯³ùmlU”Ø—Xz ­ìS;ÒÁ’½yXžMÈð›’]h|¹ ˆü¬a^6ÕévH£ÊšÈØDuöGÑwdp7™õñàéÖd“ó?¢Ñ>;ô¥:žu ôÍáS>3ÞÒ÷“ÉU·ák&½þ½e|‘ÝÛZuFÒ0  ¬±üÕ¸¢ +iÑ$Œ.ÞoŠárò"~ÖùôÕ³zUF•=GÉÝ©‚~éRÜ×h4ÖÀeiâw±žRü/dRÁŒTkÍ#wƒ0&§šžh,Gë±Ãñ°`¿pLsî'úm¯=±çɱe—~–¯#\‡zó,ªÊÃã•ì9»^Bü¹“ÿC=u°cDk þD8œ/'V¶4¥? a¶d»Ø\ñQ­mÓõ:F,ÇÇÔ²\ñÎ<šr9oâ\è‰ñÓ­b]Å»¦f;Uˆ#e2S> xV¥˜ÃŽ­ˆ†ê§—jŠP™­¸¡.!‘#È÷©voÔ`ÒSº’ûþž}°S‰Ô&|ÚÊ=Ê4#æÌ—î–Á2$!ù¯Õ³ƒ’(Z3ítU•âz«.V}e¼¬œh>d$zH¤†5ç6ã§üL5‡êC º/Jd~:¦¼ífIu„ÌuüŸðc%Õî¹£s ñ‚O>»9‹=l¶ÖÓ+#°HÒI-÷@?JP1ih¾ &îÉô]“¿|Xä´Úăvú²†(á“¡´5CzC¢4ú1.XÐ̓§ KK¦Œiúºz#Ò.âöG]‚'×Ô¯¿Ò_X‹_°þx4‚ðÅ˳#¤ä"«P¹–j –Ñ–BYíˆ87ŒÀz" IOÒxásØlŸ±›Épk7KðA ç/ɇHùM¸ž6 +T S!õ\¶ZãÒJ)¡#¢:sÌæÀŽ_îR·è¢#Ô¦Bò:~‚3LѸ‰dR” ÙZ˜QÅ‘ÀOäw‡ˆoJ]¬ |*L1qB')ÇL²$Î. c¤Á}2´äêâqzE¸iÜ(€ËÀkD[ˆ„gÑŒŽ²ÞÝ‹ÏY…Ê4寖|îVO.Î߶,ïOñBϽ×õžldX|ÀVlË„ Ñ2âÖÓà NDè{òBláy„VT›3Ò„E/uà÷ú\¿·ºÜgì7±ËÑ"Ý¿"³ ¡>²¿(C‹ãžeŸ›PRòFWŸ«"ÃÐ¥¤YXíùñÄXY6è +êOqÚô¡9U¤ $Ö=6Ððü|Hò‹°s%nS,{¨üˆ&õÊ’—8$²cå’6¿p[Žx7íj£\k@?®ð¶ "Ü<4s=3Ña½BÚ_Z¼–âç0h^×IÓ¡gÀDFÌû"O,v}V%t ïæûüH¦¼¯¸Êi¹ò¢ŒÞf4ðAÖÕð î[ù×%£©!¿Ñôør{&ÿö§õ 'QºµÝ‰’s$ +Vº<3ÿiúü`+zв±ƒõ¤âBy¿e5m¨á^[ÄyaS©aŠ€()ÞŸíÆÜ=7w3ÔV³Md& ðÑÈå’½Teöä´þe¢QŽh¬õ äØîαÿ”øg´>»6¹”¼g´(>\PóÔkºßo†‘vÝ8‹¥‡HZR¯±˜(rÔs•Ì7R¶s×»LíªøŠæüz!ÁÈ U[–Õ²69§QŽƒ.[¿’6çÏhüS—Wse®÷±dßbfïyîI‡dÁFbNþ%ÕgÔÆGœ¢,bœrü(šÙÂ%+'‹ Òl£g"îuªrC`Wro¦1€5ÇCÈ…çpû¶šÍÄ]sG¹ÑOnäàrqœìZI=…M}…)äCQÊ~ ê!µŸ¾Dz9·%eÞ!­û©ÆÁ”,Ý,>׿¿âb‰lGûrs RøV0' uV·ƒÔ) É ²;^%!#úㆹå"à÷È“µ‚i4Í p#Öo·¤_Œä%±!¥Óæ`…(`¢ix¸ü={Pìr {[£3þÝɶ*\ÔvµvÈÆe~0{zŠJ"É®Ñc +µÄÀ‹í_~ …U¢÷íýwõœÅ6o¸JÚè¨OÊÿ7E®Õ?ÿm]~»úàD¾?œñŽ¹,à¾$ôƒc2‹™‹ãé¸æß‹M|&ìšp{³×Ó\Ì «e •Œ¤·Æý:®s”CrªÞr±[G^…_x[´?ÒØæå'®Öܬž ¥Škv5‰GlŸ뽺>QÄè5ó†…¼~šÒÙŽÝ  ÙvnÂ|*ÑÐaòÝ¥ÉÿÞ^á=tønÚÖ•_ÎïxPðdòùCß•b­RæwWbgÖJ?~årοþC¬[BýädƯ{ñ h§úÍwÓ‰Ï'}2~Ñ]Ø6å°âÙŒ9û ²&ÜÔîNÖñûö¡î±`luî‹)G2O=ßùEßCùä”Õùù[ +¹ÓÏ™wŸ˜sìÇÆâ@•»¯M·åöMXvºóEÿÿu9~Û¤k²¹¶…ê¼ ª?yÉg“º”òÌÜ{ç;OÛ«YŸ$3iÕæ#ÛÏn•8²oväóŽ7¯ã}ËÏëÕýÜá?÷þ¹ësÿ„æÕäÈ©Ù÷pö.Õ`¹fýO©a›K<­ÛNîêè=|ˆuÖïD©â¹µßýÝ^Ú(šDªM?T¹CÂxÝ;)ñ´g¥ÙENÓ/Û¾}õ%×ÊÛJ®Q†…É9©‰E%ù¹‰EÙ\³¢bendstream endobj -802 0 obj << +1018 0 obj << /Type /Font /Subtype /Type1 -/Encoding 2140 0 R -/FirstChar 40 +/Encoding 2705 0 R +/FirstChar 35 /LastChar 90 -/Widths 2153 0 R -/BaseFont /XYWDPB+URWPalladioL-Roma-Slant_167 -/FontDescriptor 800 0 R +/Widths 2718 0 R +/BaseFont /MRHKYV+URWPalladioL-Roma-Slant_167 +/FontDescriptor 1016 0 R >> endobj -800 0 obj << +1016 0 obj << /Ascent 715 /CapHeight 680 /Descent -282 -/FontName /XYWDPB+URWPalladioL-Roma-Slant_167 +/FontName /MRHKYV+URWPalladioL-Roma-Slant_167 /ItalicAngle -9 /StemV 84 /XHeight 469 /FontBBox [-166 -283 1021 943] /Flags 4 -/CharSet (/parenleft/parenright/hyphen/period/zero/one/two/three/four/five/six/seven/eight/nine/A/B/C/D/E/F/G/H/I/K/L/M/N/O/P/Q/R/S/T/U/V/X/Y/Z) -/FontFile 801 0 R +/CharSet (/numbersign/parenleft/parenright/comma/hyphen/period/zero/one/two/three/four/five/six/seven/eight/nine/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/X/Y/Z) +/FontFile 1017 0 R >> endobj -2153 0 obj -[333 333 0 0 0 333 250 0 500 500 500 500 500 500 500 500 500 500 0 0 0 0 0 0 0 778 611 709 774 611 556 763 832 337 0 726 611 946 831 786 604 786 668 525 613 778 722 0 667 667 667 ] +2718 0 obj +[500 0 0 0 0 333 333 0 0 250 333 250 0 500 500 500 500 500 500 500 500 500 500 0 0 0 0 0 0 0 778 611 709 774 611 556 763 832 337 333 726 611 946 831 786 604 786 668 525 613 778 722 0 667 667 667 ] endobj -739 0 obj << +955 0 obj << /Length1 862 /Length2 1251 /Length3 532 @@ -11417,889 +14029,1331 @@ endobj >> stream xÚíUkTgnõJÀ+Å€€¸ -æ2@ Š,Ë%€ -‚T†dBI& (— -A@0¨P¹TZ)­`åb°¢àY#BAn¬\uÝôØ¥?wíÙ™?ó>Ïó½ß3Ïûó™™0½ Nl$vA„bHi€³›÷a €D2ÎÌÌ…!1îÄ0 ííAÀI €T€lG£iT;œàŒ„E¢¼`®°pþlQd8 `”Ç‚„€$æ¬ âÞ‹‹#‰€Ÿx-®^°F#`6‚›ÇAp0Oˆ#-:b9`· ³%aï¨a¦ Ìägf‘ù‘æàH9ùo˜ZÙÜEÂç»C‚ÅöK)ý‰‡<~ä["“ˆapCØ0*\)õ—͹ÁlžD°’eˆ!>å$ æô!’­©ËOä“Âl&OÌâˆ/‚—pXÈ^i‹oÉi¿éågõv®K$â Å"Ã`€ü^½Tƒïk,%”'üÉD2Ä„Øûî+`Åf_Y›' (T[BQ(‡ ¬¢Ñ À²a)K1Ç$¢cK,š€ƒ ¸Å±‚Ö‰ÅCY|˜µ85ñ"»LPR–9üˆLÁ0bÁ|˜óGØú-¼<ô÷¸-†Cè{ËX¡">$â.ÁŽNG¤ÑŠ=@°·Å~m;;jÌ¿ Y……⥳‰Åÿ®æð°‘Á°fáz»–CRH^urEìçïüðIëe[¥ºW³Ù·66ŸÇŽñ¦žó4 —Ž+¯žãCúûY§tÑ+îé_M—è^¼šVTî›Om"öxã#Ódk^[™2äá‡N|£4¤5¡Î~»m{ïô¶¸6slÝï|ãÜ`·öFK¯“–¦›íz/h|¸ 9ð¤sëdm\Þ¬‰Û÷]L¼È%Í\ÁqÔš†fã8 -…•çˆSË=•ò˜>{~½Gz“¿ô©qªiŠÙóVïréLZ¬aôo·Â4ñwSÇ2Šg¾öÐÂ5ӯܑ'ÝP’2ã÷6»µ=²æ¾ÚÜfå.û$˜#†øeõéÃÏJëåÚÝõz î®{½Î™/ µÜ;4Ò(n’«³²Zî‰1~xܦ£ûÎÞÒGñ‚t ¾ûÚ3 —á¹¼ÖÈh<~=Œ¢e*ë²32ÿêÐ+Æêòµ¢‹M¢’Kñc‰´þc`ÕÍÎ.ðj<ãHN,c’‘¦—|-Æ‘ãí«,›7ÊêôzjÎÊä}:Æšýʬ(=…‰¬RÈãœÑžÍLÏ`¸{ú~©w¤9/)À#à¹ZÝ÷¢âYrvÇØ–„1u2ãDëËÁ «)Ѹ·6íRW©oŠ¡y$|©ÁÑf¦@Ó©üìzCä´ß¤û^<ÐÅ-LÎæFM¥žû‡é˸Áß'¿ßXBø)ÚrhB¹µ/{&nÄÍàd÷¹Ò£Î¡ºÌØ„Øk?n—ÔsDeIíÊ5Oñ7­;ýö= ‡Çe 3ajèz”Ë®8h'$Ô\×-”…ÌîЉМV*¦…­FÔO™àšÞ­;öL~¬}¹ÀkäÔŽŸÔKIëw5ئ«nz“yèy]?÷“пéÎúª_…çÍVWyÈúä—qæ7Jüþ—¡ÒÉðõù×nɯɉ.„Ö‰Öþ[E¶Tű‡“Êë•7Æ$ 7Ìe$åmÊÁ„3YlÿÒ<Ÿ‹?ª="YWT«š{êæSE aÐ=EÕ§´y”óÌe¼Âa²²ÔŸö¹÷¾_ã¨bÎI§?Ez“ØýB£®UjTæC¯J™š.Ñj}³•™Õ>ä1¨'›³²¤Sª×Hö5€4ûÝý†;öpæ.ü&µoY7î£HŒ¶×ñ -ntÆY~¬óôç»Í»_sóŸ׈N‘Ññ‰ëüï«V©Ô§Âh÷åcĺ´ ¿ºï*T¦$ÏGlɺÞX±ëP£Ù»å¡Ýñ ³M¯-TßfV1MW÷-”TômÃÅê‚Hâíenáú„Qkâ󢄆ŽpæÀ\—$§!7!Ç]~%Šœù¤)ömµÑ)Ç÷D_uo€£ŒÚjîü5ÕñX׺™»÷àÔúBÙ˜«jU´fŸîÝN—²QÝÖ…Zöî–Û£Ž!CN×´$Aü6ÍŸd~M ÁÏ'/]sÆfC"b’“0Þ]°]ßp]¶Ñ^‡ïkšÇ?¡>œÝê9h;>•MsÊo:Â(žGŸ7ùñ›¨£ªÿµá£¿ôµè«êꎞîìJö‰u5k—¦œQNmÜÙÞM8±+Ûã1ãdß~ºëþ9¹Öê¤òXvGH½ wXÒ“í¥Ñ+㬠ìÍ­à| CþÜÿüO4À®n# Åý ¥]þjendstream +æ2@ ŠMË© É„’ L P. (‚€`P¡r¨´RZ/ÀËÅÄŠ‚g¹iL@°rÕtÐc—þÜýµggþÌû<Ï÷~Ï<ïwÎgfâéCpb!Á° "@"HœÝ|d$’qffÎ( ‰¸ˆ`$‚ihoNâ¤d;…L£ÚáÌg$< +å†pD€…óg‹";À‰£\&$Ü æc=˜ðA˜\XEœx<À{q…ð†…0 ³ˆ8X\¦†C¸iÑCÀF»e˜%GE¨3X`&?0‹,DÀ‹X0GrG°½`ÌÉÃÔÊæ.bÏâ/¶_JéO<Äçò¢Þ*~¸X£€‚QÁJ©¼lÎ fqÅü•,Cñ¸L'A  ‘lM]&¸B®fyrELÀ†xBx ‡¬•V°ø–Œ|ý½Ý÷zY½ëé q¢Qá0@~¯^ªÁ÷5–Ê•d"™ bBì}÷¸b³½&Ââ +B +Õ€PŠÂa'«¨@ p,XÀÌ1‰(@DØ‹&`#(nq¬ 5@brQ&f.NM´È.T€Œeÿ"S0 …˜0fÿ¶~ /ý=n‹áúÀ2Àf˜ 9K🃣ÓI bìm±A[ÀÎŽûoB¦Eahélbñ¿«Ù\ld0,™¸Þn„éš_“R·÷ü>"i½l«R÷j¶ø×ÅpY±>Ôs^&!¢²ÑåÕ2|˜Bÿ ¦Ã)]ôŠA¦{ÆWÓ¥º¯¦Wøg'P›‰=>ø¨¤téš×Væ£ Y„ïéÂo”†´fôÑÙo·mïÞߦsŽ¥¢>ß47Ø­½ÑÒû¤¥éf»Þ šnÂG <éÜ:YŸc'sâö}W†'^è’n®`;jOC³qìH…ÂÊkÄ©õžJyLŸ5¿Þ#£9@òÔ8Í4Õì¹Ü§B2“góÛ­pMüÝ´±Ì’™¯=´pÍÆôëwdÉ7”¤¬„}MÆ®Fm¬9¯6·Y¹K? !Z¯º4RgÐúøà/Õ`ê•ææò¸PXamžñž§Ñß7ìœ;ˆÏŒ%~Ysúг²™vwƒ¨»ë^¯sÖË"-÷tŠ›øꬴŽsbŒ„·éè¾³¯ìQÿƒï¾ö +¬Åez@.¯52[‡_§h™J»ìŒÌ¿ò}ÅX]±VXj±IXz)a,‰Ö ¬¾ÙÙ>PgÉcL2ÒõòB®%Â8r‚}µeËFi½^OíY©¬OÇX³_™­§0‘V‰‚¸ì3Ú³Y™žî^þ_jÄiÉOô|®V÷½¨|VŽœÝ1¶%qÌOÂ8!98a5%÷Ѧ]ê*óO54‚/5:ÚÌj:Uœ]¯b(Üö›tÿ‹º8E)9œè©´sÿ0}?øûä÷‹C ?ÅXMh ·öçÌĸœ,çï ëç}ö7ÝYõ«ˆüù£Ãêã*iŸì2îÂ&Éüßÿ2T6±¾àÚ-Ù5Ñ… Ÿ÷ß*¶¥*Ž=œT^¯º1&n¼é`.%)oS&žÉf”åû]üQíż¢²x\ÝÜÔS?Ÿ4(\‡î)ª?¥Í£ìg.ã•“Ue´Ï}öÿO±O:½øû)Ò›¤îõr‰Q¹½:ujºTKþf«gvûÇ žtÎÊ’N©Y#ÞßBÒíw÷îØÞ»ð›Ä¾uݸŸ")Æ^Ç;¤Égù±ÎÓŸï¶ì~Í)xv\#&U6\LÇ'­ ¸¯Z¥RŸ6 +§Ý—VŽë‹Ò/ü꾫H™š2¹¥`èzSå.ß|F‹OëC»ãf›_%Y¨¾Íªö4]m\Ò·PZз —¨ >"‰¶—¸EèFỉϋ;"<æºÄ¹y‰¹î²+Ñä¬'eH‰¿ÜF§_ÒsYؽŽ6j«m ¼ó×4Çc]ëfîÞƒÓŠ¤c®ªU1š}ºw;]ÊGuå u¬Ý­·GC‡œ®i‰ƒymš?/H7‚„Ã~ùš36’“ÜŒÀñîÂíú†ërŒö‘ؼ|xó<þ õáìV¯AÛñ©šSAó_ñ$$æ¼ÉßDU¬ý¥¯U_U_ôtgWŠ_œ«é\»$õŒrjãÎön‰]9'û¾ »žÑ蟓i­N®ˆcu„6Ø ñ‡Ä=±9Þ½RNáÚ Þ¼Jö:äÿðÁý¿ÁÿDìê†P‡Ð0Ü¿$8þyendstream endobj -740 0 obj << +956 0 obj << /Type /Font /Subtype /Type1 -/Encoding 2154 0 R +/Encoding 2719 0 R /FirstChar 13 /LastChar 110 -/Widths 2155 0 R -/BaseFont /JMBPRZ+CMSY10 -/FontDescriptor 738 0 R +/Widths 2720 0 R +/BaseFont /VXRNEQ+CMSY10 +/FontDescriptor 954 0 R >> endobj -738 0 obj << +954 0 obj << /Ascent 750 /CapHeight 683 /Descent -194 -/FontName /JMBPRZ+CMSY10 +/FontName /VXRNEQ+CMSY10 /ItalicAngle -14.035 /StemV 85 /XHeight 431 /FontBBox [-29 -960 1116 775] /Flags 4 /CharSet (/circlecopyrt/bullet/braceleft/braceright/bar/backslash) -/FontFile 739 0 R +/FontFile 955 0 R >> endobj -2155 0 obj +2720 0 obj [1000 0 500 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 500 500 0 0 278 0 0 0 500 ] endobj -2154 0 obj << +2719 0 obj << /Type /Encoding /Differences [ 0 /.notdef 13/circlecopyrt 14/.notdef 15/bullet 16/.notdef 102/braceleft/braceright 104/.notdef 106/bar 107/.notdef 110/backslash 111/.notdef] >> endobj -736 0 obj << +952 0 obj << /Length1 1616 -/Length2 25334 +/Length2 25435 /Length3 532 -/Length 26225 -/Filter /FlateDecode ->> -stream -xÚ¬ºc”¤]°%\]î²,Û¶mÛvuÙ¶mÛ¶m£ËU]¶í¯ß÷Î;ëÎüšo~äZωˆ³cGìsb­'3Iä•hŒí MDílhhé9*ŠjòÖÖÆvÒ4Šv6€¿f(!' ;[a'N€š‰1@ØÄÀÈ`ààà€"ÙÙ»;X˜™;ÈÿbPPQQÿ—埀¡ûzþît´0³þ}p1±¶³·1±uú ñ½QÉÄàdn0µ°6ÉÉkHÈŠÈÅdUb&¶&ÖygCk #€´…‘‰­£ ÀÔÎ`ý €‘­±Å?¥9ÒþÅpíMŒ,þn3q32±ÿÇE °7q°±ptüû °p˜9Ø:ýí“ÀÂÖÈÚÙøí¦vÿ²w°ûaó×÷LÞÎÑÉÑÈÁÂÞ ð7«¼°èðt27pú'·£Å_7ÀÎôo¤±‘ó?%ýëû ó×ëd`aëp2qsú'—¡ ÀØÂÑÞÚÀýoî¿`öÿÒpv´°5û/Ô3ckGÇ¿0±ÿéÎÕ ø_ª7°··vÿw·Ý¿Qÿ“ƒ…“£‰µ)-ãßœFNs›YØBÑýsT$lMí ôÿa7v¶ÿOŸ‹‰Ã¿ "ÿçÌPü%a`lgkí061…¢“µsú›@þ§2íÿ;‘ÿHüÿDàÿ'òþÿ÷¿kô¿\âÿ¿÷ù¿C‹:[[Ëؘü» ðŸ3 øgÈØþoÑ6Öîÿ§øÿ©fò$ÿ0N[!`köWzZúÿ0Z8ŠZ¸™Ë[8™L ¬ÿöé_»Š­±‰ƒµ…­É_=ÿm%€†žþ¿ù”Í-Œ¬lÿi<˸Llÿ;÷¿ýËœNLD\H^꟩ÿÆÉÿÕÞIÙÝþ/µÿQŠŒñÿ\üƒ"(hçð¤a`eÐ0²3ý½rŒ f&ïÿCÆþk-càä`áÐú[6=ÿÅÿÏ­tþŒˆ­‘ñ?§EÉÉÀÖøïûŸ†ÜFÎuý÷Îÿ-ú?×ÿu7#¨µßvF\A–i™éNuè¹#SÂZ} #Áö¥ÊE~5v½¾ia8*õ?jƒi›f8¿ÚÝ—Ïì?$)ÇúЬÉzSL®òq¼‰(ú ·H;Ù¨ètKaÓÏÕ¢<¯—¤w@5YéUw§uK>Àqg:™ ¯Ÿ)üˆ\ -üPˆŸìá|ŒRbQ»š€ê -ÏÎIOžŸÈ†ÆGG†{oÁú°©rb’p¹€Â’FúýÊÁæÓT©©jUmÛëÕb3ô]ÿ””s -Îl~^õ­H¹²çŸÈôÿbاÑÙ®ï岞ÒæNHÙ ™C ½‰h1R^iC«ÙÂ{»AùÖˆqwÛÁxyÒWcÁ·ÿ¡y÷'‡—ÁOéTñ´šŸ­wôêuòÓsPMTUËçýNÀ(5±†ÅÄ ö¶‘ÛMüc,‚¨×]EI[™Y… ¸îˆ0^ ÆMÏm}™× Ë 3ž@óÉ ª0öGƺ°>KÛyE‡“åÜTh6þÁØŸøÐJ¢w¢§æ_[c ³öB8xÕ¾Vk”Ô‚—I¯¿ä„÷gÞk‰òŒ+(}‘²Å+åýdä„P9Œ,U•äD¡&w("Z·´U¾D£|yÛ)Õ‚þ0ŽÖ)¹` Á6l¬NÒµ½žŒÍ&²˜ W WâãÆ[.¸N5ÈõëZS† -€gÍý¬ÌV” C†û3æèºnMp»-˜…Z‘˜æj¤¯gÜ\}–ʈ}—}ÍšP«¤{}ò#U/ÉXÑ…€¼ðk¬¾ëÜV­Ð<´eÁºµýt.<Á0œ7Íw©~‹A“1²Ù°¢%îßD?âÝjÑä¤[,È4ý© -ÔI™Èüíç‘,ª!Û^ó&I|ú,~C¼ð O¯JëŽs/)'UgL—æªöÛ'ŒŸKnõætÉËÁ!;ÙÜ\õýâÚõþ#ˆ%æÈMµB”j!ˆªÎŒ o¢†PU&ø’¿ß¹PÃ$Þ;Ž‘»w©*t!Šꌄ|Õj”1íw-¡LÕÙ—›ö‚ߎ…>ßË>#ÈQƒ›a"¦´Ú×5ù“97Ûô ,h˜Ú?ä°wïا*\Dxc(uè³?^NWù,±CVØñÁáŒÅú3ý XÎfM.êÈ4Æ$œFß©þsÂ&^ÎtI¼\nk2NÓrÅ[>K¿·ŽñtPã(–v°õø¸qËxm°T +š[_]ÓHÑZŸæ¶ÅaŸhj¨Â-.åÂÄi⩾ÌRLC°ñáÎÍ|Æcþ®#snu„Áïr‡1¥—‚uÔîwÚosàðFÉ =ÂÐÜ:ž:ÎUšelòéÕY󸚉ƒ+ŽÜ×$í¸‡„ýM·bƒI”Âïò´Úê`9åÃÄu1КBPbdÁ‰[OQWúŒªø Á Ðë+Ç~1˜ö»z'à£R74ņš’”&üg½†W E¦÷àÆ»¨¸ð«ÊŸÅ\> ½’Ц¾®ŠÝ‡Phoº×ŸÜÝfaÄJ5¦ ³¢¤úЈ2G¨jÁ›žª{ôï÷1ïñÎ?EËKgå+ž³µÃ|ú$$Í¡ÃûyÕ´p À~·X5 -Ïþu¿^ù5cÔÃ[î˜4mô–CÌb^Ûe m¦Ýìž88ç}gõi.Ó 6Û²¡{ÇÙº[·:±’‚~s¼r^®µ{×y"j¾À`UŠ2f5?+ún ¸ ¼â@œî׿…@“%5£shàî‚Œš¶{++¬#ÂЙH¼GH–T l™!Ñ+PH­ÞPË9­«·Ä[ZYIçi\eyr*–¨Ö{Gnðx*yçK ’„èD2JG«L¸Vä±èG6<… †Žçð9‡X¹;‹X‡ã$]Hñ8ÇR™¿}t%بêŸZ¥ -´êÄÐÓ -Þkvßèåà?`Hdò8Ÿáz„û%u•$õAºu™\›+Gr*|wݨWÔÐæ>zuÚÐÜHq…ȃŠ0?‰Ù“]¢¨=+ûfUˆb9TV¶54ç,Te5®ÅjÈzÃà͹ÿšôÖ§"´ø´[mIƒ¡®\úàâLˆ½áï]šæÊ}Ëu_:jÆPß -–€íÖ—ݯUÛˆ¢¿ß$»Zµg-SÃ]‚.(#º™‡`¿ Ât´Üæ 6¿mà¯ò™9M}§’ˆù'WÃÙð´£ÜNæÜ‚é§$# ÁIÀq¯¹™|rË­$Àq·Ô”ÒÿZ¸“…m9à ¬0ãÞqVËZžÔÉúD?Ç‹™ýCòö± )'êwîß4'–½”ÑŒèšóaºáÇìY_ ÷]×ÌmÝäÍv784"œT&؈0‹ öµ­’üÞ£ZŽ3£¾¥Æ#­Ä#©K¼VNªÅªË¼T­¶¸¼¬Ó¿ç 'æ>Ç丕\<¥¥º€w)¦0©þí’%¼bŸ¬ðómiM—†E¹Tƒï4•Z)‚NuÝ1CèÌó,$U˜¿–³,âù$Ù*䵜 JøÃò…Ÿ`¾Bd,O/Y2çÑ}ðÂg¹±ñˆ‰£¨,áW9ç·³ -ýl…;œë‚$#¥Rј'ûBYâSö JLj N·—“\ð“ë¨zå0y¥~Сª{úë#Òsa¢¸²ÆfÙà´ñéöªðc~ßâ} ]˜ V42lï -T ›+=Ý"N¸F{VwÜ«Ýê'O¼o3Mk¹‘)& Y)‘-ÍÇaÊgþÆ®“¬AmIÂùϺvUÐiÝZw,:ÃzáÌxƒ âöÌjT21î n¢å­ Ç-§ä>1Ó,Æ×ò¹`uC¼ƒc ·¦¦ßæö%E_GOä ¬ ºTs'\- ¼òé1ʈ-Ð!^eʧý7íñB9 - §Mâc9ߺ4ôn9IÀ삲£(ê‰`ì5±bú–ÝèxMò±8õ1é]ôÎc-LðÛDZv;8lA¼ó/Y“º«,•×¨öã}íøá{˜®à0˜ÅUVÉ+c`¾˜f×~§¨¾¦Aлw~”æ¿ógfL¶vÔí,ÿ Š -˜r ]w9jr‡šØ[O§ÎéåMÍÏÞ@Í?éÀ0ÕíµDJF„rFhS[ͺ.ÆŠz¤9dR’XL -fÎ$Ë\nÞq94e#q0r±MnJïù» 1ç5Gö>’JôFí¶ú•,„DZ”í:ïºÂ €…´i*Œ•²Êcé”À‡nIÊQ“:­PݤNíYSXœÜvu›Aò=„•îÙ®A«bÉÖAŠ¬ö<$X#ÄøœR}X&¢UÎÈK"4áÕö¶ÿPbe¼ÎŠÅ— -ª *Aº\Õ@^¿>V1Ö†ÑîçhµäÀɱ~°ìj-ýflâÉL8D¼ÈV©§p¤‡Ekc4²îþÝc=´BªÔ"–¹² + „›šíwp ‹ÚjOI­{4°ؘ…‹VxáOR¡®TÈGA ì³+ ®À©„”À3ã×ËbÀõøϬ¸»eéj .5ß?.4?‚w1¤ÉÙ,ðà_–yC Qöê¶9›«¾_¼­pJ-G¥™Ñx¨^ð5xŽ“L¼ðh¼D°A€'áO¶0„0²8t³˜¡hÀ~AÛ{ˆ&î)'`Gï^¦‰m ½\‹HBõoW"Þt.Äñ˜êò[Ê&G>¬šX>­|¶F‹ÿF9ÈG: -}ˆÀu‰‡FëOðѾÒ`g!ë˶’Si™Ûs„×dŒìΈ”’G‹ŒÒ÷¤úPXŸ‘ÊX*òp¾š£µô†;pšX ¯»Õ䄾ÐÐÅ·.ÊÆ™³õK· ó§r±çÌg<¢åûœs§0œRÁãýËdò3‹Lqø%$ØDë=+¶X—¥ˆÚHï´m%¾”+pÔg­2œÐSíÛ&ÛÆ’ú‡®–ø‘™ÔD”sƒVL?‘¯Ž -ˆ!Ýkk»†“×ÉÇ.¾á®ì6Ëq_6…áNÝ«—6™T¶Sµ–F¦›–‰0;4Kÿ½26aþ2+Ai};bŸÀ‰ŒIu)I£YÅï“y¨)õ‹—­VïEeõ–œ+e"ÑèËF ÏèwéV¹Õ> ^;"ZÀÌ}¯å®I„ -ÚŒW?ð9ÉšjgÄO¤¨Ê£%Oy-¨Ê¾ÆÃt­ŠÉ2¶”êy (6eÅF~!²×9ÞÕ=¨NdÔ_Èí]Þ[‰+£øþþ>»`.‡`ÔŠk™½¼CæêU¬ùôÃÅN²3Ë -Ú¬wî‘ê"¹¼|=’4v§Ù:¬)ÈÝ%¿Ÿë°yÔÅ)aÆÃ=Ax•qÊ8úçUûƒòM[iñÊŽBËE7ø·džŒ¿_SMé)7ç \=aY„2Ǹ,DôÝØÌ¿ðÿtöÒãž¿â K‚7Ö–ªëÏ«wV÷ž®a@¡ §¶¦Û£;4É™ÕÖYYøuzD×/e£*)£‘ò9fS$ 6úÀ÷ÒlE;ûrðã`Û¸ËCë*‰{•mÖƒºàÊ–Mx¥PJÇn7ß7Á±^m©Þ®;±ùM6ÂqN;Me.”·k–ü¸¿mF²jkÁÒ⥠êv„,Î8½Õ­Mþk´«Á5­ ÜªUô æ^NÁ&ºg3w‘²X4YeWn)•#~…¼qòõh¯jH¨Åö¤Tpû÷ؾö|]–öÎ…¸GxÖÀ´K<$LŠ+êT -ÔUñ`•5Þ -¶¾¨1&µwÉù|ì9UÛ39TQ÷䆹í| ¡Ã(=̨º; GLâ§6ÿãì¸Ì¡"¾Ž•w…B|(iïˆ'Å'º¬ú[7ô ¹r+£²*iÌÆä;¹E}—ûOþÊF\]¦l{YåAF=AD -»÷I¦aôIãÔ'§»ÞÄû✨œùZzñÌkåÌú9¡ÓŸ&G ‡Iiä¿–žÓîè½À¤Œêˆc­Òئ¼¹!·5â[$µúÙÌZÜ›˜@_q´öOAš -´afÓ´s!(ˆ)§é‡¸˜Š  Mí0Âß<_°7;3s]˜(ª¬Þ)JÁsTæû°€½F’§Ò“_íç#¹ÏïЉ¯"#(àÖ!È¢‹ù£áõDóòöÔfÆë"S§ÔtN'Þf~¥ê:#Ï¡Ú®“×5¬'9/ŠŲº©C;ÀÞºñ Ñ8 0×[ÐÎ"F‡LÃJ½†¸§Ì0Hx_Ò#—ä˜ L슷>72ŸÂa¦ЧÖÛ×w¬l’ö‚º>„ÕžU’v7“[ø×û†÷¡¯f}&å}µ @-rá™Õ -1«¬Ù]͊¼аŽÎžl_ø)J%r˜#sŽ-Àë÷­Ýà,Ó’µÿV¨ðyºoèLLe·rÝLû—‚ f{ûc†lî %Gä·Ú÷<{­ëk†¯¹­ey4X«Þ>¹×¢ìØÀª"¬‰åLóp å4I»{lî5QÞ9ãÃôId3–Ò_`gbת}û -rÂWf¯(¾ Ê.Tsûœ$rG~‡ÌR)G…-ú²O2cl?ÂBüX CÇäd"iXćÏà÷ÈÏ:ŽDN?’OÁLf4ÍÔ ©é9÷°Ó?—P5Â+ ¼þÒ† yÓôÔ#ß3-­Ò.\±´ù¥„• çÄŽV¿¸:…ŸÏj¥×ÎÛ|M¿Ÿ®'Š©iÕἨ;¹‹*ƒúŠðºG£o´×ã®æ¬Ñ@z-Ã=å÷îÛƒîØ_¯.1êeEV'†–¤þ%@X`5ª¦ÔeÎ*‡kúÌa¾heäY„‚šaÛ<-î‘^]üiˆã–ºZË'ºÿEeŽÃïõ§]Ã3¤¬„0¥`ñÊ“êí~¹/^C«ÿÊZ¸Ödá·›¹±å¤@§ùÅßQ4Ìo@÷4‡wÜ-5꓉êÁGÚSŽÛËÏnj¬ß" gNïTåå48‡Zõ¶YQªéø-0¯ÏCÒþØ´EI%±ÀÄ,ueíËÚ 8–ÇþÓW¥ÂÔr×!KšÂÎèü`‡ž„Õà@l®/«Øþæ.z”ÈÙä+ö…m\0 ‹¾¾„,qÚd~ï#ç7K{êºýÂI_r(®¬µ׉ÒõN/ˆÏñó÷¦ÙèbDßÑÑ#…iâ·d‡W¸ˆ½÷2šЛ­ðƒ‹_e ". (ø§ãÙ”'§ÉDØd (F¸Úù¶|‘³e¾Q6 j1‰jߢÂü®ºÛ2SRßè²+6\Ž¹FÝ‘ZüýuMb±*eR^ÞzWjSC¹0r”2â²]òÃ5|ô¹Ñ^òI€Õ+`쫆‹ÐtúIÚÙô©Úòó¬ƒ î -ä¶Ôñ{mƸM¯ýœîdßËæ6Ú´Qµœ -‹¬)Ì Ÿž6Ö=jÖdÃ;í¡Ô¶„µ¼n:_>;y""¸ü,߸藵’ðȲd Ëd¨Q TÇëìÙÚÏÜ­•ïØ`.ø|Mõíº$õ´#É*šö7 ´¢Z•—Ã^SúëVa=žBžk#UõuƒKVQVQJÕÞL§Q¶Å¡ïºÜöÞÖøMØ¥b]k®Ûý7>ݳd«,B?.ÿ@uÏD®3uçæM ‰0).WòòÉÈhW' Vws˜‡×ˆ¢ƒ•\ -=;3؇ZÑíx§fÇu1{©‚qnˆé%Ñ)(Û+Ë*jóºpd±NãÎH¶›áóú E‹´Ø*ë_ªŒ®MuL¡Q°­èlq±ô¦‡³ý4ýCÂ4Š -õgðeµ™ ýÙabÎbg›iÏRZkaPC+ˆrÖƒŒF&õ*4¥vè°½4ü`o²O¹Û•{6oŽ;ǧ5M²*ËË»mýæAd/œvH&TvןŠ•×èë§fè"W"Ô ˜_©§D´ß-ê{IU#\Ôw€18_1mGwÃI&Ùj™6j%µΑ4»o»R.*Z¼Ê…jº…i7“—n+2{'oœnó„É^*½mp`6id¢ýU•DoPþO z¯@@W7Q!˜ã¯º| —qu ËNƒò,ÖÆ8þÉòê’xÅ“œ-LÂæ“š¤Ö,Q‘ݾŠY]ò:ú©s¸÷8UsÞ ð„Œ)ü<²oD¹B2 -Q9ÁïÕ@[E£©ë|å»Þ¡–åq¡¢ pȫУá'¨h æl¥ËˆxKw,Š–Z=S÷z ë‹TgÔèŸ)¸ yXɶÚj"С~Ù·©y¾Wjǵ­ -)˜Y?þÄô‰H;§#ËaY‹zv,„krÇ)Æ-¼›è™«Ÿg\VÆAÜ®ô ×f-²”x éH9ØM±·‘úÕ¿)ÇDEðHÅ#Àë-WΈbe8Ôç˜y•ÛaÈÓ¶#„ŠB€s¨Ô[¿Ñ¬å=%*žÞ$ŠÞµmu|6$)!¨z°ŸøǸô†áîÊMÌ]Ê„hf⃕ðH! -Z_!ÎØÏ™P°‚ž§TÙ s§ÌÛ ˆo{V®!(H”4o|ؤvIÒ†¹./ÔPÒùä³L6ŠH±ÞNÛ¯9s=N­ âkûrë¡¡ #Ž™.|eìÀ‡Ú½ìðâ+}(|ô’‹Ñ<w–ãÇûpÌ'ä çEFeÆZeý‰¶{ÌÌŠZâ;•–½D±Õ½v)<Ô3ÿ./|\×øÁ¨b÷ïWSDh~2vLñÛ¥“¤KE'LúlŸvQiuRî–±Å+{J¼Q*P­/QÁÓ÷“M¶äÂh$ÞE?&•é—ŽåaX&’@7?“Ÿ¢£DsüÛ™µ×Ìò"²"3]CxÏ}Þ“|mï/ÏC¼ãÜÔAÕ5ÙÐLÚ;î ¨ÅGX¾çE˜Ç¸–SÈŒáÄäóþ©Ò"eÌ/(qxBšp+²zGJÏð/ð^3£¦¯DüÆÕqŸfk)KÏpHóÚ¥÷$tÏ–9%7³2ÜAP ï¡~+)@°‰Tù©Ža™p¢ °µWƒV'Æv+ÀW¦_|\1gýÕ›ÿä°Wˆ–FAXq‚¬cà×¼²)sø¿íFã»)Q~žéüÈ Û°¯Cë5Ýp }PqfEÓ3zÎâºî#˜Ý€†.„¢-o ¿t61ßÔúªONkØݧ”¦ãWå'Šéi›Î¥lvê”ô÷ÞÕ8R¼Ù[M\šÅ2‡çà -O>´?ˆw]°÷¨Ãæ'²€n]*¼½ZX6ÏvJgv’‚¶Á =£;–ðO ½‘*-ŸâÝx>G( †Væ3ÀamÔ­{b|¥ %D~!Ù;'½Xï×>Å{2\ôsA¢›åÖOUiCYxm]¦ý,+“+ÎLïûôcK”¿´ãOn¶Ó†2pÖh¿EßµWê¼Ý†a#’Á°ImǨÐ5<,”ç'—ÇI$º¬ªêßbŒ>"1^ÓZ-âáÛÝ-ƺ%·£¹¤“—Í¥’IÙ ÕÛzbÑéš}¶~Ä©âLÄ6 ãaÕÁqðP2´6GðâPx,ro½sayjñ¥\Mó8Ë49öÑ~q|¾^þZ:@MSAÜÓÕ}$\æý¸ú† -ÔSßõ}FÆúcþ„"Ã\|¯*)ÕI ÓÔ–,õ†˜¥I" -n½ü.ñø*ì AÆtþØãR‰øæåUçÙ +KùMg”m{·Hn-dðƒ­ -'´ ‡úÃi©šTâ¦a4ÛÀór4C{$ÐI™}ø¢Ù>a‘Z(žxSomgìY/àOêÛ–·Go<Ü;œö£~NCbŸPT{ŸíþBÎÞ×pR½P¤ä¹ÃV‹»MÿpžíÜ*¨‚]”Yè=¡zéêÛCœ£LŸ3t7_>&IZoômG‘f~•¤Ôóþ{àMßq;:Š»Åu ¦€©ÓZOk˜ˆ<´XmümŸãT`»u6J+kŽ¦‡+Ö3ê~ªdô›™Ò]þAO†ðq†Â…“”ÈH®è$#c*ÿ1^ïÉ’^‹ÍR¹aéc‚ç'JžÂF°úÝŽH18LVÙë`¨çòö«;nQRGí\vß]"zÊ°¼~Ë *¬‰@ÔàÀ°··¹Kâ•ÂëÐÎF>:W®Þ¾eÎA°îÁ¯ñ6\¶ÍEäO5ÏOéÄšKÒÉ›b$ÆLñ™Z -ª`Ί‹šXN”ÀU?Ž¢®ºëÈ5ËXrB0n9½âà!§æ®»u*PSçoiyµÚÒLNöolU®/'²ºNl¾+ -z·ô̇oŠ%ž}Áwiô[ªÙ׶K¸pWâ^­níåÛiíèf.\«™CÐ f¤: l©N}Vâk¿3 Ê[‹æ+>C²W97û&Î_lûnú6±pÎÈè?9+Ì^?…ö z×û±·ÝIÉ*ð¸ãEu…nÄsA´Ç×ñ^dŒ–kC2^FvBñ§ Ó¬Yƒ¸†|óIÔµ%y$¥Í•Èƒ’¬¿BPÞƒúuÓ?fÒrJZÔø¯e¢ú -WL©,ãõ®<ò ¼z8ØAÚBeåŽýAf!Òç.P£MX“mtŠž¼ßZ‰^`«-Þè|‘ ª<:´N†„¥,ûP£—ærÌö)ìÆFSuê‘Ù-Qà‘×® -õó"KŒŸIF€¥%(³–_@k°„ -j-éù•_"R§‡7D.àúœµÁK`RŠcàÅRÓ¶µËê‘V¡€Â‚¾±Ð ‡‰ŸV':–ðê$íôÃDgènº¾Í·ìM‡k/‡&ŽNYúÞVÆ3‚tӾݭæ;["Û‰`Ëk•¬‡~bŒók-<ÓLÄHsH‡X®¡Ê%¨};É„ÞÌ“Äo·ç™HV²[]û:ûýã÷ön±Út‹©¯¼€ x-0å­ ¤ò3(×|–¤á#¸Úª$xœ£“µ[=~©øwBˆ¢ÞЦîx´-«’Â@iaéLßü` la"qÞÈ çïÃ+®(XÿµgˆTäq·¼O$:ʃú^ÐØwàÇ7Å棣t4i–êk3´A·‰púTœ« 檾{<\-ÚHœžÜ›Ðð_%{žjoÉe«=’»sþ)¢ñô0Ùšª:Êò7çVÀ×RÄpi´Z=<=z…\Ë!õ4$ed銛Kju~’á, §Å.?&‰@\ š¾_x6ÝÍä­[<v0$å#‹EԪѦ*=6Á?0KJŽ†«êé†à9ñ‡:‚£´°Ou¹zÖ˜öèè+I‘ž~™DØ8þY %èàt:eòñ$ÃlÁ)ls®€ Ž¶;;˜‚Q²‚;3Ùöµ1`˜çÑ.*dýý€%ÚcªÏÓSeË€ƒæô¢òœÀœ„PÚÜ ½mÎF|P™îi¡ñµGwÐáÙQQ¯9µlôœfûü­"8›»´áb…ùv9Ï2{s’¡HË8!¹<°ðwô¨3¬¶hÛ¸£nvâàßÒj}-Ÿ »b` s«¾o×,Å—ˆ2í? -–qÇÙ¶â(ŽÇwû',»_eßùÈvôÕÝU]wùd}ðy0=˜$IyO›ÍÈ€œ=»U9e~5ÉŒœ¼uo{´Ñä¬nEhÕkPía˺OoÑQ2úˆ9Ôì&\`}ÕGÈÔ³ktð´bÖ¬5‰\5 °ÀÃbC“ -8×Ù¾]“’h·À¯6æâYn%«çŒò2Ã>¾õúŒP?$8uŽÁp+F - ™ðˆfd;®"¤¹dA¾£B·KµAPùsF_óuª†. áŠD*Aü¨ÊiðÔ•Çð—3+¥]ª„kyÕ£dfÕp¥ß†ÜŒ&è tÝøgXÕ€Š¢ ãŸ6MªE×ôR¦™–/œÅOtÞÖôÝýÙbE€(àºè±GÑ@…¸A¦½¹ûÆŽJÉìÁÚ ˜‘êæ§p„¼a¦ÎïbH—@$ÕflÕ?îTù×7íÛ|¯œ1¿T({i•ò¡Òj[T b>J°ÿ܃>Ž.èh‹æ -v¡=å ze׶)ö\à˜¯y€Š|É) Àµêú<`I@Nw¦éŠHræ­Ôóºƒuy.)ø·Û‰Ýê‚í\üèG®øÜè 8tÏ»ôanퟒJRo╨,ëE…cc!U!ž¤ºõN±“¤×[zçQ¤QC"5ä ã‚Ê|7ù9s0˜L½I½\ðî §¼õq·aø‹_®sÅ$Ö꩜Ė]dyé=t°P‚Ö¦—3YoÝçÒ2Ëp•ç]Lò2†ÎïOñfÊäNªQJUfî‰8¶÷$ý›°‰¯öOv¢8ÉæòLvViÊZã¬à¥Wf¥2# =ÛiïXs»&ÇjšœhèL¡2ïŽ9Ä! Pé\L mØ:É<¥Æ‘Ä“$ó?jÂùTA>—1Ûƒçtu„³°0w|h¾6bzÀ¿–ÙɸâœV©<Á,Z"X¼×e3„RÄrç*ÌLå¿¡höç~uÊQw³[K,…^ÃâÏ ð{Ç©¸<_=ë í8B³–·Åc¨z,êF½g-¦UÎ’Û3tl¿tÜ\º­æÖMžIWiª­XSsZ"³`«nÍ[ýá#ì~FÓ°RJMFÖÅZÿÃxåAÖT< K%ž/ÚÙ‰#Ê(¢µÑôzâHT†‘^h•#PZ‘i}1Œä=û}Jn gI¦ãá]Ûìd°?÷M{;þ"*ž‡‹w1EòË|øz•ÐØÿ¡Èÿ.²·CdÛƒ+Ž>ìuÒ,låj±ô@x÷¬,’óržI&vË`XÓRz“GkOš( -<”â׭Ҫܹçò3¼+çÓ2> $´‰G£éœ'¹’Ž¼ˆÔ -ªwQå\T1‡`ï–*!7Ñb¬§¤ƒÌ%©©Â+¨÷|¸M·äv×·vã„z²Žç§ñN4És÷ôq€ÔüY ÐW8­-²¼ -!STlÕȇ=f¿lOtÀGF­FTØÌ]¾Žr»j€¨7mÞ±Ï[Üû)ѢÈõ|ÿ`yzŠöÒé±<‡‡a^!½Ì=UÆø×ÈÂúa¤Î†¯=Æ%L€®"¿ý%âwQ˜H_éwõ#"ÜH„-»Ö0PõºÞ¥@°lÛt´+Ã=¼~•¬Z>ñ~)E‚®8¿’…@ Å²!tiv6diü•â¨n© J@u˜$íoá}ÝÉ–i3Áñ§EÊ®äK„o«9 ‘9Px¶:lrÔpÊÕ²²`¸uÓ/µo­î’h±†™º¤Õá¤Üôƒa30 ?GÝf× k!{h¢Ræ×;ì]OËÄ(«‹ž<üÓÎÃijW$Ä,= B‘Å)HS†b@‚ÕIw´«–¨;¬Ùlͨn³]]CþÃzÃÅH4¯9¦d˜«çï¡~¬ˆÊ \ES ·Â>VjPÈ7³ßtë™LËYýUå€(ÉxpЋØÁß`›¿ÃTdߢ}éøO Éñ¬1°y°‰¼wx;l¦"–SH{ïÚË“°ØéÆÛ'µ‚ ‰œõO -‘xÑ6@·î“ü <SË~m!¾áº™Àƒøu’°ag¥Þ¼ÃæÚ ñŠw­“ë•Î2z­B•CÜ.7 `˜Uy̨²Bzx’qê/›ä?º—d¾¨¢ ѧcŠA×<38æª"<ž ‚õÆ—½!A.Á& ­¼ém³y%U6L_éµµ'¶TŸ€^Òšè¯`3k‘«åìpÕŽ)r™ôž(ªêýx:Ú‰•'‹µ?.×Uô1n mÏKÆúC³ÆË¥‡Hörºðµ’h† ;$•úÆ6 û}TOVè—뀘¦†ÑÑœ‘¤rµ¬ÁÇJÈ–÷©¯+®…"|a ‡‚΃Éê°ùd@œgø²ú@0ÂRü+1Ï©tÓOÊ|ò—\¦»'© ­í|çì7=áü÷8þEËžsmRà…‡[T{ â›ÌHƒ–°±F‘ç3Ôù½&åó?e1OAh¹¿æTÛ*&MׄR’íUVJÖUüB’c_8ܽ›ÌËï¿žÚzÍS}XâË´] Nâ®@"ÂÈì·ŸPoêj"~])HIÿs#õ²½]Â1í¬à2ù)ˆÓFvL|]-Aøè›\™ÈÐ/KÊ -;i÷¤ð =¨?³F‰%dr,¯Ô=wxŽ$Ì„½‹eÐQ˜ } èax>,¢RÔ÷ÕüMoÖ+&Dù ={ùfs9 µ¨<|ó\¡Ð’0së·§!Æì¡K^j1®!çóã7ƒÂF!2ùš/ÞQ ýW…!dHc±g±Ä{«£Pa,†S™"GÂd¯Íçe䶬ÍöáÇþ°ËV¼Èˆ€CaDÜøçf:*ºXþÉÁŽ)2Å·áV׫ÂPHLVz륚íä«Ÿ96? Í2åÈÕZrÍ­Í »È»Tn¢"Öhd T3‡½:¬&™t0M ;Éà¡?„R„ùHÌ÷ŽlߪeÌ—cN^Žaî[¦|©"ÏP%]Éúí9F{ ,R˜,wÃy'kÊ?Ázï×J#ů§¼¶7èÑf[ØÖ¸Ü8m>é,Õ£ñgsöèîǼ–Ÿ >¢’mƒ»šz¶‡–œµýdïŽf[¹öEódd@â?õ–ûn±áH¬‘YÄ.·äÈ"R½¨³® ®c41V8;MmàZË¢ò·ÝHu0”`QMĦ‹Â‘.;¢¯|í/âcbÇóŽ—GÛR>BŒÛb}7krê«À¡꓃ BÓwè‰)YXP›Ålè•1«€KDà©)ÎýâÌ2~eœM=¤®%Õ3– Cu^yQ ä7ô£¿˜ e*²»ž¬js»¯ù‘1'¡Û~POœÓü T™æ·UFaØ­ŸsA?Áè¼³Þïê/Ã×›Ý/ˆ' xû:ï+#™>ãàiýƒžþˆ¶ âh1CJi•ÅĨ 0+íˆ ªä›Ò¼fÓjæ®3„":b^¿’ž¾>œ ÒGßzHűI ŠÍ2‚W<—ø­î±aj4Dµ“ 5«\6†3Ÿ‚ c½Fbá¯8çÒIzTp…!‡ˆ­W@Ö…•Le2ˆm¿MߨC8Žžç¾|à̤ÞBÂîÞÄx˜1=WUTw.ÒB²è¾Ôç+Sïj©zx¡Ê-iSŒÌ¥ŠvÔ¼+ù$zÁÏ™FK0&}–ã㪼¬Y‡~9M+Ã¥SÐ%Ì.äÛ¼­=éšâÒá™>uMÎWÐ_Jú±Å("3²8Bwú÷7Ôm´pJ°B4¥”Nƒk[‰urÙÍù¤†sH÷Ö°aÍúFŒÆ]bføÓy<;X†4Ò²RÖ:’êa“‘qXL¢e9G膥`ÓC®%…›ëTÕ“PnòDXup­<§Û­Èž¤ODZ‹ø5­¦/»#øí>¹Ý¨€º ~'–®y×âSï2ˆÊ²„´` l—Ú-|Us¡o(ШUó4¶ƒ¼&‘níüÅçcè¯7Lçdk~Üæî…MTx€iÊL1ĺŠœŽõ‰4Ábͯ†Á¬R=ÐFÿ‡ hC(íú6IÙÇ0”¬ aúÊBJiÞþv£¬zh7ùp¢wÉ×é–WŠ|WXva,qkOæê¸ü¢AÂLR¿i9ßv«!Uno¿¾Ó7…­EýØé2CGÊHß soo¹°®âîç´ÃÓ.·ü‰XÝ[ä -sŽ[ò¯ÆºŽÏ ZªT˜Fu醭aw;ôfI´ª|fÜÚâñ‚ÑîB5ç:ô›C]Åt)´¨ [³')Öá(Ö²Xý” ©A8çŒFŠƒ9'™ûkóm Áh%žºË!]Çqf°pPŠpÛh T€[LœPv?çM4™£nÓMZw ×Ð]ÚUå)nÆ<DíÃÐ0ŸJç!pº­µB‡#_JÔ&bƒfç×M2ÇjH@§ùåAßÄt -Ópd½Ô[`çCDîãY`=O¨ã<IÅÿò‹I‡ªF< óPZä„N|£Ñkÿh!Jž¾”Ú§x¼¬ÃÇ`3´üµj¥mÛ*õ·ÒÝ“$Á³a†£òÑ*ààw¥+}ü[=5êÔ;ºžiþÜÉzÇS^ dSuœÏóÿüÿ,.Ä2lsŽ¸@î³ñÀH²Ç¦¸c;däýHŽˆEpcæ2®ªÉ'ýœ²( HñíÀfº6¢~ãÍè’6yÏØlêÖ¿Œ·ð‘®ª_0°—j†BƒLgxN†N¼¸4tãr&ð$Òá“×⳦\׬#RdBÚsdz/¬Ôü(Lš]ÓÄ>ºís~þ”êýÆ ›¦£€Ó‘(?¾lˆ$Æ_L¯þN_‘çSQìÎ8µG–æoWåŸw<þÞÅ`2(n4~i-ºª©[íòU®Ü€GO ‚6 }€ÞÓŠáºý rU«"K£;Ûðž_csû¸W–àTÕm wÅ›ð®Û>üì‘\£þ‡¯ïútàùëÏAW*‘˜ SôÛoba£¾u‚Ѥ5÷„®Ç.¶ï(>KK? 9àR©â‚?¿$cHp‹ëʳ&¾4(b£R\uÖ¿íØ×ÿÅ`Tf`lqñ¿è•¶‡Þ¬ Ê®£JñŸ9W¥3}ZV~ý¡’„¶ßt°üèR=>ëYmâ…lÊü“«Ám”’)é²Ó³ÏZ¨B©}šè&­ -Á¸ç‡ÂúIo>¢ž Y†¬ƒ;¢+A²neçΚ[czýMµm/p5@?¶~t€pð’ºF°‹[Ç - }W—ÔÖ¤í®dÏê3Æ­­Ò‡¿$ºÕVP› øÅVc%3¥@¡íä&žH˜.ÀýÁ6vÀáõ£…z…BqÛNÉš›2•TûD:½õ®àxü\Æ/(tùDѦ$C‹%Ð}B–ÌCÀèçQÅÞ §ŠµHËÅL9Ú~[[f︙¼mZŒ=6% Ù]NÐu¤s0E‚ÿYð»\I'T‹p>̵†ƒ"H= ‘ª-ùQLO*I!P9RÖ° ´ŽšL¾QfÈýíDzjDûYEùœÑåZòËëâ¹ Ü 8ê²€È}†Ýù«]5ÖôV‡Š2Ûy¿Ì¯Ê”¨ÈHs¾©Ónb„ÏçXÊ°& ëçï‹šß÷¦‹:ü…諭==’åÐýzúÙL}ˆÀ^Úíéˆù×½ê9a´¹©ôz£œ]?¯™ ,}QhyÜK(þ|Íöªgˆ˜€!¨Z Ñ„œpaÌ9…åôÀ!ñ¥ —Þã⢻IW±~W)ôXäW³ü€@óœMÝ>Ç똾r-ên´}h†,#Pû -tE$ úoÜK‚†¥ocÙÙ E/¥ïµªmí’£ær`![Ô¬Oå¡ôVqé;9Í¥¤Ýý}K œUåzWiÒÚ=þ º«ë#óç'ý/Š>a¥ìsµ -žž3¬ªA9^éH_ˆÊ3ìšæدÙnà‹)áâm>À}ÐhàÄšŒ åø3ÓÝŸ•Tw²•ä!l}òrû´žMßÁž}µe¤Ä¨(ÔvÇ µþ«Š ÉpÝ8})Z¯ìfä8»8Iƒ~±žH.<³»k—Ã¥ÌdÕ¹<™Xð’hɤbÕs!÷Müÿ´/$¥nŒñIpƒR{Ä„'âcêRIÙ=\XÌDçl„ñÙ7<²´-œà SæÞ’ÇVûñâ¸bå#É^e‚ÏÙþ*Y¥µ -÷5bóWŸüÕôt³C9D$š)I®«K$j tR(PPÀ"“‰ìXjÄrÍq=L7Dã`f*n^˜ÑééÍz˜`ÕîÊ_Òºn°u|ù5Öe3Œ?Ä‚! ×J„·LR8“*'²¸¢hŽ•ˆã€AŒe~ô"ž^'Ô®qiÙ&­´fˆÄãow^xvÁoóÏRvÎ?îè†÷ÖlùÑ2ú«4Nc|mOdòpÝ.#8£²#îK²nd¹!6Hßçw¿Mï;ž†‚ìÞ BUuו€‚CTl®´ÔZ¡ØlAi!Lëö.¨N«¬œÏÂðNÕ ÷?õaØÞ&.8ï †‹Gq2x4Sâ@ò~ê–œ%´Æ­j¤«¦³úN‚Ó˜N SˆWVµêYkÇ°¬5²¥áŽ¥ôbûz\séeñ½kQZy¤h*Z–E(ÚRˆ3 Fè~˜;ã|$ªÓÃ[®ÍÖ-˜N]ˆÉáÙP<|Å:³èôFÎõSº6¾Ï,)£Tÿ¨²š -ÑåêB:­ÃÖŠ Êx$To9@H¸%±.¨Ì~jô&+A 7—ê³Óê®ãO ºQœß ÝÓ¼UëªðKŒGf´Â8Jý?âá~«¦°,i´KRQFÈ:çZÔ²öhÚO>Oɽfx‡2ȪA™`dµjg ÞqÚþæb[{e=?_)ºüDÁêÊl[TÌ37Æ8)Ñn+àAíMõ­¨Š"z´CE'h˜¹BÅQqzïªö0|#aÄ—loàÊ—v’³XfŒ´xè@—zÁÄJ/Ÿa‰¹­2ŸÝ¥1%~¬uÂ…ÚÐ63íè4(ÖOHv´Éã‡6ø‚æ *ñ;yŸÄp+íKÈG?üþúI‹À7 \sNw%Ø’‰î;J¸To•Ö!NÉSenéN†£²p¬î“‹vÇìàà¥vŸæ:ûó”Åáê–Ê Å’gäÝÙ›¼í*p1IýŽµm©– Ý¥Þ™P`<êÿk¿œ–+Q,š¤Ó±­Û¶qb»cÛÛ¶m۶ӱѱíŽçþüMÍú€õ´jWmâžnâGa¯/e®_°^èd!xìí¢ ¯¾>äÂH³Œ’L­‰uw›Õbd>)ÅxWÛµWã h”M¬Sçà’.³™FðuÖîë' $ä|?3¹O€úu?,€XFc”ÝÙP;™ò~ÃSG\iÈÑI¦„õðçBl9Áó<×`Xzr˾uӷÑH?sÝ‚±LɱT†UJʇ ß6¯BOcE7W‹oûvO¾ÍTúŽ§¯KˆwÙÔôã¢K)]€úøoé)c«¨T½«ÄBgOBiž?Ôu$i6§(`«N"¤VqôB¨/ç¾›G’¶ÝÁaäz©¶îp”kQGU©·T½qk”D”øŸ*Íø^nãGò 4¯ d¶¯'ã*Öáå,Ù£b|Êsé†,§²Ð¦Z¢€%¦N<4¯ƒåôbtß+ÁxÎq„íöU'éù³“ÁÄ€?å(Ÿ6î §SÕY·ùÑØ5E¬©ƒi• Ó¶ ã;Ü«Q²õò¿ßÃNè[ÿŠòÞÓ1äï[}ˆ·8—^°xôï¬3¶µ±‘¢5:ÿˆÏÝ•AOoË° -4­úWM‹~©¡CÏßÊÿU-Ÿ}ìŽY¾†¢á_±@Yh€íu›øbÔnW,ø”=ízt<îKfp¥]“ŸqæÅÞ-3Æn’aZ|ìŠï|=AW?~†ŠŠ¬‘-šë\ïb;üšsî¶j÷Žmùé4§xßîh&ô¥ü"{kƒ³é|‡l#g nl+Ï7#R±´Ö>õŒ™Y©âeë:@³Í¿xçc…/}RÖ¸g´µõIßârÎëýM•4yþ^Ú'ȇ·ø§–ýͬ&‘^×Á7È:6'ó'r2!LÇ1¤Abw>ñg²*¯Ž¾O‚Gk(9ïu -%¶íV,ÜQòQÛÆtäf‡ÅuZý~J´A{3’ÀJ™‰&Ð0M\ý\¶XÀö1S¤³ô;5¯EaÏôJ0·/›Í4j³} -eOLÌq3©¶Ô}ÅÂù„וSmZógÀ:dôe7ðA¡€5úêKíÿ¹â®RâáÏÚçËÀ BE* h} Ý9htå_W´Ô½3ÁmªÅŸ¾?~M_ï9be·â™ô¹-ð`á\Wqv|®³8_'Óey‡ÈŒƒ‚ï°óƒ~Ø//ê,·"FxÀÉ€[.+OftI8gÀAÃÝþ’âüQ¸¸Ør~€rKò¬IlòJ‘+6¬¾•~Æíöî.ìRÖÎgmîàYÑ€´g±ëë7LÒ(©Ùü|I#¯–>Sy go§Éè0Ø‹P['3o^‡× ‰G=Û%Y¯?&IO¼VD .©7AÕÂÝC+äàº)Nmè:me°ÆO3›_ÅòvóBÊ›¬L.hÜLÏå\®¼5~ѦùËLÀöœmf°™ö.%0랇>¸2UáSB/o›ú"¥uŒ -…™¡é*®ïÏZžx;À-Ïåìƒ"ïÚ†ùòù·)*¤¥3ËÚ^ý=äÜúP~Ø.†ÜT Ë ‹ùæ(Õ¯ ^þkΛ±¢é ¤TrÌ°íåZãÒm5Xî3·#xæÓÄ·¼+»b{ÿÃ0œ}-å1˜Ë¾•áQÎÁz‰Â¬ÊÞ¹tEpyIêY`à7¢K KÀ½1«Òâ -+aëØ “)¯[L’ïµ' ò+Ÿ°Ÿl‘\ñ™ÛtôÍ<ÌÖëwÊ¢bð59Ð*ßCdŠã•Q¦T¹/®¬“¯}%%§º/»ï³t.fÌ fMÚ˜Õ]Õ4}/ ÃÆѾ9ÿ5$ÉýÓ\úP/eë1WÞ³…Óv`ÓHT»Š@NùÛèjÔø«Â2¬ËXì^â{ËÆmô«—Ä 3¥è)Ç UGø:ÿ‚|…o?W6Á~ÇÈ!]ØâgÆ®±ê3_áoxFP²¾Nµ¢CŸs|’u(ÙR«ãòâü)ÞNcZöÒ¼°nPF›‘úâP‰6úÓ(1êv¾o*ï›”|QÐù#$!4SzâS#Ž·uþI6Då%3פx{ˆé´¯KKÁçÌ®CÌ|HuæË‚Þ||ó_¡Ò£)®+yû|(ëîßâ‡Ë@Ü2…Ž—2DӪæÇNA´[÷õrðtSðø{ƒhóÉ®p‘þ7.Ï(’u€Øfl1©Ü•Ô<†âÌnj$~à-Ì£ølÉFb@êD•ˆ,X äÊ[ÝŠ•>´³cxË%ssøɆ£M>ÃJ¦öÇ\\|ía¶d:£ãÏO(c‹ÝÒ$ôèq˜±58Ãrt îv&ßÆSŽ}O «Û©-$ï‰#‡`gÃíñ‰Ÿ -mèLj¿I¼Äyê4¢“xC‹´¾}í_dšÈb‡a¼Ð˜,ÇÁ”jÿ»¡| -ôÏ™¶ôúû¿ -h?IOø¿{EÁk–X4~Ôåqp „DuNLi’ã¨L’¸œKŒ}ƒ—Öxåp·UÚ¡e=.L,¾uêÀ±Ó>Ø6¶Ëh ¾­I ©¥2ÈæýkæYל2oíˆ6KîØà|ž ° -4£|í 4öî #a`ãåƱÂcJN¿$DÁäÊ:ß÷”¶Sù¿š0'x\n)|”"<jÈàlZñL|ìó “ ¨EëhÈ`TdÈægòㄲ'{°›ö…`*ÌñN¦ÈKìí111—Q'ÁX¢‡^¡8fŽ$°}d+xÑW_Ìñ÷õ•Â  Rö>ü?ëáˆò$ƒ‚EÍ›z`…Ó.´ïîÞ9C˜Lö*¸`b@åMlå½/O‹EW98d¨T36ã±ÄuÝY;h?»Ä˜¯?S/óÉL\ ÞÂÞá·˜É=8ŒõÁ e÷µ¡? -¦?Ä›Q‰ìó -€u“¶o-ռζÈFE£ð.åƒÊŠë>{‰*¨òwµš°s÷ãÁ±A -Ä¡gK°–jྤvÖ?”lMöV([®™4úÊáD3p½$V¶Å,t‰#”ò·k¼Í_y´©¡4A{;D9"š;ó;ée$X|9T7N®åüok½µÏÝ3äñ= àŠŸœó ,çPzìýªk,AUóÚd¢`VX¬@a!G»¸¬³^„žÍdSïÄâzy’_W}T kÓˆ}¯µj,BMðî´¥{¦XS~§aN·¶®žc“£Ô‘«8³s&ëÊ‹·Å &èñÜ”?äý«>ÀÞ×]Q´®óP™Øk`ßäÕÝf û®‹Y×Z«ruì=È3€1\&ÀHCNXùlu[80ëFÝŨïØìNÄ]© -˜%0œÒAJ^ý´¼%¤w}/ ö‡î²òAæìQæãžûnúéùÎÕŽÙPÒòçÌÃzÈ/Z;ž)\x‘ÚìëÖÞ9”U.‰Ó_>ò_øá5Uûc-­@6 QEæ*D}X2a/GúGc1§OMc-Œ¾2å\¶ý„ÆP¶ó2¥‡`1”{݆àYšU!²TQŒywµÄB´¶BSÒhឤ2šA1±3_oyPüTIŠ¼û«õ[»TW”—¡6ŠÅ~u‘#·ëõpmðI„#³ZÕY$Øóyø2XõþÇ0†¸-{ñÍ·¾ªå¼2ñåÐèœ/ûY-T !ÓXÈ`lgÀðß‹Ù§¦ßªY¥.ÓJÔÝ2ù¦Qâ2¼·ÓýÎhð4[YŒX¾i‘å÷Í6C1ï²ÂlA`ü_ð¦rk: -_ÃýS‡µ )1ŒÊOesLQ² -Ôqµwˆlød {ŽÞ‹t¢ Þâ+ïí[^.\1} )ÃÌÚtú¢à›%×ùRO|cÇŠˆ?ô€L]£µúem˜m…pRn7+o“Þ«¶›4s·Í –çë:yÊtôÒ² ê+ã\æ—‹HöɈD#|q™eѺTÀ?È6@å¦}Òú”¶¢§†ñ®ÐJÛ?ûÝ( -!N™<‘cÞšó¬1¬ -Jµ¸Q¾n ݧ¿žc@\é—‚õ’®TŸ3«0ÔꑯJñ­c81ÚGe:’¸ëðîÞ€0c(¤¢H¸ŽhÏ)^÷MÉ*ïYŽ0… -¸* ÞNK -Ä'Εo äNïçÊòHª,—üw*»ú.|¶0ÚIÐ ž4[Vƒç›-Gy2½ û{(b'óXèŽïÝÕˆYzåeø’ºkSoðÕzN -…Ï\{¥?!݈¿Q 圲,é“Ó{Ü™Óó½%·‡ƒR™ØKY,áëÎú¤ÌLŠšàßÎÐc+t_5ñ‡^€ ¨aà¹3n<‰¨ t6.ôÌö›Šûƒì-w\£ÐZÆ.ž(¯íôúDÀëôèT!þYÑPêÒ•m‘Q•ôƒMƒhØ›‹Öš– Z¿,ÃCó -ËÝ@Á¢gßqìöD€¶þ¸µÿO™ë&Ñsu€r“·NŽ¸¬¸Ü/½à=Nº&F¼«F_ L-C§ˆ}yï=]Ií˵¦² †¤Ä,Õmza­®4@Aĺ@q‘s “†D(7–Øuç´qçGªw=cP Ïú#ÆÅ·¹ªËPl²Uø¾d¤GË^ôë/mŠ¯,¾RÁõw虎ðÏËxuë¡‚êìI¡Ï™Cè<«ßÙÈIz‡¿T/H$ø›Ÿ1ZÉvPæªhÊ'ŒåÇDS.„˧M6ΰP¸%É‚Siæ*aÓõû@ ~ä¢×Ûê—}¿ÊcM$ îœGéµírжJYÉÿ|#1ƒÔ;àÐ7pð8rü5%_yÞ„r”]ãk‚ò‚ˆ<"ê™kk?IÚSþOXÍ̳ߙñʱi `eV`Én‰R‰v«qu×Jzb;7ŽÖ_íETL"Ð8a$ÓìÜ8;tHiúÑÒi:!ZFQ«Ë²¹ÆÐ!»€d8Ú6,èÇ%\&¬H‹\ZØQ·§CÏâZZ4AÁi¹ZòÇÛzجêS×Qר˜¡óù•Hî,?X´†àñÃðnÛº‰9ß–ü_/‘ñé3ÄýBOÃö%O«ððÖ9Eçp¯¡œªJÁYÉN0Ä%ÏÚïêEZÔ!”øÚßÜ“‚ïW<Àf§¡&½äŒ/I?aB'·ú‰²Y«·y45,¹Üjʪ<=ÛVáje{‚¿œÄÑõK>K$9Ü21s–ÀáÍÞ·­XlO[!9NìP%§ØKBÄûïi+‰¦óÁ×ZRÑòYÈÙÅB±á‹‡”#(!¦Ò–+±ÕŠø®ÚK®<]rk—À!‡jÉ¥¡æì<Õ í‘Ϥ@™Xä¨L:¤µ¸Ë$E䪕âxKq\ÿD.bá%,Chm±$T~Ùàó^ã±Ê]ÊÐGùNÆ "§I,~ÞQ†ždºÙ ù°–`NÖ"Sj1¯…i+gK¤·!Éõný\VÌøºNnqy‡Üsä §©«ww~=Äq‘b²­GŸ¥Ã›×û2·J³ID¢DŒØDIôLÓV –­~&J‹=—YN«ýœúËY#é¬QZ¹ˆ˜|aÛ`„·›ÊºÿA!ß¹ ZbëíæC"ÑB^@*ztc9„)þœNIÛ E:2"ù1ÂrŽ(”qØŽÔÔu$æzÝ€LêL¦ÌÅ&â-3Ïû€Q ê´[?ô‘Ý}·]C,È×çŒ5Cè•\Å©$Ãæϯ£È§{ýÂ[VNB¨æ(êî¶ OÝÒnÝšÀîL|H¢ð˜²÷¬žTÍý.”ò–â„Aã¡,ÇسÞÉz`Þ¾¼k~AÙTÇ]°ý眆÷ùóØG`9mMüFGŠŽÆGù5œ…R¿!ÁBö²*u¨¢|¼Û}õ}l¶x«$˦­k¢ÿ¾Æv^ü¥ÄP##nÓÒÆGnÙ €•&:Ž3k'*ø0 |ñOh”IßòcØÇF”Ù7""QÙMP†O2PO:¶?Ñ°Õõ:)ï*קMB_q«Ûêã¼j­'wú±3ɤ’Þ&‹7KÙ3ºº‰+Uu}••²-}AœÓئPVǘ@‘ï3«CÜLx¶°^MÓÆ?` äijbH )-™ Ã8 Gn¤R\/üd~–òÅî<¤'aÀÍ´Éy¬.ŒbZÀ¯ÄÐh3ëÓ-ÏÇi[ºx}Ñ?[íÙe§ÍM@^‚šÉoþ7졇ßK°1ÝBéÚK™üoPº-¨Ï^Fž+wñYø¢WÛŸ³ã®ðS·‹:>ÓÖ¶¨±ÎieÎß fmô„ÜΓê‘ÖºÃgt2ˆ ]¥…sRÈú‹:÷®oü']­eò-ÄdÞ¦+v{ÇÂeaTÊ•µpj諪µ7SX 3OéiØ®ªwOPj:ÚÔ‰~¾žiÏØIXÛÖ;‘bâc†´®M£<‰ê¦ë)¡D·'²\ªïJmú¶gáåãVÛ¤úµŒ —Óë‹ú¦áîJ~°¥R¤±Dé@>c#÷‰,rrXå{*ãh'=iU³ºi÷–EŽmk÷r6ÄB¤V9Ïzs“ã]­(‚-‹ïkÕZ@½Æñ´…J:,õ(!TÏaj®Ác}ãö‹Íf†|ä„ Úz²€+•“¹yïÉ|Îøúö¯ü «˜ŠçܪΙ¢¿­ü|”z<¡¸d!+iéûž¯i£bݘ ,¸¹Y¿Û-³Gõž—û2z¨_-R·`Á`¥ÅŠ‚nü먋á,ªê/Öꎇ@ñçÅÀ‡µ"z¡Œ{«C˜ï¬ëÚm`J`öÙÿx<òxà!º Ѹ÷Uâù€nöé.R€Aå)\á{«^×S'©/ÏkCpb@hÙ,R=RqæëfâLsÆåªÐ‡vÌáà |Àyéäg,åå~B’fwñÝ—&Y4Üõbã>¤8·õLªº\ÑI¦·öIºõW°£ž¼§UÃ)KBB”¬öÿÿew= 4—ïSJle7ê$6Æ…WÀ‰6Ï7òõý¸ð.üÂöWIÙ{Ùíoû8ëäU±Û=6ÉÛ ÝÆÒ¬åhn@‰æq æ[Ž% -¶Èãé©t²„4å¼н”n_0gþZXßåì…×bKÀ!È*Š¢Só±[¸ùq]²Q¨ù8Èßu‡HTs5ÞV¥XH¶{í»Œ†í`Ù·Tî+ž†äLC"ábYàÁ™ÈŒšyU'ÊCÿn.ÐG£ù=ñïxÔÑ' -R㻯ÙQôÏŽ}Ô Z—7“Á ¬¤jžé ñ"FOiŠ>?ÎyÛ!änQT)Æd§ Õ©Jü[—p1}àn‹߯¶ñˆ#ªU{¹SV}¿W†yT¼"~,*0W‰™ý.ÜXxäݾw‚”ÕÏ#hïyª ?N8,¬Ÿ¢Ò‚÷†—ó]ÅŒPpFÅKÕ~G‹kýj Ý¿þKIÕ$õºÁÞº©‰uVé¡OýC±ÉåMìi ž2C´gyƒ?’ËvH4åËÌŠJ ÂCéØK!ÄÕãþIêf|ÐÝþs/ô³@Ä:÷8=]׆ËlÙím1qGoi{tÒ-3î.¡¡¡)òË“–š1®”9c¿X;È:Œ5ð4‘t# `bK)qA¢ ©˜æš ›c´­5ÁzZ1ŠÞÖª)\“²1ì×±u27Õ@}}·f RÙáÝoW9Ç\P¦0»EÆ}UB%×/y×—¶¤^â¡26ýù,bÍŽóPI2ƒM<¦éË:ª‚ »û­h¡1¢Yâl8.ì4„ãGóqj#ÊÑYœÆïüO«È#!˜na¬âldfk“ ÅÎ.Ô{aTOFç x˦â[ô)fËádï°ÏçºU.‡¹¨¤93ž°‘òóT@œEgf>êd ³·N­[±mÕ_ „Éå¡«åc -bJÁœ>ZÔ¶X-wJÂp²u©âÆ0S§±sª3KÅæóì“#‹yžÇ­¶÷ âÙØn¼ú}åÔ\C"…}ñõkRO‘"ÆÉصCŸ°Ç&î—»ýl#˜LV¢n÷‘¡ÈÀ)5~ÁrioΟeÓH²ƒ'¨ŠÒc~1GÙÏVÛÔ&¶b®Æz†­(óÞçy]µu9Û³·ºSß<ñ‘¨¥ÔÆúµ•†Š·ý]n>+`½÷£¯´¢w¬lŤŸÊPh;w#7Ž®vUs Ë0 ÒÕ1©HÖW¦Bü0%Ï x4î/ƤúEGû ¤y+Ë(§ÛH·ïv²x¹1= ›uBCpƒÉŒ5¾ÂÇ™Ò{A•0žÑ5'†:]+³ lYô9²Ÿo Û;O%í§æe½;ió]…J.Å*¸½ÚWféë]šÆ¨’IFD>’!(š 9$˜Õ{è{W»‰êå|rg,fi©†Yœž›V™êkS3ððŠ³Œê£s(h"ñÞJÚ¹‚ërG×ȃ®Ÿ¦Ô\ãûö! ]aX -=ÄWDe1ˆ¦H”L9ʳ‹Šâ(ÉLU~f 3Š^ùž©DÃUBAB´m0Ap ÿØÁ÷4@-ð³ÅÌO­‰D^¯-;H'?Çé -A™âõ2ѶŠŸÓ¶Äøí÷w6Ê+–IºÓœnµq×oúWïkN)ï‡mÖ8/1aÀÈ[­ø'! ´ŒÄPxÉ¢rB<–ðœØEÔ?Pr|7°™2­²3Dá ÄWUOš9¬hÓÄ5@)NI´°›s0ÇÖnŸ[fö½U¹fHɸ>›»|¾¸¬{ü*ÄØ*X‰À¤ø‹Ã’mdñ„]8Î̱r¯éúë$Ÿ5îyôÅ 1™ú&àv(WØáñªLŽe½pò‰õTàb{´ŠÄB!ð¸YRE!ɾdä\ÁÔ| -Äôò} 0á·Ï<ðx­×³5(©²ÓÇXõ̼‰h8L©m¢Í°]ºÓŒx$“ -­u|Ðí8t^ˆš/€‹MÝp­_’<{*ñ>Jn ÐÅ—6¹s²R¯aÆ‹úr×€]9ä¯:²(`\‰áÉlA7¾ĦK”ž·†9z8nb64Ë¢jE¢$µ1V|·ZBËÐöX#Y»ͪföWßqYûlf/ö»­8Fj…›ë_X1¡ÁèínÕ (N1©þ¢CÑð´ýÆ9(AÄEêÞ–«ôáÃÉ€ÖÜÑf}_¢£J¾:¤ íéJ$<ÂBÿˆSUÅöìMø›Yr¤˜¾ÃÈ×`Qíå?›Ù±VƒÝŽˆ½¸ÂˆÚÖñhÃÙƒXÔ‡7Ó¶,Í!Á•FÿÁEè^F ¸¯xÀÁ¦ÿàB*·ÛvªR&¤N<•ê`¢µ+çN¼é¬ -g¤£Ê¾2f~mû„m}…i¶xÄãæužÙÆœ»‚ÙüÂx\Ôt{™C Àåò ›ËøýÈ·'5' ªzqvipd×kµ»¶j©@ƒæ…:Íw¾?bøàôVs,%ãIP¡ÍSÃ…„A³ô‰ìDª`Ïûñ,{r˜¦fY—AÀ˜EÏ¡+LNä^õ,¸¬Y¼B™¡9ÛœÐç†dbTC4è¿JLWl©0Âkž ^¸ùT›Úò«¾¦ét«§^Þí§/‡3SÄ蚇dQœv(CÜ쇵È%#¾j0Æ7›5pEZ‡ì—,í¼éÀOÇéÃõ¤¯(CæýéZb4üÁP”™Γ{5Þ…k`åùÃJÙãpÔféAvs,µp̈Õ.¨±g¸Ño¡µ°±P9:Ý,'c|Ì1eÁh†M~‘fQÞúûdú9’LÈúôÖN0–"/Ó|8׃ҿ]‰/ óûÚûس˜z$©Ôü³[<~q÷é#ƒä2 -'óP4I×¥ŸÐ?`b¬FH. ÷R}ÿÀ#] «iÀAñ7FÌÐ5øùq6O‰ Ç/êúWbõÑFåq-¢´ð §]xžök%˜Ã–td˜¯‘ŒÎ¼r¿?qEµÀ¡Glq_åOÎ1ŠL$HülÓ‚|²ëÅ›:vÐ Ø›¨†À<¬è2ëg8„7ë%j ÅL/ARWˆŠmõƒÑ ±)Cðî&œ£Ò(q14ŒED;ÌjdW åqêÒÚ8ß'‡õt˜{r›`üz$¸~ЗV-ðr#QcªžÉ¹=H­EÍëCóIîÁÕŒ–aYÅuz8UG²þºÝ¡HJP+dGR]¤IؘNd'×DóN'é[ºqÆIÒĵF,·;Å—d•”©7•‘W­_ˆF®kô­é¢á£tΘ ~­ yTjænUÀNöÂߥ6”éŸì¶\e>:3‚t{ù^÷p*kõ!1ñÖ3«/¥tŒëÖÈ|æeWç¯ÛQ#`IbýÍÃ$ŒPÍXÉSKUŽž¡’` ËAÅžþ›m­%N©ò’÷Y ¥Ê¡K_º`ÕsYGõ¾ìŸö¨,4ƒ“³›¯HC'Ÿû89cá[ã Û2?ÆN¼ ü±ù#°¥ª0ägã¶,Š¢œ¡. éj”¿ê?ÉxG# Ò+“Å.ă-†cå-Yo¢UÄVõñÈö15Ò»æ¾Ýc@@íéíAŸ LüUÜêÏÉ…ÜÔ¿©ÿÌZÏ‚ñåÎSUn9“mbµf[‘€Š±ÑT8D1¿4г#hqÙך½E9É{Ь¶uîœb…M'­?/ÖGÐÿéε%¨˜Gš±Ñ3 ?hßó¤¸þa¶„çŽØyžÓ€’^`´ý×Þz\‹÷¶v«áP{ÑÑ•Ih~×`5»æ0ïfM…ÂÛ -ä&oH[œ¯A•9fÜË•ÿ+J†'¡1ê’ëyC \<†æ›îyʇfäiX.²¢¦ ËÅoöøA…°•#ó3ÆÎÑ—ï;¦ûÁ_;râw‚›ìĽÅzi“Ã+Yxh­ÀêÐÃz5xu¾5)sþ³py}Mµ~à óÿ¸ÿüŸ˜Øš9ÿv°3r¶û…¹+endstream -endobj -737 0 obj << +/Length 26323 +/Filter /FlateDecode +>> +stream +xÚ¬ºc”¤]°%\]î²,Û¶mÛvuÙ¶mÛ¶»lW—mÛúú}ïܹ³î̯ùæG®õœˆ8;vÄ>'Öz2“„@^‰FÀØÎÐDÔÎÖ‰†–ž ¢¨&o`mm`la'M£hgcøkf"!r01p²°³6p2ᨙ„MŒŒŒ(€½»ƒ…™¹€ü/õYþ ºÿ§çïNG 3[éßk;{[§¿ÿוLLNæ&S k€œ¼†„¬€\LV fbkâ`` w6´¶0H[™Ø:šPLíÖÿ±ÙÙ[üSš#í_,G€ÀÑÞÄÈâï67#û\Ô{ GÇ¿Ï G€™ƒ­Óß8Ù,l¬ÿ!ð×nj÷/!{»¿6}Áäí,ì³Ê ‹þO's§r;ZüuìLÿFÛ9ÿSÒ¿¾¿0½N¶Ž'7§ršŒ-í­ Üÿæþ fï`ñ/ gG [³ÿb@ p013p0¶6qtü óûŸîüW€ÿ¥z{{k÷wÛýõ?9X89šX›ÒB10þÍiäô7·™…-Ý?GEÂÖÔÀ@ÿvcgûÿô¹˜8üÛ òÎ Å_Æv¶ÖîcS(:Y;§¿)äÿw*Óþ¿ùÿÄÿOþ"ïÿ?qÿ»FÿË%þÿ{Ÿÿ;´¨³µµ¬É¿›ÿ9cÒ€†Œíÿm`caíþŠÿï‘j&ÿAòÿ#ádð·¶få §¥ÿ£…£¨…›‰±¼…“‘9ÀÔÀúoŸþµ«Ø›8X[ØšüÕóßVhèéÿ›OÙÜÂÈÊöŸÆ³ü‡ËÄÖø¿sÿ+Ñ¿ÌédÅ¥dU¨þ÷™úoœü_í”ÝíÿRû¥ÈØÿÏÅ?(‚‚vnOVV #;Óß+ÇÈà`fòþ?düˆá¿Ö2Nn­¿eÓ3ü[üÿøü×Jç¿ÁˆØÙÿsZ”œ lÿ°ÿiøÇmäìàðW×ïüߢÿsýïQ71q31‚ZýcgÄd™–™îT‡ž;<)¬ÕßÇ2l_Ú¨\TàWc×뛶ÃQ©ÿQLÛ4ÍùÕî¾tfÿy Iy8Ú‡fMÖ›br•ãMDñ»q“´“ê0€N·6ý\-ÊózQzT“•^õpwRAQ·äwº“Éòú™ÂÈ¥À…øÉÎÇ(µ!µ ¡ ©®ðìœ4ñäù‰lpldx¨÷ì÷6UNìO.PXÒH¿_9Ø|š*"U­ªm{½Zl†>¢kŸ’rNXÁ™ÍÏË#¾#)W–cÜàã™þ_ û4Ã[õ½\Ö“ÚÜ )!³(¡7-æOªS+1mh5›xob7(ß1ncnÛ/Oúj,ØcVâ?4ïvrxü”NO«ùÙzG®^'>=ÔDUµ|ÞïŒRkXA boë ¹ÝÄ?F#Øé€zÝUd´•™U˜€€ë¾lÓèÅ`Ü”ñÜÖ–x½° 2ã 4wH^P „±?2Ö„õYÚγx,:œ,g'+@³ñVÁ¶ùÄç)€v(‰Þ‰žšmŽ6ÌØC +áàUûZ­RR Ž_&½þ’ÞŸfx¯%Ê3® ôEþsÈC®” ô“‘Bå0²TU’?…šÜ¡ˆhÍÒVùòýåm»T úÃ8Z§ä‚Û°ý ³:I?Ôöz"6›Èbœ^%\‰Wl©à:Õ ·įkU*Bœ5÷³2[Q‚j`tgÔÑuÍšàvK0 µ"1Í5Ô.H_Ï,¸¹ú,•û.ûš5¡VI÷úäGª^’±¢ +yá×h}×¹­Z  ypÓ‚u=jëé 3\xœa(74nŠïRýƒ&cx£aYKÜ¿‰~ػբÉI·XiêS¨“2ø ú›G²¨†lkÕ›$ñé³øI ñƒ<½*­;:̽¤PœT1]š«ÚowŽ0~,A¸ÕO˜Ó%/‡ìdccÅ÷‹k×{GKÌ‘›j™(+ÔBUÞD# ¡6ª:Mð%¿s¾†I¼;v #wïRUèB&%Ô øªÕ(cÊïZB™ª³/7í¿ '|8¾—}Z£6Ã*DLi´¯kâ'/rn¶èXÐ60µ!~Èaïގا*\Dxc(uè³?^NWù ±CVØñ Áá´ÅÚQ[´¬5üŠvȈ0Kïø^•vµÚ*V¦°cœ (p3“¸µMÖiÒ|#Óƒ}5ãByE¦Ç•yÖÌÞ¢º<^×<;>3ýXÎFM.ê8ÈÆœFß©þsÂ^Î tI¼\nk2NÓRÅ[>Ëooã© Æ,í`ë±19â–±Ú`©@W4·¾º¦á¢Õ>Í-‹Ã>ÑÔP…[\ÊùñÓÄS}™Å˜†`ãÃímš/øŒÇü]GæÜêƒ?å£,J/k¨Ýï´ÛÞæÀá’z„¡¹uMv–ԌΡ» :0jÚê­¬°ŽCgþ!ñ!YBRÕ¿i†D¯@!µrC!,ç´¦Üoieq$wj¤q•M4räMÈ©X¢Z_ì¹Îãi¨ä/JF y Ètp(¬2îZ‘Ç¢Ùð‚:–ÃOxäb=ê:äH@,bŽ“t!ÅãKMdþöÑ•`£ªj•*ЪC[L+x¯Ù}£C”‚ÿ€!‘Éã|†ëuî—ÔU’ÔézÔerðˆá Ã\·ÍZ åjWqFW [ï•~s­É"Ëšã±ÄÜ]£Vf;ŸTiËá®Ë)Mîr“p¦ì*žx×çRiH¯Ñ)Ç€(gÕrÎ÷G²/܇ç»l—W>aÏB·8zÉCö +SŸÒð¾ÿVVí ý1*YØe"KàP½µyüˆ»4¨ù:ad8åË>)4 ü.~æ„#×ݤãŒo*ðY­oRhŠRâÇ^Iréç­«ˆeö¤8ó'\,|Èìk8‰–6óì }ü¾¤ùj‹ÏL>Š°²‡ÌgñšÐ¬þ¤–\0é b¦¿bh¡!­{âaÀbOé¦Üàõéhiä¸á +X z‚G)gàcúl¶É©ðÝu½^QC˜ûèÕi]s]°?Å"*Âü$fOv‘¢ö¬ì› T!ŠåPXÙÖÐœ³P•Õ¸« "è ƒ7käþkÂ[ŸŠÐâÓn¥% „¸rñƒ‹3!ö†¿wqŠ+÷-×}ñ¨C}3X¶[G\v¿Vl=Šþ~ƒìBjÅžµ@L wº Œèf‚ý.ÓÐr›'<Òü¶Ž¿Âfæ4ùJ äŸt^ gÃÓŒr;‘s ¦ŸVhŒ@€'ǽêdòÉ,·œÇÝRSJÿkþNF¶å€ƒ²ÂLŒ{ÛY-k^zB$ëeì/ff‡äícA3RNÔïÜ¿iV,{1£Ñ5-æÃuÝÙ³¾î»®™Û:ºÉ›í%n`pD8©L°aìkK+$ù;½Gµ.gZ}1J9ŒGZ1 ˆGR—xµœT‹U—y±ZmaiIç÷:ž3œ˜û,“ãfbpñ¤–ê<Þ¥˜Â„ús´K–ð²}²ÂÏ·ÅU5^åR d ¾KÐLTj¥:Õ5Ç ¡3ϳTaþZβˆç“d«×Vp6(áË~€ù2‘±<½d=ʬG÷Á #œåúú#&Ž¢² ‡^å¬ßÌ +lô³î@p® ’Œ”JEcžì e‰;LÙƒ*#.P8Ý^NrÁO®w¢êåÃPäåú‡ªî©¯HÏùñâÊ›%ƒÓÆ{¤Û«Â¹}‹÷þta2XÑ`È°½W(Pl®ôt‹8áníÝ1¯v«Ÿ<ñ¾Í4­åF¦˜4d¤Dr´4J„)Ÿùë¸L²µ% ç?·ëÚUA§tkݱxèL ë…3kà N,ˆÛ3«QÉĸǹ‰–B´‚7’ûÄL³_ËgƒÕ ñŽ1Ü +˜šæ}›Û}}<‘3°2èRÍp´$ðʧFu(#6AìFÏÊ2/ÕÐ:C +Ífg4ÎS" >ˆö—H¨äµ>8h¡Š¡3lÒ +{%ྼ¿#‡«BÈ,>‚^@Ò¬Ç0nÓCížU½šÂZ ^u»éên®p% À#d_Ðby¾ÅéZDzl€÷„R%ìS¢Ù+L}êPS«‰$1Ád8Ç2cæÃJœ¸Lx™ Š¬3µ”êR'1ãøj”õz×>‰Lþ(²¬’|ê0aÑ“F±ŸÓ@=›ù~Ï¿úê|ô¿æe•|¶ÌaÅ%`n2ꎥ›÷£(Y°+ϼ<š5ºiÒª­¾^ƒß*ñ™ÉšÔ]e©¼FµïkÇÝÃtE‡Á,¬°J^óÅ4»þvŠêk€½{çGiþ;¦ÁdkGÜ>Àòß è¡€)GÑu—R &¶©‰½õøtêœ^ÞÔÜøì-ÑÔü “Ý^‹¤dD(g„6µÕ¬kbŒ¡¨Gšƒ&%‰Å¤`æL²Ìµáöè7˜ƒ“6‚Ã[ä¦ôžÊs^sdï ©DhdÑn«_ÉBH¤EÙ®sñ®+ +ø—I›&ÃX9!«<O |è¥5©ÓÑ +ÕMêÔž5…ÅÉmW¶Ä!ßCXéží´*m¤ÈjÏCB€5BŒÏ)Õ‡d"ZÕጼ B^moJ ¡ì‘×Y±øRAD%HX—«Èë·ÀÇ*ÆÚ0Úýé –ì?9Ö–]©e¢ßÄŒB<ÙÁ„CdÀ‹l•z +GzX°ö0F!ëþ½{¬‡VH•ZÄ2[t”€pS³õ.aQ[í)©u3Ñ +/üI*Ô•ª"ù(T€}vÄ8™xfüzY X¥û™w·$]-aÁ¥æ»ãBó!xCšœÍþe‰7Ä…`¯n‹³¹êûÅÛ +§ÔrDš‡ê_ƒç8ÉÈ˳f^‘±Ðòé£ÆK$xþdC#‹C7‹Úˆì´½‡hâžrvôîešxÐÖðà˵ˆ$Ôï­JÄ›'¯ë¡¦¯Cy2äÀªŸå‚¡ŠÆZd1”ûÎçÐ"ÁØSX}j3r>“¢0¥\Ò;QõԾɇ¥-§ ¶ŠX©Ýo‹ LëèR×R$A[sã¦ø—òÂ`®/lÜ#ùhŸÁœŽq½Ä 'õzkü™]sÑ ÜÞ¬(Q¹Íþ©iv`cöù¸-Óz X_ÑZzVm÷ïȆ·ÐQfúq¯<–^È¥Òî\èƒçB©.ô lräê‰åÓÊgj´øod‘ƒ|¤ˆ¡Ð \yh´v‚öµ:ãY_¶”œJË”(Øž#¼&bd·‡¥”<Xd”¾×!}ÔÃúŒT†‰ÀR‘‡òÕ­¥×Ý“ÐÄJxÝ­&Æõ…/¾uQ~4NŸ­]º›?•‹=gæ8ã +ßçœ;…!à< +>î]&“ŸYdŠÃ/"Á&ZïY±Åº,nGÔ®Gz§õk+ñ¥\£>k•á„žjß6Ù6–Ô8tµÄO§&¢„œ´bú‰|uTè@ ê^[Û5œ¼N¿C'¾ŠŒ |€[ƒ ‹.æ†×KÍkÈÛS›«‹LRPÓ9›þ•ªëŒ<‹j»F^×°–ä¼ BNËZLè¦íSxëÆ3Hã€Â\oA;}ˆ2+õâVœ2ÍH á}I\’c‚H0¾+ÞúÜÈ| +‡™r@ŸZo_ß±¼AÚ +êú<V{VIÚÝLná_ïÞ‡¾’õ™”÷Õ.µÀ…gV+Ĭ²jw5# +óBÂ:2s²uá§(•ÈaŽÌ9:¯Ü·2tƒ³DKÖ<ôG¡Âç龡31•ÝÊt#íg\ +.˜íu6îi²ÙJŽÈoµïxöZ×× _s ZËòh°V5¼}r¯ÙÑþ3DXÿ8Ëé6æQàÊ)’v÷ØÜkxÞÝé÷)Jæ¿ßd%ÌAm=ÇÂ(#Õ KY8ý_ +u1`ÑΑI¬ÎP¨@àÜžÇ?M}®‰# ¯‘½Ð‘˜W–íg wÃ!hºÊ¢ßµÝf‚]\@˜¶Lyìodªš¹øw‡“>B«Õ·¼Ë¿/K€µUræÈŸ¾UI±íº«à ß–Ï°êEˤúÍv°Aõ="™‚—7YðÞúÒmÒ–ŠƒïÙ{óEƒ1°0[=Z>Â|¸ªÞ¬O ‰Î§uw¸OL¾+‚Æ…‰ÝmdYÎHŽ¶d6)îf¹³|õiÃ?Rëv&?¿;5âf³¸ÃcÃ+©@¨¢®Á¢zª?%ÉȾª ¿—0;¿ÀstÀZÕù{Ëõ½l5¤1.q~<ú£Ö8Ï–í£ŸËækì*„ç^ﶎÊ# uæ +g…ß·.:ÿaâ5’Ö‹AZiD+¦ßuFƉ }¶û½é2™¸ (ùp~·ª³x¢ :’3 ¶¾/e…)ÁÌ +¼äÇRi¯z>ïuÙ1VÏм ÿ¬&‘ 3ŸL.~Y +_²©Ð‹âOàvH"r§¦$ µém½‹bS™ Ê´íðà4Ò§ÏUGB]¾\,k¶Q¥b=RÊ@¥=Ã~51.=!ê´ùFß l ‚&mò·³Ûïð¢Ì2ùzAS’VŽÃJŸ|)Ï!ã¡=ÜHŸwÃØ4*ö‚õ¶ê¹¦pT™ÖÔöä&º,Ä‘ciQª ôyi´zoj/»«"fuCR×óÁ¨A€$c÷¾E׽݂“Ù²)Ò››òUóAJ7JC“ðÐIïäZºÚÿúzëñX:ܪÑÖÕùK”ìÆ_•RÆŽå¼Ù!òTçžÃÙZszäXŽï€mLu ÑiÙ&ŸÈCŽÏ È4¤ -ÿ^{°Ù¤‡tÛEþÇbQwÈ—ô,G§8ÑÄ^û® Çðª4î‡c‰¹ j%cx ËŠž+qšér ´Ê/W?KìŸ%¼Nt ¾:c¯ì bóÜw² +º'7$c²ÐˆÐ!•ÎݧC½¬ç$Ê?bï¨þìl"OâŽK±¾'˜w +bx—‰Üêüj¹£O@ÿÙ,s[»6ýªícávÑY¹hd_æ“,VŒ œb¨ +‰ð#"^ÆÃg¶µ¸!ÿÉ#i/“ªñd—ÁÐRD4ìŒ-%…·#àrþvf"I(&!QƒÑCG¨swEe`Ff÷Ëڌ札RC†×Ëîï+ZsÃãØHz–Xf--¦¼…”N)±;±shs{£•aVXAת]¾b9ï"Áúpœä•Ôm90$j®„ÎxLYxCÀ8ÏB¿Ãí¼ìùìéÒeEá…i˜U ê#‘ÕA¤’¯ÍŒ’a +«Ç­´©¾T#$5? éŸè¯¡³präZè<§ ÑM{å«¡x¦¯¡É! ‚)±6¿Up‚Ó¼ÌÑÜŒ0+ü9r×óÕ>ÞYãÃô d3–Ò_`gbת}û +rÂWf¯(¾ Ê.T³ûœ$rG~‡ÌR)G…-ú²O2£l?ÂBüX CÇäd"iXćÎà÷ÈÏ:ŽçEN?’OÁL¦5ÍÔ ©é9÷°Ó?—~P5Â+ ¼þÒ† yÕôÔ#ß3-­Ò.\¶´ù¥„• çÄŽV¿°:‰ŸÏj¥×ÎÛ|M¿Ÿ®'Š©iÕἠ;‡¹‹*ƒúŠðºG­o´×ã®æ¬Ñ@z-Ã=é÷îÛƒîø»^]bÄËŠ¬N -IýJ€°ÀjDM;©ËœU×ô™Ã|ÁÊȳ5à +¶!yJ6Ü#½ºø5ÒÇ-u ´–Otÿ‹Ê‡ßk§]Ã3¤¬„0¥`áÊ“êí~©/^Cë÷•µp­Éü7scË Oó‹¿£hˆ-Þ€îi î¸[jÄ'Õƒ´§!¶—7žÝÔY¿EΜީÊËi`µêm£¢>TÓñ1Z`NŸ‡ ¤'ü±i“’Jbÿ€‰9XêÊÚ—µp,½ÓW¥ÂÔr×!KšÂÎèü`‡ž„Õà@l®/­Øúæ.z”ÈÙä+ö<7›ƒ\i0zlý£b©UÐ{S›|€h•Yƒ‘æ>…mL0 ‹¾¾„,qÊdnï#çK{êºýÂI_r(®¬µ׉Òõv/ˆÏñó÷†ÙÈBDßÑÑ#…iâ·d‡W¸ˆ½÷šЛ­ðƒ‹_¥¿". (ø§ãÙ¤'§I?DØD (F¸Úù–|‘³e¾Q6 j1‰jß$¢Âü®ºÛSRßÈ’+6\Ž¹FÝ‘ZüýuMb±*eR^ÞZWjSC¹0r”2â’]òÃ5|ô¹Ñ^òI€Õ+`ô«†‹ÐtúIÚÙô©Úòó¬ƒ î +ä¶Ôñ{uÚ¸M¯ýœîdßËæ6Ú´Qµœ +‹¬)Ì Ÿž6Ö=jÆdÝ;í¡Ô¶„µ¼n*_>;y<"¸ü,߸藵’ðð’d ËD¨Q TÇëÌÙêÏÜÍåïØ`.ø|Mõ­ºí$õ´ÃÉ*šö7 ´¢Z•—C^“úkVa=žBž«ÃUõu‹VQVQJÕÞL§Q¶Å¡ïºÜöÞÖøMØ¥b]«®[¿o:}ºûg<$ÈVX„~\î@uOG®1uçæM ‰0). UòòÉÈhW' Vws˜‡×ˆ¢ƒ•\ +=;3؇ZÑm{§fÇu1{©‚q®‹é%Ñ)(Û+Ë*jóºpd±NáNK¶›áóú E‹´Ø*ë_ªŒ®NvL¢Q°-ëlr±ô¦‡³ý4Ý!aA…ÚxYGmfBv_C…³ØÞbšÅ³”ÖšÐÐ +¢œñ £‘I½… +M©:l/ ?Xå›èSîvåžÉ›åÎÁñiM„ED“¬Êòòn[»yÙ §” •Ýõ§âCå5úú©:‰È•5æ—€pªð)-Æw‹ú^RÕõ` ÎWLÛQÁÝ°N’ G¶R¦ZIí¤s$ÍîÛî…‹Š¯r¡šn¡CÚÍä¥ÛŠÌÞÉç…Ûiçtd9,kQÏŽùpMî8Åx¢Ew=sõóŒ«ÓjÀ˜#ˆÛ•¾€áꌳE–o!)»)öÒoõoÊQQù,bR¬÷„Sö«NÁ\S_+Ç‚øÚ¾‡Üzh(èˆÃA¦ó_Ûð¡v/Û¤¼øAÇJ +½dcb4Çåøñ¾ó?Ä 9èùD‘Q™q…@Y;Ñv/£™YQ‹|§Ò²—(¶º×.…çb˜r&âßå…k?UŒãþýjŠÍO&ÃŽ)~«t‚t±è„©@ŸíÓ.*­NÊ}Ü2ö¡xyB‰W!Jªõ%*x|ê~¢É–\Ä»èÇ„2ýâ±¼3 ËxèÆgòSt”HbŽ;³öªY^DVdf¢kèï¹Ï{’¯íýåyˆwœ›:¨º&šI;cǵø° Â÷œó(—ÂR +™1ü˜|Þ_"UZ¤l€¹y%NOHnEVïpéþÞkfôüÔ•h£“ߘ:nâÓL-eéYi^»ô~¿„NãÙ§äFV†»"Šá=Ô%61‚*?ÕQ,SN4¶öJÂÊøè6cøò䀀à‹+挿zóN{…hi„'È~Í+›2‡ÿÛn4¾›åç™ÎÌ°u[ñú8´^Ó‘u—‘gV4=S ç,® à>‚™uhXáB(ÚòÖðKgó ­¯úä´†Ý}Ji:~U~¢˜ž¶qé\Êf§NyñHï]#Åû˜½ÐÄÅ,sx®ðäCð3шx×y{Ÿþ:l~"û8àÖÅÂÛ«ù%ól÷¨tf')hÌØ3Š°c ÿÔЩÒòIÞõש£1„Ò`he>ÓÖF]к÷'ÆWºPBä’½sÒ+5ñßÚ§xOÆ«à‚ž£.Ht3<Àú©*m(ó¯­K´Ÿe`erł食~ Òb‰ò—vüÉÍ6£ZC°QÎí÷±èû¡öJ]7 ëÂ0lD26 ²íº†‡…òüäò8‰D—UµR}c›ŒÑG$Æ«Z+E<|»»ÅX·ävT —tò²ù¯T2)ë´z›O,:]3ÏÖø1Uœ‰˜Ct<¬:8.J†¶Cæ^ +ENc­wî ¬ O-¾”+ÉagÙ€ÆAÇ>Ú/ŽÏ×Ë_‹¨i*ˆ{ºº„˼WÐPºb껾ÏÈXÌP@d˜‹ïU%¥:©a:ƒÚ’¥Þ³4IDÁ­•ß%_…=!ȘÎa\*ß¼¼ê<»áae)£éŒð"0£míÉ­¦€ |°Uá„6ÁâPx0-öQ“ŠCÜ4Œdx^Ždh:)³]4Û',P Åoè­noƒ=ë줾mz{ôÆøÃi?ê—á4ô!ö åðA5±÷ÙîÏçì} %Õ EJž;l¶¸Ûü +³]AQ°ë±€2 ½'T/]y{ˆs”és†îæëqÀÇ$Ië¾í(Ò̯³’”šeÞ¼é4nGGq·¸Ä0uZí‰b óÑ£€‡« ²``ƒ¿ísœ l·ÎF)peÍÑôpÅzFÝO•Œ~3SºË?¨àÉ>î#À€B8 p’Ù)À`¤cLå?Æë'DÒk±G*7,}LðüDÉSXV¿;Â)‡É*{õ\Úz5pÇ-Jêè Íî»KDO²‘×oyAƒ5ȃèòö6w  Q¼RxÜ^ÏGçÊÕÛ·Ì9Ö=øÕ!ކ˶±€ü©¦âù)X“`I:qSŒÄ¸Œ)>]K!@ÌYqQ Á‰¸âÇQÔUw¹jKNFÀ-§W<¬<èÔÜu·¦BEjêü--Ï¢V[š©ÀÉþ­±Âõå$@V×)Í÷qEAâ–žƒùñðM±È³/øã.>cS5ûÚvñîJÜ«5À­½|+­ÝÌ…k%SbºÁŒT„-Õ©ÏJ|õO†AykÑ\ÅgHöÊŸQçfß$àϹ‹-ß ß&Îiý'g…ÙÂë§Ð>Aïz?¶ã¶¢;)Yw¼¨®Ðõx.ˆöø:¾‘À‹Œ‘rmHÆËÈN(þ4ašUk×Ïb>‰º–¢$藍´Ùy°B’µWÊ{P¿núÇLZNI‹ÿÕLT_áŠI•%¼ß†Ë‡ü¯6d¶PY¹£;È,DúïÜ¥ýj´ «²NÑ÷›ËÑkýlµÅë/ráB•G‡ÖÉ°”ejôÒœ@ŽÙ>Ã…ÝØhªîB=2»% +<òÚU¡~^d‰ñÓÉ°´eÖòóh –PB­åÃ=¿ò‹BDêôðÉ\Ÿ³Öy LJq ¼X*`Ú6wY=Ò*PØC2À×ç»á0ñÓ +òDG^d£~‚ÈâÌÝMÕ·ù–½épíEàÐÄÑ)KßÛÊÃxFnØ·Û¢ÕÜagKd;lzm£’•âÐr~­†gš‚‰iêËU#T¹µo%™Ð›y’øÍâö\8ÉJv+¡k_g¿üÙÚ-V›j1õ•¯¦¼uT~fåšË’4|¤W[‘s4`²¡`«Ç/ÿNQÔÜЋ¶eURè/-,îë‡h-,@$Î>¡óüsxÅÕeë¿ú ‘Š<ò–÷‰DGyPß ûîÝóüø¦Ø|t”Ž&ÍR}m†6à6NŸŠsu!!À\Õw‡ë EÉ€Ó“{þ«dÏSíÍ"¹l¥GrwÖ?E4žæ"[SUGYþæÜ +øZŠ.V«‡§G¯Kb)¤ž†¤Œ,]1ccQ­ÎO2œ…á´ÒåÇh‚ TÓ÷ã φ»™¼u‹gÂö<†¤|d±‚Z5Úd¥ÇøG?fIiÿÑPU=Ý Ì­}¢à“RIêM¼•e½¨pl,¤3*ÄT·þÑ)0v’ôz‹ïü1Š4jH¤†¼a\P™ï&?§’©7¨— +Þ=á”7?îÖ ñËu.›ÄZ=•“ز‹,-~ ‡JÐÚôr&ëm û\Zæâo®ð¼‹I^†ÀÐùío¤Ll‡ ¥TeæN"‘ˆc{Oп ›Xñjÿd'ÚŽ“La.Ï4ag•¦¬5ÎÁ +^|eV + ó8BгMðöŽ5·krÌ¡¦É‰†Î*óî˜E”•ÎŔІð®8𱊭C‘ ÁSjÜNŒ1I2ÿñó¡& ‘Oäs³=xVWG8 sÛ‡æk=¡ük‰Œ{>Îi…ÊÌ¢%‚Å{M6C(E,w6¡ÂÌTþŠföW§u7»¹Äb(á5œ!þ¬Ÿ±wœŠËóÕ³Îàö#4ky[8†ªÇ‚nÔ{ÖBzQå ù·=CÇzñ+AÇÍ¥ÛJnÝÄ©‘tÕ¨¦Ú²55G¡%2¶êFÑœuÐa÷3š¾€m”Rj2²®h,ÖÚ/Æ+7*°¦â©\X*ñ|ÑÎNDP~D­õ¦×G¢2ìˆôB«ÜÒŠLëë¼èŒ!$ï™ïS¢pKÈ8K2o ïÚf'ƒýÙoÚÛ±Qñ<\¼‹Á(’_æC×㨄ÆþøEþw‘½"[”Xq¬ða¯fÙ`Ë7P • ×»ge‘œ—óL2±[Ú–rЛç¾l‚¾ÄP# 3ÿJÌs*Ýð“2Ÿø%—éîIjCk;×9óMO8÷=†Ñr€ç\F›x¡ÅáÕƒø&3Üà¥l¬Qäù u~¯I¹c¾Só„vûkVµ­bœÑtU(%9ÜZe¹d5PÅ/$9ö…ÃÝ»IÁ¼üþë©­×Ì3WäTz§pÝí¤çÄê&ÓYM~1¯èš2õºnÅfµ—Ž³QfO­ö‡4îKïËkY.&꯳yÿˆÃct:ÚiþYƒ½Ö@0.¼Ø›å¸Ì`ã:S5ãFRaKl;:VBJís¹³¬o*ms@UÒ¥ÂÙሼ3¥U ˆìôrÙЙêÃ"_¦íBpwBFæoû9õ†®&âו‚”ôQ·QR/ÛÛ5!ÓÎ +.“Ÿ²l8mdÇÄ×ÕB„¾É•‰ ¿eI¹Q!b'ìž´ô§W)±„LŽå•ºgÏ‘„™°w‘£ : +3¡= ϧ‘¥QTŠú¾šèÍzÅ„(¿¡gÎ"ßl®3‡ ”‡îoÞƒ+Z¦oáöà4Ę=tÉK-Æ4ä|~üaPX/D&_õÅ;*¡ÿªð!„ i,ö,–xou*Œ…Â0c*SäH˜èµù¼ŒÜ’µÙ:üØr9Њ6p(ŒˆÿÔLGEË?9Ø6E¦ø Cø6ÜìzU ‰ÉJo½TÓ xõ3ÇÂæ´Yæ ¹ZK®ºµdy—ªÀWÄ ÷—Jbæ°W‡Õ$“¤)!`'<ü¡a¾ó=¤#Û·jõ嘕Wqo˜ý–)_¬HÅ3ÔAIW²~{ŽÑÇî/‹&Ëß]wÞÎZƒòO°^åûµÁHñë)¯­ÿ z¤ÙÖ¶5.7N`‹O:KõhìÙœ=ºû1¯å'ˆ¨d[àÀ®¦ží¡¥gío²wG³Í\û¢922 ñŸzK}·Øp$ÖÈ,b—›rd)^ÔYW† ×1š Ëœ¦6p-eÑù[n$„:J°¨&bSEa‡H—‚ÑW¾öqŽ11ÀcyÇK#m)!Æm±¾59õU$}À[çÓƒç¸×‚%÷‚~H®‹>¬¬ß5LzcxíEk“ˆ¹ú¼Ñs:A²óp6¹önÁ¥+²àP õÉA¡‚éÛôÄ”,,¨Íb6ôʘŽUÀ%"ðÔ”ç~qf?2ÎƉRW‹êKС:¯¼(Pò~£¿˜ e*²»ž¬hq»¯ù‘1'¡Û~PŸÓìªLqŒÙ*£0ìÔϺ Ÿ`tÞYïwý.Ã×›Ù/ˆ' xû:ï+#™:ãàiÝAÏDÛq´˜&¥´‰ÊbbÔǘ•vÄUòMj^³i5s×B1¯]IO]Îé£o>¤ˆâØN§ÅfÁ+žK|ŠV÷Ø0µ¢ÚÉ„šU®=ÙOBб^#±ðWœsé¤ >*¸ÂCÄÖ«ö#ëÂJ¦2öǶߦ¯×!GÏñ_>pfR o"awo`¡áÒ½ˆ5dX³¶£q—˜þtÏ–!´¤”µ†¤zØddœ“hYκ®F)ØôkIáæ:YõäcT…›<–E\+Ïév+²'é‘Ö"~M«éËî~»On7" .ˆß‰¥ë…EÞµðô»w DeIBZ0P ¶Kí¾ª¹Ð7hĪy +ÛÁ@^“H·vîâó1ôצs²5?ns÷ü*<À´eºbME„NÇúDš`¡æWÃ@V©h£ÿÃ8´¡ ”v}‰¤ìcJVÐ}e!¥´ï »QV=´›|8Ñ»äëTË+E¾+,»0–¸µ'su\~Ña&©ß”œo»Uÿ *··_߃i‹›Âæ‚~ìT™¡#e¤ïº¹·7\XWqwƒsÚái—[~‹D¬î¶- r…9G„-ùWc]ÇgP-UŒ*L£ºtÃæ»z³$ZU>3níñXÁHw¡šó ‰NúÍ¡®bºZÔ…­Ù“ëPkY¬~J†‹Ô€ œsF#ÅÁ¬“Lÿýµù–†`´OÝe‰®ã3X8¨ E¸m4* aÀ-&N(»ŸóšÌQ·i¿&­;Ðkè.í +ò$7c ¢öázh˜O¥ó 8Ýúæj¡Ã‹‘/%j±A³Àóë™c5$ Óür’ o|*…i(²^j”-°ó!"÷ñ,°ž'Ôqˆ¤âùŤCU#‰†y0-Hr\'¾Ñè5‡¤%O_JíS<^ÖácP°ZþZ5‚Ò¶m…ú[éîI’àÙ0ÃQùÎÇhpð§Ò•>þ‰­žuê]O‰´öd­ã)/P2‚©:Îçùþ– b ¶9G\ ÷Ù¸8 ÙcCܱ2ò~$GÄ"¸1ó ×?Õƒä“~VYP¤øv`3UQ¿þftI›¼gl6yë_Æ[øHWõ[0°—j†BƒLgxN†N¼°8wtãr&ð$Òá“÷ûÄ;gU¹®YG¤"È„´ç>Žg_X©øQ˜4»¦‰=|dÚçüü)Õû6MG§;#Q~lØ +,IŒ¿&˜^ý¾"Ï ¦¢Øqr,Íß®Ê>î&x콋Ád@ÜhìÒZtES·Úå«\¹ž@mú½§!ÂuëäŠVE–Fw¶á=¿ÆæÖ!(*p5®,Á©ªÛ(î²7á]·}ø Ø#¹Fý_ßµ©Àóן®T"1'¦è·ßÄÂF}k#I«î 5\]lßQ|––~rÀ¥RÅ;¿$cHp‹ëʳƿ4(b£R\uÖ¾íØ׿Å`T¦alqñ¿è•6 ߬ Ê®£JñŸ9W¤3}Z–íP JBÛo8X~t©Ÿõ¬Ä6ñŠB¶ +eî$Âjp¥dJºlw Äì³j…P*GŸfºI«B0îù¡°~’Á›«'H–!kÇàëJП¬YYã¹³æÖ‡^SmÙ \õÓ® ¼¤®ìâÖ±hßÕ%µ5i»+Yç²úŒqk«ôáï$‰nµ‡Ôf(~±ÕØDÉŒE)Ð_hÛ¹†‰'¦óp;ØæaÀ8¼~´P¯P(n[)Yãb“¦’jŸH§·Þ?€Ëø%ƒ.Ÿ(Ú”dh±ºOÈ’yý<ªØ›aàTR±i¹˜)G[o«K,c7·M ±Ç¦$!»K ºŽÔ`¦H°€âyßÑËåtBµçÃ\k1(‚ÔéڢáoÅô¤’•#e »@ ਉäeF€ÜŽ€h'2hÔS#ÚÏ*ÊçŒ.×’_XÏe˜à~ÇR†5¡X?ÿ\Ôü¹ˆ0]бà/|Wõíé‘,‡þ­§ŸÍÔ‡ì©ÝžŽ˜Ý«žÖO››J¯7rÀÙõóšiÊÒ…–§ß½„bçk¦Wu(CÄ AÕ‰&ä„ cÖ),§‰/½ôŽÝMºŠõ»ªH¡À"¿â8˜åšçLêÖ9ŽXÇÔ•kQw£íC3dÚW +"YЇ|ã^4,}3ø»Ëö:-z)}¯Tmk—5— Ù‚Î@…x*m¤·*ˆKßÉi.%íîŸ[Jà¬*×»J“Öî±gÐ]X™Ÿô¿(ú„•²ÏÕ*xz^Ì°ªäx¥#}!*Ï°kšc¿fº/&…‹·ø÷A#«ƒj26”cÏLw;Ë©îdËɃØúääöh=¾=ûjK6H‰QQ¨íŽA«¿¯*Æ%§Áuãô¥h½²›5Zãìâ$ ~‹õDrá™õß]»l.f> «ËåÉÄ‚—DK&«ž ¹oà÷ø§}!)ucŒM€£”Ú#&<S—JÊîáÂb&:g#ŒÍ¼á‘¥mâ›2÷–<¶ +Ü5Ç+Iö*|Îü®’UZ­p_%6opõÉ_IO7;”Cô@¢™”人D@2¡B'…õ,0™ânN-ÖkƒS[7p,sÍ >­ëÝ]àÚt¶Ÿ¾ÿòM5nڛē ìhT?]ÙÅ+e@Ch@JH$ êÏ&>2ýã°£­ YúDXQÕ¾ŠÈ‰Õ ŠÃÒâ¦Æ\x+¿`2eÉ µ^´ôB|iCEÊ·\=Ùü*7CRLžÜt›x,3¶J%A ~†Ó`®*w‡Zý.¨#WÈáˆêS‹“É*&ÖLL~'Ñ;¶M'&% ê"×[*moº¿ôH^ú‚ nM6)•U«¬¢WVg§Ä&x Kí{Ç¿]zÉ +¹º˜X£fÜ<#}ôÞœl:\ ö%\á·Ñ–ÔõWYŠd÷ŒÂ[‹¡Þ äº\œÚ9IxúIÞpÌšäµBÔ:¶—³ìôxÅÚQn¸ÌÄ/„ÂœõÞwŠëÂ\Ó ùÐÈ/ç:køTqjNÅë“j…㜸\—³†g›d8¤¤ŽšÚ’ãLZ¾Ã¸]âì´¶Ï T&¬ï66ªÌ½*|¥0w« vî&‹®l5fÙšEÉÿô̹ñ$\wñ£O*9ÑÔÅþ–œÓ'¤ŽY…gðP±°Ñ‘*3•ˆ~ª +MpÂœ(i¹p—ÂMœ;Uk>$×,>c§ˆa&¼(öBŽ“,Ÿe£Ü +ýG±ýN;ã8ñsø¨ï牑1 \°Q“âæZbgxÁqÚŸ¦)1â­Ûw!hK{…Ñh­¯\¾ò–§¢,ˆOÀ°h|ÎÞØéjn‰‘£#ÍúÅ4|ÑÓ²qÔÑÁ¹õ1³Gï¶&dðb<àËVOÇW­R‰<­¦*›¸!ôøP_1[,±Œv÷~Î Š¾rŠ€¹³¶fúÎÒ6Ð…i„ €ƒC#ÂuÃè÷Ê­¢‘i˜=ÒL\™¼æÕÙ¢'¯Æ’•Â835PòîL±ÇSÌÍQýí–Ór& €cÛ¶9±&¶mÛ¶mÛ¶&úbÛ¶mÛÉþï°w[ÛÐ7]§ê´sÐç eˆ%Ó29§b²øǦ+îäò3ÎøÅ/åÚ¬¿ÛŒS¾\æDéH¶ÎÇhyvÿ9ž^¹þS”s9õsꔜ\ÊP[ ãÇcƺîÄJ¡Cr‰ŠÂéå»N,à] 5ý…–øþ$Þ8†$Šø윈Oݨ<˜c½åÙ~JÊÊ9¥÷ÍhçS€iÅÝbd%÷:ãÈd`‘KêÞÙßdžs%¬àÏnLdèŒ÷Òv7© +ý¿'¾-ØGŸs¶Ö¶ +48§4î²Gá0>¾Wlx{O..ʼn6mD¸—ÚµQ¤]ä]Ž.†Ø0k–:3ê‘M}úf¸âH]*Ñ|ïâ |@…Òï‡H ™ÂÖ„ Æ;¾晜åâÈÑ¥¹Ìx0»°WäîÎ{Þ~ +ƒÐ ñ2×"ËOÿi"4§^¦"ˆËoå<ð­áÏ'¸ä[ÓÄõ* wX¼ê `؆ ÅuŒÕ×´$¦0o±ƒ¢ã ÿnlkÄ=³÷0ú@TÓ~"Ó,àçÜñOÞ\à}ü½ mxTÀÈ ²?+Ÿðwíxª¬ò“ÞcÄ1¨+EâyT;°O +”¼´„Ì•4YHU†Ûî: À’´6c§ŸL<ôwÐvbif”” èAÆ1`Ï”yþ–b“àÂ…–WƒÌà.šžîý˜ìãObéFv©rüh€ÕÌ} §¾ FUStŽüõ¥¶£ŽÆÝAï¥i’h Õj=úè@ÂÅðÂÅþ°•¼Sá"ŸÎîÓb¸®"úáÀT°îJƒôúïë&n‹™Ë‚'ÊøOIµé„o„œrÃîä8й+óu¯é¬¦ÎuܬȔ + AˆÄÒŒS€w¢3"cöèF‘þH™ÿU¬þ›€ªb;6ý@>œãžÊß7)Sz'Ìä­Cs"Oõ«—$Ö‡Xž|ê#ϳ݀¸®3Éþ¸x0±Ý¾Æ@ÁJ&íæ×jJ¨µjÃ[ä-ÙL˜N`žFšxóMCÜÞ ›³R_Óf·âéÛßVç v¡>  $àdã<#OG1Û¢F7û™m@`ƒ“rº”®½C><ªˆF[·ŽI<.f$#Ðüõ‰F¼ úóÓZ—zð}‚4JÚ‡©‚­oI†yjø[xWûêJ¢rédªM.£ é¤+ÿÖÁHc4àÎ’» KA(‰ÔÎH$ƆÑåϨÓ})mŒ=TmñyDÊö7©ÏîEx×$Ž¾—6êñUÙªû®'.•ÁÛ|uKuË 5y¢¼qžYàΈf'«|~ÁÅ Þ°Mœ6Qï¥ùTú‹­K¸«ÿ*èžø’ªq7ØØ]—It§$&p`Iç©Å2‰õ؃jÏÕ›“ªÝ;$ù‰’wÜ®\#諸,©ÝAÕuÍ–[ˆÃÚy”a‰@ÔðkÓq l‹ã„ªiÊÈ´8üø11—z]S”y.Ó‰Ž¡ä™’KS¡ÖÃŽª]ˆÓþR \L_A8D[8ÔWIµú.€Xm:;a1i”D¡rœ9?ÃÍÇy¿DcŒµüHËûEíN `«Ä0«gP²x_—t¤‹ò`$“4™É¿¶ìÏB–Ïñ—½ ÈO [±€%~@ó{Pæ>5&m7 B7,•"~³È7 °í¡èë<]€Ö»ôZzËËæꬼ.“ú²ûcñkèw29…É!®C³h‚øouÓTI֧͆g%72bæ•2æ+š>J\¶¨"f#ô!}“me1ë5Ä-t’d 8Ë(Ä^ìmn-ÊläŽíw­5q1U>f\}±ã±-ý°+òÛ"@vÉ2TÆ«¹¥ +ìÎ[ ¶ ÿøVfÄX#Û;Á7å‰ +SCsìtLÑp|† _VçuÞEª¡ôx7?Ž ëDäMvŽCÛp—àŒCˆ~xeÇè ñ„E ©Vš‡Ûé¥ÀÜpŒc1C xnÏÛppÔnÆÀŒ:ݨ¬}tS4ÎÕº´ÐûKÜ^ÅÝbh6˜,•áNfÊm×A˜ªŠ ·×鶠™‚mƒpÞÄÄ%å˜swÃÕö) +5n V¨~vu²H§xæùpðms¹¿ÃÁ’£;>^tùù—FVN_í!–tïYš° ù\ ü¹— h;°?;{í.+¢ö-ße×½´a…úL[{«-F°fWþ2'ùCQ”Ø5áV:áþ¶î†¥ý÷EXî8/ æˆÂØ™8Qo5ð~…zˆ. s¦H¯vÝSââyó’Ì’ÒÄÅØÞ60ÜtfíÌ{°§mŠÒ¸0Ý«|bXA¹áÅ[æ͇ÈÜ:î_Ünt#®äI÷kŠÏ …ç1+¸ˆ‰ÏÓ"êÞKÖ{ÓÛ/‹ ¢üí¤rÊ…èthì¹9Uˆî‹t–T{´Sï„óo°@.¦œî'`܃@Éõ¡&Ž)›@ü)ª*¢\æ’Æ\w¥+¦ß‰Ö[!\àn³W»óÏòy"×ÅUù&§xÞfq®fÕð FU`gõÂP (Tí@1åo^•P£ÀÀ4ÌìÈ,kÎ×ÚL½ôfB:6Ñ䟨sàÉ„61‰Ãûy|«<º„GCÝEƲ’]Ø/ Öyâë‘Ò±¯§1*9pèÞAäÎÎ=ƒ@Ì'°ÔqÁ/éû7#¨®VvÝ™ó!NE»¨é'zÏ“SŸ¼ZÌ·la‚¦Ë"BM‘â¾RšB°áÏIU°gfý–zð–üuñ?yî%“Çaàòikí붤ÇS|’J¨Îú]£W¹á—XQ|/¨Q$·ÿJ ua±gƒ¢ –å_ƒ!ã=üYG5¼J¼†jÁqŒÚhä&àÿâ^LÊ:®lt­œ1€åËmù. +wv¤89Œ{*îçiMgë {.z%Þ_+›¡7Áƒ¹«°,aWz‰-«‘.ÚñÅ.a.¹üšD6ª/ÊJuíÞùÌÓîpñFÁ “Ã(Ãh¸ è£Ãl¶bòÆÙÒùŒ™á«ÍUþíùäEáOÇizÃÑC·8=|“„ÿPˆò ‹ÒíÒµþwR[2WëßñY†îKyU<³ÉÏx6œ€´á­‰ùaÌ«–í/G»üœ”üÆés¡Óâ/öìrôd‡!¦Ág+æÃRÐù=à 1kj“d‡_†¦K8§¶Þ³Ç{”‘Q[AÕ§Ž2‡¯¯žüÔ®—nWÛµ`²ÊÿÍŽ@Æ~i’¼÷ s^Ã9ÃòÊBµY§hÍs5‹vÃx'£älÐöäüÓjkIz Ù·bv áI`As[_¸ï +ƒÄ(}®™˜/—BÅeUx:ð,¦ -‡¿ðP R^M•jœìØÄL×ö°ÃìX <Ô¬½¸.G·eÎBs¡ÝÏñ}ú55”’c0ùu½0Gî(OSån:Nˆì¯”WÊh\†(¤f1ŸhË>ä$?¾#"†ØPðŸÄãÜY1"³Ï?“M¡¶2¢Þ6ë«3:j;¯T•k¤Ñ(CïÐIW‹/˜£å•-”UàO䊶$U­^”ÈÅ¢'TóîÄ=_ɱˆÝ FñÖ'Ò­˜ºÝF¢ŽJ9u\Wµ:íÍnO>ÚqÚÇÄ;Ñû(OA'©‹3è¬?ßh Õ¬áÆ|ö\Çê‡AÃìTK‡ X,ã5¡Orð¹Ë 0Œ¤åU›ç€ %ΣÅû*‡$ªmظqç‰s²'E=/Ü1J‹ñ«¹á7³`’$zŒŽš ^ÆA*…¢ß*ÁÛy’ ²§7däÏŸ-[m‘ºÑë¯àrÛÞ˜;»™{sut¦>ç;qAs4ø,NÉ¢4n¬(¾¹Ò}X <‰´¸Ñv5tâ¢Ä¼f:Å(õ#¬ +oµ òš }ú¯oñO;xGÖy$öî%0¼˜n„xç²klÈ ŠQñÒZ³E’\ƒË!žÊN¬@qñ™Éñ:7"+ÅV›Õ’ÑÏWÈ"êžSÂoºQõÂõ}_'ÝÈ°áo¶ï>1ño‹fc( BûùoȾªúÆ/ÿÉjpÇ-t=Ÿ@H}¥ØôûÓº"}‘¹1ÍÕO†YžudHâë¹é©¾Ä3¼Tê«jì¿¢¯:!#g7ö{á\SâŠS  þÂ.çŠÍ§&ãz¿Õ®`/÷îïY0[;%°ýÔy D«F}T±i„)È„câÅèoóv@Šˆa©hÒ1íU+fa`ƒkm~›U˜°Ëe~—ÔO¯•j® „išD(˜°¾ùak• à_°M9Qú‡¨]`e‚¤tþýº†L*¡âóË”¾€ pe8YoÿÖ̪î@ù8³ «.÷ âÖ¾¾˜PèÊÇp4Ž9aÍ/!õŽíwZ+@ÒOš·p·JÓÒmïw]KEÈp›žN•¤CiŠá¼L!×5òàd íÂq‡]ÎtD?ÒSÂ5g¸oç>Ô¥çÁI Õï`ŸÌ^šá ùÒ#èóB:©‘êÛ;:— Ìâ2†¾³>–È#©u¼‚! Éùøf]pî­Ä–Á[oò19—¥b½âÉxQÔΞH:B\ÃGMÆ·ö³5/‚)¡Ô©àg»g¼«‹<œÇ‡D§>¡?»§ýe³R[⪠+Sêò Uµ°W¦+­¨SÒÇp§-ÿDjë3Ž sneé6O¾ÍlY¡¸;ãß¿Ç5ú˜Lý:àÑ0Š[5´q!‹:Ms<”ýñÊ’º?ú„»£þyQ|ULëÁÒŽ~ w˜™³T³îœ>l¸ŽqèJ™V[5ÊO§ÕXüŠ¦x:u‰t‰åÆÕ#;IITBÂ!ñà•¶õêd}T|KË® +›Ü«¨Ö5"sVÚGZò×gkïá.W +ÈMBU7{:ãKIÐ +ˆ—ˆw›&(8Ü“æ½Ì±ñ1ÑÔ^Ú¯Ãàrð£0ë[kf÷Õ*}¹ß@„Æäö}7YÃê¨Æz'·KeªÛ$Ó²bI EÙ#ßï{†,’æÕ~ExT.!Ì.ѸqGhý9p2À@Êp_Œ^Šòû»âÑ@Æëøæn ^ãÂÍ’ºñjQ‘ãj韹ԤíÌw/®xáúÄ3@ŽKÑå=µ…T¯à™ªFãõÏ'‹J.ô'¤w£1’ñú8ŠCå#ðóÔ†,éx‘ï6ÓÆ/Hi4’&ÕM~ÿh/ˆGðvâ2•øÃ:jp} ¤gIp;pƒRM1¸ÄÜo¡\ +rGþ@Lrêjhx%8ŸÚ>l«Ý^=é⪲ F+©d€†µ‰¼½¾B`o%冴ržÊ7.Õ…þÓ”.ÓÃOçkÀîöHÐ?šnü\ûÊ—–ò¦þIØcl6_å?2aZòEô‡C8žF~Ôè,KzŒoŒ‡JO*·ÒÄh^–R…{Q '!²·¤äõì‰ +ás(;Í9r£aC¶Ê`:ðY;ÛQ™!¾4Ê——rÌ|¸’¢Î_”àvî‰ÐRëX.üfvÜd¢9=‚Ð]·b>ùÆÿÌÎë'Ãè¢9"¶•†³¡Õ—lS-†ÜZAqªïÙØÕèúD žÓ”5Š•sAŽª¤{ žç?˜X{.ú:„bíò·ëÕÊÝEhâ.ÍúB_ƲÁæSËvçô]þŸê7Xà…ÕÒ— Î  UÕD”7¥OªˆÆr#\¿»õe]©ôwÞ#Ê q°ŸuMÙþ›Šü$ÔÍÈͨ­ÎÜ°é´=•qð#çgþÕPäŒÏ´áÏûójb2Žû‡¤S°RY«Ã€…rSðûÁ2ïü‘lãïPi5v\?%•–ì|]‡?jßSšaõæ…à ·ŸâK‹âS7§xÐhît²­ííXÌ÷»øñ½QYM·õÉÛ*02÷—'(~@÷*cx.ag$Ì.6ÊÎ0~zGóÓþZ²¿o­xä²&ËN‰U]œPÄZ/ú~Q¶Îö\[Ö$ñãR[öé–’t—/)$¯h´<¤ŽcéýÃÄð±9>Z|É ˆÞ¨¬ghH€ñj~…îç °QÏšd"ÄÙdž>É×¥‚–ÉsJ¿öãô5BíìÀ½Ã¾DÑYÁß9TFÛiô…H¿=~!µ”_£ÿÕhz Ûé³RÇ=@QXÚ›$ùQŸ2laŽ(ðvºQ„ ]jŠÖ-`ëÇ8öJ•§ä.?N*êh âÚ2T‰1ßš—Š ØH¸XiÅsèG ñÜH¤¤Ò»¬²Ø2qTÿHj¸U´úX>ísý’jÊ–å¨*ì"‰Â;FtÒb[9S™õmIße +êÙ©ï•×`±–¼ì«í‚ú{}Xíl\ER«êb{E,ìêlÁ¨ž¶`Ë eFõÌÔøÜ ¤ó¼ Ú˜Â_‹Ú}L݇yûCö=z´©Å¯ž.ÉÔQ;¨iœ„ 6J†bj ‘ýÎn¤‘M©l"cÊ9Ѷ›|îÄó¯”ííU}]íbÐn ܮфôK¤‰þ䯸¡§ÚŠ±[ÂãÏ.åð¢X Øm‘yLpÅì•\’ho;¶ÓèïÙ±Zظ¿‘+ÿ¼÷£Ì®Î2é€_zñÌ·^ioůW'<ßf(àÂÏ›¡‹"Ç™·Åô%O™Îr(ÊQzΩDP±pH*u`ب#_çß!×Vê´P2âý/ˆ|ð ‹„oçš>“ÇCü±ð+5ëã(w8ëÉ,4ë1Ù|†U_5Y}6bïü§a…«JhÛà’;îdÁq¤Ÿr(ÂkVU˜U”UH3~Ì cs_lŽ+ä¨ÿhK9õ°7V? +PÔ3)lmŒ;œ¸—ü“5|—î”+ÀTÅv‰¼Ô_òF^›b QãLT?yÇ¥ðb²èewïA© !ÅdYò]mÝ ÏÈÍ[ŸC9Év%?Ó8|5hç´¯¾±ÛØ!Vu9=ziSݦÀî.YÊtrg¤Eæ“M€”6lA«X9·Í]ÿ;Ïÿ…ily@±ÝrW‘Ä–q±éi½‚Í)踂°ózgùÓRb˜È©ó4"ñ®, ºÞ¶_ÖÄ·ú“bµó˜¡lòUÉv²1‚åM)K(§ÓCŒ„YÀÖ²E¤$®“Vn.Ÿ…dìV[ÒƹGs +\°l{ˆ<­û$\Û5•/—»ì…ñVT~BŒ-ÍPÕ¨Áª•¤;çì‰R½‘€óÊ6Ç›fŸ©é\_–ú˜Çkè~/ôí¼ÜòÌõ8úBÇ—^ýØ€PQ¥ ³ÛúCÚsß (e–²$‡²‹Zoê/’G¹!…Þ–*û‘0ëŒH¦l‚Ë,·î«UtoÐpiØ ¸é:P—ìª|T0¼û•¨Á.I™>qÝ䬈 ·“*ô×píû ×ä£ ž‹0˜?Rñ1BÀ>ƒIÒ½ÐÇlàM7ú˜ Vÿ1_I©Sœ *îÆÿL^È®pµçòÙ ¾úK&pNM•»h0JPÒ×H•Bùö)»E|Ùq±P0‚8«záj­ö!€ïφÖxÂST]Rç‘RÇBh…ÙŠøŒ§Í¹¿h‘z™š-B·g¥èhhŠ‡ú©[*-öW¿ Ýk™êFÍi™?Dvr_´ ÖŠ,]%&z´µ­b š}!4E.OÈ꺟¿®a(th$³£´'uOºcŸŒ)Ók»óo¸.(6ôãzµÒN+O‡ ‘(Ë4$u×PjzJŸR®¨.÷Á„ =ÞÖ v×?úF1Ίi*B“™FT, ±K¸æ¥±Ò_™Hf73ë#I|’W«ÌΧÛ}†,ʃ.Ž•„¢¤ò·ô³é²1ëÓ’è—Çù/ VT2×Y J«„1¨”t²òšÕd}™ÀÞõmuªêzì¥j×LÛ"`“¹ú,ÜŸþ8ù_*‘äm"!éÛÖR1G,UÃäÓñóî§eú4ól *¶ù.¡žð“ÝËè)Çl(X1ÊVXÃÎÔ Êí ÖwhL¤ì ®@9ahŽàô ?Ötß8 “ÒôUn>6þû¯Šr²²8\¤!õ†o§‰^ÎòßuZC’ù”ª”DèIöùéýƒÀpuÕ?Õmg˭ͨº‹ÞC‚¬Ú’ÑûJžô E”n‡ ”“%F7ÿ8ÉÔw*J!ÔI4-w xÓ‡‚32‚F·ÓãP>›ÁýÔgñªc Î5õVÓ¤öû4+Ë™@%;”pÅV_¦˜ãû4É”66`%9etIhÓiãšOƒ;Š•¹Oß;dÎOY…݆Ô˪rÿðgÖŠú]k¨ð–×ä ÌæèšÕsÜï&ÂÑ©¯¤”:€—1µ›æ½ßÃœ»Mãe´ÍŽ³2®Írtj9 ÅZìì†Ì–¿€ƒ¨ÁIÒ2ü;^é—:„ªÜ‰ƒè»r[{sÅží"Üqác‘Ò¶þÞb.,“Å‹Ñòm÷…aÿÃN”ˆžj,?w&+çÊoØ`QÜÚŠ¥ãüh*ës8· FÕü£n °‚)•Å·ðË¡xYà;éÊy%Ÿõ¬ÙÀ•MmR'¡<²Ñ^ˆV¨ß<´PKŽvKlô½ÚóÎвß¿`Ž|Ù?±Ì-Ê@H†­O.oühr +‡)Í1p’}l‹ÈÙ¤û¨¯šð1ônQ“Öü:”ƒ‘96êì(…+õƒ<“4Ã7Q|ÿF1°²¨üñ#\õl1ï,äÝ?7Âeì7®Œ½nØ<É„3ÄÓ›rhNBRòÂÑC +^[ÜÀ!ÄŠxMcOÝ—ÙPFt>l¿‹JF¢‡ßÂöð1’£†°åïxDÑv hÇÚ +¥åã—r¢fY—òU·zifÁUÆz*JfU¤ËÞ ½ ýä|ÿ:Ð(Pk<’¥WÝìo*Á]ö…gP³Šþ,ÚFjî¶%™;ɘ¹á9L9.DœÇǦÝ@sOµhòÚ³BãtÑsÒ~ˆ®›×)-ÉAª×ZØkfbTfðNššöVUÇåøîÆè&ܼ+0™Ž#õ±8håÌñÉð¨}êeía¬N…Iû{ ˜ïÂΟ&vÊÈë:s]>°WŠë‚ W ·1®$&-/~æ.`É.m6$ûŲüIÀ‰Ú¤5utý³ ÊäÇSméWX`  ÍFÛm @¢ñТ¥êf3­™ÔC¿ÁFÕÆ"œØ™»á䦳(5I¸/L½’¡Y²ìñÓQ#”ý†YhŽu}T¤¤¼?¹N/Ö‹c ¿5Ll0¡Ë>‚w¸ìÛl­\pÓ;jC©ür»-JÝW¿¶Ùå mÜ1&Êî­ò4WÃ’Yµ+Äü#-½é"”¥{užo‘ÊëæSýË•@’Ô=õ˜½½Ž3³ÎØ}Vs’:Á ú“æ‘«£»{gˆó#Ñqöúb‚6+7îŸw&ŽXÙÿy¨7ípý„¬ó󋃱wéÍãCN(³¹9ã啦°ìX";¥‡üÌøf­gÜGÀÖ]S—ê£fçù¹”åI|Fys±fèÇøý8AœFæõÛŒ.W¿Hø,ÌFFÙQѹ,PŸåí F"O­rŒ\4nšÑž3"VÂ5°Êpø-f¥šs +ÇГöÞVMýͲ:“®³m›ÓWBÖþü/ùÁÿ ±©¡“‹½­¡“5ÌÿBy@endstream +endobj +953 0 obj << /Type /Font /Subtype /Type1 -/Encoding 2140 0 R +/Encoding 2705 0 R /FirstChar 2 /LastChar 216 -/Widths 2156 0 R -/BaseFont /GEHCPQ+URWPalladioL-Roma -/FontDescriptor 735 0 R +/Widths 2721 0 R +/BaseFont /NGRKNU+URWPalladioL-Roma +/FontDescriptor 951 0 R >> endobj -735 0 obj << +951 0 obj << /Ascent 715 /CapHeight 680 /Descent -282 -/FontName /GEHCPQ+URWPalladioL-Roma +/FontName /NGRKNU+URWPalladioL-Roma /ItalicAngle 0 /StemV 84 /XHeight 469 /FontBBox [-166 -283 1021 943] /Flags 4 -/CharSet (/fi/fl/exclam/numbersign/dollar/percent/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/equal/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/bracketright/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/circumflex/quotedblright/endash/emdash/Oslash) -/FontFile 736 0 R +/CharSet (/fi/fl/exclam/numbersign/dollar/percent/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/equal/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/bracketright/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/circumflex/quotedblleft/quotedblright/endash/emdash/Oslash) +/FontFile 952 0 R >> endobj -2156 0 obj -[605 608 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 278 0 500 500 840 0 278 333 333 389 606 250 333 250 606 500 500 500 500 500 500 500 500 500 500 250 250 0 606 0 444 747 778 611 709 774 611 556 763 832 337 333 726 611 946 831 786 604 786 668 525 613 778 722 1000 667 667 667 333 0 333 0 0 278 500 553 444 611 479 333 556 582 291 234 556 291 883 582 546 601 560 395 424 326 603 565 834 516 556 500 0 0 0 0 0 0 0 0 0 0 0 0 0 333 0 0 0 0 0 0 0 0 0 0 0 500 0 500 1000 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 833 ] +2721 0 obj +[605 608 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 278 0 500 500 840 0 278 333 333 389 606 250 333 250 606 500 500 500 500 500 500 500 500 500 500 250 250 0 606 0 444 747 778 611 709 774 611 556 763 832 337 333 726 611 946 831 786 604 786 668 525 613 778 722 1000 667 667 667 333 0 333 0 0 278 500 553 444 611 479 333 556 582 291 234 556 291 883 582 546 601 560 395 424 326 603 565 834 516 556 500 0 0 0 0 0 0 0 0 0 0 0 0 0 333 0 0 0 0 0 0 0 0 0 0 500 500 0 500 1000 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 833 ] endobj -713 0 obj << +929 0 obj << /Length1 1614 -/Length2 24766 +/Length2 24903 /Length3 532 -/Length 25647 -/Filter /FlateDecode ->> -stream -xÚ¬zSm]³eÙ¶]uʶmÛ¶mÛö)Û¶mÛæ)ó”«ëû¯:n÷S÷}Xkfæ92GÎ{G,RBy%c;CQ;[gZzNE5ykkc ;iA;kc‚3 )©£‰³…­°³ 'š‰1°‰##)½‡£…™¹3ùõYþ !0ôøÏÏN' 3[²ŸWk;{[çˆÿçJ&&Îæ&¦Ö&Brò²bäb²*b&¶&ŽÖò.†ÖFÒF&¶N&¦vŽÖÿ¶ 0²³5¶ø§4'Ú,''{#‹Ÿm&îF&öÿ¸¨ ìMm,œœ~Þ ,œÌ lzàlG`akdíbü»©Ý¿Ù;ÚýDØüø~Àä휜Œ-ì ~²Ê ‹þOgsçr;Yü¸ ìL"íŒ\þ)é_¾˜¯³…­³‰»ó?¹ MŒ-œì­ <~rÿ€Ù;Zü‹†‹“…­Ù1 &p413p4¶6qrúùÁþ§;ÿU'ÁÿV½½½µÇ¿vÛý+ê?9X8;™X›ÒB10þä4rþÉmfa E÷ϨHØšÚ0Ðÿ›ÝØÅþ?|®&Žÿjù?3CñCÂÀØÎÖÚƒÀØÄŠNÖÎù'%ùÿ›Ê´ÿs"ÿHü?"ðÿˆ¼ÿâþwþ·Cüÿ{žÿ;´¨‹µµ¬É¿6üÇC MðÏ%óØXX{üßÂÿ{¤šÉ¿qü¿¡H8ü4BÀÖìG zZú3Z8‰Z¸›Ë[8™˜Xÿté_v[cGk [“5ÿÕHzúÿæS6·0²²ý§í,ÿæ2±5þïÔúq:95uEYªÿóFýWœüòÎÊö?Ôþ½;ãÿ\üƒ"(hçNàEÃÀÂH@ÃDÏðsà~øp0±øü_2þ ˆá¿Ö2ÎŽîZ?eÿìü§øþk¥óß`DlìŒÿ™%g[ãŸñúOÃ?n#GÇUÿuâŠþõ¿ÝÄÄÝÄj}ÅΈ+Ø2ýw†szîÈ”°Ö@ðHˆ}i£rQ]¯_zøG¥þGmmÓ çW»ÇòûÏ#IÊã±>4ë_½©&×ù8>ÄýˆÛdlTÇtº¥°jÑ^7KÒ» š¬ôªÇûS -Šº%`¸3LŽ7)ü‰] üQHžíá|ÒâP»šê -ÿ\%ý}þ54>:2Ü{Ú„M•IÊå -KåïƒÍ§©R!RÕDzÝžeÌ}øØ"œ³\ʤ!g?5íµ Îk“T $f}QìŒ}}œ7Ãë–aI­zQ£Ø`{1®ËÊ›¡9sõ‰ór5úË<#¤=ø…ˆ´±36…è4Ó+òŽÇ¾a‘Ïp:‰é"“|:[5P6“Ó½«D¡;MMM¬:NNIˆ0þŒÞû+âÝzzÜðà\ -Š—€’»qt‰ÿß)âxô0EBå)¦d4Ôà,Y=2€Ä„ÖÈ=ðK86iÓ·½µS(ç óQôx;”ˆwMÒÝ\]°Ň„ŒŒÄŽ¸¼'Ž‚ŒHè¬|Ûd@I¹²‘E —çê‰xERµÆ[ºª–ØÞ÷6µt×Ûô”Uâ£ÀíÇÏcí—‡²áŠù¥t/ëE½N r…5õƒ‡À}[ÖvÞbO¿öxî3–^üX³~ݱÚtX”·úbÛ»Ze¦B}Dþ¡¥±{dyÉÞâþÝbæZR4ŠR`s§Ú1w p˜aºÃVÒ}ŽÔŠ'X7zÉ(S†Å£À¥AKÝÁÆçr&ì椫û\šì‘F­ÆLu×c¶X‡YÈnT<)—l%WªzÈ -Ì0Lo”2´“4c×±¢»ò“÷é·%¶œìÔr÷«rOxRæ@oÑ[#OóÐY„ý‹UՈʼn%?¼H»@yÖÞãLùbùÛq÷›c}DNCýŸoì sÑr?áƒÔÝÛóŠJx>æ?¤å‘]ò;ÔHbÓ‘¾tTï¨)Âm"È|Ó\¹¢óCÁ†e`ç'(Ël-zÝÇ.æf ì„©ƒ5 /Â/‘˜ÅÓSþÃEÞW;mdu‘ýêØ®=)À6li»ÙæüÖEÍX»Æn–ç]6 -Ȇ§yð»Ô™6üÏ2Röv•ŽQvvåôTÂ*¦(?ç)m¶5”OVÀ#8”¦Ú•4áîPñ"!Ýa¶é]\yc™··sãAZPU6gbß+:*(¥Þ'V­PÜ…¥Û)+#®¦.ráýô[yÞ]²ÅÕ¦<×µAÅÊ|…ø Ý&Û¦ÖŒß,`ÄÆ -\w­wñ0‹²R§ËJ†H®oQSÓâ(b½,íµ‚9¹/#Ýýo ¹|Êq3d›p+¯º>2£~ìîšzµ´[=1#„ãW*Ža†Æ4õzð­âü¦`E'K‡vU?Ê ±lyZ¨ö©­O›iÁ&6xDÏ/ -8øªˆž!/ˆalÁæG¼¸PIQÔ'âf΂ÏÈs%ÔÊbÞ)r1X#Þm@i°c€B  x›¦çë}4ÕU _ÚI ߪÒ­gë–i“êÞ* ]pÕ~éÆ)‘¾ùB½Çµ6úþD+.|qŒæê²^”¥1=XXOV°kØ2å<’*«9°ŽxòH ´›ñû]·ñ8l35Çï>oøeD-ª ï(cÛ¶.ûK@!¨ õ¾5üE³DP:[ÞŽ3ÆôŠˆ}ÕFŒPˆ¡‰„Ü6t±ä͉ -|\4YÍùô\VŽAò¡iÙœÐV•1ë#~Ú¦c®IhòT3S–ÎÎÛÞc|³!6½ñà †ã;–iòྲྀ\{ê€ ß„†EødAØÆ(éžDô öè"Oï?órš"µkñ㥡} põCÛ|TŠ°jö·1.+îq æš½ÕÖÓ¨0A" BZ8Okaƒ¦Ø;oHÇóô$Dœì@_æ‚y:hã0 ›š®Ï/óÞš~½dç"¤ªÛ•E¹ž(ÓmÅlQ$uÑU/Ã| b·8œߺ©17Ñ€2‚èe¾z@ypO2Mé—”Ý÷n‚pnA'¿1ٷل‘ñSoˆ*[¤.€ jÔ=R`>oQ³‰voqÜÕ€,ì;ÕùoƒÂUp…ø<Þ¼nd‹*Θ`Ð…²2€·½OÛ§²|#ün”5¸•õ²ùœ×¼¬³Õ²¬0'MSh%.é4îVáÏlx -'Œ†Ý¥ýrˆøœ]E ‚ˆó(‚ƒ+c[€Éj‹®¦Qíä¼_Þâgˆí44U÷“É;2–×LC -JOÉÒ4WÑœž:óû\™Ñ™ïÞ! ×yÖ\3Ûø=«/Τ€çÞ¸ ¯æŸ/8ˆÇîc+Š GI1(yBª5ŠÝ¾^ºk½“»¿Btœ'Ïá‚<ÚÂÓè¸Gù‰4E–'m$âÖ…;©ßÈ€,ÌH©ÈªÎØuW7ðÅ}Qgg.UÜ€‹öË„¯Ô—+D+K.j’™pìlîw>k»«áª‚˜NYK/ >œ$¢/Ü×ë°R -ˆÐ÷™êq¥@ûÏ|åRøíçÒ¨Zqé1#.²[Â^%â”(:^ŒD”ÚPØ•/ð -ÐJºN$†¦ædœÆak¯n¡mk5¼{n -©.׬nà'' 2‘î3ˆ2?g‚Ó<ûeZ‘™a÷­6™'zOÁt­:ñÕBzÚFÑ£AjÅ6©²}Ôq”‹ðü¬fŠ™ðaNõRäm€É€e‰aS—š=ø„PD‹ Å©?Κ-Év“Ü*.ºå„í_óÄpçÂ’EJ-Mn’†´#Îó¿?JýjÌàUàTƒ* - dªÑ‹ï­M1–7°¤*’±¹+DÞÄZ·íøjâ?å½Ü ðûLÃ+“:öýÇÈç?·Œ=¹>y.ž¡Qvãà…Ï™\Tz‚ëv<Štbèû°Ú¥€gÒgñ] ÃÊ JÛv§¬µë-èÀ\Õé)Ñ&ë!d9¯!(MX0Ý?Tpï.mêßýßVýÔÅJ/Qq“êå5„ -”;çÙßëÀÓùÙ—8Ç!‚Kùz.Áøò¯Xñ€¯ÈHêKŠ\M(€Á½µBO8 çXE_æsÃYZ·èp6aaLÞ5f(wS;áKéªOÙÓzôx -Õ§µ÷YÍÛž—™®Î燸-f: sôqó957ì>\Ç´¶ ¬C½}8$;DPì…eªì¢V¼'­ØíÄ<È“½Ü¾NO(߈]øé¦ÛÅr_[Þ*ʇ¡ÆËÆ<Òx ç˜î®l!™(Gζt Ë¡J6Úöž¡Z|û±¹¥Ø¦‹±<)”ávs"¯ÿB77ù>±9 -Ä’£×¬÷°zJmp¤0ZgôìuáÜí™ô!F…ªä Œb“Ð.ƒ ‰¢9wØhQÝ+âGùTjx­~wtñ».^jËð‘g&rÖ̹V§#KÚý®Œ¿çqÑHºö”Å~àlsLÓfH9áNjn£W4`oÑ£:»Øš^ÀÅK¥ŽÒúƒòL9ôlÊ0Û‰B˜ÚÔ#k|yË¢\Ÿ=*XˆÕÄ óRi× à¦H~&¸·—ϲSz…€ÕhßÝ0Ö/äH—Ì-Z‘m®Ûû <€úQ³Õ0zÒבß8r¨tIÏ'Õ`™@*ØÆ®@fÃ&€IѪ¥v%QÏ:®Á:.s&ŸëF­¤ƒQüʸúW ›_!Ò0sI"A4ªØ¼D×Ä÷¨C!n†Ñðú;+‘Öº{ýŠ÷ÊdÒ”üÝz/176ßÆÊê0l®«ßCヤb£s0 N­÷ä?‰ X! ¦œ´Î`ÿ¾‰$ý:Š¾]‘µß«kw#+‡üåj$P®¶½¬6>žæØñ^70•öKú€ø$ˆ]ïï­óÝo¸@g\³°Gé_›_¯›ÓŒÉeeXY¿³}ôiºiG(Œ·´‚&*ú~ŽÇzªF`4&šš8+‘o""7÷Ý3ƯU¡³ß-Aöêxáªî]2ÌÀçpÛdJ˜ -9ÅùbW<-—Ô9âEjRœáÖÚîö©ÝRËâG^ì sJ¬¾bíÇAÂxÙýeØ­ÒæÊ>•¸jÀ ,WÐs -ñÝ‹¼I2ˆô|ß{1¦[y#²š‹9ö_ÀSƒæŸ’™fyf+(ý -K#Îø/÷2ž;¼£§Zç$Êò^Mú½0)íN(ïó‘µ<‘Š6lþ;9ÅуŸ)Ðæ¦óF}»ºÐ=À¸¶V Û˜Å/éGŽIÌYW¯µ=·ŒìŶÑ;˜vìbs¯+YÈý/âwåáNV­&Þ÷¥0óŸ7¯Â$6/ ÈÉa…Ø藺¢ z|£>†²ª=–û&‘*hGTщÌ÷]š‚ëœ1Õ­šƒ”éYr}Ë!Øŧ¿åÈ<œ#ëý«Y)‡òöx~¿˜æ}{rÑ\¨®ÚK±ÈýZFÅ>V;H4®WV<^»óF†â„íÔ—î²\ƒj4Õ!š¼2¯6Gp?“‹Zi_<ÎnnŽiµ)Xg¬N~_@–GÑI; ñöa±»ùu: øàý‡—¶ËÙloOµŒ…6÷¼V¹1 ‚*ÞÕÀ³Ü2 ŽOÚy‚³OÀBwFÆSwß× Må·>æ"ng,Ÿ¬$¤€w;ÌEÞf7âúe-¥nXe€žªpºLa :¡…ÏÃŒ^^r¸ØˆÁOäÓ· XF“ã®qœø±NÈ…!-# -«Mˆí&/·}Î I Ø%΄%0W¦É·¤¬´{âI\5d§1ÖÙA)£7½¡TDƒÖcÆãM~ÉÛ0l4ÚÔÕÝ„ùäˆ÷)—h7¿d~aùruÖ[l¡F÷è\)ãƒ|9Ù¦'ýŒÓoX™!Ï·²6…ñCìÿDapï“AVá ösò߬!»eÅX#}°;©JƒaíJÁ,;ÏÊó-%•6¹“ÉÓ1­Ù7Ó.QŽMœé`èð!s™ãÆÒb¢Vyz×¾Ï@ä[ RÒ…¸•°¡½oºì=Å0Î/˜ƒíÃ݆ÛÝ4uCaåïæT{!¤$šb-»™5– 4³dtõTÁP ­»ž:0ÛªÍÜ|njŽëéY Žž0“|1&‰•rœR»)ÂPåø2SÙà Là ÔÍD›ñØ•¼ƒe¸Ñ¸üñ§fžÚ£ƒrÿCâ"Ci°Õz(¾7ª‡V6c·µ^_ŽõÝX±–Ú¿ÿ¶ƒ,ºx@#f×ÍÉ—ÔÐt<­µÑÞ¯SwE[Øx-Í­.¸éOÞ¥f¹xpõº¼›ÅÅ?¬’ágI!Ó~lñ¿ö]>i}aÙ£™ÚØåƵ3.žÇ,>Fa´—ìy‹”li‡ WMq9WÍ!.iÒwy, -‰¾É%|¾Uůx¯¸;%ÒŠƒ}5]åD„¢J›œ)h#?yºâþ-^ø*#G„ Ú”¢‘üÀÄi;IÑÉ2çŽÌ/~é)Ñu 죯ã3noዯ78]P³]nÃ|¾g -6ψ6o‘PBšP'̧AFæêdf?P0dGC×´rW›çB¼¼6&³SÊr¥Ü •¬SS‰ÓòñÞõT9Žú¼K)Œ\û)°bç¶Õ†3´$ZÞ#&†×ææjsmÂCf‰àS4XäHF Z”ÔzϘ(Pt -|ÿÖc2›#á¦$'j‡ß|c›xß3ÃlÞ“”3Bm€Ü9ºš?¨ -LÈJ„5(µ -S|ØHˆGð—Ã=>ôԑʇÞw1®V®Áç€R=äŽK‚uW—e“ 4¤µZ^ öçý†Ï#ÃÎDžâØmwp#ŸT-Œä{Mô§SqêßÑZ!¯È¥û;Åcï¤ág´SƒqÑq/V1aŶõrR€ñùòdfN51©é‹å=túúöp›˜Ùøfqû— áoœOwÖÚu»a?Oƒ=ûàÃ<´ç{±Yúk}Wy†C†³Änµ›à’v€­âfI‰Ïì•Öˆ 5À×¥µ#t }¿ÍÓËx¹¯W–Éw \[^ü©®¢¾ÛèßWñ{‰³èGªAÁ”9•¦Ð˜¥H®!’¾¬²²Üc§c‡-Pâ©P¤!A¸öÕO“L¾S¸p¼²pàx]øŒ©cYÑF6ÚÖdòmýqJ•·àØM¸Ø[?§€YJ2”µ„,,º›]£/oŒÉcQ`»Îßr¢_ÒG[‚e5ÞÖ'·Ù€@®­·;úÚFºñ(êÒÝM#4{èÄ ¶o+¶Ê^\¸g9–À ™«„!pÔ÷Ào¬99Æ"ŠâÜùüçÜ[êJG“DÝñ±h0D´«U? ©$-p®IOŒæ·­-–Ò¨#­l6±…šå$Þ<÷š©^AåyŽ·±TðºÇIæ±k¯Ì{gþ2Ð'‚S»iï:+£Ö0NAr=”kˆ¡j+¥)¸’d¼ñeKpÓÿþKô^MËQŸØøjiíD$bÙbQ>}W"йÝÍÆa]ptYˆQèxwU?X`Ù*5wi|­`ÿT{o¢”¥TÕAñÛ÷=ø9½‘ß@šÖ}¼"D–˜G®ê“[­Op¸Ì¯¤E.€Tä”?Wç+:±B¤Ýê/ýµ»Ôt0¦æ<¨ökºíúðƒ–Ë$N‰öWÏ:^åßm -#‘%‘Ï+0{—¹Vx³½û³IÏßç@ ›AÖå]d˜± ÜšfÓ 3.ˆ•Lçû^«ªwkFOpªÍm“é éâKL§.ã¬f0æµ2x‘$âGÈÛ~Í…†ÙgpèÙzœlŸTêŸß'Ah7‹#m¢(´â'Z %åÝa&˜P[&W)íýyÝaHÄrÇxg+Ešê»ÎÑû ^äŽ(úÖß `–ºr¶jºù7Yþsß›ûPDS"äÊ"pqšQ¦Mê´šsËÚ‰ÉöR'  )Ú0çöÌzlšºð•`^•¼ßÖ ——úq2‹ãqÙ•ÚüŒmÄàðr²ÉEhÈဘÏ˽ÇEFá}y:%rÜ€ŠíÀƒ -¤á¾}˜D'N+nš~¯Ðß0’ƒo™¬WOÜs:¡ðwaz;A³cJ©ÚäA çÖûÈ<’+UȯÉCvL¥ºøPô‚Û²sùô* ze-£Šü;2 «ù«#_š¤£s¾þ vêÄ‹úñe‡Î‡CØ“¨Ï>¼»,æñ’peàùhôm2’ÏÝ°MÍ[®¼¬Ý’‹÷ €"_o UÅôh£ ÖB57„ý^æÛT'kiWCEÏr§ó•vOƒ*åµA´™Ç94\Ò»`´—ͯ{Ø­²ÈÈÛáåúX&¾øoä¦0ÔØðk> HøöŸ+åªØ=âø†M¼·‘vk[|º$»öð¦»tâ—@m ÇÂ:°€Ë8WùŠ7Š²ZƒÝ3Sq4@ÄtWð‘)6ýî D0ø)×ï)5ë¦xÅ"YÖQ¡-Yz»²4û&X³ZþË¥FßJÙU§Õ1l…ìDô¶¿+GÊȵ|Æ¥4>Û"ð Dz»}ªkÄCV­¿•îá•a‡ÁuìSÅÚFpÚý¡ôú=Þ O«‘NM/-: 7‰Ï”;É)6V©ìenìRvNì‚ ‘è“íƒr—#Go“ô¦ŠFWÔl™ŠQe¸ß(„ضêKIÚ-™š”…5(žÛ—Dî;Ϫ" äÈUºÉª¿kY›#ìÏaFÎϬ0>"_ø6ð"§XÂ[]ób -©ØWÚ¿\N[Ž”ÀöŒÍ&nâáµ9vdµÍ¢–£¡!Šã5iAÅ@ñ/*w.¸Ã(:³›Åå×Î6îu1Ü3î᪾ûõW¤®48ð“ã‹KÓ^¥3Tòte:ëù`Ë"‰‹º‚p­,»iAX/†HÛ˜?äµÞ)RR«Y?êxjÒ/½)‚P8ñ“—»C>Är–BŒ!†¬gÝ@¯kîÚ“èNü½?DÆF¹U<þ5”I.:´s¾Ÿj-p“Ã䊰"ŸªcÂ#Œ:B +?/P— wég&åoï²û×!æ9œa pñ|Š®¥Þ²K5lïøŠÑ9„CF †ºž/õ¬;¿G@!íxc|ȹD¤.׎n^H$ßÄÛÂÓq]Èõ+É{¸i™’ -“*ÅûÖ€H-eëpg,eƒ|ÍaJtžŒ/dŒú*Λ¢ 6ºK2;”‹x'.QŸ[å ÌñÚ:ŸÄTß $$¯µ“Í¥¤·4UA -~:Š0NÇŽŸÂy¨r“Ñ$85¿Aš«`!¨WÄF'*nNÁbt*Ú*¼ëëÂæ;ŠEôû”ÕaÇòõT~ÔÖ“S4Ÿò3<5×Ø\ÛJ´Æß&æ–“O=P©[¨P$“Óµãñ€ èiªš_`Ž.Šó{h/"•"v¥¯CŸ)-FßE¶ÛA<Ýï KF‡é9 ‚'ýøa¢4*$'=ÝèO áequGf0[éÒ´ò¢ïÑÞ7™Ë©4€ÐóØxâ%%Ì:¼ã/º.@ªã#)NˆÈÌaÀSt–k ’»´jˆ5b;¦¿J;÷Ò±C°7·ä°ƒÂKŒwA¹5S‚é%8.nN`ºê9_Žû¡ôÓ;Sæüê\g|¢Häae#§û×çÛu¦;¯ºÖÈÊXšŠäo+7×m4”°‹ª0Ýë#4åâ8hù‚˜RË9«»åì{°S©ã£›ªˆ¿z rª“ÊûýÎœ•VØÖi!z_)õ¸¨VS[i²sõq£Ë%®µe?åw«ìbØ-…97Á |Êš aü’Þ[ -4%Å5k£½02ƒÁw¿b¶8y<•«ápÁÒ*Á–Èp«¯,”&«‚rÃæG€Tëƒç¦£¤å¿”X{Š”ùH;_ÕZ ¼ë/i)ï1Èû£.5n仯ðå9 =)ÂéÌW%^}@|Ѧ{P`Áíea°,pS L§Ü”üÚ®Û7CÖÄbÀtÝzÏ3$rX§5Ø¢Pü–„˜jW~\\{ 7NìySE¼9 ]ºž½"„i5¿ÓúÅXôxBää\„“y”\á¼¼!‡k(MÂÖL]*/öðéžä§FJ{Y<Á&eš¯lõ‰Ïƒï…Ì‚+üŽŠ<Ù@9vOŽ’¤ä[RY·ZßUMZûp4–DagPcZ‚%V_©Þ\;=MåWÛ¾ÖG -›¶ƒ¯ñ¦¯<¢—h¸E“;Ukê ñÏCX ™¹&]U;Ûh VýÛ›ˆ‰±È“pc‚Ûùí tTÚ½JŸzõE™ ’O›IG©ÎWð€A\~a OÄãö!!Š×K+˜eè-£¢~½'‘Þ$i²º„‚&ᩯ† þï8^%:'†Æ¨HÆè cYòÝEMÆä˜éb§™å>à&©/8!¹ ½¦e -J±&éù雈‹˜9›âÆæZue)äG $ LË#[|íÕϬ4ÈÝÕbO -€£AÚ¤x8mw›þÖµÔ„±ßxèÍ#ºaýªU!˜ù´TßN.ÓÙÇ-É™Q‚«iy@ŒWc²8qá/øç ‹ïåqYw'`:ÓN·ˆ=óC$?Œ¸m¦÷öÕû—ÂhÀSx/JÌ.Ló±˜× -*¥6©!bÆ¥$ž)ÈFå¨3Çx=H3/xR ÎWGzÊt¡Dc€Ê'ÒHD´öXM-®ÁöpáØîÐÌ’!#ŠÅø*ÒÕ Íè/<Ô¢8>§Ð†ó÷‰rŠeÀìåtѦ’ ¾Lñp m… U?ˆ+Ã:N¤5ûÕt'°‡¡†µÐuî¸_‘ßçêZÚÃ黲s™x¸ÅâÉÚ¿dŽ «K²/gº†™xÆÄᇤ'Õ¼bpb4C¢êš×²ë”€¹j6‘oÑ¿š…JŽi8É—©ßNN1˜ëÑ]l€c²ŸHFç¶îv/qt¤ª½ :[¥§ÌOýýÞ6ä éè­áF2“¶ÿ™ ÷•æÙy+àäjLã,Æ«J5ïr{òZÄ÷ ݆̃§cè‰áÕÏÝAj¿©U¥ÚÖ­c¿jdO×h=ö–®¸H*í%„Sb¡Î¦Ö”2+½22Êç(&ƒCWœdQ÷ßCÅ_%;Ù*Ô ^õj'Dx÷tÈ6 -½ŽîÏ>¿ÇrøKKíùƒrÍAfjxy‘ ^W_ª^ø‘UŠäNGReÈ\®v/ÖVö†¶Rú׌hÉýy3˜Œßc¼b'óÑl«ð‘Ä›k,¢°§ƒ.ˆkx„Kªý( 9×^ÅÈüsk%áIÔ5fð÷ mV:Bô— óütÑ×LmÇIL£F¤ê\@ñþ¬d<?©Ÿ¸ü*Yáv°8/æ6²¬çYF|±¼Û(=<èÝ`[AbÝdƒ#´zäè|œüK÷ŽUŸF¡Öt õÒyŪ)è´rSSd}ë"`!ê÷”Æìê×ÑúŒïÅõ -…d«…œ#£}þÂÀÑÜÂG( ÑhQ/Um+‹|“·^±OI$ѸÙ0ãÆVèþ )ÆJ3ÍLJ_ñ·ÿÑLÖ÷¥Ÿn­Þo”vÒJáØêqmìíçâ%Á­Ãcœ~ªzVÈ‘søqÕ g%ŽQÌ4³æ`£E–/T““?§púyÂå[uïлJ÷ödhºHÐÈÜlM~MTüpÜ„Ÿ[,1|-iÈÀ…´²"ùÄûø„pÐ ŠCCà ˜ÒFŸÃ^'ŽI…42ñÉ…Éš¥†¼*sjx'-ž¯ÿÌ`”Ú¿Èk¯‡?£ID9/ø†h wÍ_lÿ’Z²T,Úy(Â5ù ¡õŒê}ûÈÃ9'¹õ_dÐ]ôAGò¤¬J\YL¶ÈÛ×ÙøǦÀ©‹cÝ›øõNÀ9nÌ;­Åyç¨ÚðV‡., HYÁä{»[úœ„8!\V\¡üè<‰'bÜšDÏgw—ì£;ÞüÒéYÀõ¥"²AL$ý,ÇÉIÃÊrôH™i3>¨¶‡¾sÍnAR~§Þ…vXI³eÙM4.ñT §ÅÔ—³­:×÷öZëœnžŠÖ¥a£ð¬øyHi:štú•YŽÝ’-h¹Ò7‹NQNÅ"$:í»›{fžòO›©¡‰¦œ×µK‚7“½au@J$k-Ç8ÿÅœ*G£uÐð‘ÂF³c|&É}UëVÄNlƒÚ÷‰x^±EJ“9[k<S]óØÝîDÎæ¨ê.Ê~PÓž­üömÍnOõ)-àW…kÖ“~(>@¨o­*ˆ[eF¡Õ…•I@XgL¡Mdæ3•Ï\ÒúÚÓ!™JÕãÁuÃQš„ˆ¸q{sÍÆ£‡µ&7š}ÀKUL»_¿øŒ@ÎÄGƘÅy -Å s?Òr&Fd¿Ä6ë&>N´.Š ¦¾1:¹rP1ûØ——k¡f)ØdQmŸèÄI BÐä5Mþ¦1T¿`m[;­z!î_µ±=ñp)ä5^Išõ@ÑðÈ š¢žAò'tG<ÞÊÁæa¯šm-mn(ØdxDØ‹o=€ôœr‚Ãl( µÔžÀ¥V´êä¼ ‚ØyÒØ% -‰|¿"]ˆnŸ†GhS”C£ãžä.%^=‰Â žš| È%ÿÅ%Ÿ/†5¥ntnt I-¿ÊÍÈ.-ÚŠ -˜4ƒ¿à†tæ-ws(›¢ü À.}!Ë•™ª^‘ 805D|~ØfÌWŸ½æ°›ã‰Å9ãqÀy[eN ù~TÒ€J…gD›¼à%HõŽN´W¤Vê Ü©&QXS²;^Æ#~o ÄSÙÄòQ¯¹Omº¿kÊ–»{.ŽwC«§Y¯[Ý›H¤Î©:¦1BQäcÕùV‹jzˆý“#:^£[~ŒŸ¬Ï¿7ûKWÙ­\ÕèþbÔÔ™î=ùµ„ÔNÎÎ4i¦Èö1häêZ:H÷ÈñÌ«ñ 0¦DR>BÒâ2'BIζ:Mˆë¯ÆZg­tí´š“I:ŽÝA_¹ÂXÿ ¾09¨‘©RI¿b»Ún¹bÕ]¶4 ê¬=/û(ª¢ïŒçÄ„F;–#ã1±¢ÊC»;*æÀ‰®ëÍ­ÔÃÅmQ I’TaYXÉßñ–#OÞÑÓÃÅÓ%”3<¯)>ÿ¸³ÜM`®C;mãð%ÿ?Äél“•òAҬ̊X ÏróüÏXâWàË’Y¤Äi0ƒŒ¦¶zšãÔøª~MÒò¦ôW”¨¡½ ƒ.W³t~ß Xx7 ÷Çý¦8•fÜ®‚’ aø÷¤¢X”dŸ›¿]c5l†i¬ro¼!Q@:Ö1«¥Ä1ûa4±µx”^pj´9KTë‹}¢6[}ßO"ÝJVÕôʼn»ÐŸ|†ö©R<3±CáBÖ°ADæG.îcZ{ÃM,—ž•Ÿ/à ËT@À¥B®Å=‡êêDY–¸Ìén^uÂ]_ö¨€·GÀ›fNPÄ„¡æ}ì[ÊÀž¤/Rø`Ð4I]]õØ Óû¡{%=àÂüc2‰ó‚êì4Ÿ -àé%.@”ØÀÄZPÑ}ú¥ÄÝØÇ<†,2xˆá+„P À:І¢€XH‚9É2¯!I‰¥“–mõ놀)ÓLvÒÀªÊŠ‘¤®­‰ŠI¾ž´ÀJ€-um~5SµÏ?¼‘ÞËxXkDZÎS§ꊿʥ'ÿâA“EÈz©Ltª=ø½¿ˆÀ¯’ëÊ›2{@?ï5ºûšõ¨N …&øºòȨŽ3HKãGš‹6hXle¡ïÿ–kMžÍMxßqhìàV…Ú¤ki1IƒË‹ë°ª¶ƒÊ9UFmwY¥YññW>èYM Ð7u -Ç:êhפ­ߛ֙C9߇¬o“‚/¶z>‡”8Õ"¬pÔ"8f@xk©óí…f¸®söšË‚ý(†'ï »Úƒ½pLjt:1[ɘú‚ËHâûŠK¥Q¹ÞAH)†3W.‡å¬ÉüÖÀU7¹þ"ݨ²_mz$(®$åÔ^ÕìÊÆŸ‡EÄÆvPºÄ¤7/' ìl\du#vتç¾½ììÄ“QP‹qH{Ä$5ƒlíÛóyïd? 2$yá9MLºG%[!/J™Í2an¶ÁœÞOz~ØŠ9@5ꎥ;V7ÎF FsÕàd—ûãת?siÜ5$$éD_j(¯Ü‡ËOÒðBO¿šq€îôN»#.Æ/8ZëùkVŒè‚¹ép›ÆjÕGpéÎØzÇöÛI9´HÓ®"!ÕJˆá«OY¢Úîµ5¤=.J×ø2yØPK0úÍÙÃPI¼ ÌIñ$GÈ^˜ÆºÌ‚cý%úE˜òï„cijñ¼•9‹ž9Ñ’l{ˆ‰$ 0¢w¯¡&jjia>’4\¸ KDÃ{pÊŒ#?ÓA þ0›9 °ñ-D>"ª:c?ܺÚ~†‡^e55¸l -:kb¾ÉLQÒcèâåSŠÛ€ …l±Ã{Y14¯ŸË#Y‘·IUHš6‰·'&:,q[ÞÀÑçºËÔg+ñA¼dÖ/LŒn”•ÿRÔ›”È€ ñ²4ˆŽ7åÚƒRÃoíئS[›IÍqÉÛ³å±FÞéÛv´.19÷Ï.í¥+åh¨>ÌíŸs”q×0u\—…Ãt|<ú§´ä ÞœJSiën@-ø;`®=ô!·þö»$¯ u#îò>(5~¯ìÕ{ âeÎÈmPHXÊ¥í‚_Þ…‡ý”ä¨H*ùÈ*ÖPÓT¼žÚ´_¨­ËÓ9¼×0ÍäúRóyÂò”ë¥k#šLkF@D,}œÐ -ˇ—ÕøêMCEýŒw·òÞPðÃ]ï-¼5L-§Ô²%\ðd*]®K¬qtmpMó¹{Â6Dm1Ð[2m¢ºûw*QÝd‹Q“÷\ÒBq¶˜™2<ôÜå `ve¹¿*9GiÐÍ - .ÓÐ']ÒÀ^Od°â®D—üå„,?#ÞWÖ³bRªv×èSž¼˜Î§ÁØ$ôÊ`mñ 2D=ón“þ´ÁžD㔹=õk½IPïÅvƒJ<¨±ÏÞtݘÍZ´G U^W0äõ¬’”¤¡ÌšÙ=JéSQŠT#’åOµŸ>]žAß÷åʇȆ³Z!“Œ®Íïå>÷Ô‹fÜ.å¾Ó;ö§h gXUãÿ‚yXÛ%…6,˜Ä™T¸«úÊ*1²ö°Ò”"‚ï3Y¶m"ˆ†s¸µÌ· Rþ;ÕõµU§é±8fŠ•ì0A¾Ç¤‘oxZ¼ÒÀá¸+ÊNVkú÷#$ Ë£6\4Štó V·‘D^2'lRw‚ fÈ2Ñ[£Ø߇`Ÿk5Ñs kÜË·g¤Ãs© ÛÂÍÝÍŸ¬B?1 |k6*yf¡3ñÚP‘|Büu+ÁËNõ8XÄôÈä‘¡ù EUQÊFÿµð¥¸ËôiÔ2¼ð`Næ}ïT´?AËÒiÎâ ú[¼5¿«-ŠCLÓÇUY$ÐÀéëh¤®WNÉJB-þ¾ÜaìÚvvÚT¤‡dŽò[µ>Æ–ø|sÔrèCd `¦Ÿü^†ÕÁÊãDÃ*ã%­ã»òýÏŸ‚«ˆ›óñÚ àfX¡6øvçŽÒ]©Â—ñV¤M"BÝèù£=&w>8Kºä*¯+– ¡ oèKᣵ4æx( =¾$h%H -£VâRÑ -ï82Ö&)°"¶E;Ü´”ŤUYvƒÜìVZ9M*­µjQSJ­)‡Ÿï@LH§Ò5Èþ¥ -½~ÒoÍdW)(Ö€çÜÀæP»€Zø¦ÂP³¢½OU®æ’mèß´¨§raäÓw@„&7ìVÛÌyå\çøiÃH47+ù׉L%wÃ8vZq‡#¨¿S·,È_N ŽÅG ÚÅ•},%šc)dù…t1Z’bw' Ý–ˆQÞ’5p4#19B¹Ô/‚ÒÖPº¥}ⱡu±âv† ×àk讌z´?O «¢kês*A„1Øb÷F–o(Êf +^e`˜Ö«ç˜Yªó[c"VÌ{ƒÝŸæDDùÛ„@†€Q"é&º±s±tÞ¤cð>ÄÜÚ.èíÊHÁçÛJ¢b^ûY­&è×`}»'бTZ}¹ë&½ÑÞæa^бŒj7Y¥0ßbªÐDý¨ªN1„á3G¾_²Þý&1UF·b üÂO|=ÇΙדnj‡üGÀ´Çδ.Œè1§ÚÖ%t|šx¨@gzM†ª)dï2^G!¥nÿ¬¡Rý•QE‰)ÖÒ•*Ñÿ}úÖ€ÚûçRTWˆ¾Ü’ŽØ¿¶eŠ-(ÒØQDñ -µQu-W€»×4~Q.£ÎÐ)ÅÈLHQ-Û(èÖü¥> ø|kúÜ„X`Ž×¾®º] #.ëwx+«;.ñml3ÁѪ۰çµsߟ֚ÝÑ­ÍÃà³ -:Ê(׸B®Ó'=êû’ýeÅ9,†`óÙ‡{ß%€ª ¢0<ý}õ¬YâÁ}‹­i@âËÂTÃEóEÎRYöõžN Gö¼ =ã4,4…B™Øi:ò 1tüʼnW¡©Ç½?PÓîºövVÓ'õœ±éÞ"Øì ‚´ñïÀñµý¹• ©JÂzùíž,JøÄUw5ç«Ø«âu«”›<k1%zQ1‚¥[f15À“¤'¦’Â3÷ ÙÇWuùµÐÐ%ßï7iåœG¥Þ@ñ¿’|ÅÇåý©G—lFê¾LŠ Ñîᄹ,¼‹ Ë°—š‚„³³’%MC+–:ôSŸO±ös£]ƒ6&#r´K—è˜#kD—·¥KØ¥ý1ù›Y|£¶0› Ö!ꇫ“tnÞ€ðžUéBN“Y£æ›Ni70R2ÝžC¾«Ü-{*ý“-Ž“˜Ñ -ˆ¬BÙp:©Ñx”Mî§?ó}¢Ø×4¹„“ùïüGßßaWGÄð«àøêÖ -«1,u6AS£áx\|czíR¢€oÀbÐ.P³¦‹Ý=Öö+<µU ZäÍ&zÐÑÅReu–«ŠŽÈ*Yìü”-RGû>çHHn;åSÃêFR"Ìf‡Åfðq¦-#†©cE/NX[\VC`“e’UWYþ¶&ãLÿîC‹Ü8Ëw°šhÁÄ‹£¥±‰¶¬j‚RÂôœ½â¶÷Ñ!/¡àÀˆ´7D­'b ß½¿ë™ÝRȧ/5ÈáqL ÝéõäírâŸÏKªú~sµÀÔ«)ôh'¢Ù`ñ:~­(IÃÕmc+Õ‚Wo¿ZåX˜§™†öŠ9£›à„V×U©%-½˜‹c현Tü’uC|ºõÛ$Y~ˆ^(c­/êE)^Ì>,­¬ˆ•Â‹Ùý¤µ†ò\Ù9Ï—›éu¬#~«ùn_©38ŒàÍ^PCÑ€dp_:»’óÆŸÌ·qÙ¿H(Yï7çüX{yÊïŸw[€°5zf[7 "¯sÅvÅô̳‡Óá2 -[5ÖðÆê_ka‘¢Þ÷£ø‘*q¥=¡R4Ð/@™jÂHµ0M’$Ùþz„ -˜É¦p8çˆC¡·š•òÏq0ÞSGD¼ÆSâT2J¹Ôi­¸É½°½äA iÎáDµ9)î“>oâÚàЂ,®DOͺ؀¢À¨&¯¬±ßŸ“ãùí„í½O Ä[¢:&ßQC—Ýåy˜1ŸÜ¨^Nò`ϯȌ)†¬!îÍÓ¤~»,˜7Õ$á/°Ûº¤zé5"™4¾bø–ˆÛM]üè»o~E®5p‰ñðJÌs¨{•moœäÜ%Ö¡A;›<Ñíô¦óñÜý¦¦@=®Ð@ZR¸ôGv Ö}¬ÇàƒO³þ›§—ÙA´|:÷©‡ž™Ï @pmðïÑçñ€R Àw<—a°Ý½7#øSBG8-(v> Û žq<]ùÞÚÖÁPdöÙò @JÞâõ•WÑ2|¥ —Ê„s’¨Ê‘i% Ìî3² °6“NP&0ž>>ÀI2åOø®¾Ój¬ŠÛ¯)ÒÀŠÜÚJ8¯Öß*fzU;.ÏZÜ$ÚùdL±’Ïëì·~‡ˆ‘#_Úq@ï1ÓÝ)§/f V¤Â†~’ŠÕ.-e`Yë1†ˆÅ&ÉÜyS¬S<Í„c)fœs Ò†fÇßyã·=%±ÒD=°©lø” ⦱Wèz©ßš!ÁÁ™ÔÊçÓ_[éŒÌ|œÐÕzÂõlkÜo[Ö>ððã²æe×ÕX¤ñîÎ×þ_¢;ë#7Õ ?q2Þ|~€\áÄðPëÁ'i]°Ñ®(”Ç¢:îšÆx7I£ -×D½í¤»a £ªâ*¶‰ÂÀÜÙš*û(Œõ¤qÁÃåäÌ°[¨.xÔŒHhý {§ú·–æýy澡:ÔuÓçg¦¨÷œ4k ÜÀ=ñïElD+Ž9Ó{û¤Î=£n„ÉÐE:xª»n½†í·ô^j>³ÎÄpbH4_de›Ó^S.t¾¤™_l¿ 3)VÐñ,ÿ²8Änd2€ø»Ì@צÍ*€]ÉãhsÀž”nä¦(ºÎõ§ÕŸW‘ÉÒî#ÐósD–&ôؤžm<[ã Xp.7ôâ(5%ö‘ì>B8‘'ÇÏÉÄ-ŽM%f+ùo0à8}¤{+Ãþ/®ò ¡‹pp… ‚óìô½ÙW¬ÒCF8fÎÞßòä6ŽÓ‘æBVÎÒP,-{DÞBЪðß“úé,¢îN`:¹ ¾ÔŒ/™t>¯‘¾ÀýÝ«9Ñ>á…‡]`5TæÑ’zûvyWX2FüºþbfO–f§>}al÷¨\ÔMê—´ìù¥ìâVPÇsp¥²oøâÇШ›x¨³N O_Ž»N=𣳧ND˜ÿ«ýzZ¯@(5Ic{Çv³cÛ¶mÛ¶m۶ƶm»Ñ™w8wóÍz€ÿ~eŸYçÞ*D+_—‚#ioÛçT¢{?Ø Ï|Xž!ÃS)Ëb×ß[ñ_ˆqM`Õ|)é)vÉEåN”ŸmÝ­ÔâÑÜêCrçéú¡]¶é -ï%,3”1•äœJñÙwG¯üûñšøoeüªyDhéNÁÁϹݎÓRþ ~¯›GßB‚\ÌŽ™;؆r•R-ŸEGT±ùø°ãѶ÷Žz ‡¤/z”Þ‰…3 ¿µf!KÜt[¢áqQ‰(¤Õþˆg§þ¬EÒudV;~_€dr‡çI;17 a £ƒžq”„)b±¿²‡s(…0 -IfLt´& -¸Õ‰]ª¼ÖÀ·ü´¨ˆúWÓž•N€ÓáÚ îËè ¥·I­Ñ—Øü:k b-F”ÛÈØyŒÔLúcÙY># S·ÿý¢žæãþx5¥ÁõëU­N)r×&O¼ë‡hÛ‚$‡Øöñ1j2Ç< up& )æDÓ˜‹Ô9TÌИϦ]ÛûÑ)Z‹HAJ›0ø¼vøg^V}o2Qâ -ŽsU ? ë{x[òq=4£øŠÉTññbEK'òmç±v§9ˆçì‘È$“CXcþ©\“±>ÊG˜m@>¥¼lX1 ©ô¸dwO AþŠEÒÖ’±Sc¸I/cK+–5>¶V‘+"zg1´:Ë™T¤þÎ -*»åMì•¡p_ÐV—+}¤ªÞTžY!æĹ(K§i"üÇ(*wOzŒF®¯’«X`Ž¡ÿ­Š¢ÉÂ9•ûóV[h#´$$£¸ -™*r[¶Â—n³î+ˆm•€Î êËÜun2qÄi"P6h£.ü·T”•OdÉ_ùüånµ~ ‡q#$i5’2ÍçšuÛOÖL[˱ÙE¶IkQñßå:¢_é²w«®º!É·Õ7ˬÞýóÌlÒλª> ^ØH•€ þfuĶgŽÍÆm4N}ÒY‡‰Fð/þM(zK¦COåúë·½Ì\?½c<'}ÚÞu*gi·êhôQ´•Vhš»7ª&º=è8?NI@ý ·Axgz¯fckp5[ü>À¦ÉÍ—>ý®ÂóKÓL†™f EÚ³:â£]åÕN³Äèx÷ú9,Ѓô^¾Æ´m=WäÔ>x ÷"9N‘Øyw#DZ.‰ÞÌi*„¸úR/ÝsF©ÚPS.çYŠÈòŽfb-?F|…í-¬{ÝOžà»ÛTháÜ=ªK8[9öMâ™ÍÃßv\©«ù P$€Ë~*À^ÄçÝTŽ]ÝLyî O¬!±KÔŸÒ`ä÷þ;ËQyC¬¿k¦ÂËᬩ£Ž” Â_Ñ#ý:{;„YSý5§È9N€˜gyä¶~ ËsÐ^Üûlœ'Q -žº²Üà9UwgÒBkÙãƒËÚž½Gr˜u)ÔëÛß°û„{¢T?,Ì’xýà‘Ò$b¿ªép×Å°·‰©È{ÃXá¤,#½ÜPÝ"QL$*/éÆù£ˆ:ÿxrG­Ñömi´Ã. DêBU%ÔEñï˜Aàâ»ÿü V¾£¥Úö°±]àÚøÖfâ¹›rƾÏcÁ¬FšF"¾7+ZÍ4´ˆ'|Áaèp›“GLÍptmL0°Ëd™Ò§l³CÙÊ5ç²k·›™²u•†(¢^§Ì€SÀóþtJ̦ îÒù<‰Ó¿`—+ƒéíÀ~Ûf&°üØ̱iZž\|¾ÙV?P¥QüèçÍ6GTqÔQ—m¡’>Ú߈3ßþ'{ãËDˆ/Ñ`ˆÚbNŠ"{YL¬ÇY‘Ô¿†•†´É»ž8 UÅt"gæ´LþÊÝ»åE´;aw#"‚Æ`l1naO)º -èòÔAé›ðöÖ_ß5Xuïwo%~’KG`4÷B9MXÄ—›Ý*¬â=cÉwú¦¶­r±¼§˜½ïÙ ÌèÀXmgsÌ{ná>³.ëÀS±¾ü¾ºÈÙ”¦ŠQ®Ÿ6È4ȤÍzÚ9Ú—¦Å÷K\ ìkCì«›!ê;àú¸èy¢Å - -"¿‘©ÜŒ˜%(–PL•„àà}çô—ìd¸A4HVs_™c‚Ò„µÜÅ‘nÜŠ¡Vz*-‰To­”â 7*úï #{y‚íl¤â:n\Æ>‡áos.ø¨ŠsýE×õ©É¡Ã<äm¶ E±¸@ˆx²îkrŸËÁ}G=1ôƒNl.&·´Mf‰2À4îۯ0ö€6Ñð G¥í¤B§R“Bt•¯º%õĪÜ~ç$`XÞ(ÿ¶ˆphíÒ[, ²·wÄ.„ˆØeæÒ$HÃù”±åá<€;]vÛàr Öù›–ÞpuU“J¯ÐœA£½<ÚÓ¤ïõV1r¿Â¥“e8Õè7Þ)h(²¼Eð¥GðЖ„ñ˜WÒMæ _Y£õ‡æÒËfcØŠ¡ÌõCÒ0—£Û²u—§§äùp3¦~ùÌ[yÔ5!Áy˜Ý Ð-¹9¨ÉŠ%Q-} /DšC¦—jn¦%>HLgùh:âî…¶Bldš½üuô݈°½‹IÖ#o½¿ùði9žìtå‰ò2¯̉ê³æÖ®Ê2VÂ^­.îÔ -ëÿ8±² -òo·Ä‰è8²{ãqÍED§G×æë±ÆöåÜbùÜß°”\&Ü‘ù­òÏ2qsÈÆ°Ûy¾>bò´ÌOX(oÁYÓ‹Þ"4Ù†w7 «~Lé'ƒ]‰v }Oä8ÝMª)Ž–X’EÀ,3bQ*ÞWAš 0 N5<_8%)FľJVßr”[‰=Wÿ:¯&,o/ÑQƒ+"%N†êémü‡*VtŸ_-’È°”´sPàkX‹'ÙÊ‘FâbMüzyixûŸGG1SÝ(&¦F›Å8'Ç9qr«E™Lôð‹ÜÒ{î}pJ‡ç"3„žœ®NÔ1 `2SÚ;{{ÿÚ«”ìŠ÷ ÿŽ¦Ï˜ 1a|67¥œtؽ_”½áFÜ•g/š:EšR˜3²F (´†»nDM†ÀÒUœÁÌVÕåq–¹4òBä£à?;±¿®Uy7-Ò¿£;©©D'eaè;Å:ÎCÂ)n.fï&#–œ¸ˆ2?\Î2 -mÁR!/¤ïmYz'Úò”¦ÀÀh'¨1I ÌѨõéI¹;b ’@\Öq×Ü[¤µ*ýôF£½™ÃØ»ÚRqõ¶›0ý×nD%ŒãßÉ€¦ ]:bĨvÿŽ“U®ïqî{ĤgÑ5Àee4ê}ââsë?†'Jïg/žÄ1àÞ¼–'=ÌNŠ³)—NcëULtbðÏ$ mw?:ji½Í€E4Èê6öʺµÉm>·’ºS î¸£”=~ø$ÄV9N·€ø.Ü.®z;…•ý37Uxõò~Z–¥]5ä´Ñ<ÒZµn•}—Vo)I -Èù#†ð÷†(£ÃÐw¾áR¼­ñ¿ø; h@À‘Ä8~©Lp©™¦¿RÒtª3ª5/0Ò¡S0±nÍ&9=Ó ÷-Áz;¢IrH©3©Òpdl²l[‹}B¿p“šÌN2ùòw Д˜…¥UhpO·  -FÖ—bowÖç'<{†Ëe/>w¤ìºO Óyf4,%[n‹¦ó<ÑȲ’Dø¯7XQ`õì¹;ðkgýÑt{D¯VC|n$è_ -5±)Ä;À†íkPAs~6wD¦l¹Y²˜'À&>)Ž:•„ΊÙtAʘxñI…Å©Ñ’"Vï·´—Á}“Ôl—Üœ2Ê?«RÙª¦» Ñ2ø¡†LŠ¶Ð*¥ÕùÏ•Õz¢W¯íPO!Zñšâ:¡••3ìv{´3:9¨;8 ~†»Gcã–XÇ*ؾƔrõFÉ×<ͤŸ”WSs¤ù€ûñúóRXÙlN|PLò4ŠÒñ£l8¯´Àøî[ë†4 Àñɽ.zšcF­{ý†ÄT¢¸ˆŽ¾‘Ð[™()ä ‡¦f¾ÆF£ðÝ´Z"gº…´>Ôæ5âµlÏâ,¥÷y”¦Ä“1Êe]#¾{Gš!ÓK±¾„OÍ÷¢ü¤ïï!Œ^{ßðÉ‘F'U0BBo÷LÉ7„ob¨AÏqØ5ƒ£&ÜçîYd5K­ÜeíO%:Ó 6™zD-߹̫\šM07œÄûga\)³?ÎÍØU>Yë7“ÚNÿM³ƒ†yŒµ¿_asáL³í|¿Œ‚Ñi(¡Ñ›à¬ìz™XHGªáO\DzŠ~o9EÁNº>¨¢r4!Öî€1/;{k=¾·¥ïTRëö îì½:¹c‹GÃáÐÙaí¿[ò!É­©Ð†Ꭰ—fÝ}†c¢³R[#ð:wAò»p@‚Ò@NÞ†ÓDùNËöî”yRbÒ%y™ÔÌњǡã0-KdiÛBqÁ+a`½£é6!ÆìÂÖ÷šóø53"%)k(h0OGµž32Š!¯‘¼ù_“Û’¸6fÜYײ#–=MBùBo)QI¶ÍE3Aè¢öh(‘‰±9ŸmûÜLH©*q2:ã¿}45«1Û¶*…Ë; õq4—ÉFeÈ»r-daº’õ¿×X}ÜÁÈ'ö ‚TjÙTûõ®Bç’¡X5>¤hŸ`Ÿ" ¤pñ5Ѽb\*]–Ù“»$BößÓžøãÊL½bð¨Æ@¶x}€×)j¹ïÀËŠh4HÄlªA§k7÷¥ßjMó*ùf“VlÜ%´þ¢.’£uXà}{ÁoT˜ ’ÓK7ú‰Éñ-5?»™ýuª¦ý5G¢M9|¬à+´¡ï˜I¯qRÒOÖÛ‘ñ0Dç"fb×a²ØtÿV¤Ÿ@-¿«¤ÆÐ$u².~@baæ|*¾ê3©%…îG÷ïã´‡N‡ ‰49‡˜"Xˆ¡|S¸ßÌFÉW壓ô?eÃýåL£Ø&tb^Ué.¸2N%æ’äMÖOw”¯çe/Öʹsê"›Y #•|mËMsßÒÉYàœÑLLz™63<>9ŸšwßEBèˆU¾D¿îÁö{'÷·n‰æŒLžkp±磚‘rôCÖP€³rúgœ§câˆE$kš¿Ÿ,­×©à>€ü3ªŸ2ÈÛ=cuT¤ `+š«6E@éú*ẳ~5¿¬'Z>t %š=:þ¤RŽeìþ«nO»ý’y0HÈë4ÚµüÍ‹;ô¨K‹iþzª -¯'l­Õ_‡2›.vèKâÔ€fïø¯âˆÚ\ŸÙÊ¡òËà.¶¸iAìU„‹Åss*’ñªÛ -ó Ë.ºÞJy'k<¬¾T¨u®rï p¦±2Äéyš˜¾Á0^øÓí ›H v,¥wó!éùž1ÄVûr#Âp_JI´¿4ŽÎ¸6ú˘ì{2{ã• <[—)¾Íj°xÔo~y‘S¿mäó¼—¯ùh§NWp¡Q2¬ð‚‰>÷ËgCX ÀõVUé³½æ·ÝbM†Ðñù6 kh*†4¬† ·ÚTã’#­Ò<÷òwHÜ2ÈAœS¼WR¬v"«¡™Ô1í2•¢¨¡;ŽÞuE@L ±Âà‘Œ”ª^4þÕŒl«áÇü̺-€¾¨“\Z™Òçtä %p´§”î–©ÚËjKûr¦ä¦¥Æ¢[~ÕÇÆêþÕ&÷»6øxŽÔߤÐ3òÛøñøíp…ò¯Ý@åjCŒ,:°”v—Vj¶ ’/—4â3Vÿ¢§öžÛuá<¤ÓÄø -Z¬Å…Fv˜fU*¬ê&'°áÚÑÌÖÿ«&45¸h+Ë Ch/äΖãoýÓ(…§A]]fçþ$ni6ñ–ÖaöqRÜ:¹µÓa¯yÌ]¿jñïšëté¤ÜK…ïÚNÝR/RàÚ¯{|Ý+î8|H@bÛr®fEéÊl.°_½€ZNe‚œæ>>îI”¢kf 5ùùª‚Ÿ»ßÈy˜Ë{2LC6þ¸ôØÅ~Û5 7Çíí=E4ÅÑjè!¹A=Ï·tg åƒ&%§ƒ—!~T‡ºÀ–¾U§/T1ìåoù¾—±Ú¨¿L—7ÛÎ…B»ñúð©JIª‘Èã¬B6ÂÀŸØ2¥7j•C†Ðâ.ü”3"OBv U‹C9jEm{‰ü6ºJÀ¶¦Gáà•PŸ… Ù(úV…yÄfö·› ²–“mTèÁ’½ú‰L9--ö´»¿sµx#¢ª}«q‹“Y*ÔV·ôZwa§:Tu$~ËÇ!5‰íåBòdô’µÀåŠWü©æºÍ”þ†ëÞ­ËêJ‘kíOµUEÉ0µ³ât¿yÎhÂRUO©x ç&<)O±\b:EÛôØ$Jpÿ‰–ÎÍS|Ût 9–dtþq6 QˆÙéDÐIÛß0âFò'¸JÌìY7¯»°:}…çqy¹•·ÜçüŒaÊ~oà韪Àæâ6°c5Œ#MóbðAÖHa5E18G:*ï }Ù5âìħϪ•Ü<—,$l]ղؗô ümn]78TÓKrº -eÁ½õiÐGÓ8¿ÙñCÊI´‚¥º]u¯˜Ôjù -JtáBÊk(WI)Í’ˆÇ ¨kFîÈJi…Õ FS„Éãâ…—¹l;£—¬(¯cgHÖ5§ýUj®¦›¤ÞNX*1a"˜…J[å?x¯5Mï@ 7‰íɳ't"Mrmc §Õnœ€rÍÖÔ<.ïo°öÝヲk¶åÎM¾×ÅŸ“p40¶Y¤ÉçŠÀ^s ëµ¬d>Rõ~YîZ_Ä둹v0§Gm‡‡N®3çï7G$*›½th•ëùý¹¡Òg)ˆ, &ƒM€¶ïÎ3«yÔ&o¹Ù›ïu–ž4«ô,öZÎOkÜ÷ªÔD%«†Déz¡v?ò‡/óÀ; Š'?§îºËcšý‹Üè~Ü÷.ïs -µ(à\èaª -E‰7jŨi¥oòƒŒ:½úþ·cêSJo*>»u+Æ#@Ä«áb\[k!s&D “‹Ãd`È´Êëš”ïhc{·5?ú¡iiîÅbx[РƒÜ¸²à‹™÷̾`_rª»“ž!R4>‚K]J…wvýqL\¶Š– þ AÓ!÷¯Kÿüê@7¿-ü'²ØAAضӃÖe ¢Þߺö;ˆsôÍxyÈDUE…ýøsÙæp£/kït6ÎîX/Ûžua·Q‘\/œ;^tøÊIø&dÖC+ƒT&a“ļMØ{$UT‘«ø.ÙN '”ýBþTŽiÔ|us)î³”n2s2tLn”Óš`$}ÂlŠx`j6#Ô—Vn3DÅBƒ¾Üâ")47#UtùÖRÓ“³8‹û‡mÂq¸ÀVôYÅshž£ºí¨ûöàÂÏÏûºyžkkÒ;ÔJÙ/c¯º6ï,ø4ë$ä[Ff&—8ãÔOø0€#›ì'L¨âJá0äï‚ž=Äï y¢z¯ëmjMU(0i´ÓòÁB­úg”GX¿‚rë•{µ)ùºà  ×·f"Õõ®‹‘†­,``ª“}BT]ºˆ»Y®ì}Þ´¶Ì‚i•Æ´A„]|(ìÓQÍííê—ÉH8ï -j!H·îà3ÁE. - ø!{mž/ƒòZú+p%Œ«u–}Fcí¿ èýˆ/ì…Ƶ1>§ÌM)ÔÐ O%Sýù8½î×Çâõ‰;‹¸¡Û#;üe,ã ’ÆÄ\õ0þ#tÎȾ³k훯"’ÃÅÆ{Ã÷âJÉt¿R4ú‡£da`{ó‚ŵ_Â÷ú¼*S½ŽµÁ˜¢eŒñ'»2òãTÊÀhÜD7Ð š^BðàF°²•B„z@jø­z„…Ä÷z‡=éYU¬×:sB®gæ#²ÁÛÔE·Ù"-‘ -dˆür4îŠ$#œ™/à·Ñw $–+3¸]Ì„5¼T87Å]ý—‰Ø¥–…ZPŽü¢ X¥Ì[šÿ8™XpÉþCi€ó`KpmMƒ*­y¨À&ÕÇ*é\—l¹ïˆü° xr#L?)¨ù¹kvü¯â|V{þ–aÀB$ÇÉÎàj`ñh›Îëæîõ­QUdj5Ë$k>7¦|©™¬âÃöõÚ¾¤,ˆÇSÎbÎ=¯ 6¢ŽIÛž‚2üúð?÷ò)CÎ|æ¡î0)ukt ùþîo#‘Æ$÷s‡³Wgª~„ŸÙñôÀԥ;ºaâlèQÌãæƒhË›ƒÌð`¾ªD`;˜ßl)Zþ¸+‚´öœ¸"nƒbî…•Wãìˆý2@4Jn²k‰Àüš>,¶èŒo¯×ý½cSò¬‚~NDD«TNo,ŠYv£ÐƒÒ˜÷-R¢%d¬ò™êe‰»CÀ÷ûú”Īoà/ŽâÈüo%×ÄR’1Ãó—G$TW~}Úæ¾Ó¬r' i kI -Z®§Ñœ8Îeä¾ÏFþ±Ã,ô\5ˆI.èÑaM 4Ž´mÇÕ‹èqWM‘±•î·egcØøí «\[þT -¿Á…æËU¨—xÙLDÞsäÓš¨Iÿµíe¬ âæN™V¸åJ‘ÑÏn§Y ÎY½–\fÐN€¨ ¡B‚?&{¬D·š‘zµÝ¥å -Iö×~pºóE¦f}^!˜tQ°Ù’‹ƒEäì>‰ n|'ÆV²5D9_äå‹7â̬FJvõ˜2È­ÛŒ’ý;Û£K¿>Z&ú‰Àš¤þØɉ,-¯,Yت–=–ÏÞáÆX8?¸#…m èÓð¥žçßèðž–u¤<5åÑwÒ6¨´ÍÔ™­×#0±q“²Qý‰±ÀåÙëã=¥—;1Â&<ˆ2’¨ਛ4ÿ1=´ˆñ¯”uà t jlÔ»<$¼³lt‡7¶Â~ølRh¸¤Â…ò^JÁuò‘{{#Xè -| f Ég¬,=‘¥vp‘·xMŒé‰_b¬5 -µœóû¿ µ§öÈ4¿À#è¸?§ß7LíXʳŒ”ñkÌ€Zî»vSLR‡û 4 ƒ?&4 =cwÓ™7mÿ­8 ‡L¡ž~šËmé0Rƒù]N9ÄO:;e0vÈ(©6‘÷ôŒ÷ÃæÓ=ÔèÖ‡7œŠ?­)Í'á ž àÇ38ƬpYBà³Â|ƾC¬D?ÖD‡§-QÊ(6ò˜¤>Œö)€*#£˜òDUdùªé³ÓvU‹ùaaæ6#÷7M‡jƒ8K §ZøP‹øÕ‰ãw© 3ê±,ÄaAÅÃÒO¦Í•Ç½,R!®(e¡|ÉÒj£_µ3b: ö[Ï㥻w©{Î u\öAøo†êm¶¿ïÆñ’8ÁX˜ž‰’ÍèQR^ÈåkP’AÛa—ËÚwÄ*ù™ü óñ»v̽–ÆÍKy ¯_È„&ÕýÜý|ÚòK6ã¥L§ñîÏ}¬O?2Y‹gl$mÓ¢ÛÏb»\feþ]'ái¬}n¦s+.Û¤TíD•6s²rý ´ ·†döNQH瘊Ø3Âs%´‰ ƒQ”Ìæç(©mIÊé`1‘rCÓ)NòÒB‘,›÷4JÓ‹d—W]M„=beÞºe(Ë ÄE&›fg¬esÅ ×"tO†2ÄÎБ.Õ(îõâwwÓú¨e¡Ž Úà"šm°Çó" -¥í’bWWž^¿§M?¼ªßªéë;ëš<™áh ±Kñŵž¢¨ÚÆóV1îcÖOÏ "ž³x4tÅ:l¼t@i×uÅ«»‡‹Á0“öë]RϺM'Ü>Á™?#ÉABlž=fÌì…ïé ÚiózõÔ¨¿!…+°2Ô’Ýzôµ¥Îb—B -y‘üP'càÜ^M#R°·ñÃ4 {LJ B«œ»×ën¾HïŸMc–9|þ*S5ïV®ñKãÁ“üvÚJ¦‰‡’à°áR‹ÁPKw©ä;ÉͳðåH-ºOÖ²ÉâØÉ*Wü—¼éýšö•p…+èó®a7AÔºº;˜âR·~4ÿÕ|S®‘mƒ®W•~ ©Ãâ‡}DL×WF5J‰åéØ|¨i÷>#\2®˜Æíß»OÍß 6.â'¢ÿp$iÊíù2ŸÒ;LÛ–Oòá ±Fóyº)‘ùµ©ãà~ ¥ŸC¡ë­„aø ÅÑ«¨ÙûGæhg [&óâ<1—Xû²Âø{iª_“¸bf)¦Œ²§T˜ ÜÓ»GAe!ógF玦àUa!*ÚZ0Ÿðç/è a0¼€ž~£œ†äwÝo âïfŸJ³xÛw® ÞaÇL¿õ0 è^š `8¿Ú Ù4Ùç÷ Ï©4†V×"”]BÝ3pþà·½_) èIÞ\H$séåXŒ{Òb^Z,ÃÛ6ö©ÉÁ ¬–R2µCÇŠ‰t(£ˆOܲÓ7‚9òó`e€² ä@y%0júAÈëRÿ˜à˜~xƒ4wÖ5çíÂàÖ±åmÝÓ×â}=Ð’tRX[>͔ҞÐRÔ "çH³l/é•_r> +stream +xÚ¬zcteß³mlÛN:¶“ŽmÛö‰mÛN:¶mÛ¶ŽÙq^ÿþWoÜ÷>½w?ì1öªª5kVÍZkœ3Æ&'VP¦4™Šìœé˜è¹‰T•Ô ml M,2tB¢¿f6rraGSCgK€ˆ¡³)7‘º© ‘ˆ©133 9‘0ÀÞÃÑÒÜ™ˆò/ íYþ !2òøÏßN–ævD_\Mmö¶¦vÎ!þŸ7*›š9[˜™YÚ˜ Ë+hJʉQŠË©‰›Ú™:Ú)¸ÙXÉX›Ú9™R™‰lþmAd °3±ü§4'ú¿X‚ND†DNö¦Æ–·™º›Úÿã¢%²7u´µtrúûNdéDdîhhçü·Î"K;c“üµ›þEÈÞð7Âö¯ï/˜ÀÉÙÉØÑÒÞ™èoV±ãélaèüOn'Ë¿n"€ÙßH€±Ë?%ýË÷æ¯×ÙÐÒΉÈÙÔÝùŸ\F¦D&–Nö6†sÿ³w´ü 'K;óÿb@Kähjnèhbcêäôæ/ö?Ýù¯:‰þ·ê íím<þµð¯¨ÿä`éìdjcFÃÄü7§±óßÜæ–v0 ÿŒŠ¤€ˆ‰ñßì&.öÿás5uüWƒ(ÿ™ª¿$ Mv6D&¦f0 rç¿)‰(ÿßT¦ÿŸù@âÿÿGäýÿ÷¿kô¿âÿßóüß¡Å\llä mMÿµ‰è?î"¢.™ÿ#ØÐÖÒÆãÿþß#ÕMÿãÿ EÒÙðo#íÌÿŠÁHÏøoFK'1KwSKgc "3C›¿]ú—]ÕÎÄÔÑÆÒÎô¯šÿj$#ãó©XX[ÛýÓv¶s™Ú™üwêúq9eMi-šÿóFýWœÂ_åU<ìÿRû÷Jd&ÿ¹øEHàNäEÇÄÆLDÇÂÈô÷ÀýåÃÅÂæóÉø/ ¦ÿZË:;Zºiÿ-ûïΊÿ÷ç¿Vºÿ FÔÎ`òϬ(;Ú™ü¯ÿ4üã6vqtü«ê¿Nüߢÿcý¯A75u75†Y_ó[¥ge8×aæŽL‰hô1Ž„Ø—6ªø×zýÒÃ÷¸* >jCè›f¸¿Ú=–ÛIQõaØüèM5½ÎÇó!¥ê/@Þ¦èä 9dÐ+…ϸPöºY’ÙÓbgT;ÞŸRTÒ+ù€ÀŸédq„ºùCåOêZàFölàkœÖ‡Þ…Ô„RWøû‚"éìÏó¡ñÑ‘áÞ;ðþ#\šœ8hrW0xŠ(‡\~-Õ +Ѫ&ðëöÜ(ÞÃÇ‘œåRMyû©i¯MH>c¸¤bq›‹bgÜë㤸>· +Zµ‹¥{ü‹q=v¾ ­™«O¼—«Ñ)X!íÁ/$ä±)$§ÁØ^‘w?í¦‘ù]€§“X.2)§©Êer[¤ .©»¹™ ;þÄýI‰ŽBà A¦¸¯»àÐaÁôÞ®|û³ 5ï8sêÓ†~Ð2V1z¶4l§ÔU=¾´<:¤¯cg°››ì°Dƒ½I¿8ÂNëù³l—y–^›oQŽ¡R]WCÁ¤œh4Ä3LdkÓÊi^Ÿ³û +"ŸÍëã-ö .TÞ;”Ïè*Yp§«© ‹ÕÀKÀk" !œÑE¾[OžKA3æTv7‰.ѧü™"Ç S"V™bIÆ@ΖӧêAžAj܃¼DPä1»!òp˜Ñ_;…qÞÈ°ÅŒW E¼k‘‡ìæêA¤(=$dd$p¹pÅå=qdÜ@ÃfçÛ%ƒJÉ—,Jjº—{°à6']ÝçÒýiÔnÌÔp=æˆu˜…îF'vù¥ìJS½£+J…½†íV†q’gâ:Vt×Cyò>½â¶Ä‘ó+µÜýªÜ‘Ü”µDØ[ìÖØÓ"tiÿbU-bqbÉ`¨ÀÞ{œ©P¬pû1î~sl€ÌmÄdPãó{a!Vî'Òa˜º{{^Q‰ÈÏú›¼<²Ka‡ E|:Ò—æ=E¤M•š'Wl~(ب âümù‚£E¿û˜ÈÅÂœ‰“8ub°†Éðâ%Cä%»xzªÀ¸Èûj§¢.²_×µ'Ô–#m÷—…€GQ3ή‰›ÕyW…­"ªÑiâ.m¦­À³ì†´= Ò1 +(g¤Q5Cû{žÒf[óÁÙ¡ä=‚Céª]Éî•.Òf›Þ%tP7–ùz;7d„Ôär&ö½¢Ói‚Rê}bÕ %\غ²c±â +áê¡טÞO¿UæÝ¥šÑ<ÑmËs]T­+¤O˜¶1¸¶ðææ#¶V0BøkÅø‹‡ÙÔ•º]Ö²$ò}‹ZZ–$ëe1¯¥P¬É}éîjÀ(RŽ›¡ÛDZù4 P™ bw×4ªeÜêI™A ¿RñŒ24§iÒƒo•æ7…j,;Ù:Œq«úÑNèHåÊÓBuNí|ÚÌ +6q!#z~`i# VEô yA ã +5?Ä…J‰¡?‘–x°Š:p´xî@ŸË*£WƒõNQŠÃómƒË@bÙ‚ÄÛ6=_ïc¨Å¨üÐIûVs/D–)h=[¿°J›ÔðV]èB¨öK6J‰ôÍî=®µ5ðç"YAr1äc¶Ð ô¢.é1ÄéÀy²†_Õ-ÿ)¥º*™ïH €Ò°@¿¿ßå|Ç1SsüîóFXF¢ÙB¤þŽ0¶m粿R‚žPï[#@U4K£»åí8c¨tÜÙÇUmÌ ƒz‘HÌkËKÙœ¨ÈÏC—ÝœÏÈcí¤šö‹›êÖ¨2f}ÄOÇlÌÒ5" CffÊÊÙùcÛ{Œ6Ķ7ìÂh|Ç*M²×îƒgO¸á»‘بˆâÇ5Ó¨ÒÃBäéýgQNS¤Nc-aAÆ×ïI?¬íG¥(»Vó²rà> Pþ ù[m=à 4Ê ´¥ó´6.xŠ½ó†ÌqüÏž„ˆ“ØË\xÈ"O<–áa3³õ™ óeáÑ[³¯—_¹H©€²(׆­˜-ª¤Ž"†êe„ƒtœñVà‡3Ð[7uÖæ#:pÖ@0ýÌWÞÉC–)ƒ’²ûÞM0î-Øä7û6Û0 +Ú 1ËÔåÈa!ÍzG*ìç-Z±î-®»°…}§:ÿmpÄ¡ŠžŸÇ›×_bJ3f†‚X ¡ìLmïÓ€àT¶o¤¬F9Ã[9/ÛÏy­Ë:€˜.ˆU ”y„b+iI§I·ª@fÓÀS8q4ü.ý—Û `Äçì*rTœGTXÇ’ \v[t5˜Z'÷ýò–Sl§‘™†ŸlÄ‘‰‚VJPzêH¶–…ªÖôÔ™ßçÊŒî|÷~E¸îë°ÖšùFÖ¼‹"{ã.⽺¾Ð §.5Õ Ô ¹ö(näzéZ¬MôNîþ +Éqž— êhËÏFÇ=êO”ù+Š<cÁ·.üIƒF&Tfj%v}Hæ®»º/Þ‹:€…tq>ÆSþRL|žíl}„¨IVâMˆ³¹¬|övW£UEqݲ–^`)d_„¯×aå0áï' +µãJc 0Οó•wê(á·ŸK£êÅ¥Ç<ÌDø¨n {AVÈSb˜1’Qêg aW¾ ¿á¨À+:Q˜šš“ñ‡m¼º…·mÔ îy©¤»\pºAŸœ,)üE»Ï Êüœ‰Nó í—éEgB†Ý·ÚdŸu5C +<…:0µo$V éÅŽi•Ú¤ËöÑÇÑ.f ó³X©f‡¹5JQ·&– %CDÌ\jö˜B‘u/‚§~;kµ$&yU]ôʉۿæIÎE¤Š”[šÜ¤ŒèGœç³>JýjˆÌUÔ‚* + e«1‹ïmÍ°–7p¤+’qy+EßÄ[·ü5ñŸòÀ^îF „}fá•Iû~c”sÄŸ[&ž¼‚Ÿ?/žaÑvãEÎY\T{‚ëv<ŠtcûpÚ¥AgÒg ]`ÃʉJÛv§ltê- \5©1&딠丯¡¨Mٰ݈?T™ðï.™mëßýߘVý4ÄK/Ññ“ê4„ T²(óìï@ +ŠuüìKœã!¥}=—à|ÖÀ¬B®ÈJH‰^M(B ¼µÂN8`æXG_æó"XÙ´èr6á`MÞ5f¨tÓ:JëiLÙÓ{ôx +קµ÷YÏÛP–™­Î›ä‡¸-f: ƒrõñò;57ì>\ǵ¶ ®Ã¼}8&;DPí…eªî¢W¼'­vb‚)^n߈§'TnÄ/üôÒ±¼×V·J +aèqÁr1t˜9f»+ (*‘³-ÃòèRö£½gè–ß~n)véâlOŠeøÝܨë?PÃ-L¿Ol‚€qäµê=¬ŸR©Ì…×9°­zGB¸w{&=GHÑa*ù£8uÊBâŸèÎ6ZÔöŠ¸ÇÑ>Õ‡žC«ß]ü®A‹—Ú!2|XIœµr®5è (’v¿+ãïùF\4“®=åpß¹ÛÓt8RÎÀàx“š›„ÇÕL9[ôiÎ.¶¦ð Ri£´c=S‚<›1ÍÆv¢§6õÈ™\Þ²©Ôÿª +Æi2ÐÓB¥·åÒ îÕ±Þ:D!€ÊW"²À˜òÞÅ¡èüxÈ÷|¡á3 2y÷n/D #PÖ2’©Èk­.؇Hd†£Lv{ÛñöûüŠ½lµt@ïH­¨­”;áBÑ2«C¬aCõIð#_”½ª†'î,ÏG¯ û)—DÆ*~Ì2ÐüQDyô¡ºôå &ßBêf†³Ê²è˜:³ tu ñ»þ9rK*8]©„·]ÆîCŽÜiŽJÆf§Ô 0ëRi× ð¦h a&¤·—ϲSz… õhßÝ0ÎÔH—Ì-zÑmžÛû S úQóÕFòב,8‘ÈùAÐM\±·ÿ âk#èÙhîYÿyTßÎ1ã€nÈÜ‘”šW¢É:µ¸a!ºN°g´‚K˜nháó0³—¦—<>.rðÃåô-Žñäø„k7a¬ êGaHˈâjr»éËmt”3SRn‰3q Ü•Yò-9;ýÀžDO ÅiL…ͯ ”Ñ›‹ÞP’A›1“ñ¦¿äm8:Új¤nKâ|Jäû”KŒ›²?p|y:ë-·Ð +£{t¯TÁ>žµÁ½¢¯.šIw™Rçè²óm+5؆+2¢¶¤Qûg ©!“Q¨¿E&·„•º"²Zhu‚è (4¡JRE†âþ [,›·äbU8ì`Hj¬F(Á2"Lã<û}蔸ÙÌívØ_ƒ8Z¢Ý|„Àh›œ_á³bŽ¾–F Èe/í‚œ6¿ì~á0€l è'oÖßN‹¾'tKà©H øêÇQud8ÖVX“'K \¸ÈÍ€‘•Û¬d Ô‹ßÜhû¹ÏýýWÅάJT¨dÝ'›h° ÙÞ @Ò«û3pw+Ä÷–ÆŒÅÎés—øj¢:\ƒ;mBÔí—¦‡Î®÷É€’N#ÒÀØóÍìÍ~êe¶!oEγqi{ÎÍ ÙDoM¬ÏÇEðMFðêã_Ïã8°©ý«¯Jw-!<À~e•\B+SÝP3èŒ"ð= 5}Ö;QÍõË^ŠïÊ¿[qªsâ#Ï·ÈXs© Å!µüôÕdx´@Æ×<8[õ^ìMÌVhx²ýç@÷Ô»¤‘ÏÙõCYÝ–«Ä*â-æ6Ò}É›@CÌ=ÒžæPÛÏÓUmeX†0>¥Š;qA0hºxôÌ%šæ¡îËÀ÷·]³c^þå˜[¶Iî4÷,_#5é¡ñ;X“g+É1¨ê#=µmuþm^G˲K‹c¦éÆ3 =U_²Ÿ}{óÉɶ=éÜ~Ã*Ly¾•µ1hÌâÇ„'Šƒ{ŸôHrHOðŸûû“7„æ ¿Z6ÐL4Ó÷€»Qª4™Ö®ÍåY»s¿¥¤Ò'w²¸q;F¸5ûfå9$X†/ñ‘2—¹nl¡-'jU¦wíû E¿•¡¥\H[‰Úû¦ËÞSŒâ¼ @¹8>Üp¼îf©óXŠ+6§Ú ¡¥0”j9Ímp\`Y¥¢«§ +–0@JèÝõ5@9>ÐmçæsS£pð\OÏJðôEXŠ±É¬Uâ”Û͆B¨Ç—ùYʦ˜nà^`nn$ÛLÆ®¬ÂÇýã?µòÔ5™ŒQË™Jƒ­×C‰½Ñ=´³q™»môûrlîÆ"HµÕÿý·”TÑ Ð)§^nL¾”¦–ãiõ@¨­Î~†+ÆÂÆkinuyÄMò.-ÛŃ«×åÝ,>áa•¬[ +…>èc‹ÿµï"¨ÈIÓè ÛÝÔÆ./>À"¸x»øÙ^ªç-RR¨¥ñR-Åå\-‡´¤DoÞå±($ú&—øôV°â½âî”Ä`(f þQ̤Ön•W†&mr¦ òäéŠ7K¢ðUVž¼)(E3ô9€…Ûn’ª“mÎU@âÒS²ëÔÇ@×gÜÞÒ—Ppþ +¶¨f»Ü–õ|Ï bžcÞ2¡„<¡N„_“‚ÂÕÉÜ~ `$@ÇдvW›çBº¼6&»SÊv¥Ü “¬[S‰×òñÞõT9Žþ¼K”)‚Zû)¸pÛjCŽÚN+ï'hssµ½6ýIa…äS4XäHA +^”Ô~Ïœ(Xt +zÿÖc:›#é¦,‹  l¾1M¼ï™áŒ ¶èIÊ¡5Díœ ]ÍT%f'Á”^…+>l$& úÃåú[úHõCÿ»_»ßðsÀG¹zÇ%Á¦«ËªIš ÚF=/÷ó~Ãç‘iç*Oéâ¶;¸‘_ºNê½&úÓ©8õÏh­°WäÒýÒ±wÒð3Æ©á¸X‰„»¸ˆRÛz99Ðø|y2+·º¸ôôÅò‹>&cc{¸mÜl|³„ýˆÈ7^€§;{í:`ØÏÓpÏ>ø0#Çù^|V”ñÚÀUéé,±[ý&¸¤h«¸YÊArÇó×J{D†:ðëÒÚ&ˆßæée¼ü×+[ŠÔ;¾ Ç-áTWQßmtÖUüÇ^ÒlÆ‘jpnå) Vi²+b¨¤ïëìl÷ØéØaK´x4èD0ž}Ó$Óï<¯l<>~ÚXvŒ‘¶5ÙüF;¼RåÅ-NSÎÖÏ)P¶’ maKËîf×èËÀÊX4ø®ó·œè—ôÑ–`9dfÍ·µÄÉmbc°k›íŽ¾¶‘nªºtw³­ ¢íÛŠ­²ÞY®%ÈBV¥*(<=Èn®±ˆ¢8w#Ðù÷–ºÒÑ$1wBú,1AjÕÅ#)K¼kòãùmË¥4ÚHkÛM\áfyÉ7ϽfšWp…ŸDÇÛ8ªÝYqRyœ:+äóÞ™? HÔošÃ»ÎJÅi5ÍERP†\¤äbchÚJé +n‡¤˜o|YÇœ! ¾ÿ|`VÓsÕ'6¾ZÃ:‘ˆ†XµX–Oß•vnwspÙDbE:Þ]Õ–YµÊGÍ]šF+Ú?ÕÞ›*g+WuPeù¾?§7 +ÊлwB…È1ƒþ”¯úäUoà.ó+i‘ =ÈÕýŠN¬m·þÃxí.=Œ­5®óš®H¿><ǤíÅ6‰W¢óÕ³NPùg›ÊXtItàó +ÂÞeî£Ñ|ïÁþlÒ3ë«a3È2À¦¼‹¢;œWË|ºaƹ’å|ßkõ@Rín-Àø A­©mr#<]b‰åô÷eœõ,ÖœvŠdüeÛ¹0ð0û .};“Íá“Jƒóû$(f ”-b4ÅVÂDk᤼;àSZR«ä*å½ß¯;l@‰8îXïLÁa¥(S}×9ú´‹¼EYaý ‚Æ©+g«¡f›"P>ç =pyEµ$C®,s§™eÛ¤O«¹·lœXì.ÅðÚP¢rnÏlƦi _‰æÕ(ûíÌñùh'³¹Ž‘Q]i-> 8F /'›\„@Hù½Ü{\dß—§S"Ç i88ŸD}öÜe³Ž—„«€ÎGcÖèP}î†-hiÝòäeï–\ì¼Oùzƒ¬*¥Go°ª»!í÷²Þ ;Ùȸ)y–;¥X¬pzV©¬ blÌ<Îaà“ßc¼l~ÝÃj—EFÞ/×DzðÇ£6…ѡdž_ókB#¶ÿ½R®ŠÝ#Žo8$jðé·Vq%¦;À~ÕÞt—nBý¬Í££áZXôCbç)¿BóFSQOc<³GELw™á2îÎ0A#Pp@žòdM©Û4ÅË*ɱ +oÉ1Ê0웘àÍk.sD•}?*åVMVÇp%:h¦·ˆú]9RG®å3/¥ñÛ@f 3öÁª®‘ÙµÿxTº‡W†×qNë#èô‡F0ôxƒO =­E:5½´è.Ü&>Sï$§ØrY§r–¹qJœ8…"1'Ûå/GŽÞ&Í”Œ ¯h92•¢Êð¿Ñˆqí4–’tZ2µ¨ kÐ"_ø7"§ØÂ[]ób +i8WÚ¿\N[Ž”!öL,Œ'nâu¸våtÌ¢–£a¡ŠãµèÁ%œÀ /*w.ˆxé:”~5K(¬mg}îu1Ý3ï㫽ûõW¤®48P‚JÈÐ_¥3UþìÊtÖ÷Á•C3s-ãYYvÓ‚²Y ±µxÈk½S¢¦U·yÔ5ôÔb\z34V£r ,w‡~ˆå.…CYϾ5„]×Úµ'Ó›øs+qˆ)‚‹v«tüc(“Rlh +ï|?ÕFð &‡Åi%DáWª®)slŒAè-¾Â¼`]‚þ¥Ÿ¹´¿½Úçp¦ÀÅó)†–z«.µ°½ã+fç.Ye8ÚzF‚ô³îüAÅ´ãñ!GÔ~0Ѻ<|ü°h¾©·‡%·ãº°ëW’÷pÓ25 6MŠ÷5¼!‰õgxj4¾‰…®µX'¡mÌ-7¿F r·p%°h&·k1ÖãÈÓTµ€àC÷÷Ð^D(:UìJ_‡$!KZŒ‹,|1*®).’D¦ßŽ¬.ËsÔÏô㇉Ҩœôtãß-Ä—ÅÕ™Á¥KÓ*‹¾G{߶S áç±ñäKj¸uDÇ ]À4ÇG`ÒÜPЙÊÀ§˜l×’%wiÕPk¤–?Ê;÷2±C†ð7·”ðƒ"KÌwA†¹4™S‚%¹.nNàºê¹_ŽûM` Ò;Sæüê\g|¢PÈàå"§û×çÛu§M:¯ºÖ(Êÿ²4ÍßVi®Ûh(áSe¹7@jÊÅsÿÐö3£•wV?wËÙ÷à¤Ñ Ä4W•xõCçÖ WðËÊœ•QÜÖm#y_)ó¼¨VW_i¸ú¸1d‚“ ×Úqžr…»Uv1í–›b‘O>eÏ€…0Éï-š‘ã›·Ñ_›ÃϺ_±Z<žÊ×p9‚áh—àJæ F¸ÕWŒÊ‹PTÁ¸ A«÷!ò2PÓŒ +\J®=EÊ~¤¯€k/Pßõ—´”÷æýÖ7öÝ× øòœ†eô毒¨> ¾hÓ;(°äõ²4\–¸©? ePiJ~m×뛇£hb3d¹n½gŠŠ=¬ÓˆlQ,~KBN”†WÅ^"Œ“zÞT‘nNÖ®ÿZƶžßiýb.z þ$®…Î\“©ªm´‚ŠÆ¨Îò&aa.òä^çšàu~{ •q¯2 ]}‘G@åŠä×aÑU®ó:`’PX@h&õx†HˆâóÒf†Bz˨¨_ïI@B&f4Mš¬.aƒ¢KBzê«!ªÿ3NP‰É¥9*š1zÆ\–|wQS…59f¶Øinµ¼IîËIL)ĨeL‚–Aj‰M>Dy€G>Á¡æ"®IÉ¡´±¹V]Y +ýÑ ×òÈ_ûAówVäïjq'!1 mS<œ¶»Í² À­ "áì7zóÇHnØ¿jU‰f~-Õ·SÊvöñÀJqg”`ÇjYÔ˜.N\ø ý>èây\ÖÛ ˜ÎôAЫXÀþPË#-Ęéý†õ¾ð¥20ÄÙß‹„i=óYÃ$¢5Â'5D̸”ijÙªu昬iåOjãa!øêÊL™-ƒ c ÐøD‹ŠÕ««Ç•c#Ù=/|€Í­˜2¢ØL®"mÐ׌ÿ Â,Jr o8𞨄¡YÌ^Nm*»Ê—ÐWØÒôƒ¹1­ãEÚp^Mw‚zyaÙOÐæŽûù}®®¥]1¾«8—)V”;¢£è|-û¯~¤øêèëÅ—Ù’§LŒ¸ñ]V¦œë"˜Ý…"GŒK×S6™€™ %Â<ö“;ÓŠ_£ìdŸ„)±cš/5-‚ÿ‚gLÂß ^·…{ø£ìö{‡ÈÈ…†¯7EÃ[!— ù¡O—zS¡Õ^·ŒÏÐ[.'ÃhQ,«]Q™¨u¥${¿ùí tAz;@;3ò‹±M]w£­6IãnxOd?/¨'ãv¼ã|õÇo¾>U%€`µæ~a¬P?ŒŒàpŽ¯H¿{5ìà‰=†ZõPìa®”|0J/‰ø(!ÎÇ =„€ ÷÷ÁÃ8ÎÏìýKÖÈ°º…!ûðr–k¸‰·al<8`jHp­+&'fsšnym@§$ÜU³©$d‹ÁÕ,LBpLÃI¾lývr‚¬áDÞb ,‹äD2&¯M·sÏ4c‰£#MímÐÙ*#u~jÖ{Û'´£·b„ÙLÚþg&ÂW$„ tçñŒiû0ÏwÂî‰í‹IP7)\¼]£#†e&ÿKá …m9Ÿ7Š?æ?yŒté.PBíØ¿P«OŸ7Ô,·ý^¾ì=ödÍ´Ø w«¶Té~‘ãÖ‹0„!3ÿc¤³LOOÕ TÆ“ÖŎЀÒÎZé³I©Î2Îf²ê¡ÜØYó.¿§ Mz/˜À:Ømt:†™è^ýLÕ¤žE«&Ò¶nûU#wºFï±·tÅCV™e¼—Nƒ>˜ZSF̪üÊ̬£” [q’MÛ•ìxd§rP?.tÕG¬“|áÝkØ!× $ ñ:º?ûüËåW,#½çÎ3©EäåE!t]}©váGQ,š;I“!{¹Ú½X[ÙÚJí_3¢-ÿûaÌp2~ùŠ“ÂG«­ÂG +n®±ˆÊž¶ ®áJ<©ö; €îÜ x+ø÷­µ –'IטáŸoŒY™(±¦¬óÓE_3µ#d1š‘jsÅû³Rñüä~ +«…ÛÁ0|ØÛ¨rž[ñÅ +n£Œˆàwƒm5†‰u“ Ž°‘£óq +/U¼;Ö}â$X…ÚÓ´Kç«fàÓ*MM‘9Œ}ì‹À@ÄèßSš³« Hd‘$ã^ÃÌ[¡û/äX+Ít~ÅßþS$3Ùß—~z]ôúYhí²ä!Ô"'ðÕã:t¸ÛÏÅK`ƒ[‡Çxý4õìÐ!#çˆ/jÎpÊ\£ØiæÍÁÆ‹‚- ^è‚…''¿O òD¹Ê·êÞaw•ïí)0 õP`Q?x9š ü°šhx‰?·Ø c~ûZ6ÒQ@ +keG +Iôñ ãa‡††+²4 ‚4¤3>‡½‚N“ kfRŠP64KyUæ:ÔðM[=_ÿžÁ*µQÐYÆŒr^ð Ñéš¿Øþ!½d¨T´#úP„oú1@Fïyô0–O6£e¤„ÏꀪOÇQ'KõÑ~çwç‰eÇj*×o^/ˆÞuDm †Ã0;&“:ÝXð¥½Mô= —PÁûEá›hÒ“+¶Mâ™Lê}û(ù'™y ^d1] ÀGò¤­K\ÙL·(Û×9Ʀ i‹cÝ›õN ™¹n,:m$øçhÚV‡.¬ +ÈÙ!z»[úœD¸¡\™V\aüΚüè¯>šbºØýúÅP¬J~ +ælî tV¸û‘–3qû%ŽY7‰‰p’u1$q…ˆÑÙÈ  ƒŠÙǾ¼\‹uûK¡&˺hûD'n"Q¢&¯iÊ7Í¡ú»šØiµ ÿҨ퉇Ka¯Ñðò(`hò쪆G6XðMÈ ²ß±à;ñÖ¶{õ°”H$3isCÁ†`Ã#: ^üëäçÔ{T\žCÙì¥öD.íðbU'çMPä Î“&.A0(œ”ûéò ût?…7Ÿ4;î¹ÁîRâUÀ0cQ¨œi)‚\ò_\òùÁ±§Ôí"‘Ïn¡¨çW¹@iÑÖ4 ä7ä3o¹›C¿¨ÊŸ€É˜ Ù®¬4õJDÅ©!óÃ&pc¾œ=p×ÀÝ\Ol΋@ÎÛªs‚Í÷£R†4ª?Gt( ^‚ÔîæÄzEk¥Ï êàE´¤ºãeí±ò÷B&UR}hwGÇ8Ñs½¹•~¸¸- +4mbA‘., +ù3ÞräÉ7zz¸xº„vFà5Åï÷`>ƒ¿ Ê3¢jÐ1 _òÿMšÎQ1Y©à$SÁÎꨄó‘ð,?/øŒ#q¹,•Mþ@š7Èlf§¯•1NK¨æ×$£`ÈxEŠÕ 6èr%ò1+Éà÷ †Cp³pÜo†WiÎë*$•FxO.†@Mñ¹™å«i;Lg{ã vÖ±Ž]--ݧ…«ýSù¯F‡K©D­¾Ø'j³Õ‡ùý$Ò­dUÝ@‚´ #PéÉghŸ&…È37)d Lt~äâ>¦µ7ÜÔjéYåù2 ºL R:äZÂs¨®NŒm‰Ç‚áæU7Üõey{²iæM\äfÞǾ¥œ âIæ"…C‹ÜåÑYŸ6½¶WÊ!Ì?Æ!“ô8/¨ õT€È(y¦Ì!Þ‚ŽéÓ/-áÆ9æ6d™ñ“±BÍ¢cˆ( +„,˜›"óšœT&iÙÎà±n”:Èt' ¢ª¬õA©AúÚ†ô ˜ìëI¢ÔJÏöG)MûüÅÁù½¬‡f¤Õ2ºs?¦ú~†‡~e5-¤\ +&{b¾é\QÊcèâåKŠ¡Û€•\±"Ó{E),ŸŸË#E‘·iUHš™·'6 &u¯_«÷–¤ËÜ‘ÛàÐðÔKÛ?¼ û©)ÑQTóQUm`¦iø:Ñ[—§sø®á›)% ¤ç7 óD¨×K×F´XÖŒAHØú¸a—/« 5:›†Šú™ïn¼#`‡+»Þ[øjXZNiåJx)T»\—ØãÚšæs÷DlIÚb`·:eÛÄôöïT£º)£&ïyd„ãì°3e2ò–/@Êr³Œ+¹Gé0Í + .Ó0']Ó _Odqâ®Ä–üå…­>#ÞWÖ³cRªv×Sž¼XΧ!8$õËàí 3D=ón“~·ÁŸD㕹=’ô™h¿IÒîÇvƒK>A¨sÎÞtݘÏZ¶G U^W0åõ®’•¤¡Íš’¥ h¨E+I‘)ò§ÚOŸ.Ï`o‹ûrBäB‹Ù­QÉF×æ÷rŸ{êÅ2n—òŠGáßûS4‡‹3¬« À=,ˆï’ÃLâÁMjÜU}e—˜ ÙxXk I“ ö™.ÛµE#8ÜZåÛ©ü™êúÚªÓòX3ÃÉv˜ Üã ÒÌ7:-^iàrÜ㤨µDÿó”íQ.E¾ù¯×H¦ •6­7Á7d•è­YìïC´Ï³šèJˆ=Ð5îåÛ3Òá¹T‚kéæîÆáOQa˜ ¹5•¼·Ð™xm¤D9!ñºˆäP;5;2}dj>hQS’¶• |-|F+î2{š· +/<˜“}ß;ëOжrš³<ˆþ–hMèj‹â×òų@W 4tú:©ë•×`±–T¿/à#]ÛÍN›‰öÍQ«ÕÇØÑ£ƒžoŽzB}ˆŒ¢ÁõSÞ˲ÛA!YÛahZg¼¤u|W¾qþ~âWt`us2yX‚Þ Ë#ÖÜîÜQ¾+U¼ñá1YÀ‰´MDª½ |´ÇæÍÿ É–î#u€ÎçŠ#K@ìÂúR8Äl#=JÇH(^ –¬¸T´Â7ŽŠ³Iª„kÙŽ0-m9i]FÑÿ«A~v+­œ.•ÞF­¨)¥V˜œËÀ7Ò©| ¶©Êh”Å¥•ìŠ'­[Ãðœ‚Ø +¨El* Å3/ZÑÿTãi.)ÑÍ¢G÷8•{ðp œ¾!î4½á´ÞfÍ+ç9'LF¡»^É¿Nd*¹ÆhÇŽ g¥n)ZR¾œ2/@KŒµK¨øXI6ÇRÉ ëaµ$ÅîN»-¢'¼%+iâ?h%Fbs„òj\¥­¡uËøÄ âÂêáÄí(- ¯!Ö0\÷è|žÀWE×ÔçT‚‰`qÄî;Œ,ßP•ÍW4$¼ÊÂ?°:¬Wϱ²¡Tç·Æ:D¬Xô»?͉Š= +¶ ƒ ¢E2Ltãæâè¾I;Æ|ˆ»µ]0ÊÈ!çÛJ¢b^ûÙ­&×à}»'0qT[}yë&P½1ÞAæá^™0qŒk7Ù¥±ßbª0Äüh«N±D3Gˆ¾_²ßý&±UG·b`üÂO|=ÇÎYדnj‡üG tÆδ/Œ±§ÚÖ%t}šøhPÀgz͆ª©d•î2^G¡¥o¯¡Óü‘UC‹)Ö”ÖSˆ*Ñ’È:k@o‹ý})f°+LXnÅ@ê_ ß2Åiâ(ªt…Þ¨¶–+ÈÛk¿(ŸQg䔈Šfl.¬¤þË8èÖâ¥> ø|gúÜ” +TpŽ‰ß¾®º]+.;+¼•ÝŸô6¶èhÕmØóÚ¹ ˆÿwkÍn‹ØÖæaðÙFu—k\!Ïé“>í}Éþ²ÒS°ÅìC½ïPUÈÉÁ¾Fö,éà¾eö4°Gñeá ºÑ¢Å"w)œçzO§$#g^†¾I†b¡lì4e—8&áâÄ«ðÔc‰þo˜iw¨ ={€õôI=wlº·(n'˜}ü;h|-Pn%Xª²ˆ~~»'›ò!é@Õ]͹à*îªDÝ*õæO͵˜ý¨¡Ò-s‡˜ÐIò3)‘™{¦_ÇWu†ùµ°\°%ßï7iåÜG¥DÞ ñ?’|%ÆüiG—lGê¾L‹`1îDx,½‹ŒÊp—š‚D~e'K™…V,u¤>ŸâìçF» nLFäè”.1°FÖˆ-oË”pÊøcó;6³ùFma7A­CÕW'éÞ¼<«1„6œ&³ƒF5Ì7Òo`¥dº%<‡|W¹[õTú'ÿX'3§ ]…±åvR§ó(›ÜOæÿD³¯ir §ðßù¾¿¡Â¯ŽˆV!"ñ/Ô­‚VcYén‚§ F#ütñé¤DÞ@Ä`] gO»{¬íWxj+.ª¶(XNô`bŠ§Êé.WQT2³Ù‡y©X¦Ž(÷|Α‘Ýv*¤†Õ¤D˜Ï‹ÏâM[E ÓÇŠ]œ°· º¬ †À'Ë&«­³ýiMÆ›þ Û‡¹q–ï`=Ñ‚HGOgmUÕ£Œí9{Åkï£K_BÅ… lo„^OÂD¹{×3»¥‘ÏXj˜óÓ1|§×“¯ËI`>/©êûÍÕ[¿¦Ð£„nƒyÄëhøµ¢$ _¯£tVQ£i@á>h•k`ažndÖ+jäŒa‚^DCOµ–¼ôb.Ž½cZéKÎ ùéÖo“lù!þy ¨Œ½¾¨­xñ×aieE¬4AÌî'½ ŒçÞÌy¾üL¯cé[ÍwûJáa߯u4Mh&÷¥³+yoÂÉ|[—íñ‹„’õ~ î5ˆ—§üþy·(;ãgŽu£ ÊzqW\plÏ<{]Cé°UMÿl‘ þµ6iÚmH?ª¿òÁä#¯´'TŠú¨ÐL«¦I‘%Û_Ѐ²øÁçq)öV³Sÿ>î%xꈈ7æÂz*@žJF+—>Í¡—‡4½±—:¨3%Ï9#ž¨¶ !Ç2àK\^×ì©ÙÃPÕâ“3ñû}r<¿°½÷i‰¼`§ë@RÇâ;jä²»<3æ“ÕËMìù™1Å”=Ö½yšÔȆ{SKù‚¸­Kª—Y#‘Mão El‰¸ÝÔ#Œ¾ûÐUâYƒ„“¯Ä>‡ù¸WÝöö'Ó͉AÍ]bØæ‰Åè¤7çî7í€5¢éó„Ò“#¤?r‚°ïã<|š÷ß<½Ìbä3¸O=ôÌ|NCê@¶x>”Zw¸¸ Cìî½#ž;êÆiÃøs‚õIÚ]ü'ÐS˜Ñì¡o Eåœ-¡¼ð¦æ+^_y+#Tr©L8‡"‹ª™VÖÄî>£ +ëá0íá3õFt;ÉÁš¼‘Þ<ÅyÕê©–ze¢lÒft£?ÿF%݇¤G[dÊ°ó2¯|?s‡·‚ÁÆ9—¸,k/KÁØÖI_ GÂ+Š$ý v$¡G|7FiÃoÑLØS‰µ¶‰V6bBš×F¬zÓä·Wè߆Û#¢š»°žq"® ¦;³Ä¬²ÔÙþSXqå§%Œo… Š¥]ôêûæ‰ÁyP;Bi)Omq”©{‡+™ Y=Ëv—0ÒË+AŸ´ë Ó&5Š÷ÓP„R'ë-â+ „ÛƵq›Ý“<–áC“Þ®›8ÔÁhîÏ#íÞ^tG†°QbŲ)N#†·î ?±°ù¦„•›£æˆa$(H쵄…PZsÑ&†®é¶àb’ã°¤Œ0‹§§ï»§óD‡~3:+éØÕä}÷ 8ñ`î©?ßÓo›wºFWÐéO´© 0Èò¹½¶BÄÛp =d²ÿP-âëÅèTÊÏÞg~®ýú=£g­l´þC}—&³¯ÁŒÊ÷ššIîä™é9©±ùÉ•àõ+#ž¢˜£ºþ\Öƒ#ÞkÝŒë&t0ÊÝá¦7Ö¶¡ä”5jÌÔ²ÉwvxÙ–î›à`¬ç÷ì¡"a¡f*í`–zL©b¤5Þ+6=jô{zÌ9ùŠ÷´zû¤dI7ý¢éaùgÌ]rä–ºúhl=M(jtn˜3à ¯L2èféòÞ¹’IPË—~/+$c ª‰Á½ˆã+Z ºù­ +Ï{ªsåšU#ô½V¼oØ6‚ž€‚êƒ37•(S¸nÛ\+5ˆððr~ÉžLO5Ÿ?žUaÂCs`~I®úb®E»IÏZ0¸y‡(.Uôë ´ŸG}µ‚wëN_À,ÛÜ€×y#ÊW/y1g°– Œ‡xcm(Ë05V#GŽŒ&µŠ{GfÍ%GIâ€ð, ´þ~Î(1‘ù<ý˜ ñ0Úà]þžÜå?*‰&ı«7(iK¸´Ù´¨;in†û^€2zïvoç"°>¸L´ ó1-—qfœàˆ¼÷A¬ÓdJÃzŸîf1‰¸¯;$‹x“ÿÕ<žÞOÕÐÂQ„—¾Ë`z [ö¼?4Z`mºÞ.>R:8üíêý^ùÊ]i‡DÈ2‰¡i±68Ü+FL»ÙÙ-Kú·”û»Ž©2wqÑ£šÍ'b(_±’üz7Ùó&-®ò3ÐóêT¼Ç`•±‰¸aýc9Ãm¤G™=V¢á2r–XÁ‘ÚðXŸ8]\ãç;}žº]6«D"WN¾¥ã¥rÛ3Q@ö&7ã%sÎ!l0ïTM7hj°¨›Råòª[ÇÚ!!Mº( ´„öaÐŒYMùctQµ +ÿ?!Cçcæ^‘O}ÿƒ5 “Cü!ØÉ»®?í|”+¨4ÂöªlØå½û$†,øá¾/ùt£ËzÒ~ج¡1ш—~DÕ1ˆ%ÀlÑ„A·ïª©þ5c ŽŒ·(ˆèß…®tÞ6ž«¨ý+>ù¤" µÕØ®¦?¤Fn®¤ðÂÀ¯BˆCÍoä ÛV ü¾‘«`$¸+°"¤u¡%f ?ýãŽVãüZékK ²}_î™ééË@©éŸ­z™xzWáQ&gvL®ÎØÕÏƉÈP¨î¬/uâ¤á£ §XdýÿÖ•fB]ç–ÍL«Š|–c¾í¸I +:À€•áŽ±¿X8Ñj‡Œ˜>Ág{ZÐ×Ø°i«‡ºyDj"Å jµK–D¥«œ.¯üç”äàd7X‘7æ<¶’Û*¢†ED6  +” ]´±1Ü?“¹FÁ&¦¡l—FJÐs²!½‹Dãpù!/dÔˆOÄŽ]{TÖƒ:_IîÖáíŒãH%#ˆ1`@®Ö|Èuåñ¢O¾.$YP'jŸ?¿5×^Ü‚îY%’ >É,MŒ20 HÒV ™H³ÊÎÒ—àýŽ³Ñ]E}Tyƒ¿Õ´9•&ÝÝ +¾²Sî¹”s¬ ¨Ë¶´óEñźA/Me‘Å"{"k½òK%FˆÉkñQÁ’A@Ã0 +é >Ÿ¼Ã<»ê +8‚ã*[KEUè)ùa$¿N¢µ øïÍÇ>:Ç4Ø-,¾Ÿò>Þ¤¹µÀžSƒ…n5É¡è7»~²§bí–Lª0¶òÍ`§R!(Æй`6pravôWáY‹¿BU¯óPI™ØPúò p:óª\œÒpnkcR€›cøƒôá‘Ácé´5¤•¤W1Â'=v/'7ÅWWâ7'Žú yÒ>;Fç:ä{g'àÉ.C»4H%ì²õ8ÃñÒj MæúmÒ“<ïPѤ}RÐQ­}Gý.\Ìûþïã Ú/X…$Ѧ{ЗÝØMÉaúèÜch¨$D +‹ÁcB +  +AàÃÐ> 4.Ðt’ÁýŽ`¡ õ1uĬS‰aÏ çF^V-š>¡ýØN ñ‡0åT¯Ù +·è‡7ëéBñ(9™ÀcY+k$þŶ«Œ=ðµ¢QwL ä<(ró`,XeG÷¦ÝY–‚®ùÕKé÷ÈÞHC°£ää$=üæ…q +_Ñ=d´)î`Åœ¬~sÙ:Uµ ´§ÞV¶_K!Ô¦`‘EùcTñYŽdÊæÎx¹ÓÀÏÕ7s,|äºS†ííRN]exÀq”›ý-Ë`ë`‰¨ÖÄc±¸.u¹g9ºBµfœ:îïæ2HV1ÒÎá¼²ø4èûõµ¯Ö‚0ë•ß|PR; =VÈüù.7ÖÎe†Ì6`>NŽûãv)ˆ˵SÖaœú·Ü?BQ Ôwø¥ÿ¢z`Xµw:HPÒѻ䛋áã5ä —Z±ÀLƒý¬ÉUoΟª)÷×þü³„.\Ð¥éN„5ð³ÆWb‘àîÎ[6†7ät +±õñ¨E'Oƒ¦ò¸Žœ­²„Œ¨ISŽ§ìº2!²³’D‡H¶ê;”|‹!¶jè²_rDꀩžÖ¸Øã}ˆ8——T²|+Å׋8¾ûW÷šo +†?Å, Ô±™x¬ç¥\3*Ï©C¶q0ëß½«™Ž>­jâÄ>Kt¤)¦k>(ªK·#:›xMµ–Ð2²ßñ®ÄýRò¡ì‘wz!î,±•ÁÌõ +DŒ–¯ØØ®0o´×\Ú²{löjâ­°C¨õ3Lu3¤RLyz§ 1ÛÁÂË6».} À|?ò{,j¢:µæû#-ÝÑ"åHbˆGžaæÀ~À_tݶÛàE• +ócÆ +ݲ+‡S?èoJ£K¤ +ÓþL5ºÐ$p•ü›yBÃ|5»w^þl23(ËÛô€åµm‘ï7ì·5v°“’._ô]ÕDO¸XR6ö}ÇÉÉ +Û7Ñ8úŠßî7;°”—\&›ˆÏæÄeâê.s¤ÆÑŽ…Y0´ÊéÞÀ âžì ‹x4ÜÁw\•fèöê°¼Ÿ3pÇOy³Í4ù”-†¢£À ÂN¿ËþÙP³z[´‹üò®¯˜ Æ®-×I£+”–öH34PçM÷|´wÁ°Qv@2vºŒR¶f¼Ÿ4È,²,BÓœ“Uêä~ó‚ù·•6oáéA+K?ó FC¤h¼ÍRÚ_±L²"çªÒÍ“÷û³ÔBKŒÃ(¼shEŽmä_ÞÙSI f8¢lEúKAfð²ÜeM¥ ÐŽ™Ü*ÝS‰§d#…$3u}!jÌïƨCaô‚”¿•Ú Q,Ü4ŒT=AÅ?AUJ” e –×S<)UÇ‘¡„cc lÛ mvØsÖË(?ú¸D˺¯xì/Pç/·‡ðbÞ÷ô‘B½š‹¡9TrÜÆarìñ té;w$ya>êT êÃÜJ³ã ]"¡µ åìIà fAua§Ÿ%½1É/uMwAÞÏ~ü¸©¿àdÒ¥JÊ$ÛÈxP‡Â´•Þú¦ˆ³P˜^}$ï)¾¥Ú,“.äey8.µëÚÈ>C¡q•B)å~ñ‡EQïAUžã0äN{²‹! ú-ƒ‹„Kß7ínðᵯ²[dš‹ (°Öÿ­VÐl‡ó{yÊnßiˆ£Í¾×Ö§÷wk¦JÐÂi×vM)ôæK"žØ9ÄÝYldgöEGÑòÇ{˜.æ Pú"—ºY²-r€tl6wïèÕ®]>C¨ièr'·¹¹ž •îÓê¤g¥r„‚>)aæЌʉ¡nºÑ‘?ÿºz"6ö›ûûV@Šà•Ëüè¦ÉÔq& ‹Å$×ãزìvž¹Ü—¯¬ØÃÄÒ8 ¦vž?÷u +ËÚ."dšñãí·<ÈAmMãsåýëà½Æ™ûÓKæPú iìЇÖó!œi "·Ìùµ.Ò6Ç$.?ò¬t}v8«ûyŒ)z|tߊˆê90¼€Ó¡˜S™ól§"xzXÂüÜZž˜’ó±3\JÑ¿öŠ1G ezGtäVÿæû^öº>‚î»Öè‡onbÎtð{5toê¦3ø5ÛYêy-sXà ˆwG7–óeª'qöª—ã”:ˆß0²ËÕfºî +RY,ÀrÚ° ݧ-¦£<@$•N\×:6EwFàC´Y«Uvvµ×çên¿ò\Vê6â~òT¥•½IýA<_½µ™íb+ö@ö­xž>o´x(°‹àšƒû‹ÿ'õeÓloZK’8´†á'ÔpøºÔfžni(|"¨,ÿ°®u ¨‹êûÔˆ,Фè¾9 {+¸$°w/ž‰’&3RÀ¯„„cÁ šOmÏHµ] Ú!ÝÕJ$Žá +V‘<}6j]'»EVîhû‚}6¡ÝÀ6àÛ·o÷CfÀ¿ièﬕò1e·)(+‚§l¦…ãƒÖˆç\àíÈìk}/y»—ìǸoÕóÑ#Žuo'i”FG œpÖCfïÌŸ¢7j½W¨évôœ­FaÇ¢~®|Z][pÔÖù(Ž¥å –pÖ– œL®€î2Ÿd#FñD§ðïƳK“UðIó‘½ØÒ^¿ºýO4Jh%9rCØ\\ú+Þüæ8[…}Ú ôu¨›ÔV¤J»ˆ¢<#¡%ÁtÇ2å 7ÙIŸÔ®O™oßpÙêÈ—µ9 §.†*iTáŠNG‚÷Yk(ÅiJÌÇgÖ'gOZU\òo®\9F®hÛŽ²v@›”PN•ªþ|z¥»"^‘—ËN§³$Ë'‡kWØœ.Þe#ÄÚä/ª«:I!îò@F.Ù§N,X!Ϫ%µpºDÖEÐ’6å5eFÙ™ÂôÛ’EöqäœØ+R²Ÿ]C~=ëÿÖxP„»w(ŠÉTn ý£êöÅëGÏ!_/Ä!„ûݸЩîçCs›äJ §±üð@ÔÖfË4á ü%å/«‚ÎüTï;MKð"3¢Îæc7  +Ú–þb$ˆF›š×4ÌGÂw6 JBÊA©­R"±#ªvw>!*3ûLß´ÖaxqUR±™^3îjÕƪ®vOÍ+ê] N nìþù‡Õ¨¸®âƒÑ±ÕÉíÍU6þ´ÉiçŒ7LGi»‹Œ¹»Ó <ɳ7£ž”Œä(æsÔ‡À®íö2`Má?`»,™Ä_tŽQi†è¾ôË»Ðã™…b_BÉÊÍømzÔ‚;ºØMNú ¡;Ùu(G…œPõ#±€IÊE«[‡n®ÎbM|”®?Cã⮪8ðgÐàFp²>%vtÜžâdBöêRÒß¹£—Ù–íòÙù;\«I¤òŲև7[±(bvˆd<˜U_ëògržàü¦>N3×I¥1Ãê8~> VóGÖÆÛqö"æi·øgzõ">¯ûÐwˆšyL«Í?ÔþÁÑųóèâ"dHì–•«èW /«óLõš^A_2—9e'ë„b·íí«(š ŽM£˜Me®opGšÁÐæÿ›-»Á,ïE*hh(wF–¼¿ô,ØG«©Wð‡¸žã–Fuµ¾^Tçðú0εÀà`=ºr ¸"HÍws‘ž8R'Q£Ê¥8èøMEF;ݵ0¬NA +`õØ i:ey/ÓT“îüÃg{qª}ŽTr 3ý\:×îY6Ò°’Ù;xŒoù3‡ý%¤àö.ÜÍ‘8iòzÍ´ÎÈéÕCùÔîÉ(ŒŒ«ªû-äd˜6í‹(ÇJT*L_4¥öÍü…°í¡M¶¤íâ‹1Ö`×xÜe²lÜá†Ö/®;Gæ+àÆÛÔÜÞ釾{å +2K(¾àÈrG€éI^ݯ§ËœE;ÉëZ$„)½J%† * ÷%„.Jr–&*¹Ü¯Ms¶°_k„îš ¿NÆS»‚wX*ÿï­fƒ=ºðW=›±7Zx‰’d­#ó’1ãZ˜5'`N @­@Ótq¶¥ÙƉ›–îà—%Š7ûÙ¹%.Ìx¤D—ãðÁ³b‰C5ø Idõk/ÅQŠ?èxãê5³¯ÄÖ>Òðuowõ=–è9­Y'àã« Õ‚zɦ±¶Ô‚>N ;}`÷*Ž¿ÃÞƒ$“ƒ†Ï|£ã·Ä#@ºêÊͪ²Æ.ˆX³¤ ¾àŽG¿¯ö„«‡w‚MšZögsÎÙQ1ª¡ï±ª;_þSì?“áx´ Ÿ‚^¯I«˜E2•“§–κÛw!l¾:‡_¼sªÔNÿ˜~ù™Û݃[²3ùULiµeižÀìe%¥½˜¨üß’O¬/°”:¿èx>D@þ¦ùòá=9'»|»Ä½Œ©L²Ä/–ê-‚½ÎìÃsœ” ~(áà,åpƒ¡ËRs,Õ:Ž±ÿÃ6hÆËÔDÞï^ÑêI¬'k𽠱ĞÙþ÷ŸøŸ…ÜÈ Æ› ;™l+ä­ñy̼Ú(g`ý s}ÔÖ’×åù$Ï–c†ƒvjlHM»kœÄ^ý08ùqS}ã!<¢¥mPYm¼ÑјÃs:öhª6¯!Û(sD¹16äÑ?«r.o™Éûòˆ ¾SšÉí³•õP1K²EreS‘(§AðÖ?žÔo§G,C<òΔ½kuló µkX“ÁñÓ—WOGˆ‹v$ÔÃÁ×a¶D´­ƒæé<xç x÷DÉ ºBõoÙòQ3ª‘GÞŠgMyÎëæ:ç èWƒ’¥oáµ=£öb2ð»±K<6ö%J{ +‹ÅK0}´zc?¹ L£Z^ FªËï;—þ d%CºŸüÂ¥ü¨)0óšâ5µû|#ñÊ1¤Šµ– Pgm _R„®z1ÙïO,îSò[³ÃY[Z…-¶2 +{å]­è«X• ²ßæF]T%9FáTâþ¥}qÚxo‚{w;w+h|ŠÏíaq ˆíX7ŒÒz¡î±vñ¨ˆæK܉bs6Ÿ±™"‚¬|;¯mš®u˜4bƼý¦þ 7õ™•»Ð¯l(hõ)&I—¼¸óÝ ô#Fê%yDôêWÖëÏäôD‡߂ù‘|}Å99Q}â> uôÒ§«h†:úVLãÖzBžÅŒå’F'üÕÆQÓ/9ÎFÝҰɵ#6snœjGöXã~ÃéPóLpJýœ&wB˽óÂób17aªÓHj;è•ßÐðS½]þÅÝpÌÚò“ ­ªAë8Kžpªä¦<ëñ-ùS¢äëÊõ&}9c­àÒo˜òt3aëc` StŒÔDr3œ–ic#Ñ‘x"£ž7ý³–þl­ÊêIF)^ˆ×LÌŠ[h£IµA _#ƒc«¬LÔ'PŒ ö–Tñ™»,Š x´År +‹;dTx¢CŠÚµ'x^3$|ÀȽ¬4ì^ᜥ$0ý'©´s ác@ÓAÙouÖŒÎ@@‹Ù[¨ñÄ#rµì‘ö9s¤Nè2êš>8*û@‹hËçESæIh’V\ºw+›øYET Žë楋ÆEêæcfCoŠåÚM¬·Ôþáéw„IiD¤^‹J­÷T¹J†a±kãÂú ôꟶÊçÆck€-T ÿŠ×Ý¥èÝû4üGl-UsÊ«nu¹0Á«…¶àöXlÇ=>…Êê.vÅÉäÛuŽçÿ{¥«› oþ²ÿk ÁG÷´ñÇáÍé’›0Q‡4~Âw±ruÀ ÷oï/ý d¢Ž, %%–ƒ~O1楪ڻ'~É_f2IR£!ë°ú[S/d9[V5»’]·ª¾Õ^i)©ßjœÕÀizp²Yß’6ìûëØ[‡mÿ®˜€†ji° YPrÌÁšóü"—9 ¸[úSU,RaJ²Ûœì8}ØÝ8ÒQqw—IOzH²òƒ¡j, ÷«úœÝ&»i€™¨š#ÖÓÔb©Ü¦…ÅÉpX×Æ•þ½€ÝNjxQŸCU¸‰!»sI.p0ŠÙÓèùbÓLN{ÅÎ ©ïE‰ôÿ¹9Kýô׌¢Kmºðö›l÷ÖIÒžñn+ª¼ó(DæþººÉÍê‰v€ðïLwtÊúB¢Ê̺ û‰¿Žê}x{\‚ºí‚ÃH¦uPjeŒ\•njók”˜‹¾c‚Ê¿ÅÅä{ã<Ó^a¯i{þˆÌlÇP·7 ™­0Uiõö…ïâv1öåbp‚…gÃ߸Kqx¿{¶ +¥`M/\oõÛþJXSù6”¿ü'ŽOØLaà¨oÍZNõµáø÷P³¬æ#À«-’·^=èCp§“´ñ»wÓ^»±òž,àìÎ-3à rg‡lÖ:G>€Ãs¦Ú£…î:œô0 ëX< Ô€µaËâøB´j[æ“÷)sàØA¯¿7oBÁÞÂÄ”A5d{Fáä;cŽ%eó*]š{+/Å=¾…61/áþàK~H¦)¡”Q"—v¤#f™&¤ŒçÖ'm·÷åS·L+3ÇqµÒ\ë\ÛŽ,Ê ]¶ÁµØ© çÒÚe8 Æ…ß°5²‡rÁè¢îàÅå§Ê^o*K{V#Ló â0Õ€‚²ÞxÂYŒ`ÒzB: [Ênةƒ´3ˆÃõ|ö3Þ+Çu[Kœ³š¸=(i"Ò„gcÚï4&=2õ9°«iŽoÖ$W¤ÜEC¶z™º¨ývЮ¿3-еDŠR ©(½­ë‘±Òl‹-z§4•Î•Ü¸MØí6nÓZóÈa‰Iý¾«@ÜÜhñ›dÇÀ"uñ£ åº~!‰qZö7Ê5=ÏsŒÐ—ã×uÆ6ÙHJÿÒP€SN$ð½½Ðîžjæè<^¥)ÔŸ×Õ—QtÚ¹ý·ãË$ÊÁ·Á„è:ˆíû㛤Põ#xiðÜØà’EuÃN±n—­¤AÕÔOpäöÊ`gWî=ÖˆqIzCQ„+šÆ´'‰ºÚÐZÛa»b’Ýwu›Ç/@ýcuö–H–6ÓÂc]Ũ7$\hwFƪPØ$VÀ{LµHÅYÁÙçÔ\Ðü;vÎñÀüM£1ô>I8wŸ¨¨ Þùâ`(:£ÕÀŘžZ[”ü ÜL¬A2Û[„°’ƒÌñ:‘<¢Lû(•ÔÇÂ=::¶†â’=2Ǩp›j‘ݳ~°ÿÒgöi­’vq«"™ûÓA`5Þûu¤ðÊ ?™Ij’Jø–¾Žq¸„;™®>û%ìDâ&¬TØÕ¯MÆJö*GÍì"Sr³Ãj¥Ìn¸6Ëš”¦ê±q.ø'ªáý"…¤—¼ rË T"s¹~Ɖ&œ”rºmí¯ÆÇh¸Œ©JÙSš“ +‡û$Ëú*Ï[¾'е5Ø̽þ^¿‚@rG{XÎN3?Ü&Óvj½ìÖfl3O­ˆÐ¥\á" ÝJ)P\°7À«J&zgT‘š|†ñhÝh^r×X&âhŒç]CŠÒ÷ˆÂú%#ÅŸß’ïçUUÒÙ$ïRDäü¾Rk¤zwŒñ­ã—Z +UßD„j%‘{7¹’&LoÅLó´T0‰*V^÷N‘³eVB)Êø‡tð_1J¿¡ãx)s0ßñ~±_+ÈLö;¾¡"ltMÚ³½­oIÆtè-Â<'_4À3.—Œò2JÄU½Û•T„¥UþÝ>A)JDyŽ«ë&á¾Ö”±‘= #¾cD6Çž@ü†ìÂà¿x¤èÑÏóDÁ»ÆŽf²4ÓÑHß™y÷\ò^¥±’í«diåúø¾ž†. +Ë—ÌF+uå| ã_ìŽ'¬gk"¸qáD]²S<þ€Õ07=Ó¾û” ³:]T?çÅ&3Ê÷Å”Ù-Ä»Ÿ—Ü^"lÊÀ %Zäß:oΠ§dÎÿ'(ÿüG~Ù™›º¸9Ú›ºØ¢ü6”à»endstream endobj -714 0 obj << +930 0 obj << /Type /Font /Subtype /Type1 -/Encoding 2140 0 R +/Encoding 2705 0 R /FirstChar 2 /LastChar 151 -/Widths 2157 0 R -/BaseFont /QOWXRN+URWPalladioL-Bold -/FontDescriptor 712 0 R +/Widths 2722 0 R +/BaseFont /NSYDKZ+URWPalladioL-Bold +/FontDescriptor 928 0 R >> endobj -712 0 obj << +928 0 obj << /Ascent 708 /CapHeight 672 /Descent -266 -/FontName /QOWXRN+URWPalladioL-Bold +/FontName /NSYDKZ+URWPalladioL-Bold /ItalicAngle 0 /StemV 123 /XHeight 471 /FontBBox [-152 -301 1000 935] /Flags 4 -/CharSet (/fi/fl/exclam/dollar/percent/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/question/at/A/B/C/D/E/F/G/H/I/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/bracketright/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/quotedblright/emdash) -/FontFile 713 0 R +/CharSet (/fi/fl/exclam/numbersign/dollar/percent/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/question/at/A/B/C/D/E/F/G/H/I/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/bracketright/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/quotedblright/emdash) +/FontFile 929 0 R >> endobj -2157 0 obj -[611 611 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 278 0 0 500 889 0 278 333 333 444 606 250 333 250 296 500 500 500 500 500 500 500 500 500 500 250 250 0 0 0 444 747 778 667 722 833 611 556 833 833 389 0 778 611 1000 833 833 611 833 722 611 667 778 778 1000 667 667 667 333 0 333 0 0 0 500 611 444 611 500 389 556 611 333 333 611 333 889 611 556 611 611 389 444 333 611 556 833 500 556 500 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 500 0 0 1000 ] +2722 0 obj +[611 611 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 278 0 500 500 889 0 278 333 333 444 606 250 333 250 296 500 500 500 500 500 500 500 500 500 500 250 250 0 0 0 444 747 778 667 722 833 611 556 833 833 389 0 778 611 1000 833 833 611 833 722 611 667 778 778 1000 667 667 667 333 0 333 0 0 0 500 611 444 611 500 389 556 611 333 333 611 333 889 611 556 611 611 389 444 333 611 556 833 500 556 500 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 500 0 0 1000 ] endobj -715 0 obj << +931 0 obj << /Type /Pages /Count 6 -/Parent 2158 0 R -/Kids [706 0 R 732 0 R 742 0 R 797 0 R 861 0 R 923 0 R] +/Parent 2723 0 R +/Kids [922 0 R 948 0 R 958 0 R 1013 0 R 1077 0 R 1140 0 R] >> endobj -954 0 obj << +1216 0 obj << /Type /Pages /Count 6 -/Parent 2158 0 R -/Kids [943 0 R 956 0 R 969 0 R 980 0 R 987 0 R 999 0 R] +/Parent 2723 0 R +/Kids [1202 0 R 1218 0 R 1230 0 R 1243 0 R 1254 0 R 1261 0 R] >> endobj -1011 0 obj << +1277 0 obj << /Type /Pages /Count 6 -/Parent 2158 0 R -/Kids [1004 0 R 1013 0 R 1024 0 R 1032 0 R 1039 0 R 1045 0 R] +/Parent 2723 0 R +/Kids [1273 0 R 1279 0 R 1287 0 R 1296 0 R 1306 0 R 1320 0 R] >> endobj -1068 0 obj << +1328 0 obj << /Type /Pages /Count 6 -/Parent 2158 0 R -/Kids [1053 0 R 1075 0 R 1085 0 R 1090 0 R 1094 0 R 1101 0 R] +/Parent 2723 0 R +/Kids [1324 0 R 1331 0 R 1338 0 R 1343 0 R 1364 0 R 1374 0 R] >> endobj -1117 0 obj << +1383 0 obj << /Type /Pages /Count 6 -/Parent 2158 0 R -/Kids [1109 0 R 1120 0 R 1127 0 R 1132 0 R 1142 0 R 1148 0 R] +/Parent 2723 0 R +/Kids [1380 0 R 1385 0 R 1390 0 R 1399 0 R 1408 0 R 1415 0 R] >> endobj -1158 0 obj << +1424 0 obj << /Type /Pages /Count 6 -/Parent 2158 0 R -/Kids [1152 0 R 1160 0 R 1164 0 R 1174 0 R 1179 0 R 1187 0 R] +/Parent 2723 0 R +/Kids [1421 0 R 1426 0 R 1436 0 R 1449 0 R 1457 0 R 1470 0 R] >> endobj -1203 0 obj << +1480 0 obj << /Type /Pages /Count 6 -/Parent 2159 0 R -/Kids [1195 0 R 1205 0 R 1214 0 R 1225 0 R 1230 0 R 1236 0 R] +/Parent 2724 0 R +/Kids [1476 0 R 1482 0 R 1488 0 R 1496 0 R 1502 0 R 1508 0 R] >> endobj -1245 0 obj << +1520 0 obj << /Type /Pages /Count 6 -/Parent 2159 0 R -/Kids [1242 0 R 1247 0 R 1255 0 R 1265 0 R 1269 0 R 1273 0 R] +/Parent 2724 0 R +/Kids [1517 0 R 1522 0 R 1529 0 R 1533 0 R 1543 0 R 1548 0 R] >> endobj -1282 0 obj << +1562 0 obj << /Type /Pages /Count 6 -/Parent 2159 0 R -/Kids [1278 0 R 1285 0 R 1289 0 R 1295 0 R 1306 0 R 1310 0 R] +/Parent 2724 0 R +/Kids [1555 0 R 1564 0 R 1573 0 R 1581 0 R 1592 0 R 1598 0 R] >> endobj -1322 0 obj << +1609 0 obj << /Type /Pages /Count 6 -/Parent 2159 0 R -/Kids [1314 0 R 1325 0 R 1332 0 R 1337 0 R 1342 0 R 1346 0 R] +/Parent 2724 0 R +/Kids [1604 0 R 1611 0 R 1615 0 R 1622 0 R 1627 0 R 1637 0 R] >> endobj -1356 0 obj << +1644 0 obj << /Type /Pages /Count 6 -/Parent 2159 0 R -/Kids [1350 0 R 1358 0 R 1365 0 R 1371 0 R 1378 0 R 1385 0 R] +/Parent 2724 0 R +/Kids [1641 0 R 1646 0 R 1650 0 R 1654 0 R 1660 0 R 1665 0 R] >> endobj -1398 0 obj << +1675 0 obj << /Type /Pages /Count 6 -/Parent 2159 0 R -/Kids [1391 0 R 1401 0 R 1409 0 R 1413 0 R 1418 0 R 1424 0 R] +/Parent 2724 0 R +/Kids [1670 0 R 1677 0 R 1682 0 R 1692 0 R 1696 0 R 1700 0 R] >> endobj -1437 0 obj << +1712 0 obj << /Type /Pages /Count 6 -/Parent 2160 0 R -/Kids [1433 0 R 1439 0 R 1443 0 R 1447 0 R 1454 0 R 1459 0 R] +/Parent 2725 0 R +/Kids [1705 0 R 1715 0 R 1723 0 R 1728 0 R 1732 0 R 1736 0 R] >> endobj -1486 0 obj << +1747 0 obj << /Type /Pages /Count 6 -/Parent 2160 0 R -/Kids [1474 0 R 1488 0 R 1512 0 R 1522 0 R 1528 0 R 1538 0 R] +/Parent 2725 0 R +/Kids [1740 0 R 1749 0 R 1756 0 R 1761 0 R 1768 0 R 1776 0 R] >> endobj -1552 0 obj << +1787 0 obj << /Type /Pages /Count 6 -/Parent 2160 0 R -/Kids [1544 0 R 1554 0 R 1564 0 R 1574 0 R 1583 0 R 1590 0 R] +/Parent 2725 0 R +/Kids [1781 0 R 1791 0 R 1796 0 R 1800 0 R 1806 0 R 1811 0 R] >> endobj -1603 0 obj << +1820 0 obj << /Type /Pages /Count 6 -/Parent 2160 0 R -/Kids [1596 0 R 1606 0 R 1616 0 R 1623 0 R 1631 0 R 1637 0 R] +/Parent 2725 0 R +/Kids [1816 0 R 1822 0 R 1830 0 R 1837 0 R 1842 0 R 1846 0 R] >> endobj -1651 0 obj << +1853 0 obj << /Type /Pages /Count 6 -/Parent 2160 0 R -/Kids [1648 0 R 1653 0 R 1657 0 R 1668 0 R 1672 0 R 1679 0 R] +/Parent 2725 0 R +/Kids [1850 0 R 1855 0 R 1863 0 R 1867 0 R 1882 0 R 1896 0 R] >> endobj -1747 0 obj << +1927 0 obj << /Type /Pages /Count 6 -/Parent 2160 0 R -/Kids [1689 0 R 1749 0 R 1805 0 R 1859 0 R 1893 0 R 1902 0 R] +/Parent 2725 0 R +/Kids [1908 0 R 1929 0 R 1936 0 R 1942 0 R 1952 0 R 1958 0 R] >> endobj -1912 0 obj << +1973 0 obj << /Type /Pages /Count 6 -/Parent 2161 0 R -/Kids [1908 0 R 1914 0 R 1918 0 R 1923 0 R 1934 0 R 1939 0 R] +/Parent 2726 0 R +/Kids [1964 0 R 1975 0 R 1987 0 R 1995 0 R 2003 0 R 2007 0 R] >> endobj -1961 0 obj << +2022 0 obj << /Type /Pages /Count 6 -/Parent 2161 0 R -/Kids [1951 0 R 1963 0 R 1970 0 R 1982 0 R 1986 0 R 1997 0 R] +/Parent 2726 0 R +/Kids [2015 0 R 2024 0 R 2036 0 R 2043 0 R 2051 0 R 2055 0 R] >> endobj -2006 0 obj << +2071 0 obj << /Type /Pages /Count 6 -/Parent 2161 0 R -/Kids [2003 0 R 2008 0 R 2014 0 R 2027 0 R 2037 0 R 2041 0 R] +/Parent 2726 0 R +/Kids [2061 0 R 2073 0 R 2077 0 R 2081 0 R 2092 0 R 2096 0 R] >> endobj -2056 0 obj << +2112 0 obj << +/Type /Pages +/Count 6 +/Parent 2726 0 R +/Kids [2103 0 R 2114 0 R 2173 0 R 2229 0 R 2283 0 R 2318 0 R] +>> endobj +2333 0 obj << +/Type /Pages +/Count 6 +/Parent 2726 0 R +/Kids [2326 0 R 2335 0 R 2342 0 R 2347 0 R 2353 0 R 2357 0 R] +>> endobj +2371 0 obj << +/Type /Pages +/Count 6 +/Parent 2726 0 R +/Kids [2366 0 R 2373 0 R 2378 0 R 2382 0 R 2387 0 R 2398 0 R] +>> endobj +2414 0 obj << +/Type /Pages +/Count 6 +/Parent 2727 0 R +/Kids [2403 0 R 2416 0 R 2425 0 R 2434 0 R 2439 0 R 2448 0 R] +>> endobj +2457 0 obj << /Type /Pages /Count 6 -/Parent 2161 0 R -/Kids [2053 0 R 2058 0 R 2064 0 R 2075 0 R 2080 0 R 2084 0 R] +/Parent 2727 0 R +/Kids [2454 0 R 2459 0 R 2465 0 R 2476 0 R 2486 0 R 2492 0 R] +>> endobj +2507 0 obj << +/Type /Pages +/Count 6 +/Parent 2727 0 R +/Kids [2503 0 R 2509 0 R 2513 0 R 2517 0 R 2528 0 R 2539 0 R] +>> endobj +2549 0 obj << +/Type /Pages +/Count 6 +/Parent 2727 0 R +/Kids [2545 0 R 2551 0 R 2562 0 R 2566 0 R 2573 0 R 2587 0 R] +>> endobj +2597 0 obj << +/Type /Pages +/Count 6 +/Parent 2727 0 R +/Kids [2593 0 R 2599 0 R 2604 0 R 2613 0 R 2621 0 R 2631 0 R] +>> endobj +2647 0 obj << +/Type /Pages +/Count 6 +/Parent 2727 0 R +/Kids [2636 0 R 2649 0 R 2658 0 R 2666 0 R 2681 0 R 2693 0 R] +>> endobj +2723 0 obj << +/Type /Pages +/Count 36 +/Parent 2728 0 R +/Kids [931 0 R 1216 0 R 1277 0 R 1328 0 R 1383 0 R 1424 0 R] +>> endobj +2724 0 obj << +/Type /Pages +/Count 36 +/Parent 2728 0 R +/Kids [1480 0 R 1520 0 R 1562 0 R 1609 0 R 1644 0 R 1675 0 R] +>> endobj +2725 0 obj << +/Type /Pages +/Count 36 +/Parent 2728 0 R +/Kids [1712 0 R 1747 0 R 1787 0 R 1820 0 R 1853 0 R 1927 0 R] +>> endobj +2726 0 obj << +/Type /Pages +/Count 36 +/Parent 2728 0 R +/Kids [1973 0 R 2022 0 R 2071 0 R 2112 0 R 2333 0 R 2371 0 R] +>> endobj +2727 0 obj << +/Type /Pages +/Count 36 +/Parent 2728 0 R +/Kids [2414 0 R 2457 0 R 2507 0 R 2549 0 R 2597 0 R 2647 0 R] +>> endobj +2728 0 obj << +/Type /Pages +/Count 180 +/Kids [2723 0 R 2724 0 R 2725 0 R 2726 0 R 2727 0 R] +>> endobj +2729 0 obj << +/Type /Outlines +/First 7 0 R +/Last 835 0 R +/Count 10 +>> endobj +919 0 obj << +/Title 920 0 R +/A 917 0 R +/Parent 835 0 R +/Prev 915 0 R +>> endobj +915 0 obj << +/Title 916 0 R +/A 913 0 R +/Parent 835 0 R +/Prev 911 0 R +/Next 919 0 R +>> endobj +911 0 obj << +/Title 912 0 R +/A 909 0 R +/Parent 835 0 R +/Prev 907 0 R +/Next 915 0 R +>> endobj +907 0 obj << +/Title 908 0 R +/A 905 0 R +/Parent 835 0 R +/Prev 903 0 R +/Next 911 0 R +>> endobj +903 0 obj << +/Title 904 0 R +/A 901 0 R +/Parent 835 0 R +/Prev 899 0 R +/Next 907 0 R +>> endobj +899 0 obj << +/Title 900 0 R +/A 897 0 R +/Parent 835 0 R +/Prev 895 0 R +/Next 903 0 R +>> endobj +895 0 obj << +/Title 896 0 R +/A 893 0 R +/Parent 835 0 R +/Prev 891 0 R +/Next 899 0 R +>> endobj +891 0 obj << +/Title 892 0 R +/A 889 0 R +/Parent 835 0 R +/Prev 887 0 R +/Next 895 0 R +>> endobj +887 0 obj << +/Title 888 0 R +/A 885 0 R +/Parent 835 0 R +/Prev 883 0 R +/Next 891 0 R +>> endobj +883 0 obj << +/Title 884 0 R +/A 881 0 R +/Parent 835 0 R +/Prev 879 0 R +/Next 887 0 R +>> endobj +879 0 obj << +/Title 880 0 R +/A 877 0 R +/Parent 835 0 R +/Prev 875 0 R +/Next 883 0 R +>> endobj +875 0 obj << +/Title 876 0 R +/A 873 0 R +/Parent 835 0 R +/Prev 871 0 R +/Next 879 0 R +>> endobj +871 0 obj << +/Title 872 0 R +/A 869 0 R +/Parent 835 0 R +/Prev 867 0 R +/Next 875 0 R +>> endobj +867 0 obj << +/Title 868 0 R +/A 865 0 R +/Parent 835 0 R +/Prev 863 0 R +/Next 871 0 R +>> endobj +863 0 obj << +/Title 864 0 R +/A 861 0 R +/Parent 835 0 R +/Prev 859 0 R +/Next 867 0 R +>> endobj +859 0 obj << +/Title 860 0 R +/A 857 0 R +/Parent 835 0 R +/Prev 855 0 R +/Next 863 0 R +>> endobj +855 0 obj << +/Title 856 0 R +/A 853 0 R +/Parent 835 0 R +/Prev 851 0 R +/Next 859 0 R +>> endobj +851 0 obj << +/Title 852 0 R +/A 849 0 R +/Parent 835 0 R +/Prev 847 0 R +/Next 855 0 R +>> endobj +847 0 obj << +/Title 848 0 R +/A 845 0 R +/Parent 835 0 R +/Prev 843 0 R +/Next 851 0 R +>> endobj +843 0 obj << +/Title 844 0 R +/A 841 0 R +/Parent 835 0 R +/Prev 839 0 R +/Next 847 0 R +>> endobj +839 0 obj << +/Title 840 0 R +/A 837 0 R +/Parent 835 0 R +/Next 843 0 R +>> endobj +835 0 obj << +/Title 836 0 R +/A 833 0 R +/Parent 2729 0 R +/Prev 743 0 R +/First 839 0 R +/Last 919 0 R +/Count -21 +>> endobj +831 0 obj << +/Title 832 0 R +/A 829 0 R +/Parent 779 0 R +/Prev 803 0 R +>> endobj +827 0 obj << +/Title 828 0 R +/A 825 0 R +/Parent 803 0 R +/Prev 823 0 R +>> endobj +823 0 obj << +/Title 824 0 R +/A 821 0 R +/Parent 803 0 R +/Prev 819 0 R +/Next 827 0 R +>> endobj +819 0 obj << +/Title 820 0 R +/A 817 0 R +/Parent 803 0 R +/Prev 815 0 R +/Next 823 0 R +>> endobj +815 0 obj << +/Title 816 0 R +/A 813 0 R +/Parent 803 0 R +/Prev 811 0 R +/Next 819 0 R +>> endobj +811 0 obj << +/Title 812 0 R +/A 809 0 R +/Parent 803 0 R +/Prev 807 0 R +/Next 815 0 R +>> endobj +807 0 obj << +/Title 808 0 R +/A 805 0 R +/Parent 803 0 R +/Next 811 0 R +>> endobj +803 0 obj << +/Title 804 0 R +/A 801 0 R +/Parent 779 0 R +/Prev 799 0 R +/Next 831 0 R +/First 807 0 R +/Last 827 0 R +/Count -6 +>> endobj +799 0 obj << +/Title 800 0 R +/A 797 0 R +/Parent 779 0 R +/Prev 795 0 R +/Next 803 0 R +>> endobj +795 0 obj << +/Title 796 0 R +/A 793 0 R +/Parent 779 0 R +/Prev 791 0 R +/Next 799 0 R +>> endobj +791 0 obj << +/Title 792 0 R +/A 789 0 R +/Parent 779 0 R +/Prev 787 0 R +/Next 795 0 R +>> endobj +787 0 obj << +/Title 788 0 R +/A 785 0 R +/Parent 779 0 R +/Prev 783 0 R +/Next 791 0 R +>> endobj +783 0 obj << +/Title 784 0 R +/A 781 0 R +/Parent 779 0 R +/Next 787 0 R +>> endobj +779 0 obj << +/Title 780 0 R +/A 777 0 R +/Parent 743 0 R +/Prev 763 0 R +/First 783 0 R +/Last 831 0 R +/Count -7 +>> endobj +775 0 obj << +/Title 776 0 R +/A 773 0 R +/Parent 763 0 R +/Prev 771 0 R +>> endobj +771 0 obj << +/Title 772 0 R +/A 769 0 R +/Parent 763 0 R +/Prev 767 0 R +/Next 775 0 R +>> endobj +767 0 obj << +/Title 768 0 R +/A 765 0 R +/Parent 763 0 R +/Next 771 0 R +>> endobj +763 0 obj << +/Title 764 0 R +/A 761 0 R +/Parent 743 0 R +/Prev 755 0 R +/Next 779 0 R +/First 767 0 R +/Last 775 0 R +/Count -3 +>> endobj +759 0 obj << +/Title 760 0 R +/A 757 0 R +/Parent 755 0 R +>> endobj +755 0 obj << +/Title 756 0 R +/A 753 0 R +/Parent 743 0 R +/Prev 747 0 R +/Next 763 0 R +/First 759 0 R +/Last 759 0 R +/Count -1 +>> endobj +751 0 obj << +/Title 752 0 R +/A 749 0 R +/Parent 747 0 R +>> endobj +747 0 obj << +/Title 748 0 R +/A 745 0 R +/Parent 743 0 R +/Next 755 0 R +/First 751 0 R +/Last 751 0 R +/Count -1 +>> endobj +743 0 obj << +/Title 744 0 R +/A 741 0 R +/Parent 2729 0 R +/Prev 723 0 R +/Next 835 0 R +/First 747 0 R +/Last 779 0 R +/Count -4 >> endobj -2100 0 obj << -/Type /Pages -/Count 6 -/Parent 2161 0 R -/Kids [2091 0 R 2102 0 R 2113 0 R 2118 0 R 2129 0 R 2135 0 R] +739 0 obj << +/Title 740 0 R +/A 737 0 R +/Parent 723 0 R +/Prev 735 0 R >> endobj -2158 0 obj << -/Type /Pages -/Count 36 -/Parent 2162 0 R -/Kids [715 0 R 954 0 R 1011 0 R 1068 0 R 1117 0 R 1158 0 R] +735 0 obj << +/Title 736 0 R +/A 733 0 R +/Parent 723 0 R +/Prev 727 0 R +/Next 739 0 R >> endobj -2159 0 obj << -/Type /Pages -/Count 36 -/Parent 2162 0 R -/Kids [1203 0 R 1245 0 R 1282 0 R 1322 0 R 1356 0 R 1398 0 R] +731 0 obj << +/Title 732 0 R +/A 729 0 R +/Parent 727 0 R +>> endobj +727 0 obj << +/Title 728 0 R +/A 725 0 R +/Parent 723 0 R +/Next 735 0 R +/First 731 0 R +/Last 731 0 R +/Count -1 >> endobj -2160 0 obj << -/Type /Pages -/Count 36 -/Parent 2162 0 R -/Kids [1437 0 R 1486 0 R 1552 0 R 1603 0 R 1651 0 R 1747 0 R] +723 0 obj << +/Title 724 0 R +/A 721 0 R +/Parent 2729 0 R +/Prev 699 0 R +/Next 743 0 R +/First 727 0 R +/Last 739 0 R +/Count -3 >> endobj -2161 0 obj << -/Type /Pages -/Count 30 -/Parent 2162 0 R -/Kids [1912 0 R 1961 0 R 2006 0 R 2056 0 R 2100 0 R] +719 0 obj << +/Title 720 0 R +/A 717 0 R +/Parent 699 0 R +/Prev 707 0 R >> endobj -2162 0 obj << -/Type /Pages -/Count 138 -/Kids [2158 0 R 2159 0 R 2160 0 R 2161 0 R] +715 0 obj << +/Title 716 0 R +/A 713 0 R +/Parent 707 0 R +/Prev 711 0 R >> endobj -2163 0 obj << -/Type /Outlines -/First 7 0 R -/Last 651 0 R -/Count 10 +711 0 obj << +/Title 712 0 R +/A 709 0 R +/Parent 707 0 R +/Next 715 0 R +>> endobj +707 0 obj << +/Title 708 0 R +/A 705 0 R +/Parent 699 0 R +/Prev 703 0 R +/Next 719 0 R +/First 711 0 R +/Last 715 0 R +/Count -2 >> endobj 703 0 obj << /Title 704 0 R /A 701 0 R -/Parent 651 0 R -/Prev 699 0 R +/Parent 699 0 R +/Next 707 0 R >> endobj 699 0 obj << /Title 700 0 R /A 697 0 R -/Parent 651 0 R -/Prev 695 0 R -/Next 703 0 R +/Parent 2729 0 R +/Prev 355 0 R +/Next 723 0 R +/First 703 0 R +/Last 719 0 R +/Count -3 >> endobj 695 0 obj << /Title 696 0 R /A 693 0 R -/Parent 651 0 R +/Parent 675 0 R /Prev 691 0 R -/Next 699 0 R >> endobj 691 0 obj << /Title 692 0 R /A 689 0 R -/Parent 651 0 R +/Parent 675 0 R /Prev 687 0 R /Next 695 0 R >> endobj 687 0 obj << /Title 688 0 R /A 685 0 R -/Parent 651 0 R +/Parent 675 0 R /Prev 683 0 R /Next 691 0 R >> endobj 683 0 obj << /Title 684 0 R /A 681 0 R -/Parent 651 0 R +/Parent 675 0 R /Prev 679 0 R /Next 687 0 R >> endobj 679 0 obj << /Title 680 0 R /A 677 0 R -/Parent 651 0 R -/Prev 675 0 R +/Parent 675 0 R /Next 683 0 R >> endobj 675 0 obj << /Title 676 0 R /A 673 0 R -/Parent 651 0 R +/Parent 667 0 R /Prev 671 0 R -/Next 679 0 R +/First 679 0 R +/Last 695 0 R +/Count -5 >> endobj 671 0 obj << /Title 672 0 R /A 669 0 R -/Parent 651 0 R -/Prev 667 0 R +/Parent 667 0 R /Next 675 0 R >> endobj 667 0 obj << /Title 668 0 R /A 665 0 R -/Parent 651 0 R -/Prev 663 0 R -/Next 671 0 R +/Parent 355 0 R +/Prev 611 0 R +/First 671 0 R +/Last 675 0 R +/Count -2 >> endobj 663 0 obj << /Title 664 0 R /A 661 0 R -/Parent 651 0 R +/Parent 611 0 R /Prev 659 0 R -/Next 667 0 R >> endobj 659 0 obj << /Title 660 0 R /A 657 0 R -/Parent 651 0 R -/Prev 655 0 R +/Parent 611 0 R +/Prev 639 0 R /Next 663 0 R >> endobj 655 0 obj << /Title 656 0 R /A 653 0 R -/Parent 651 0 R -/Next 659 0 R +/Parent 639 0 R +/Prev 651 0 R >> endobj 651 0 obj << /Title 652 0 R /A 649 0 R -/Parent 2163 0 R -/Prev 615 0 R -/First 655 0 R -/Last 703 0 R -/Count -13 +/Parent 639 0 R +/Prev 647 0 R +/Next 655 0 R >> endobj 647 0 obj << /Title 648 0 R /A 645 0 R -/Parent 635 0 R +/Parent 639 0 R /Prev 643 0 R +/Next 651 0 R >> endobj 643 0 obj << /Title 644 0 R /A 641 0 R -/Parent 635 0 R -/Prev 639 0 R +/Parent 639 0 R /Next 647 0 R >> endobj 639 0 obj << /Title 640 0 R /A 637 0 R -/Parent 635 0 R -/Next 643 0 R +/Parent 611 0 R +/Prev 635 0 R +/Next 659 0 R +/First 643 0 R +/Last 655 0 R +/Count -4 >> endobj 635 0 obj << /Title 636 0 R /A 633 0 R -/Parent 615 0 R -/Prev 627 0 R -/First 639 0 R -/Last 647 0 R -/Count -3 +/Parent 611 0 R +/Prev 631 0 R +/Next 639 0 R >> endobj 631 0 obj << /Title 632 0 R /A 629 0 R -/Parent 627 0 R +/Parent 611 0 R +/Prev 627 0 R +/Next 635 0 R >> endobj 627 0 obj << /Title 628 0 R /A 625 0 R -/Parent 615 0 R -/Prev 619 0 R -/Next 635 0 R -/First 631 0 R -/Last 631 0 R -/Count -1 +/Parent 611 0 R +/Prev 615 0 R +/Next 631 0 R >> endobj 623 0 obj << /Title 624 0 R /A 621 0 R -/Parent 619 0 R +/Parent 615 0 R +/Prev 619 0 R >> endobj 619 0 obj << /Title 620 0 R /A 617 0 R /Parent 615 0 R -/Next 627 0 R -/First 623 0 R -/Last 623 0 R -/Count -1 +/Next 623 0 R >> endobj 615 0 obj << /Title 616 0 R /A 613 0 R -/Parent 2163 0 R -/Prev 595 0 R -/Next 651 0 R +/Parent 611 0 R +/Next 627 0 R /First 619 0 R -/Last 635 0 R -/Count -3 +/Last 623 0 R +/Count -2 >> endobj 611 0 obj << /Title 612 0 R /A 609 0 R -/Parent 595 0 R -/Prev 607 0 R +/Parent 355 0 R +/Prev 387 0 R +/Next 667 0 R +/First 615 0 R +/Last 663 0 R +/Count -7 >> endobj 607 0 obj << /Title 608 0 R /A 605 0 R -/Parent 595 0 R -/Prev 599 0 R -/Next 611 0 R +/Parent 591 0 R +/Prev 603 0 R >> endobj 603 0 obj << /Title 604 0 R /A 601 0 R -/Parent 599 0 R +/Parent 591 0 R +/Prev 599 0 R +/Next 607 0 R >> endobj 599 0 obj << /Title 600 0 R /A 597 0 R -/Parent 595 0 R -/Next 607 0 R -/First 603 0 R -/Last 603 0 R -/Count -1 +/Parent 591 0 R +/Prev 595 0 R +/Next 603 0 R >> endobj 595 0 obj << /Title 596 0 R /A 593 0 R -/Parent 2163 0 R -/Prev 571 0 R -/Next 615 0 R -/First 599 0 R -/Last 611 0 R -/Count -3 +/Parent 591 0 R +/Next 599 0 R >> endobj 591 0 obj << /Title 592 0 R /A 589 0 R -/Parent 571 0 R -/Prev 579 0 R +/Parent 387 0 R +/Prev 587 0 R +/First 595 0 R +/Last 607 0 R +/Count -4 >> endobj 587 0 obj << /Title 588 0 R /A 585 0 R -/Parent 579 0 R +/Parent 387 0 R /Prev 583 0 R +/Next 591 0 R >> endobj 583 0 obj << /Title 584 0 R /A 581 0 R -/Parent 579 0 R +/Parent 387 0 R +/Prev 579 0 R /Next 587 0 R >> endobj 579 0 obj << /Title 580 0 R /A 577 0 R -/Parent 571 0 R +/Parent 387 0 R /Prev 575 0 R -/Next 591 0 R -/First 583 0 R -/Last 587 0 R -/Count -2 +/Next 583 0 R >> endobj 575 0 obj << /Title 576 0 R /A 573 0 R -/Parent 571 0 R +/Parent 387 0 R +/Prev 571 0 R /Next 579 0 R >> endobj 571 0 obj << /Title 572 0 R /A 569 0 R -/Parent 2163 0 R -/Prev 243 0 R -/Next 595 0 R -/First 575 0 R -/Last 591 0 R -/Count -3 +/Parent 387 0 R +/Prev 567 0 R +/Next 575 0 R >> endobj 567 0 obj << /Title 568 0 R /A 565 0 R -/Parent 547 0 R +/Parent 387 0 R /Prev 563 0 R +/Next 571 0 R >> endobj 563 0 obj << /Title 564 0 R /A 561 0 R -/Parent 547 0 R +/Parent 387 0 R /Prev 559 0 R /Next 567 0 R >> endobj 559 0 obj << /Title 560 0 R /A 557 0 R -/Parent 547 0 R +/Parent 387 0 R /Prev 555 0 R /Next 563 0 R >> endobj 555 0 obj << /Title 556 0 R /A 553 0 R -/Parent 547 0 R +/Parent 387 0 R /Prev 551 0 R /Next 559 0 R >> endobj 551 0 obj << /Title 552 0 R /A 549 0 R -/Parent 547 0 R +/Parent 387 0 R +/Prev 547 0 R /Next 555 0 R >> endobj 547 0 obj << /Title 548 0 R /A 545 0 R -/Parent 539 0 R -/Prev 543 0 R -/First 551 0 R -/Last 567 0 R -/Count -5 +/Parent 387 0 R +/Prev 463 0 R +/Next 551 0 R >> endobj 543 0 obj << /Title 544 0 R /A 541 0 R -/Parent 539 0 R -/Next 547 0 R +/Parent 463 0 R +/Prev 539 0 R >> endobj 539 0 obj << /Title 540 0 R /A 537 0 R -/Parent 243 0 R -/Prev 483 0 R -/First 543 0 R -/Last 547 0 R -/Count -2 +/Parent 463 0 R +/Prev 535 0 R +/Next 543 0 R >> endobj 535 0 obj << /Title 536 0 R /A 533 0 R -/Parent 483 0 R +/Parent 463 0 R /Prev 531 0 R +/Next 539 0 R >> endobj 531 0 obj << /Title 532 0 R /A 529 0 R -/Parent 483 0 R -/Prev 511 0 R +/Parent 463 0 R +/Prev 527 0 R /Next 535 0 R >> endobj 527 0 obj << /Title 528 0 R /A 525 0 R -/Parent 511 0 R +/Parent 463 0 R /Prev 523 0 R +/Next 531 0 R >> endobj 523 0 obj << /Title 524 0 R /A 521 0 R -/Parent 511 0 R +/Parent 463 0 R /Prev 519 0 R /Next 527 0 R >> endobj 519 0 obj << /Title 520 0 R /A 517 0 R -/Parent 511 0 R +/Parent 463 0 R /Prev 515 0 R /Next 523 0 R >> endobj 515 0 obj << /Title 516 0 R /A 513 0 R -/Parent 511 0 R +/Parent 463 0 R +/Prev 511 0 R /Next 519 0 R >> endobj 511 0 obj << /Title 512 0 R /A 509 0 R -/Parent 483 0 R +/Parent 463 0 R /Prev 507 0 R -/Next 531 0 R -/First 515 0 R -/Last 527 0 R -/Count -4 +/Next 515 0 R >> endobj 507 0 obj << /Title 508 0 R /A 505 0 R -/Parent 483 0 R +/Parent 463 0 R /Prev 503 0 R /Next 511 0 R >> endobj 503 0 obj << /Title 504 0 R /A 501 0 R -/Parent 483 0 R +/Parent 463 0 R /Prev 499 0 R /Next 507 0 R >> endobj 499 0 obj << /Title 500 0 R /A 497 0 R -/Parent 483 0 R -/Prev 487 0 R +/Parent 463 0 R +/Prev 495 0 R /Next 503 0 R >> endobj 495 0 obj << /Title 496 0 R /A 493 0 R -/Parent 487 0 R +/Parent 463 0 R /Prev 491 0 R +/Next 499 0 R >> endobj 491 0 obj << /Title 492 0 R /A 489 0 R -/Parent 487 0 R +/Parent 463 0 R +/Prev 487 0 R /Next 495 0 R >> endobj 487 0 obj << /Title 488 0 R /A 485 0 R -/Parent 483 0 R -/Next 499 0 R -/First 491 0 R -/Last 495 0 R -/Count -2 +/Parent 463 0 R +/Prev 483 0 R +/Next 491 0 R >> endobj 483 0 obj << /Title 484 0 R /A 481 0 R -/Parent 243 0 R -/Prev 275 0 R -/Next 539 0 R -/First 487 0 R -/Last 535 0 R -/Count -7 +/Parent 463 0 R +/Prev 479 0 R +/Next 487 0 R >> endobj 479 0 obj << /Title 480 0 R /A 477 0 R /Parent 463 0 R /Prev 475 0 R +/Next 483 0 R >> endobj 475 0 obj << /Title 476 0 R @@ -12324,328 +15378,338 @@ endobj 463 0 obj << /Title 464 0 R /A 461 0 R -/Parent 275 0 R +/Parent 387 0 R /Prev 459 0 R +/Next 547 0 R /First 467 0 R -/Last 479 0 R -/Count -4 +/Last 543 0 R +/Count -20 >> endobj 459 0 obj << /Title 460 0 R /A 457 0 R -/Parent 275 0 R +/Parent 387 0 R /Prev 455 0 R /Next 463 0 R >> endobj 455 0 obj << /Title 456 0 R /A 453 0 R -/Parent 275 0 R +/Parent 387 0 R /Prev 451 0 R /Next 459 0 R >> endobj 451 0 obj << /Title 452 0 R /A 449 0 R -/Parent 275 0 R +/Parent 387 0 R /Prev 447 0 R /Next 455 0 R >> endobj 447 0 obj << /Title 448 0 R /A 445 0 R -/Parent 275 0 R +/Parent 387 0 R /Prev 443 0 R /Next 451 0 R >> endobj 443 0 obj << /Title 444 0 R /A 441 0 R -/Parent 275 0 R -/Prev 439 0 R +/Parent 387 0 R +/Prev 427 0 R /Next 447 0 R >> endobj 439 0 obj << /Title 440 0 R /A 437 0 R -/Parent 275 0 R +/Parent 427 0 R /Prev 435 0 R -/Next 443 0 R >> endobj 435 0 obj << /Title 436 0 R /A 433 0 R -/Parent 275 0 R +/Parent 427 0 R /Prev 431 0 R /Next 439 0 R >> endobj 431 0 obj << /Title 432 0 R /A 429 0 R -/Parent 275 0 R -/Prev 427 0 R +/Parent 427 0 R /Next 435 0 R >> endobj 427 0 obj << /Title 428 0 R /A 425 0 R -/Parent 275 0 R -/Prev 351 0 R -/Next 431 0 R +/Parent 387 0 R +/Prev 423 0 R +/Next 443 0 R +/First 431 0 R +/Last 439 0 R +/Count -3 >> endobj 423 0 obj << /Title 424 0 R /A 421 0 R -/Parent 351 0 R +/Parent 387 0 R /Prev 419 0 R +/Next 427 0 R >> endobj 419 0 obj << /Title 420 0 R /A 417 0 R -/Parent 351 0 R +/Parent 387 0 R /Prev 415 0 R /Next 423 0 R >> endobj 415 0 obj << /Title 416 0 R /A 413 0 R -/Parent 351 0 R +/Parent 387 0 R /Prev 411 0 R /Next 419 0 R >> endobj 411 0 obj << /Title 412 0 R /A 409 0 R -/Parent 351 0 R +/Parent 387 0 R /Prev 407 0 R /Next 415 0 R >> endobj 407 0 obj << /Title 408 0 R /A 405 0 R -/Parent 351 0 R +/Parent 387 0 R /Prev 403 0 R /Next 411 0 R >> endobj 403 0 obj << /Title 404 0 R /A 401 0 R -/Parent 351 0 R +/Parent 387 0 R /Prev 399 0 R /Next 407 0 R >> endobj 399 0 obj << /Title 400 0 R /A 397 0 R -/Parent 351 0 R +/Parent 387 0 R /Prev 395 0 R /Next 403 0 R >> endobj 395 0 obj << /Title 396 0 R /A 393 0 R -/Parent 351 0 R +/Parent 387 0 R /Prev 391 0 R /Next 399 0 R >> endobj 391 0 obj << /Title 392 0 R /A 389 0 R -/Parent 351 0 R -/Prev 387 0 R +/Parent 387 0 R /Next 395 0 R >> endobj 387 0 obj << /Title 388 0 R /A 385 0 R -/Parent 351 0 R -/Prev 383 0 R -/Next 391 0 R +/Parent 355 0 R +/Prev 359 0 R +/Next 611 0 R +/First 391 0 R +/Last 591 0 R +/Count -28 >> endobj 383 0 obj << /Title 384 0 R /A 381 0 R -/Parent 351 0 R +/Parent 375 0 R /Prev 379 0 R -/Next 387 0 R >> endobj 379 0 obj << /Title 380 0 R /A 377 0 R -/Parent 351 0 R -/Prev 375 0 R +/Parent 375 0 R /Next 383 0 R >> endobj 375 0 obj << /Title 376 0 R /A 373 0 R -/Parent 351 0 R -/Prev 371 0 R -/Next 379 0 R +/Parent 359 0 R +/Prev 363 0 R +/First 379 0 R +/Last 383 0 R +/Count -2 >> endobj 371 0 obj << /Title 372 0 R /A 369 0 R -/Parent 351 0 R +/Parent 363 0 R /Prev 367 0 R -/Next 375 0 R >> endobj 367 0 obj << /Title 368 0 R /A 365 0 R -/Parent 351 0 R -/Prev 363 0 R +/Parent 363 0 R /Next 371 0 R >> endobj 363 0 obj << /Title 364 0 R /A 361 0 R -/Parent 351 0 R -/Prev 359 0 R -/Next 367 0 R +/Parent 359 0 R +/Next 375 0 R +/First 367 0 R +/Last 371 0 R +/Count -2 >> endobj 359 0 obj << /Title 360 0 R /A 357 0 R -/Parent 351 0 R -/Prev 355 0 R -/Next 363 0 R +/Parent 355 0 R +/Next 387 0 R +/First 363 0 R +/Last 375 0 R +/Count -2 >> endobj 355 0 obj << /Title 356 0 R /A 353 0 R -/Parent 351 0 R -/Next 359 0 R +/Parent 2729 0 R +/Prev 343 0 R +/Next 699 0 R +/First 359 0 R +/Last 667 0 R +/Count -4 >> endobj 351 0 obj << /Title 352 0 R /A 349 0 R -/Parent 275 0 R +/Parent 343 0 R /Prev 347 0 R -/Next 427 0 R -/First 355 0 R -/Last 423 0 R -/Count -18 >> endobj 347 0 obj << /Title 348 0 R /A 345 0 R -/Parent 275 0 R -/Prev 343 0 R +/Parent 343 0 R /Next 351 0 R >> endobj 343 0 obj << /Title 344 0 R /A 341 0 R -/Parent 275 0 R -/Prev 339 0 R -/Next 347 0 R +/Parent 2729 0 R +/Prev 131 0 R +/Next 355 0 R +/First 347 0 R +/Last 351 0 R +/Count -2 >> endobj 339 0 obj << /Title 340 0 R /A 337 0 R -/Parent 275 0 R +/Parent 331 0 R /Prev 335 0 R -/Next 343 0 R >> endobj 335 0 obj << /Title 336 0 R /A 333 0 R -/Parent 275 0 R -/Prev 331 0 R +/Parent 331 0 R /Next 339 0 R >> endobj 331 0 obj << /Title 332 0 R /A 329 0 R -/Parent 275 0 R -/Prev 315 0 R -/Next 335 0 R +/Parent 131 0 R +/Prev 287 0 R +/First 335 0 R +/Last 339 0 R +/Count -2 >> endobj 327 0 obj << /Title 328 0 R /A 325 0 R -/Parent 315 0 R +/Parent 287 0 R /Prev 323 0 R >> endobj 323 0 obj << /Title 324 0 R /A 321 0 R -/Parent 315 0 R +/Parent 287 0 R /Prev 319 0 R /Next 327 0 R >> endobj 319 0 obj << /Title 320 0 R /A 317 0 R -/Parent 315 0 R +/Parent 287 0 R +/Prev 315 0 R /Next 323 0 R >> endobj 315 0 obj << /Title 316 0 R /A 313 0 R -/Parent 275 0 R -/Prev 311 0 R -/Next 331 0 R -/First 319 0 R -/Last 327 0 R -/Count -3 +/Parent 287 0 R +/Prev 303 0 R +/Next 319 0 R >> endobj 311 0 obj << /Title 312 0 R /A 309 0 R -/Parent 275 0 R +/Parent 303 0 R /Prev 307 0 R -/Next 315 0 R >> endobj 307 0 obj << /Title 308 0 R /A 305 0 R -/Parent 275 0 R -/Prev 303 0 R +/Parent 303 0 R /Next 311 0 R >> endobj 303 0 obj << /Title 304 0 R /A 301 0 R -/Parent 275 0 R -/Prev 299 0 R -/Next 307 0 R +/Parent 287 0 R +/Prev 291 0 R +/Next 315 0 R +/First 307 0 R +/Last 311 0 R +/Count -2 >> endobj 299 0 obj << /Title 300 0 R /A 297 0 R -/Parent 275 0 R +/Parent 291 0 R /Prev 295 0 R -/Next 303 0 R >> endobj 295 0 obj << /Title 296 0 R /A 293 0 R -/Parent 275 0 R -/Prev 291 0 R +/Parent 291 0 R /Next 299 0 R >> endobj 291 0 obj << /Title 292 0 R /A 289 0 R -/Parent 275 0 R -/Prev 287 0 R -/Next 295 0 R +/Parent 287 0 R +/Next 303 0 R +/First 295 0 R +/Last 299 0 R +/Count -2 >> endobj 287 0 obj << /Title 288 0 R /A 285 0 R -/Parent 275 0 R -/Prev 283 0 R -/Next 291 0 R +/Parent 131 0 R +/Prev 275 0 R +/Next 331 0 R +/First 291 0 R +/Last 327 0 R +/Count -6 >> endobj 283 0 obj << /Title 284 0 R /A 281 0 R /Parent 275 0 R /Prev 279 0 R -/Next 287 0 R >> endobj 279 0 obj << /Title 280 0 R @@ -12656,101 +15720,95 @@ endobj 275 0 obj << /Title 276 0 R /A 273 0 R -/Parent 243 0 R -/Prev 247 0 R -/Next 483 0 R +/Parent 131 0 R +/Prev 219 0 R +/Next 287 0 R /First 279 0 R -/Last 463 0 R -/Count -26 +/Last 283 0 R +/Count -2 >> endobj 271 0 obj << /Title 272 0 R /A 269 0 R -/Parent 263 0 R +/Parent 219 0 R /Prev 267 0 R >> endobj 267 0 obj << /Title 268 0 R /A 265 0 R -/Parent 263 0 R +/Parent 219 0 R +/Prev 263 0 R /Next 271 0 R >> endobj 263 0 obj << /Title 264 0 R /A 261 0 R -/Parent 247 0 R -/Prev 251 0 R -/First 267 0 R -/Last 271 0 R -/Count -2 +/Parent 219 0 R +/Prev 259 0 R +/Next 267 0 R >> endobj 259 0 obj << /Title 260 0 R /A 257 0 R -/Parent 251 0 R +/Parent 219 0 R /Prev 255 0 R +/Next 263 0 R >> endobj 255 0 obj << /Title 256 0 R /A 253 0 R -/Parent 251 0 R +/Parent 219 0 R +/Prev 251 0 R /Next 259 0 R >> endobj 251 0 obj << /Title 252 0 R /A 249 0 R -/Parent 247 0 R -/Next 263 0 R -/First 255 0 R -/Last 259 0 R -/Count -2 +/Parent 219 0 R +/Prev 247 0 R +/Next 255 0 R >> endobj 247 0 obj << /Title 248 0 R /A 245 0 R -/Parent 243 0 R -/Next 275 0 R -/First 251 0 R -/Last 263 0 R -/Count -2 +/Parent 219 0 R +/Prev 243 0 R +/Next 251 0 R >> endobj 243 0 obj << /Title 244 0 R /A 241 0 R -/Parent 2163 0 R -/Prev 231 0 R -/Next 571 0 R -/First 247 0 R -/Last 539 0 R -/Count -4 +/Parent 219 0 R +/Prev 239 0 R +/Next 247 0 R >> endobj 239 0 obj << /Title 240 0 R /A 237 0 R -/Parent 231 0 R +/Parent 219 0 R /Prev 235 0 R +/Next 243 0 R >> endobj 235 0 obj << /Title 236 0 R /A 233 0 R -/Parent 231 0 R +/Parent 219 0 R +/Prev 231 0 R /Next 239 0 R >> endobj 231 0 obj << /Title 232 0 R /A 229 0 R -/Parent 2163 0 R -/Prev 131 0 R -/Next 243 0 R -/First 235 0 R -/Last 239 0 R -/Count -2 +/Parent 219 0 R +/Prev 227 0 R +/Next 235 0 R >> endobj 227 0 obj << /Title 228 0 R /A 225 0 R /Parent 219 0 R /Prev 223 0 R +/Next 231 0 R >> endobj 223 0 obj << /Title 224 0 R @@ -12763,9 +15821,10 @@ endobj /A 217 0 R /Parent 131 0 R /Prev 203 0 R +/Next 275 0 R /First 223 0 R -/Last 227 0 R -/Count -2 +/Last 271 0 R +/Count -13 >> endobj 215 0 obj << /Title 216 0 R @@ -12921,12 +15980,12 @@ endobj 131 0 obj << /Title 132 0 R /A 129 0 R -/Parent 2163 0 R +/Parent 2729 0 R /Prev 91 0 R -/Next 231 0 R +/Next 343 0 R /First 135 0 R -/Last 219 0 R -/Count -9 +/Last 331 0 R +/Count -12 >> endobj 127 0 obj << /Title 128 0 R @@ -12995,7 +16054,7 @@ endobj 91 0 obj << /Title 92 0 R /A 89 0 R -/Parent 2163 0 R +/Parent 2729 0 R /Prev 67 0 R /Next 131 0 R /First 95 0 R @@ -13038,7 +16097,7 @@ endobj 67 0 obj << /Title 68 0 R /A 65 0 R -/Parent 2163 0 R +/Parent 2729 0 R /Prev 7 0 R /Next 91 0 R /First 71 0 R @@ -13147,2213 +16206,2779 @@ endobj 7 0 obj << /Title 8 0 R /A 5 0 R -/Parent 2163 0 R +/Parent 2729 0 R /Next 67 0 R /First 11 0 R /Last 23 0 R /Count -4 >> endobj -2164 0 obj << -/Names [(Access_Control_Lists) 1635 0 R (Bv9ARM.ch01) 945 0 R (Bv9ARM.ch02) 990 0 R (Bv9ARM.ch03) 1007 0 R (Bv9ARM.ch04) 1056 0 R (Bv9ARM.ch05) 1155 0 R (Bv9ARM.ch06) 1167 0 R (Bv9ARM.ch07) 1634 0 R (Bv9ARM.ch08) 1660 0 R (Bv9ARM.ch09) 1675 0 R (Bv9ARM.ch10) 1896 0 R (Configuration_File_Grammar) 1191 0 R (DNSSEC) 1123 0 R (Doc-Start) 711 0 R (Setting_TTLs) 1560 0 R (acache) 997 0 R (access_control) 1320 0 R (acl) 1199 0 R (address_match_lists) 1172 0 R (admin_tools) 1030 0 R (appendix.A) 614 0 R (appendix.B) 650 0 R (bibliography) 1683 0 R (boolean_options) 1072 0 R (builtin) 1404 0 R (chapter*.1) 745 0 R (chapter.1) 6 0 R (chapter.2) 66 0 R (chapter.3) 90 0 R (chapter.4) 130 0 R (chapter.5) 230 0 R (chapter.6) 242 0 R (chapter.7) 570 0 R (chapter.8) 594 0 R (cite.RFC1033) 1811 0 R (cite.RFC1034) 1695 0 R (cite.RFC1035) 1697 0 R (cite.RFC1101) 1793 0 R (cite.RFC1123) 1795 0 R (cite.RFC1183) 1755 0 R (cite.RFC1464) 1833 0 R (cite.RFC1535) 1740 0 R (cite.RFC1536) 1742 0 R (cite.RFC1537) 1813 0 R (cite.RFC1591) 1797 0 R (cite.RFC1706) 1757 0 R (cite.RFC1712) 1853 0 R (cite.RFC1713) 1835 0 R (cite.RFC1794) 1837 0 R (cite.RFC1876) 1759 0 R (cite.RFC1912) 1815 0 R (cite.RFC1982) 1744 0 R (cite.RFC1995) 1702 0 R (cite.RFC1996) 1704 0 R (cite.RFC2010) 1817 0 R (cite.RFC2052) 1761 0 R (cite.RFC2065) 1865 0 R (cite.RFC2136) 1706 0 R (cite.RFC2137) 1867 0 R (cite.RFC2163) 1763 0 R (cite.RFC2168) 1765 0 R (cite.RFC2181) 1708 0 R (cite.RFC2219) 1819 0 R (cite.RFC2230) 1767 0 R (cite.RFC2240) 1839 0 R (cite.RFC2308) 1710 0 R (cite.RFC2317) 1799 0 R (cite.RFC2345) 1841 0 R (cite.RFC2352) 1843 0 R (cite.RFC2535) 1869 0 R (cite.RFC2536) 1769 0 R (cite.RFC2537) 1771 0 R (cite.RFC2538) 1773 0 R (cite.RFC2539) 1775 0 R (cite.RFC2540) 1777 0 R (cite.RFC2671) 1712 0 R (cite.RFC2672) 1714 0 R (cite.RFC2673) 1855 0 R (cite.RFC2782) 1779 0 R (cite.RFC2825) 1823 0 R (cite.RFC2826) 1801 0 R (cite.RFC2845) 1716 0 R (cite.RFC2874) 1857 0 R (cite.RFC2915) 1781 0 R (cite.RFC2929) 1803 0 R (cite.RFC2930) 1718 0 R (cite.RFC2931) 1720 0 R (cite.RFC3007) 1722 0 R (cite.RFC3008) 1871 0 R (cite.RFC3071) 1845 0 R (cite.RFC3090) 1873 0 R (cite.RFC3110) 1783 0 R (cite.RFC3123) 1785 0 R (cite.RFC3225) 1728 0 R (cite.RFC3258) 1847 0 R (cite.RFC3445) 1875 0 R (cite.RFC3490) 1825 0 R (cite.RFC3491) 1827 0 R (cite.RFC3492) 1829 0 R (cite.RFC3596) 1787 0 R (cite.RFC3597) 1789 0 R (cite.RFC3645) 1724 0 R (cite.RFC3655) 1877 0 R (cite.RFC3658) 1879 0 R (cite.RFC3755) 1881 0 R (cite.RFC3757) 1883 0 R (cite.RFC3833) 1730 0 R (cite.RFC3845) 1885 0 R (cite.RFC3901) 1849 0 R (cite.RFC4033) 1732 0 R (cite.RFC4034) 1734 0 R (cite.RFC4035) 1736 0 R (cite.RFC4074) 1746 0 R (cite.RFC974) 1699 0 R (cite.id2506284) 1890 0 R (clients-per-query) 1604 0 R (configuration_file_elements) 1168 0 R (controls_statement_definition_and_usage) 1043 0 R (diagnostic_tools) 978 0 R (dynamic_update) 1066 0 R (dynamic_update_policies) 1118 0 R (dynamic_update_security) 1330 0 R (empty) 1406 0 R (historical_dns_information) 1677 0 R (id2466560) 946 0 R (id2466583) 947 0 R (id2467290) 1081 0 R (id2467308) 1082 0 R (id2467474) 948 0 R (id2467483) 949 0 R (id2467723) 960 0 R (id2467745) 961 0 R (id2467779) 962 0 R (id2467863) 965 0 R (id2467956) 958 0 R (id2470261) 972 0 R (id2470284) 975 0 R (id2470382) 976 0 R (id2470404) 977 0 R (id2470502) 983 0 R (id2470537) 984 0 R (id2470564) 985 0 R (id2470598) 991 0 R (id2470625) 992 0 R (id2470637) 993 0 R (id2470731) 996 0 R (id2470742) 1002 0 R (id2470774) 1009 0 R (id2470790) 1010 0 R (id2470812) 1016 0 R (id2470829) 1017 0 R (id2471235) 1020 0 R (id2471240) 1021 0 R (id2473016) 1048 0 R (id2473028) 1049 0 R (id2473683) 1098 0 R (id2473700) 1099 0 R (id2474421) 1104 0 R (id2474439) 1105 0 R (id2474450) 1106 0 R (id2474554) 1107 0 R (id2474680) 1112 0 R (id2474728) 1114 0 R (id2474742) 1115 0 R (id2474791) 1116 0 R (id2474859) 1124 0 R (id2475006) 1125 0 R (id2475156) 1130 0 R (id2475394) 1138 0 R (id2475524) 1145 0 R (id2475545) 1146 0 R (id2475578) 1156 0 R (id2475862) 1169 0 R (id2476724) 1177 0 R (id2476752) 1182 0 R (id2476957) 1183 0 R (id2476972) 1184 0 R (id2477070) 1190 0 R (id2477213) 1192 0 R (id2477656) 1198 0 R (id2477699) 1200 0 R (id2477846) 1202 0 R (id2478275) 1210 0 R (id2478292) 1211 0 R (id2478315) 1217 0 R (id2478339) 1218 0 R (id2478498) 1222 0 R (id2478624) 1223 0 R (id2478676) 1228 0 R (id2479437) 1239 0 R (id2480103) 1250 0 R (id2480163) 1251 0 R (id2480548) 1253 0 R (id2480621) 1258 0 R (id2480685) 1261 0 R (id2480729) 1262 0 R (id2480744) 1263 0 R (id2483230) 1292 0 R (id2485002) 1317 0 R (id2485061) 1319 0 R (id2485635) 1335 0 R (id2486906) 1353 0 R (id2486966) 1355 0 R (id2487320) 1368 0 R (id2487822) 1382 0 R (id2489986) 1428 0 R (id2490140) 1429 0 R (id2490192) 1430 0 R (id2490410) 1436 0 R (id2491952) 1450 0 R (id2491959) 1451 0 R (id2491964) 1452 0 R (id2492318) 1463 0 R (id2492352) 1464 0 R (id2494048) 1519 0 R (id2494430) 1525 0 R (id2494449) 1526 0 R (id2494537) 1533 0 R (id2494706) 1535 0 R (id2495944) 1541 0 R (id2496072) 1547 0 R (id2496093) 1548 0 R (id2496388) 1550 0 R (id2496524) 1557 0 R (id2496542) 1558 0 R (id2497015) 1561 0 R (id2497140) 1567 0 R (id2497155) 1568 0 R (id2497267) 1570 0 R (id2497289) 1571 0 R (id2497305) 1572 0 R (id2497434) 1577 0 R (id2497504) 1578 0 R (id2497676) 1579 0 R (id2497738) 1580 0 R (id2498169) 1587 0 R (id2498604) 1599 0 R (id2498610) 1600 0 R (id2500077) 1609 0 R (id2500084) 1610 0 R (id2500529) 1612 0 R (id2500534) 1613 0 R (id2501479) 1619 0 R (id2501648) 1620 0 R (id2501989) 1629 0 R (id2502163) 1644 0 R (id2502312) 1645 0 R (id2502440) 1646 0 R (id2502588) 1661 0 R (id2502594) 1662 0 R (id2502605) 1663 0 R (id2502622) 1664 0 R (id2502753) 1676 0 R (id2502993) 1682 0 R (id2503180) 1687 0 R (id2503182) 1693 0 R (id2503191) 1698 0 R (id2503214) 1694 0 R (id2503238) 1696 0 R (id2503274) 1707 0 R (id2503301) 1709 0 R (id2503326) 1701 0 R (id2503351) 1703 0 R (id2503374) 1705 0 R (id2503430) 1711 0 R (id2503457) 1713 0 R (id2503483) 1715 0 R (id2503545) 1717 0 R (id2503575) 1719 0 R (id2503605) 1721 0 R (id2503632) 1723 0 R (id2503706) 1726 0 R (id2503714) 1727 0 R (id2503740) 1729 0 R (id2503845) 1731 0 R (id2503910) 1733 0 R (id2503975) 1735 0 R (id2504040) 1738 0 R (id2504049) 1739 0 R (id2504074) 1741 0 R (id2504142) 1743 0 R (id2504178) 1745 0 R (id2504218) 1753 0 R (id2504224) 1754 0 R (id2504281) 1756 0 R (id2504318) 1764 0 R (id2504354) 1758 0 R (id2504408) 1760 0 R (id2504446) 1762 0 R (id2504472) 1766 0 R (id2504498) 1768 0 R (id2504524) 1770 0 R (id2504551) 1772 0 R (id2504590) 1774 0 R (id2504620) 1776 0 R (id2504650) 1778 0 R (id2504693) 1780 0 R (id2504726) 1782 0 R (id2504753) 1784 0 R (id2504844) 1786 0 R (id2504902) 1788 0 R (id2504926) 1791 0 R (id2504934) 1792 0 R (id2504960) 1794 0 R (id2504982) 1796 0 R (id2505005) 1798 0 R (id2505051) 1800 0 R (id2505075) 1802 0 R (id2505125) 1809 0 R (id2505132) 1810 0 R (id2505156) 1812 0 R (id2505182) 1814 0 R (id2505209) 1816 0 R (id2505245) 1818 0 R (id2505286) 1821 0 R (id2505291) 1822 0 R (id2505323) 1824 0 R (id2505369) 1826 0 R (id2505404) 1828 0 R (id2505431) 1831 0 R (id2505449) 1832 0 R (id2505472) 1834 0 R (id2505497) 1836 0 R (id2505523) 1838 0 R (id2505546) 1840 0 R (id2505592) 1842 0 R (id2505616) 1844 0 R (id2505642) 1846 0 R (id2505668) 1848 0 R (id2505705) 1851 0 R (id2505712) 1852 0 R (id2505769) 1854 0 R (id2505796) 1856 0 R (id2505832) 1863 0 R (id2505844) 1864 0 R (id2505883) 1866 0 R (id2505910) 1868 0 R (id2505940) 1870 0 R (id2505965) 1872 0 R (id2505992) 1874 0 R (id2506028) 1876 0 R (id2506065) 1878 0 R (id2506091) 1880 0 R (id2506118) 1882 0 R (id2506163) 1884 0 R (id2506204) 1887 0 R (id2506282) 1889 0 R (id2506284) 1891 0 R (incremental_zone_transfers) 1078 0 R (internet_drafts) 1886 0 R (ipv6addresses) 1140 0 R (journal) 1067 0 R (lwresd) 1157 0 R (man.dig) 1897 0 R (man.dnssec-dsfromkey) 1945 0 R (man.dnssec-keyfromlabel) 1959 0 R (man.dnssec-keygen) 1976 0 R (man.dnssec-signzone) 1993 0 R (man.host) 1930 0 R (man.named) 2047 0 R (man.named-checkconf) 2019 0 R (man.named-checkzone) 2031 0 R (man.nsupdate) 2070 0 R (man.rndc) 2095 0 R (man.rndc-confgen) 2124 0 R (man.rndc.conf) 2108 0 R (notify) 1057 0 R (options) 1276 0 R (page.1) 710 0 R (page.10) 1034 0 R (page.100) 1861 0 R (page.101) 1895 0 R (page.102) 1904 0 R (page.103) 1910 0 R (page.104) 1916 0 R (page.105) 1920 0 R (page.106) 1925 0 R (page.107) 1936 0 R (page.108) 1941 0 R (page.109) 1953 0 R (page.11) 1041 0 R (page.110) 1965 0 R (page.111) 1972 0 R (page.112) 1984 0 R (page.113) 1988 0 R (page.114) 1999 0 R (page.115) 2005 0 R (page.116) 2010 0 R (page.117) 2016 0 R (page.118) 2029 0 R (page.119) 2039 0 R (page.12) 1047 0 R (page.120) 2043 0 R (page.121) 2055 0 R (page.122) 2060 0 R (page.123) 2066 0 R (page.124) 2077 0 R (page.125) 2082 0 R (page.126) 2086 0 R (page.127) 2093 0 R (page.128) 2104 0 R (page.129) 2115 0 R (page.13) 1055 0 R (page.130) 2120 0 R (page.131) 2131 0 R (page.132) 2137 0 R (page.14) 1077 0 R (page.15) 1087 0 R (page.16) 1092 0 R (page.17) 1096 0 R (page.18) 1103 0 R (page.19) 1111 0 R (page.2) 734 0 R (page.20) 1122 0 R (page.21) 1129 0 R (page.22) 1134 0 R (page.23) 1144 0 R (page.24) 1150 0 R (page.25) 1154 0 R (page.26) 1162 0 R (page.27) 1166 0 R (page.28) 1176 0 R (page.29) 1181 0 R (page.3) 971 0 R (page.30) 1189 0 R (page.31) 1197 0 R (page.32) 1207 0 R (page.33) 1216 0 R (page.34) 1227 0 R (page.35) 1232 0 R (page.36) 1238 0 R (page.37) 1244 0 R (page.38) 1249 0 R (page.39) 1257 0 R (page.4) 982 0 R (page.40) 1267 0 R (page.41) 1271 0 R (page.42) 1275 0 R (page.43) 1280 0 R (page.44) 1287 0 R (page.45) 1291 0 R (page.46) 1297 0 R (page.47) 1308 0 R (page.48) 1312 0 R (page.49) 1316 0 R (page.5) 989 0 R (page.50) 1327 0 R (page.51) 1334 0 R (page.52) 1339 0 R (page.53) 1344 0 R (page.54) 1348 0 R (page.55) 1352 0 R (page.56) 1360 0 R (page.57) 1367 0 R (page.58) 1373 0 R (page.59) 1380 0 R (page.6) 1001 0 R (page.60) 1387 0 R (page.61) 1393 0 R (page.62) 1403 0 R (page.63) 1411 0 R (page.64) 1415 0 R (page.65) 1420 0 R (page.66) 1426 0 R (page.67) 1435 0 R (page.68) 1441 0 R (page.69) 1445 0 R (page.7) 1006 0 R (page.70) 1449 0 R (page.71) 1456 0 R (page.72) 1461 0 R (page.73) 1476 0 R (page.74) 1490 0 R (page.75) 1514 0 R (page.76) 1524 0 R (page.77) 1530 0 R (page.78) 1540 0 R (page.79) 1546 0 R (page.8) 1015 0 R (page.80) 1556 0 R (page.81) 1566 0 R (page.82) 1576 0 R (page.83) 1585 0 R (page.84) 1592 0 R (page.85) 1598 0 R (page.86) 1608 0 R (page.87) 1618 0 R (page.88) 1625 0 R (page.89) 1633 0 R (page.9) 1026 0 R (page.90) 1639 0 R (page.91) 1650 0 R (page.92) 1655 0 R (page.93) 1659 0 R (page.94) 1670 0 R (page.95) 1674 0 R (page.96) 1681 0 R (page.97) 1691 0 R (page.98) 1751 0 R (page.99) 1807 0 R (page.i) 744 0 R (page.ii) 799 0 R (page.iii) 863 0 R (page.iv) 925 0 R (proposed_standards) 1083 0 R (query_address) 1340 0 R (rfcs) 967 0 R (rndc) 1212 0 R (root_delegation_only) 1472 0 R (rrset_ordering) 1022 0 R (sample_configuration) 1008 0 R (section*.10) 1820 0 R (section*.100) 2106 0 R (section*.101) 2107 0 R (section*.102) 2109 0 R (section*.103) 2110 0 R (section*.104) 2111 0 R (section*.105) 2116 0 R (section*.106) 2121 0 R (section*.107) 2122 0 R (section*.108) 2123 0 R (section*.109) 2125 0 R (section*.11) 1830 0 R (section*.110) 2126 0 R (section*.111) 2127 0 R (section*.112) 2132 0 R (section*.113) 2133 0 R (section*.114) 2138 0 R (section*.115) 2139 0 R (section*.12) 1850 0 R (section*.13) 1862 0 R (section*.14) 1888 0 R (section*.15) 1898 0 R (section*.16) 1899 0 R (section*.17) 1900 0 R (section*.18) 1905 0 R (section*.19) 1906 0 R (section*.2) 1686 0 R (section*.20) 1911 0 R (section*.21) 1921 0 R (section*.22) 1926 0 R (section*.23) 1927 0 R (section*.24) 1928 0 R (section*.25) 1929 0 R (section*.26) 1931 0 R (section*.27) 1932 0 R (section*.28) 1937 0 R (section*.29) 1942 0 R (section*.3) 1692 0 R (section*.30) 1943 0 R (section*.31) 1944 0 R (section*.32) 1946 0 R (section*.33) 1947 0 R (section*.34) 1948 0 R (section*.35) 1949 0 R (section*.36) 1954 0 R (section*.37) 1955 0 R (section*.38) 1956 0 R (section*.39) 1957 0 R (section*.4) 1700 0 R (section*.40) 1958 0 R (section*.41) 1960 0 R (section*.42) 1966 0 R (section*.43) 1967 0 R (section*.44) 1968 0 R (section*.45) 1973 0 R (section*.46) 1974 0 R (section*.47) 1975 0 R (section*.48) 1977 0 R (section*.49) 1978 0 R (section*.5) 1725 0 R (section*.50) 1979 0 R (section*.51) 1980 0 R (section*.52) 1989 0 R (section*.53) 1990 0 R (section*.54) 1991 0 R (section*.55) 1992 0 R (section*.56) 1994 0 R (section*.57) 1995 0 R (section*.58) 2000 0 R (section*.59) 2001 0 R (section*.6) 1737 0 R (section*.60) 2011 0 R (section*.61) 2012 0 R (section*.62) 2017 0 R (section*.63) 2018 0 R (section*.64) 2020 0 R (section*.65) 2021 0 R (section*.66) 2022 0 R (section*.67) 2023 0 R (section*.68) 2024 0 R (section*.69) 2025 0 R (section*.7) 1752 0 R (section*.70) 2030 0 R (section*.71) 2032 0 R (section*.72) 2033 0 R (section*.73) 2034 0 R (section*.74) 2035 0 R (section*.75) 2044 0 R (section*.76) 2045 0 R (section*.77) 2046 0 R (section*.78) 2048 0 R (section*.79) 2049 0 R (section*.8) 1790 0 R (section*.80) 2050 0 R (section*.81) 2051 0 R (section*.82) 2061 0 R (section*.83) 2062 0 R (section*.84) 2067 0 R (section*.85) 2068 0 R (section*.86) 2069 0 R (section*.87) 2071 0 R (section*.88) 2072 0 R (section*.89) 2073 0 R (section*.9) 1808 0 R (section*.90) 2078 0 R (section*.91) 2087 0 R (section*.92) 2088 0 R (section*.93) 2089 0 R (section*.94) 2094 0 R (section*.95) 2096 0 R (section*.96) 2097 0 R (section*.97) 2098 0 R (section*.98) 2099 0 R (section*.99) 2105 0 R (section.1.1) 10 0 R (section.1.2) 14 0 R (section.1.3) 18 0 R (section.1.4) 22 0 R (section.2.1) 70 0 R (section.2.2) 74 0 R (section.2.3) 78 0 R (section.2.4) 82 0 R (section.2.5) 86 0 R (section.3.1) 94 0 R (section.3.2) 106 0 R (section.3.3) 110 0 R (section.4.1) 134 0 R (section.4.2) 138 0 R (section.4.3) 146 0 R (section.4.4) 150 0 R (section.4.5) 158 0 R (section.4.6) 194 0 R (section.4.7) 198 0 R (section.4.8) 202 0 R (section.4.9) 218 0 R (section.5.1) 234 0 R (section.5.2) 238 0 R (section.6.1) 246 0 R (section.6.2) 274 0 R (section.6.3) 482 0 R (section.6.4) 538 0 R (section.7.1) 574 0 R (section.7.2) 578 0 R (section.7.3) 590 0 R (section.8.1) 598 0 R (section.8.2) 606 0 R (section.8.3) 610 0 R (section.A.1) 618 0 R (section.A.2) 626 0 R (section.A.3) 634 0 R (section.B.1) 654 0 R (section.B.10) 690 0 R (section.B.11) 694 0 R (section.B.12) 698 0 R (section.B.13) 702 0 R (section.B.2) 658 0 R (section.B.3) 662 0 R (section.B.4) 666 0 R (section.B.5) 670 0 R (section.B.6) 674 0 R (section.B.7) 678 0 R (section.B.8) 682 0 R (section.B.9) 686 0 R (server_resource_limits) 1362 0 R (server_statement_definition_and_usage) 1304 0 R (server_statement_grammar) 1416 0 R (statistics) 1586 0 R (statistics_counters) 1594 0 R (statschannels) 1427 0 R (statsfile) 1283 0 R (subsection.1.4.1) 26 0 R (subsection.1.4.2) 30 0 R (subsection.1.4.3) 34 0 R (subsection.1.4.4) 38 0 R (subsection.1.4.5) 54 0 R (subsection.1.4.6) 62 0 R (subsection.3.1.1) 98 0 R (subsection.3.1.2) 102 0 R (subsection.3.3.1) 114 0 R (subsection.3.3.2) 126 0 R (subsection.4.2.1) 142 0 R (subsection.4.4.1) 154 0 R (subsection.4.5.1) 162 0 R (subsection.4.5.2) 174 0 R (subsection.4.5.3) 178 0 R (subsection.4.5.4) 182 0 R (subsection.4.5.5) 186 0 R (subsection.4.5.6) 190 0 R (subsection.4.8.1) 206 0 R (subsection.4.8.2) 210 0 R (subsection.4.8.3) 214 0 R (subsection.4.9.1) 222 0 R (subsection.4.9.2) 226 0 R (subsection.6.1.1) 250 0 R (subsection.6.1.2) 262 0 R (subsection.6.2.1) 278 0 R (subsection.6.2.10) 314 0 R (subsection.6.2.11) 330 0 R (subsection.6.2.12) 334 0 R (subsection.6.2.13) 338 0 R (subsection.6.2.14) 342 0 R (subsection.6.2.15) 346 0 R (subsection.6.2.16) 350 0 R (subsection.6.2.17) 426 0 R (subsection.6.2.18) 430 0 R (subsection.6.2.19) 434 0 R (subsection.6.2.2) 282 0 R (subsection.6.2.20) 438 0 R (subsection.6.2.21) 442 0 R (subsection.6.2.22) 446 0 R (subsection.6.2.23) 450 0 R (subsection.6.2.24) 454 0 R (subsection.6.2.25) 458 0 R (subsection.6.2.26) 462 0 R (subsection.6.2.3) 286 0 R (subsection.6.2.4) 290 0 R (subsection.6.2.5) 294 0 R (subsection.6.2.6) 298 0 R (subsection.6.2.7) 302 0 R (subsection.6.2.8) 306 0 R (subsection.6.2.9) 310 0 R (subsection.6.3.1) 486 0 R (subsection.6.3.2) 498 0 R (subsection.6.3.3) 502 0 R (subsection.6.3.4) 506 0 R (subsection.6.3.5) 510 0 R (subsection.6.3.6) 530 0 R (subsection.6.3.7) 534 0 R (subsection.6.4.1) 546 0 R (subsection.7.2.1) 582 0 R (subsection.7.2.2) 586 0 R (subsection.8.1.1) 602 0 R (subsection.A.1.1) 622 0 R (subsection.A.2.1) 630 0 R (subsection.A.3.1) 638 0 R (subsection.A.3.2) 642 0 R (subsection.A.3.3) 646 0 R (subsubsection.1.4.4.1) 42 0 R (subsubsection.1.4.4.2) 46 0 R (subsubsection.1.4.4.3) 50 0 R (subsubsection.1.4.5.1) 58 0 R (subsubsection.3.3.1.1) 118 0 R (subsubsection.3.3.1.2) 122 0 R (subsubsection.4.5.1.1) 166 0 R (subsubsection.4.5.1.2) 170 0 R (subsubsection.6.1.1.1) 254 0 R (subsubsection.6.1.1.2) 258 0 R (subsubsection.6.1.2.1) 266 0 R (subsubsection.6.1.2.2) 270 0 R (subsubsection.6.2.10.1) 318 0 R (subsubsection.6.2.10.2) 322 0 R (subsubsection.6.2.10.3) 326 0 R (subsubsection.6.2.16.1) 354 0 R (subsubsection.6.2.16.10) 390 0 R (subsubsection.6.2.16.11) 394 0 R (subsubsection.6.2.16.12) 398 0 R (subsubsection.6.2.16.13) 402 0 R (subsubsection.6.2.16.14) 406 0 R (subsubsection.6.2.16.15) 410 0 R (subsubsection.6.2.16.16) 414 0 R (subsubsection.6.2.16.17) 418 0 R (subsubsection.6.2.16.18) 422 0 R (subsubsection.6.2.16.2) 358 0 R (subsubsection.6.2.16.3) 362 0 R (subsubsection.6.2.16.4) 366 0 R (subsubsection.6.2.16.5) 370 0 R (subsubsection.6.2.16.6) 374 0 R (subsubsection.6.2.16.7) 378 0 R (subsubsection.6.2.16.8) 382 0 R (subsubsection.6.2.16.9) 386 0 R (subsubsection.6.2.26.1) 466 0 R (subsubsection.6.2.26.2) 470 0 R (subsubsection.6.2.26.3) 474 0 R (subsubsection.6.2.26.4) 478 0 R (subsubsection.6.3.1.1) 490 0 R (subsubsection.6.3.1.2) 494 0 R (subsubsection.6.3.5.1) 514 0 R (subsubsection.6.3.5.2) 518 0 R (subsubsection.6.3.5.3) 522 0 R (subsubsection.6.3.5.4) 526 0 R (subsubsection.6.4.0.1) 542 0 R (subsubsection.6.4.1.1) 550 0 R (subsubsection.6.4.1.2) 554 0 R (subsubsection.6.4.1.3) 558 0 R (subsubsection.6.4.1.4) 562 0 R (subsubsection.6.4.1.5) 566 0 R (table.1.1) 950 0 R (table.1.2) 959 0 R (table.3.1) 1018 0 R (table.3.2) 1050 0 R (table.6.1) 1170 0 R (table.6.10) 1534 0 R (table.6.11) 1536 0 R (table.6.12) 1542 0 R (table.6.13) 1549 0 R (table.6.14) 1551 0 R (table.6.15) 1559 0 R (table.6.16) 1562 0 R (table.6.17) 1569 0 R (table.6.18) 1581 0 R (table.6.19) 1588 0 R (table.6.2) 1193 0 R (table.6.20) 1601 0 R (table.6.21) 1611 0 R (table.6.22) 1614 0 R (table.6.23) 1621 0 R (table.6.3) 1201 0 R (table.6.4) 1240 0 R (table.6.5) 1252 0 R (table.6.6) 1293 0 R (table.6.7) 1383 0 R (table.6.8) 1457 0 R (table.6.9) 1520 0 R (the_category_phrase) 1234 0 R (the_sortlist_statement) 1374 0 R (topology) 1369 0 R (tsig) 1097 0 R (tuning) 1388 0 R (types_of_resource_records_and_when_to_use_them) 966 0 R (view_statement_grammar) 1407 0 R (zone_statement_grammar) 1323 0 R (zone_transfers) 1073 0 R (zonefile_format) 1399 0 R] +2730 0 obj << +/Names [(Access_Control_Lists) 2059 0 R (Bv9ARM.ch01) 1220 0 R (Bv9ARM.ch02) 1264 0 R (Bv9ARM.ch03) 1282 0 R (Bv9ARM.ch04) 1346 0 R (Bv9ARM.ch05) 1525 0 R (Bv9ARM.ch06) 1536 0 R (Bv9ARM.ch07) 2058 0 R (Bv9ARM.ch08) 2084 0 R (Bv9ARM.ch09) 2099 0 R (Bv9ARM.ch10) 2360 0 R (Configuration_File_Grammar) 1559 0 R (DNSSEC) 1412 0 R (Doc-Start) 927 0 R (Setting_TTLs) 1980 0 R (acache) 1271 0 R (access_control) 1710 0 R (acl) 1568 0 R (address_match_lists) 1541 0 R (admin_tools) 1304 0 R (appendix.A) 742 0 R (appendix.B) 834 0 R (bibliography) 2107 0 R (bind9.library) 2316 0 R (boolean_options) 1361 0 R (builtin) 1785 0 R (chapter*.1) 961 0 R (chapter.1) 6 0 R (chapter.2) 66 0 R (chapter.3) 90 0 R (chapter.4) 130 0 R (chapter.5) 342 0 R (chapter.6) 354 0 R (chapter.7) 698 0 R (chapter.8) 722 0 R (cite.RFC1033) 2235 0 R (cite.RFC1034) 2120 0 R (cite.RFC1035) 2122 0 R (cite.RFC1101) 2217 0 R (cite.RFC1123) 2219 0 R (cite.RFC1183) 2179 0 R (cite.RFC1464) 2257 0 R (cite.RFC1535) 2165 0 R (cite.RFC1536) 2167 0 R (cite.RFC1537) 2237 0 R (cite.RFC1591) 2221 0 R (cite.RFC1706) 2181 0 R (cite.RFC1712) 2277 0 R (cite.RFC1713) 2259 0 R (cite.RFC1794) 2261 0 R (cite.RFC1876) 2183 0 R (cite.RFC1912) 2239 0 R (cite.RFC1982) 2169 0 R (cite.RFC1995) 2127 0 R (cite.RFC1996) 2129 0 R (cite.RFC2010) 2241 0 R (cite.RFC2052) 2185 0 R (cite.RFC2065) 2289 0 R (cite.RFC2136) 2131 0 R (cite.RFC2137) 2291 0 R (cite.RFC2163) 2187 0 R (cite.RFC2168) 2189 0 R (cite.RFC2181) 2133 0 R (cite.RFC2219) 2243 0 R (cite.RFC2230) 2191 0 R (cite.RFC2240) 2263 0 R (cite.RFC2308) 2135 0 R (cite.RFC2317) 2223 0 R (cite.RFC2345) 2265 0 R (cite.RFC2352) 2267 0 R (cite.RFC2535) 2293 0 R (cite.RFC2536) 2193 0 R (cite.RFC2537) 2195 0 R (cite.RFC2538) 2197 0 R (cite.RFC2539) 2199 0 R (cite.RFC2540) 2201 0 R (cite.RFC2671) 2137 0 R (cite.RFC2672) 2139 0 R (cite.RFC2673) 2279 0 R (cite.RFC2782) 2203 0 R (cite.RFC2825) 2247 0 R (cite.RFC2826) 2225 0 R (cite.RFC2845) 2141 0 R (cite.RFC2874) 2281 0 R (cite.RFC2915) 2205 0 R (cite.RFC2929) 2227 0 R (cite.RFC2930) 2143 0 R (cite.RFC2931) 2145 0 R (cite.RFC3007) 2147 0 R (cite.RFC3008) 2295 0 R (cite.RFC3071) 2269 0 R (cite.RFC3090) 2297 0 R (cite.RFC3110) 2207 0 R (cite.RFC3123) 2209 0 R (cite.RFC3225) 2153 0 R (cite.RFC3258) 2271 0 R (cite.RFC3445) 2299 0 R (cite.RFC3490) 2249 0 R (cite.RFC3491) 2251 0 R (cite.RFC3492) 2253 0 R (cite.RFC3596) 2211 0 R (cite.RFC3597) 2213 0 R (cite.RFC3645) 2149 0 R (cite.RFC3655) 2301 0 R (cite.RFC3658) 2303 0 R (cite.RFC3755) 2305 0 R (cite.RFC3757) 2307 0 R (cite.RFC3833) 2155 0 R (cite.RFC3845) 2309 0 R (cite.RFC3901) 2273 0 R (cite.RFC4033) 2157 0 R (cite.RFC4034) 2159 0 R (cite.RFC4035) 2161 0 R (cite.RFC4074) 2171 0 R (cite.RFC974) 2124 0 R (cite.id2511436) 2314 0 R (clients-per-query) 2034 0 R (configuration_file_elements) 1537 0 R (controls_statement_definition_and_usage) 1329 0 R (diagnostic_tools) 1252 0 R (dnssec.dynamic.zones) 1432 0 R (dynamic_update) 1356 0 R (dynamic_update_policies) 1318 0 R (dynamic_update_security) 1721 0 R (empty) 1794 0 R (historical_dns_information) 2101 0 R (id2466563) 1221 0 R (id2466586) 1222 0 R (id2467270) 1411 0 R (id2467406) 1413 0 R (id2467477) 1223 0 R (id2467486) 1224 0 R (id2467726) 1234 0 R (id2467748) 1235 0 R (id2467782) 1236 0 R (id2467866) 1239 0 R (id2467959) 1232 0 R (id2470264) 1246 0 R (id2470288) 1249 0 R (id2470386) 1250 0 R (id2470407) 1251 0 R (id2470505) 1257 0 R (id2470540) 1258 0 R (id2470567) 1259 0 R (id2470601) 1265 0 R (id2470628) 1266 0 R (id2470709) 1267 0 R (id2470734) 1270 0 R (id2470745) 1276 0 R (id2470777) 1284 0 R (id2470793) 1285 0 R (id2470816) 1290 0 R (id2470833) 1291 0 R (id2471238) 1299 0 R (id2471243) 1300 0 R (id2473326) 1334 0 R (id2473338) 1335 0 R (id2473765) 1371 0 R (id2473851) 1377 0 R (id2474284) 1393 0 R (id2474301) 1394 0 R (id2474340) 1395 0 R (id2474358) 1396 0 R (id2474369) 1397 0 R (id2474405) 1402 0 R (id2474531) 1403 0 R (id2474580) 1405 0 R (id2474594) 1406 0 R (id2475200) 1418 0 R (id2475281) 1419 0 R (id2475706) 1433 0 R (id2475744) 1434 0 R (id2475780) 1439 0 R (id2475862) 1445 0 R (id2475899) 1452 0 R (id2475912) 1453 0 R (id2475945) 1454 0 R (id2476040) 1455 0 R (id2476050) 1460 0 R (id2476059) 1461 0 R (id2476072) 1462 0 R (id2476178) 1463 0 R (id2476187) 1464 0 R (id2476224) 1466 0 R (id2476314) 1473 0 R (id2476484) 1479 0 R (id2476648) 1485 0 R (id2476786) 1486 0 R (id2476891) 1491 0 R (id2476900) 1492 0 R (id2476931) 1493 0 R (id2476986) 1494 0 R (id2477085) 1499 0 R (id2477420) 1505 0 R (id2477466) 1506 0 R (id2477521) 1511 0 R (id2477651) 1513 0 R (id2477672) 1514 0 R (id2477705) 1526 0 R (id2477921) 1538 0 R (id2478882) 1546 0 R (id2478909) 1551 0 R (id2479115) 1552 0 R (id2479130) 1553 0 R (id2479160) 1558 0 R (id2479303) 1560 0 R (id2479837) 1567 0 R (id2479880) 1569 0 R (id2480027) 1571 0 R (id2480455) 1578 0 R (id2480472) 1584 0 R (id2480496) 1585 0 R (id2480519) 1586 0 R (id2480678) 1590 0 R (id2480804) 1595 0 R (id2480856) 1596 0 R (id2481481) 1607 0 R (id2482215) 1618 0 R (id2482345) 1619 0 R (id2482666) 1625 0 R (id2482808) 1630 0 R (id2482872) 1633 0 R (id2482916) 1634 0 R (id2482931) 1635 0 R (id2486190) 1673 0 R (id2488442) 1703 0 R (id2488501) 1709 0 R (id2489121) 1720 0 R (id2490256) 1743 0 R (id2490452) 1745 0 R (id2490806) 1754 0 R (id2491308) 1772 0 R (id2492919) 1803 0 R (id2493178) 1809 0 R (id2494065) 1827 0 R (id2494273) 1833 0 R (id2494320) 1835 0 R (id2494745) 1840 0 R (id2496290) 1858 0 R (id2496297) 1859 0 R (id2496302) 1860 0 R (id2496774) 1871 0 R (id2496875) 1872 0 R (id2499008) 1939 0 R (id2499554) 1945 0 R (id2499572) 1946 0 R (id2499660) 1949 0 R (id2499829) 1955 0 R (id2500999) 1961 0 R (id2501195) 1967 0 R (id2501217) 1968 0 R (id2501579) 1970 0 R (id2501716) 1972 0 R (id2501734) 1978 0 R (id2502206) 1981 0 R (id2502331) 1983 0 R (id2502346) 1984 0 R (id2502458) 1990 0 R (id2502481) 1991 0 R (id2502497) 1992 0 R (id2502694) 1993 0 R (id2502763) 1998 0 R (id2502800) 1999 0 R (id2502875) 2000 0 R (id2503386) 2011 0 R (id2503821) 2019 0 R (id2503827) 2020 0 R (id2505363) 2028 0 R (id2505369) 2029 0 R (id2505814) 2031 0 R (id2505819) 2032 0 R (id2506768) 2039 0 R (id2506800) 2040 0 R (id2507209) 2049 0 R (id2507520) 2068 0 R (id2507601) 2069 0 R (id2507660) 2070 0 R (id2507740) 2085 0 R (id2507746) 2086 0 R (id2507757) 2087 0 R (id2507774) 2088 0 R (id2507973) 2100 0 R (id2508213) 2106 0 R (id2508401) 2111 0 R (id2508403) 2118 0 R (id2508411) 2123 0 R (id2508435) 2119 0 R (id2508458) 2121 0 R (id2508494) 2132 0 R (id2508521) 2134 0 R (id2508547) 2126 0 R (id2508571) 2128 0 R (id2508595) 2130 0 R (id2508650) 2136 0 R (id2508677) 2138 0 R (id2508704) 2140 0 R (id2508765) 2142 0 R (id2508795) 2144 0 R (id2508825) 2146 0 R (id2508852) 2148 0 R (id2508926) 2151 0 R (id2508934) 2152 0 R (id2508961) 2154 0 R (id2508997) 2156 0 R (id2509062) 2158 0 R (id2509127) 2160 0 R (id2509192) 2163 0 R (id2509201) 2164 0 R (id2509226) 2166 0 R (id2509294) 2168 0 R (id2509330) 2170 0 R (id2509438) 2177 0 R (id2509444) 2178 0 R (id2509501) 2180 0 R (id2509539) 2188 0 R (id2509574) 2182 0 R (id2509628) 2184 0 R (id2509667) 2186 0 R (id2509692) 2190 0 R (id2509718) 2192 0 R (id2509745) 2194 0 R (id2509840) 2196 0 R (id2509879) 2198 0 R (id2509909) 2200 0 R (id2509939) 2202 0 R (id2509981) 2204 0 R (id2510014) 2206 0 R (id2510041) 2208 0 R (id2510065) 2210 0 R (id2510122) 2212 0 R (id2510147) 2215 0 R (id2510154) 2216 0 R (id2510180) 2218 0 R (id2510202) 2220 0 R (id2510226) 2222 0 R (id2510272) 2224 0 R (id2510295) 2226 0 R (id2510345) 2233 0 R (id2510353) 2234 0 R (id2510376) 2236 0 R (id2510403) 2238 0 R (id2510429) 2240 0 R (id2510466) 2242 0 R (id2510506) 2245 0 R (id2510512) 2246 0 R (id2510544) 2248 0 R (id2510589) 2250 0 R (id2510625) 2252 0 R (id2510651) 2255 0 R (id2510669) 2256 0 R (id2510692) 2258 0 R (id2510717) 2260 0 R (id2510743) 2262 0 R (id2510766) 2264 0 R (id2510812) 2266 0 R (id2510836) 2268 0 R (id2510862) 2270 0 R (id2510888) 2272 0 R (id2510925) 2275 0 R (id2510932) 2276 0 R (id2510989) 2278 0 R (id2511016) 2280 0 R (id2511052) 2287 0 R (id2511064) 2288 0 R (id2511104) 2290 0 R (id2511130) 2292 0 R (id2511160) 2294 0 R (id2511186) 2296 0 R (id2511212) 2298 0 R (id2511249) 2300 0 R (id2511285) 2302 0 R (id2511312) 2304 0 R (id2511338) 2306 0 R (id2511383) 2308 0 R (id2511425) 2311 0 R (id2511434) 2313 0 R (id2511436) 2315 0 R (id2511524) 2321 0 R (id2511533) 2322 0 R (id2511558) 2323 0 R (id2511589) 2324 0 R (id2511734) 2329 0 R (id2511829) 2331 0 R (id2511837) 2332 0 R (id2511928) 2338 0 R (id2511981) 2339 0 R (id2512045) 2340 0 R (id2512060) 2345 0 R (id2512260) 2350 0 R (id2512392) 2351 0 R (incremental_zone_transfers) 1368 0 R (internet_drafts) 2310 0 R (ipv6addresses) 1515 0 R (journal) 1367 0 R (lwresd) 1527 0 R (man.arpaname) 2670 0 R (man.ddns-confgen) 2655 0 R (man.dig) 2361 0 R (man.dnssec-dsfromkey) 2409 0 R (man.dnssec-keyfromlabel) 2428 0 R (man.dnssec-keygen) 1446 0 R (man.dnssec-revoke) 2471 0 R (man.dnssec-settime) 1447 0 R (man.dnssec-signzone) 2498 0 R (man.genrandom) 2676 0 R (man.host) 2394 0 R (man.isc-hmac-fixup) 2687 0 R (man.named) 2556 0 R (man.named-checkconf) 2523 0 R (man.named-checkzone) 2535 0 R (man.named-journalprint) 2578 0 R (man.nsec3hash) 2698 0 R (man.nsupdate) 2584 0 R (man.rndc) 2610 0 R (man.rndc-confgen) 2642 0 R (man.rndc.conf) 2626 0 R (managed-keys) 1468 0 R (notify) 1347 0 R (options) 1317 0 R (page.1) 926 0 R (page.10) 1308 0 R (page.100) 1954 0 R (page.101) 1960 0 R (page.102) 1966 0 R (page.103) 1977 0 R (page.104) 1989 0 R (page.105) 1997 0 R (page.106) 2005 0 R (page.107) 2009 0 R (page.108) 2017 0 R (page.109) 2026 0 R (page.11) 1322 0 R (page.110) 2038 0 R (page.111) 2045 0 R (page.112) 2053 0 R (page.113) 2057 0 R (page.114) 2063 0 R (page.115) 2075 0 R (page.116) 2079 0 R (page.117) 2083 0 R (page.118) 2094 0 R (page.119) 2098 0 R (page.12) 1326 0 R (page.120) 2105 0 R (page.121) 2116 0 R (page.122) 2175 0 R (page.123) 2231 0 R (page.124) 2285 0 R (page.125) 2320 0 R (page.126) 2328 0 R (page.127) 2337 0 R (page.128) 2344 0 R (page.129) 2349 0 R (page.13) 1333 0 R (page.130) 2355 0 R (page.131) 2359 0 R (page.132) 2368 0 R (page.133) 2375 0 R (page.134) 2380 0 R (page.135) 2384 0 R (page.136) 2389 0 R (page.137) 2400 0 R (page.138) 2405 0 R (page.139) 2418 0 R (page.14) 1340 0 R (page.140) 2427 0 R (page.141) 2436 0 R (page.142) 2441 0 R (page.143) 2450 0 R (page.144) 2456 0 R (page.145) 2461 0 R (page.146) 2467 0 R (page.147) 2478 0 R (page.148) 2488 0 R (page.149) 2494 0 R (page.15) 1345 0 R (page.150) 2505 0 R (page.151) 2511 0 R (page.152) 2515 0 R (page.153) 2519 0 R (page.154) 2530 0 R (page.155) 2541 0 R (page.156) 2547 0 R (page.157) 2553 0 R (page.158) 2564 0 R (page.159) 2568 0 R (page.16) 1366 0 R (page.160) 2575 0 R (page.161) 2589 0 R (page.162) 2595 0 R (page.163) 2601 0 R (page.164) 2606 0 R (page.165) 2615 0 R (page.166) 2623 0 R (page.167) 2633 0 R (page.168) 2638 0 R (page.169) 2651 0 R (page.17) 1376 0 R (page.170) 2660 0 R (page.171) 2668 0 R (page.172) 2683 0 R (page.173) 2695 0 R (page.18) 1382 0 R (page.19) 1387 0 R (page.2) 950 0 R (page.20) 1392 0 R (page.21) 1401 0 R (page.22) 1410 0 R (page.23) 1417 0 R (page.24) 1423 0 R (page.25) 1428 0 R (page.26) 1438 0 R (page.27) 1451 0 R (page.28) 1459 0 R (page.29) 1472 0 R (page.3) 1245 0 R (page.30) 1478 0 R (page.31) 1484 0 R (page.32) 1490 0 R (page.33) 1498 0 R (page.34) 1504 0 R (page.35) 1510 0 R (page.36) 1519 0 R (page.37) 1524 0 R (page.38) 1531 0 R (page.39) 1535 0 R (page.4) 1256 0 R (page.40) 1545 0 R (page.41) 1550 0 R (page.42) 1557 0 R (page.43) 1566 0 R (page.44) 1575 0 R (page.45) 1583 0 R (page.46) 1594 0 R (page.47) 1600 0 R (page.48) 1606 0 R (page.49) 1613 0 R (page.5) 1263 0 R (page.50) 1617 0 R (page.51) 1624 0 R (page.52) 1629 0 R (page.53) 1639 0 R (page.54) 1643 0 R (page.55) 1648 0 R (page.56) 1652 0 R (page.57) 1656 0 R (page.58) 1662 0 R (page.59) 1667 0 R (page.6) 1275 0 R (page.60) 1672 0 R (page.61) 1679 0 R (page.62) 1684 0 R (page.63) 1694 0 R (page.64) 1698 0 R (page.65) 1702 0 R (page.66) 1707 0 R (page.67) 1717 0 R (page.68) 1725 0 R (page.69) 1730 0 R (page.7) 1281 0 R (page.70) 1734 0 R (page.71) 1738 0 R (page.72) 1742 0 R (page.73) 1751 0 R (page.74) 1758 0 R (page.75) 1763 0 R (page.76) 1770 0 R (page.77) 1778 0 R (page.78) 1783 0 R (page.79) 1793 0 R (page.8) 1289 0 R (page.80) 1798 0 R (page.81) 1802 0 R (page.82) 1808 0 R (page.83) 1813 0 R (page.84) 1818 0 R (page.85) 1824 0 R (page.86) 1832 0 R (page.87) 1839 0 R (page.88) 1844 0 R (page.89) 1848 0 R (page.9) 1298 0 R (page.90) 1852 0 R (page.91) 1857 0 R (page.92) 1865 0 R (page.93) 1869 0 R (page.94) 1884 0 R (page.95) 1898 0 R (page.96) 1910 0 R (page.97) 1931 0 R (page.98) 1938 0 R (page.99) 1944 0 R (page.i) 960 0 R (page.ii) 1015 0 R (page.iii) 1079 0 R (page.iv) 1142 0 R (page.v) 1204 0 R (pkcs11) 1474 0 R (proposed_standards) 1372 0 R (query_address) 1726 0 R (rfc5011.support) 1465 0 R (rfcs) 1241 0 R (rndc) 1579 0 R (root_delegation_only) 1880 0 R (rrset_ordering) 1294 0 R (sample_configuration) 1283 0 R (section*.10) 2244 0 R (section*.100) 2576 0 R (section*.101) 2577 0 R (section*.102) 2579 0 R (section*.103) 2580 0 R (section*.104) 2581 0 R (section*.105) 2582 0 R (section*.106) 2583 0 R (section*.107) 2585 0 R (section*.108) 2590 0 R (section*.109) 2591 0 R (section*.11) 2254 0 R (section*.110) 2596 0 R (section*.111) 2602 0 R (section*.112) 2607 0 R (section*.113) 2608 0 R (section*.114) 2609 0 R (section*.115) 2611 0 R (section*.116) 2616 0 R (section*.117) 2617 0 R (section*.118) 2618 0 R (section*.119) 2619 0 R (section*.12) 2274 0 R (section*.120) 2624 0 R (section*.121) 2625 0 R (section*.122) 2627 0 R (section*.123) 2628 0 R (section*.124) 2629 0 R (section*.125) 2634 0 R (section*.126) 2639 0 R (section*.127) 2640 0 R (section*.128) 2641 0 R (section*.129) 2643 0 R (section*.13) 2286 0 R (section*.130) 2644 0 R (section*.131) 2645 0 R (section*.132) 2646 0 R (section*.133) 2652 0 R (section*.134) 2653 0 R (section*.135) 2654 0 R (section*.136) 2656 0 R (section*.137) 2661 0 R (section*.138) 2662 0 R (section*.139) 2663 0 R (section*.14) 2312 0 R (section*.140) 2664 0 R (section*.141) 2669 0 R (section*.142) 2671 0 R (section*.143) 2672 0 R (section*.144) 2673 0 R (section*.145) 2674 0 R (section*.146) 2675 0 R (section*.147) 2677 0 R (section*.148) 2678 0 R (section*.149) 2679 0 R (section*.15) 2362 0 R (section*.150) 2684 0 R (section*.151) 2685 0 R (section*.152) 2686 0 R (section*.153) 2688 0 R (section*.154) 2689 0 R (section*.155) 2690 0 R (section*.156) 2691 0 R (section*.157) 2696 0 R (section*.158) 2697 0 R (section*.159) 2699 0 R (section*.16) 2363 0 R (section*.160) 2700 0 R (section*.161) 2701 0 R (section*.162) 2702 0 R (section*.163) 2703 0 R (section*.164) 2704 0 R (section*.17) 2364 0 R (section*.18) 2369 0 R (section*.19) 2370 0 R (section*.2) 2110 0 R (section*.20) 2376 0 R (section*.21) 2385 0 R (section*.22) 2390 0 R (section*.23) 2391 0 R (section*.24) 2392 0 R (section*.25) 2393 0 R (section*.26) 2395 0 R (section*.27) 2396 0 R (section*.28) 2401 0 R (section*.29) 2406 0 R (section*.3) 2117 0 R (section*.30) 2407 0 R (section*.31) 2408 0 R (section*.32) 2410 0 R (section*.33) 2411 0 R (section*.34) 2412 0 R (section*.35) 2413 0 R (section*.36) 2419 0 R (section*.37) 2420 0 R (section*.38) 2421 0 R (section*.39) 2422 0 R (section*.4) 2125 0 R (section*.40) 2423 0 R (section*.41) 2429 0 R (section*.42) 2430 0 R (section*.43) 2431 0 R (section*.44) 2432 0 R (section*.45) 2437 0 R (section*.46) 2442 0 R (section*.47) 2443 0 R (section*.48) 2444 0 R (section*.49) 2445 0 R (section*.5) 2150 0 R (section*.50) 2446 0 R (section*.51) 2451 0 R (section*.52) 2452 0 R (section*.53) 2462 0 R (section*.54) 2463 0 R (section*.55) 2468 0 R (section*.56) 2469 0 R (section*.57) 2470 0 R (section*.58) 2472 0 R (section*.59) 2473 0 R (section*.6) 2162 0 R (section*.60) 2474 0 R (section*.61) 2479 0 R (section*.62) 2480 0 R (section*.63) 2481 0 R (section*.64) 2482 0 R (section*.65) 2483 0 R (section*.66) 2484 0 R (section*.67) 2489 0 R (section*.68) 2490 0 R (section*.69) 2495 0 R (section*.7) 2176 0 R (section*.70) 2496 0 R (section*.71) 2497 0 R (section*.72) 2499 0 R (section*.73) 2500 0 R (section*.74) 2501 0 R (section*.75) 2506 0 R (section*.76) 2520 0 R (section*.77) 2521 0 R (section*.78) 2522 0 R (section*.79) 2524 0 R (section*.8) 2214 0 R (section*.80) 2525 0 R (section*.81) 2526 0 R (section*.82) 2531 0 R (section*.83) 2532 0 R (section*.84) 2533 0 R (section*.85) 2534 0 R (section*.86) 2536 0 R (section*.87) 2537 0 R (section*.88) 2542 0 R (section*.89) 2543 0 R (section*.9) 2232 0 R (section*.90) 2548 0 R (section*.91) 2554 0 R (section*.92) 2555 0 R (section*.93) 2557 0 R (section*.94) 2558 0 R (section*.95) 2559 0 R (section*.96) 2560 0 R (section*.97) 2569 0 R (section*.98) 2570 0 R (section*.99) 2571 0 R (section.1.1) 10 0 R (section.1.2) 14 0 R (section.1.3) 18 0 R (section.1.4) 22 0 R (section.2.1) 70 0 R (section.2.2) 74 0 R (section.2.3) 78 0 R (section.2.4) 82 0 R (section.2.5) 86 0 R (section.3.1) 94 0 R (section.3.2) 106 0 R (section.3.3) 110 0 R (section.4.1) 134 0 R (section.4.10) 274 0 R (section.4.11) 286 0 R (section.4.12) 330 0 R (section.4.2) 138 0 R (section.4.3) 146 0 R (section.4.4) 150 0 R (section.4.5) 158 0 R (section.4.6) 194 0 R (section.4.7) 198 0 R (section.4.8) 202 0 R (section.4.9) 218 0 R (section.5.1) 346 0 R (section.5.2) 350 0 R (section.6.1) 358 0 R (section.6.2) 386 0 R (section.6.3) 610 0 R (section.6.4) 666 0 R (section.7.1) 702 0 R (section.7.2) 706 0 R (section.7.3) 718 0 R (section.8.1) 726 0 R (section.8.2) 734 0 R (section.8.3) 738 0 R (section.A.1) 746 0 R (section.A.2) 754 0 R (section.A.3) 762 0 R (section.A.4) 778 0 R (section.B.1) 838 0 R (section.B.10) 874 0 R (section.B.11) 878 0 R (section.B.12) 882 0 R (section.B.13) 886 0 R (section.B.14) 890 0 R (section.B.15) 894 0 R (section.B.16) 898 0 R (section.B.17) 902 0 R (section.B.18) 906 0 R (section.B.19) 910 0 R (section.B.2) 842 0 R (section.B.20) 914 0 R (section.B.21) 918 0 R (section.B.3) 846 0 R (section.B.4) 850 0 R (section.B.5) 854 0 R (section.B.6) 858 0 R (section.B.7) 862 0 R (section.B.8) 866 0 R (section.B.9) 870 0 R (server_resource_limits) 1752 0 R (server_statement_definition_and_usage) 1690 0 R (server_statement_grammar) 1814 0 R (statistics) 2010 0 R (statistics_counters) 2018 0 R (statschannels) 1826 0 R (statsfile) 1658 0 R (subsection.1.4.1) 26 0 R (subsection.1.4.2) 30 0 R (subsection.1.4.3) 34 0 R (subsection.1.4.4) 38 0 R (subsection.1.4.5) 54 0 R (subsection.1.4.6) 62 0 R (subsection.3.1.1) 98 0 R (subsection.3.1.2) 102 0 R (subsection.3.3.1) 114 0 R (subsection.3.3.2) 126 0 R (subsection.4.10.1) 278 0 R (subsection.4.10.2) 282 0 R (subsection.4.11.1) 290 0 R (subsection.4.11.2) 302 0 R (subsection.4.11.3) 314 0 R (subsection.4.11.4) 318 0 R (subsection.4.11.5) 322 0 R (subsection.4.11.6) 326 0 R (subsection.4.12.1) 334 0 R (subsection.4.12.2) 338 0 R (subsection.4.2.1) 142 0 R (subsection.4.4.1) 154 0 R (subsection.4.5.1) 162 0 R (subsection.4.5.2) 174 0 R (subsection.4.5.3) 178 0 R (subsection.4.5.4) 182 0 R (subsection.4.5.5) 186 0 R (subsection.4.5.6) 190 0 R (subsection.4.8.1) 206 0 R (subsection.4.8.2) 210 0 R (subsection.4.8.3) 214 0 R (subsection.4.9.1) 222 0 R (subsection.4.9.10) 258 0 R (subsection.4.9.11) 262 0 R (subsection.4.9.12) 266 0 R (subsection.4.9.13) 270 0 R (subsection.4.9.2) 226 0 R (subsection.4.9.3) 230 0 R (subsection.4.9.4) 234 0 R (subsection.4.9.5) 238 0 R (subsection.4.9.6) 242 0 R (subsection.4.9.7) 246 0 R (subsection.4.9.8) 250 0 R (subsection.4.9.9) 254 0 R (subsection.6.1.1) 362 0 R (subsection.6.1.2) 374 0 R (subsection.6.2.1) 390 0 R (subsection.6.2.10) 426 0 R (subsection.6.2.11) 442 0 R (subsection.6.2.12) 446 0 R (subsection.6.2.13) 450 0 R (subsection.6.2.14) 454 0 R (subsection.6.2.15) 458 0 R (subsection.6.2.16) 462 0 R (subsection.6.2.17) 546 0 R (subsection.6.2.18) 550 0 R (subsection.6.2.19) 554 0 R (subsection.6.2.2) 394 0 R (subsection.6.2.20) 558 0 R (subsection.6.2.21) 562 0 R (subsection.6.2.22) 566 0 R (subsection.6.2.23) 570 0 R (subsection.6.2.24) 574 0 R (subsection.6.2.25) 578 0 R (subsection.6.2.26) 582 0 R (subsection.6.2.27) 586 0 R (subsection.6.2.28) 590 0 R (subsection.6.2.3) 398 0 R (subsection.6.2.4) 402 0 R (subsection.6.2.5) 406 0 R (subsection.6.2.6) 410 0 R (subsection.6.2.7) 414 0 R (subsection.6.2.8) 418 0 R (subsection.6.2.9) 422 0 R (subsection.6.3.1) 614 0 R (subsection.6.3.2) 626 0 R (subsection.6.3.3) 630 0 R (subsection.6.3.4) 634 0 R (subsection.6.3.5) 638 0 R (subsection.6.3.6) 658 0 R (subsection.6.3.7) 662 0 R (subsection.6.4.1) 674 0 R (subsection.7.2.1) 710 0 R (subsection.7.2.2) 714 0 R (subsection.8.1.1) 730 0 R (subsection.A.1.1) 750 0 R (subsection.A.2.1) 758 0 R (subsection.A.3.1) 766 0 R (subsection.A.3.2) 770 0 R (subsection.A.3.3) 774 0 R (subsection.A.4.1) 782 0 R (subsection.A.4.2) 786 0 R (subsection.A.4.3) 790 0 R (subsection.A.4.4) 794 0 R (subsection.A.4.5) 798 0 R (subsection.A.4.6) 802 0 R (subsection.A.4.7) 830 0 R (subsubsection.1.4.4.1) 42 0 R (subsubsection.1.4.4.2) 46 0 R (subsubsection.1.4.4.3) 50 0 R (subsubsection.1.4.5.1) 58 0 R (subsubsection.3.3.1.1) 118 0 R (subsubsection.3.3.1.2) 122 0 R (subsubsection.4.11.1.1) 294 0 R (subsubsection.4.11.1.2) 298 0 R (subsubsection.4.11.2.1) 306 0 R (subsubsection.4.11.2.2) 310 0 R (subsubsection.4.5.1.1) 166 0 R (subsubsection.4.5.1.2) 170 0 R (subsubsection.6.1.1.1) 366 0 R (subsubsection.6.1.1.2) 370 0 R (subsubsection.6.1.2.1) 378 0 R (subsubsection.6.1.2.2) 382 0 R (subsubsection.6.2.10.1) 430 0 R (subsubsection.6.2.10.2) 434 0 R (subsubsection.6.2.10.3) 438 0 R (subsubsection.6.2.16.1) 466 0 R (subsubsection.6.2.16.10) 502 0 R (subsubsection.6.2.16.11) 506 0 R (subsubsection.6.2.16.12) 510 0 R (subsubsection.6.2.16.13) 514 0 R (subsubsection.6.2.16.14) 518 0 R (subsubsection.6.2.16.15) 522 0 R (subsubsection.6.2.16.16) 526 0 R (subsubsection.6.2.16.17) 530 0 R (subsubsection.6.2.16.18) 534 0 R (subsubsection.6.2.16.19) 538 0 R (subsubsection.6.2.16.2) 470 0 R (subsubsection.6.2.16.20) 542 0 R (subsubsection.6.2.16.3) 474 0 R (subsubsection.6.2.16.4) 478 0 R (subsubsection.6.2.16.5) 482 0 R (subsubsection.6.2.16.6) 486 0 R (subsubsection.6.2.16.7) 490 0 R (subsubsection.6.2.16.8) 494 0 R (subsubsection.6.2.16.9) 498 0 R (subsubsection.6.2.28.1) 594 0 R (subsubsection.6.2.28.2) 598 0 R (subsubsection.6.2.28.3) 602 0 R (subsubsection.6.2.28.4) 606 0 R (subsubsection.6.3.1.1) 618 0 R (subsubsection.6.3.1.2) 622 0 R (subsubsection.6.3.5.1) 642 0 R (subsubsection.6.3.5.2) 646 0 R (subsubsection.6.3.5.3) 650 0 R (subsubsection.6.3.5.4) 654 0 R (subsubsection.6.4.0.1) 670 0 R (subsubsection.6.4.1.1) 678 0 R (subsubsection.6.4.1.2) 682 0 R (subsubsection.6.4.1.3) 686 0 R (subsubsection.6.4.1.4) 690 0 R (subsubsection.6.4.1.5) 694 0 R (subsubsection.A.4.6.1) 806 0 R (subsubsection.A.4.6.2) 810 0 R (subsubsection.A.4.6.3) 814 0 R (subsubsection.A.4.6.4) 818 0 R (subsubsection.A.4.6.5) 822 0 R (subsubsection.A.4.6.6) 826 0 R (table.1.1) 1225 0 R (table.1.2) 1233 0 R (table.3.1) 1292 0 R (table.3.2) 1336 0 R (table.6.1) 1539 0 R (table.6.10) 1950 0 R (table.6.11) 1956 0 R (table.6.12) 1962 0 R (table.6.13) 1969 0 R (table.6.14) 1971 0 R (table.6.15) 1979 0 R (table.6.16) 1982 0 R (table.6.17) 1985 0 R (table.6.18) 2001 0 R (table.6.19) 2012 0 R (table.6.2) 1561 0 R (table.6.20) 2021 0 R (table.6.21) 2030 0 R (table.6.22) 2033 0 R (table.6.23) 2041 0 R (table.6.3) 1570 0 R (table.6.4) 1608 0 R (table.6.5) 1620 0 R (table.6.6) 1674 0 R (table.6.7) 1773 0 R (table.6.8) 1861 0 R (table.6.9) 1940 0 R (the_category_phrase) 1602 0 R (the_sortlist_statement) 1764 0 R (topology) 1759 0 R (trusted-keys) 1828 0 R (tsig) 1388 0 R (tuning) 1774 0 R (types_of_resource_records_and_when_to_use_them) 1240 0 R (view_statement_grammar) 1789 0 R (zone_statement_grammar) 1713 0 R (zone_transfers) 1362 0 R (zonefile_format) 1788 0 R] /Limits [(Access_Control_Lists) (zonefile_format)] >> endobj -2165 0 obj << -/Kids [2164 0 R] +2731 0 obj << +/Kids [2730 0 R] >> endobj -2166 0 obj << -/Dests 2165 0 R +2732 0 obj << +/Dests 2731 0 R >> endobj -2167 0 obj << +2733 0 obj << /Type /Catalog -/Pages 2162 0 R -/Outlines 2163 0 R -/Names 2166 0 R +/Pages 2728 0 R +/Outlines 2729 0 R +/Names 2732 0 R /PageMode /UseOutlines -/OpenAction 705 0 R +/OpenAction 921 0 R >> endobj -2168 0 obj << +2734 0 obj << /Author()/Title()/Subject()/Creator(LaTeX with hyperref package)/Producer(pdfeTeX-1.21a)/Keywords() -/CreationDate (D:20100910020422Z) +/CreationDate (D:20110609034043Z) /PTEX.Fullbanner (This is pdfeTeX, Version 3.141592-1.21a-2.2 (Web2C 7.5.4) kpathsea version 3.5.4) >> endobj xref -0 2169 +0 2735 0000000001 65535 f 0000000002 00000 f 0000000003 00000 f 0000000004 00000 f 0000000000 00000 f 0000000009 00000 n -0000328752 00000 n -0001011409 00000 n +0000347882 00000 n +0001171649 00000 n 0000000054 00000 n 0000000086 00000 n -0000328876 00000 n -0001011337 00000 n +0000348009 00000 n +0001171577 00000 n 0000000133 00000 n 0000000173 00000 n -0000329001 00000 n -0001011251 00000 n +0000348137 00000 n +0001171491 00000 n 0000000221 00000 n 0000000273 00000 n -0000329126 00000 n -0001011165 00000 n +0000348265 00000 n +0001171405 00000 n 0000000321 00000 n 0000000377 00000 n -0000333388 00000 n -0001011055 00000 n +0000352551 00000 n +0001171295 00000 n 0000000425 00000 n 0000000478 00000 n -0000333512 00000 n -0001010981 00000 n +0000352678 00000 n +0001171221 00000 n 0000000531 00000 n 0000000572 00000 n -0000333637 00000 n -0001010894 00000 n +0000352806 00000 n +0001171134 00000 n 0000000625 00000 n 0000000674 00000 n -0000333761 00000 n -0001010807 00000 n +0000352933 00000 n +0001171047 00000 n 0000000727 00000 n 0000000757 00000 n -0000338040 00000 n -0001010683 00000 n +0000357230 00000 n +0001170923 00000 n 0000000810 00000 n 0000000861 00000 n -0000338165 00000 n -0001010609 00000 n +0000357358 00000 n +0001170849 00000 n 0000000919 00000 n 0000000964 00000 n -0000338290 00000 n -0001010522 00000 n +0000357486 00000 n +0001170762 00000 n 0000001022 00000 n 0000001062 00000 n -0000338415 00000 n -0001010448 00000 n +0000357614 00000 n +0001170688 00000 n 0000001120 00000 n 0000001162 00000 n -0000341386 00000 n -0001010324 00000 n +0000360599 00000 n +0001170564 00000 n 0000001215 00000 n 0000001260 00000 n -0000341511 00000 n -0001010263 00000 n +0000360727 00000 n +0001170503 00000 n 0000001318 00000 n 0000001355 00000 n -0000341636 00000 n -0001010189 00000 n +0000360855 00000 n +0001170429 00000 n 0000001408 00000 n 0000001463 00000 n -0000344566 00000 n -0001010064 00000 n +0000363802 00000 n +0001170304 00000 n 0000001509 00000 n 0000001556 00000 n -0000344691 00000 n -0001009990 00000 n +0000363930 00000 n +0001170230 00000 n 0000001604 00000 n 0000001648 00000 n -0000344816 00000 n -0001009903 00000 n +0000364058 00000 n +0001170143 00000 n 0000001696 00000 n 0000001735 00000 n -0000344941 00000 n -0001009816 00000 n +0000364186 00000 n +0001170056 00000 n 0000001783 00000 n 0000001825 00000 n -0000345065 00000 n -0001009729 00000 n +0000364313 00000 n +0001169969 00000 n 0000001873 00000 n 0000001936 00000 n -0000346148 00000 n -0001009655 00000 n +0000365390 00000 n +0001169895 00000 n 0000001984 00000 n 0000002034 00000 n -0000347859 00000 n -0001009527 00000 n +0000367049 00000 n +0001169767 00000 n 0000002080 00000 n 0000002126 00000 n -0000347986 00000 n -0001009414 00000 n +0000367176 00000 n +0001169654 00000 n 0000002174 00000 n 0000002218 00000 n -0000348114 00000 n -0001009338 00000 n +0000367304 00000 n +0001169578 00000 n 0000002271 00000 n 0000002323 00000 n -0000348242 00000 n -0001009261 00000 n +0000367432 00000 n +0001169501 00000 n 0000002377 00000 n 0000002436 00000 n -0000350787 00000 n -0001009170 00000 n +0000369881 00000 n +0001169410 00000 n 0000002485 00000 n 0000002523 00000 n -0000351046 00000 n -0001009053 00000 n +0000373219 00000 n +0001169293 00000 n 0000002572 00000 n 0000002618 00000 n -0000351175 00000 n -0001008935 00000 n +0000373347 00000 n +0001169175 00000 n 0000002672 00000 n 0000002739 00000 n -0000354406 00000 n -0001008856 00000 n +0000373475 00000 n +0001169096 00000 n 0000002798 00000 n 0000002842 00000 n -0000354534 00000 n -0001008777 00000 n +0000373604 00000 n +0001169017 00000 n 0000002901 00000 n 0000002949 00000 n -0000365183 00000 n -0001008698 00000 n +0000388343 00000 n +0001168938 00000 n 0000003003 00000 n 0000003036 00000 n -0000370204 00000 n -0001008566 00000 n +0000393969 00000 n +0001168805 00000 n 0000003083 00000 n 0000003126 00000 n -0000370333 00000 n -0001008487 00000 n +0000394098 00000 n +0001168726 00000 n 0000003175 00000 n 0000003205 00000 n -0000370462 00000 n -0001008355 00000 n +0000394227 00000 n +0001168594 00000 n 0000003254 00000 n 0000003292 00000 n -0000370591 00000 n -0001008290 00000 n +0000398736 00000 n +0001168529 00000 n 0000003346 00000 n 0000003388 00000 n -0000374998 00000 n -0001008197 00000 n +0000398865 00000 n +0001168436 00000 n 0000003437 00000 n 0000003496 00000 n -0000375127 00000 n -0001008065 00000 n +0000398994 00000 n +0001168304 00000 n 0000003545 00000 n 0000003578 00000 n -0000375256 00000 n -0001008000 00000 n +0000402912 00000 n +0001168239 00000 n 0000003632 00000 n 0000003681 00000 n -0000382582 00000 n -0001007868 00000 n +0000405926 00000 n +0001168107 00000 n 0000003730 00000 n 0000003758 00000 n -0000382711 00000 n -0001007750 00000 n +0000408706 00000 n +0001167989 00000 n 0000003812 00000 n 0000003881 00000 n -0000382840 00000 n -0001007671 00000 n +0000408835 00000 n +0001167910 00000 n 0000003940 00000 n 0000003988 00000 n -0000385631 00000 n -0001007592 00000 n +0000408963 00000 n +0001167831 00000 n 0000004047 00000 n 0000004092 00000 n -0000385760 00000 n -0001007499 00000 n +0000409092 00000 n +0001167738 00000 n 0000004146 00000 n 0000004214 00000 n -0000385889 00000 n -0001007406 00000 n +0000409221 00000 n +0001167645 00000 n 0000004268 00000 n 0000004338 00000 n -0000386018 00000 n -0001007313 00000 n +0000412890 00000 n +0001167552 00000 n 0000004392 00000 n 0000004455 00000 n -0000389940 00000 n -0001007220 00000 n +0000413019 00000 n +0001167459 00000 n 0000004509 00000 n 0000004564 00000 n -0000390069 00000 n -0001007141 00000 n +0000413147 00000 n +0001167380 00000 n 0000004618 00000 n 0000004650 00000 n -0000390198 00000 n -0001007048 00000 n +0000413275 00000 n +0001167287 00000 n 0000004699 00000 n 0000004727 00000 n -0000390327 00000 n -0001006955 00000 n +0000417044 00000 n +0001167194 00000 n 0000004776 00000 n 0000004808 00000 n -0000394104 00000 n -0001006823 00000 n +0000417173 00000 n +0001167062 00000 n 0000004857 00000 n 0000004887 00000 n -0000394233 00000 n -0001006744 00000 n +0000417302 00000 n +0001166983 00000 n 0000004941 00000 n 0000004982 00000 n -0000394362 00000 n -0001006651 00000 n +0000421100 00000 n +0001166890 00000 n 0000005036 00000 n 0000005078 00000 n -0000397957 00000 n -0001006572 00000 n +0000421229 00000 n +0001166811 00000 n 0000005132 00000 n 0000005177 00000 n -0000401403 00000 n -0001006454 00000 n +0000426552 00000 n +0001166678 00000 n 0000005226 00000 n -0000005272 00000 n -0000403004 00000 n -0001006375 00000 n -0000005326 00000 n -0000005386 00000 n -0000403133 00000 n -0001006296 00000 n -0000005440 00000 n -0000005509 00000 n -0000405940 00000 n -0001006163 00000 n -0000005556 00000 n -0000005609 00000 n -0000406069 00000 n -0001006084 00000 n -0000005658 00000 n -0000005714 00000 n -0000406198 00000 n -0001006005 00000 n -0000005763 00000 n -0000005812 00000 n -0000410382 00000 n -0001005872 00000 n -0000005859 00000 n -0000005911 00000 n -0000410511 00000 n -0001005754 00000 n -0000005960 00000 n -0000006011 00000 n -0000415203 00000 n -0001005636 00000 n -0000006065 00000 n -0000006110 00000 n -0000415331 00000 n -0001005557 00000 n -0000006169 00000 n -0000006203 00000 n -0000418952 00000 n -0001005478 00000 n -0000006262 00000 n -0000006310 00000 n -0000419080 00000 n -0001005360 00000 n -0000006364 00000 n -0000006404 00000 n -0000419209 00000 n -0001005281 00000 n -0000006463 00000 n -0000006497 00000 n -0000423146 00000 n -0001005202 00000 n -0000006556 00000 n -0000006604 00000 n -0000423275 00000 n -0001005069 00000 n -0000006653 00000 n -0000006703 00000 n -0000426095 00000 n -0001004990 00000 n -0000006757 00000 n -0000006804 00000 n -0000426223 00000 n -0001004897 00000 n -0000006858 00000 n -0000006918 00000 n -0000426482 00000 n -0001004804 00000 n -0000006972 00000 n -0000007024 00000 n -0000431831 00000 n -0001004711 00000 n -0000007078 00000 n -0000007143 00000 n -0000431960 00000 n -0001004618 00000 n -0000007197 00000 n -0000007248 00000 n -0000432089 00000 n -0001004525 00000 n -0000007302 00000 n -0000007366 00000 n -0000435541 00000 n -0001004432 00000 n -0000007420 00000 n -0000007467 00000 n -0000435670 00000 n -0001004339 00000 n -0000007521 00000 n -0000007581 00000 n -0000435799 00000 n -0001004246 00000 n -0000007635 00000 n -0000007686 00000 n -0000435928 00000 n -0001004114 00000 n -0000007741 00000 n -0000007806 00000 n -0000440159 00000 n -0001004035 00000 n -0000007866 00000 n -0000007913 00000 n -0000446716 00000 n -0001003942 00000 n -0000007973 00000 n -0000008021 00000 n -0000454268 00000 n -0001003863 00000 n -0000008081 00000 n -0000008135 00000 n -0000454527 00000 n -0001003770 00000 n -0000008190 00000 n +0000005294 00000 n +0000426681 00000 n +0001166599 00000 n +0000005348 00000 n +0000005408 00000 n +0000426810 00000 n +0001166506 00000 n +0000005462 00000 n +0000005513 00000 n +0000430749 00000 n +0001166413 00000 n +0000005567 00000 n +0000005621 00000 n +0000430877 00000 n +0001166320 00000 n +0000005675 00000 n +0000005721 00000 n +0000434027 00000 n +0001166227 00000 n +0000005775 00000 n +0000005817 00000 n +0000434156 00000 n +0001166134 00000 n +0000005871 00000 n +0000005922 00000 n +0000434285 00000 n +0001166041 00000 n +0000005976 00000 n +0000006025 00000 n +0000434414 00000 n +0001165948 00000 n +0000006079 00000 n +0000006136 00000 n +0000437328 00000 n +0001165855 00000 n +0000006190 00000 n +0000006245 00000 n +0000437457 00000 n +0001165762 00000 n +0000006300 00000 n +0000006356 00000 n +0000437586 00000 n +0001165669 00000 n +0000006411 00000 n +0000006472 00000 n +0000437715 00000 n +0001165576 00000 n +0000006527 00000 n +0000006573 00000 n +0000437844 00000 n +0001165497 00000 n +0000006628 00000 n +0000006671 00000 n +0000437973 00000 n +0001165365 00000 n +0000006721 00000 n +0000006777 00000 n +0000438102 00000 n +0001165286 00000 n +0000006832 00000 n +0000006878 00000 n +0000441694 00000 n +0001165207 00000 n +0000006933 00000 n +0000006980 00000 n +0000441823 00000 n +0001165075 00000 n +0000007030 00000 n +0000007087 00000 n +0000444830 00000 n +0001164957 00000 n +0000007142 00000 n +0000007182 00000 n +0000447718 00000 n +0001164878 00000 n +0000007242 00000 n +0000007315 00000 n +0000447847 00000 n +0001164799 00000 n +0000007375 00000 n +0000007448 00000 n +0000450309 00000 n +0001164667 00000 n +0000007503 00000 n +0000007561 00000 n +0000450438 00000 n +0001164588 00000 n +0000007621 00000 n +0000007678 00000 n +0000450567 00000 n +0001164509 00000 n +0000007738 00000 n +0000007797 00000 n +0000450696 00000 n +0001164416 00000 n +0000007852 00000 n +0000007896 00000 n +0000453505 00000 n +0001164323 00000 n +0000007951 00000 n +0000007991 00000 n +0000456304 00000 n +0001164230 00000 n +0000008046 00000 n +0000008114 00000 n +0000456433 00000 n +0001164151 00000 n +0000008169 00000 n 0000008240 00000 n -0000457350 00000 n -0001003677 00000 n -0000008295 00000 n -0000008358 00000 n -0000457479 00000 n -0001003584 00000 n -0000008413 00000 n -0000008465 00000 n -0000457608 00000 n -0001003491 00000 n -0000008520 00000 n -0000008585 00000 n -0000457737 00000 n -0001003398 00000 n -0000008640 00000 n -0000008692 00000 n -0000463748 00000 n -0001003265 00000 n -0000008747 00000 n -0000008812 00000 n -0000472151 00000 n -0001003186 00000 n -0000008872 00000 n -0000008916 00000 n -0000493407 00000 n -0001003093 00000 n -0000008976 00000 n -0000009015 00000 n -0000493536 00000 n -0001003000 00000 n -0000009075 00000 n -0000009122 00000 n -0000493665 00000 n -0001002907 00000 n -0000009182 00000 n -0000009225 00000 n -0000500581 00000 n -0001002814 00000 n -0000009285 00000 n -0000009324 00000 n -0000504097 00000 n -0001002721 00000 n -0000009384 00000 n -0000009426 00000 n -0000507277 00000 n -0001002628 00000 n -0000009486 00000 n -0000009529 00000 n -0000514841 00000 n -0001002535 00000 n -0000009589 00000 n -0000009632 00000 n -0000514970 00000 n -0001002442 00000 n -0000009692 00000 n -0000009753 00000 n -0000519163 00000 n -0001002349 00000 n -0000009814 00000 n -0000009866 00000 n -0000523056 00000 n -0001002256 00000 n +0000460499 00000 n +0001164033 00000 n +0000008290 00000 n +0000008337 00000 n +0000460628 00000 n +0001163954 00000 n +0000008392 00000 n +0000008453 00000 n +0000460757 00000 n +0001163875 00000 n +0000008508 00000 n +0000008578 00000 n +0000463625 00000 n +0001163742 00000 n +0000008625 00000 n +0000008678 00000 n +0000463754 00000 n +0001163663 00000 n +0000008727 00000 n +0000008783 00000 n +0000463883 00000 n +0001163584 00000 n +0000008832 00000 n +0000008881 00000 n +0000468153 00000 n +0001163451 00000 n +0000008928 00000 n +0000008980 00000 n +0000468282 00000 n +0001163333 00000 n +0000009029 00000 n +0000009080 00000 n +0000472974 00000 n +0001163215 00000 n +0000009134 00000 n +0000009179 00000 n +0000473102 00000 n +0001163136 00000 n +0000009238 00000 n +0000009272 00000 n +0000476695 00000 n +0001163057 00000 n +0000009331 00000 n +0000009379 00000 n +0000476824 00000 n +0001162939 00000 n +0000009433 00000 n +0000009473 00000 n +0000476953 00000 n +0001162860 00000 n +0000009532 00000 n +0000009566 00000 n +0000479805 00000 n +0001162781 00000 n +0000009625 00000 n +0000009673 00000 n +0000479934 00000 n +0001162648 00000 n +0000009722 00000 n +0000009772 00000 n +0000483004 00000 n +0001162569 00000 n +0000009826 00000 n +0000009873 00000 n +0000483132 00000 n +0001162476 00000 n 0000009927 00000 n -0000009980 00000 n -0000523185 00000 n -0001002163 00000 n +0000009987 00000 n +0000483391 00000 n +0001162383 00000 n 0000010041 00000 n -0000010079 00000 n -0000527219 00000 n -0001002070 00000 n -0000010140 00000 n -0000010192 00000 n -0000530375 00000 n -0001001977 00000 n -0000010253 00000 n -0000010297 00000 n -0000534314 00000 n -0001001884 00000 n -0000010358 00000 n -0000010394 00000 n -0000542730 00000 n -0001001791 00000 n -0000010455 00000 n -0000010518 00000 n -0000542859 00000 n -0001001698 00000 n -0000010579 00000 n -0000010629 00000 n -0000546041 00000 n -0001001619 00000 n -0000010690 00000 n -0000010746 00000 n -0000549267 00000 n -0001001526 00000 n -0000010801 00000 n -0000010852 00000 n -0000554329 00000 n -0001001433 00000 n -0000010907 00000 n -0000010971 00000 n -0000558052 00000 n -0001001340 00000 n -0000011026 00000 n +0000010093 00000 n +0000488573 00000 n +0001162290 00000 n +0000010147 00000 n +0000010212 00000 n +0000488702 00000 n +0001162197 00000 n +0000010266 00000 n +0000010317 00000 n +0000492179 00000 n +0001162104 00000 n +0000010371 00000 n +0000010435 00000 n +0000492308 00000 n +0001162011 00000 n +0000010489 00000 n +0000010536 00000 n +0000492437 00000 n +0001161918 00000 n +0000010590 00000 n +0000010650 00000 n +0000492566 00000 n +0001161825 00000 n +0000010704 00000 n +0000010755 00000 n +0000496584 00000 n +0001161693 00000 n +0000010810 00000 n +0000010875 00000 n +0000496713 00000 n +0001161614 00000 n +0000010935 00000 n +0000010982 00000 n +0000503534 00000 n +0001161521 00000 n +0000011042 00000 n 0000011090 00000 n -0000558180 00000 n -0001001247 00000 n -0000011145 00000 n -0000011222 00000 n -0000558309 00000 n -0001001154 00000 n -0000011277 00000 n -0000011334 00000 n -0000558437 00000 n -0001001061 00000 n -0000011389 00000 n -0000011459 00000 n -0000562254 00000 n -0001000968 00000 n -0000011514 00000 n -0000011563 00000 n -0000562383 00000 n -0001000875 00000 n -0000011618 00000 n -0000011680 00000 n -0000564065 00000 n -0001000782 00000 n -0000011735 00000 n -0000011784 00000 n -0000567156 00000 n -0001000664 00000 n -0000011839 00000 n -0000011901 00000 n -0000567284 00000 n -0001000585 00000 n -0000011961 00000 n -0000012000 00000 n -0000576166 00000 n -0001000492 00000 n -0000012060 00000 n -0000012094 00000 n -0000576295 00000 n -0001000399 00000 n -0000012154 00000 n -0000012195 00000 n -0000592451 00000 n -0001000320 00000 n -0000012255 00000 n -0000012307 00000 n -0000595699 00000 n -0001000188 00000 n -0000012356 00000 n -0000012389 00000 n -0000595827 00000 n -0001000070 00000 n -0000012443 00000 n -0000012515 00000 n -0000595955 00000 n -0000999991 00000 n -0000012574 00000 n -0000012618 00000 n -0000607186 00000 n -0000999912 00000 n -0000012677 00000 n -0000012730 00000 n -0000610897 00000 n -0000999819 00000 n -0000012784 00000 n -0000012834 00000 n -0000611156 00000 n -0000999726 00000 n -0000012888 00000 n -0000012926 00000 n -0000614299 00000 n -0000999633 00000 n -0000012980 00000 n -0000013029 00000 n -0000614558 00000 n -0000999501 00000 n -0000013083 00000 n -0000013135 00000 n -0000614687 00000 n -0000999422 00000 n -0000013194 00000 n -0000013239 00000 n -0000614816 00000 n -0000999329 00000 n -0000013298 00000 n -0000013350 00000 n -0000617602 00000 n -0000999236 00000 n -0000013409 00000 n -0000013462 00000 n -0000617730 00000 n -0000999157 00000 n -0000013521 00000 n -0000013570 00000 n -0000617859 00000 n -0000999064 00000 n -0000013624 00000 n -0000013704 00000 n -0000622193 00000 n -0000998985 00000 n -0000013758 00000 n -0000013807 00000 n -0000622322 00000 n -0000998867 00000 n -0000013856 00000 n -0000013896 00000 n -0000625918 00000 n -0000998788 00000 n -0000013955 00000 n -0000014002 00000 n -0000626047 00000 n -0000998670 00000 n -0000014056 00000 n -0000014101 00000 n -0000629692 00000 n -0000998591 00000 n -0000014160 00000 n -0000014219 00000 n -0000632705 00000 n -0000998498 00000 n -0000014278 00000 n -0000014342 00000 n -0000632963 00000 n -0000998405 00000 n -0000014401 00000 n -0000014457 00000 n -0000636831 00000 n -0000998312 00000 n -0000014516 00000 n -0000014574 00000 n -0000638438 00000 n -0000998233 00000 n -0000014633 00000 n +0000509939 00000 n +0001161442 00000 n +0000011150 00000 n +0000011204 00000 n +0000513027 00000 n +0001161349 00000 n +0000011259 00000 n +0000011309 00000 n +0000515884 00000 n +0001161256 00000 n +0000011364 00000 n +0000011427 00000 n +0000516013 00000 n +0001161163 00000 n +0000011482 00000 n +0000011534 00000 n +0000516141 00000 n +0001161070 00000 n +0000011589 00000 n +0000011654 00000 n +0000516269 00000 n +0001160977 00000 n +0000011709 00000 n +0000011761 00000 n +0000521189 00000 n +0001160844 00000 n +0000011816 00000 n +0000011881 00000 n +0000541024 00000 n +0001160765 00000 n +0000011941 00000 n +0000011985 00000 n +0000562621 00000 n +0001160672 00000 n +0000012045 00000 n +0000012084 00000 n +0000566256 00000 n +0001160579 00000 n +0000012144 00000 n +0000012191 00000 n +0000566385 00000 n +0001160486 00000 n +0000012251 00000 n +0000012294 00000 n +0000570803 00000 n +0001160393 00000 n +0000012354 00000 n +0000012393 00000 n +0000574151 00000 n +0001160300 00000 n +0000012453 00000 n +0000012495 00000 n +0000580978 00000 n +0001160207 00000 n +0000012555 00000 n +0000012598 00000 n +0000588866 00000 n +0001160114 00000 n +0000012658 00000 n +0000012701 00000 n +0000588995 00000 n +0001160021 00000 n +0000012761 00000 n +0000012822 00000 n +0000593028 00000 n +0001159928 00000 n +0000012883 00000 n +0000012935 00000 n +0000593157 00000 n +0001159835 00000 n +0000012996 00000 n +0000013049 00000 n +0000596321 00000 n +0001159742 00000 n +0000013110 00000 n +0000013148 00000 n +0000600259 00000 n +0001159649 00000 n +0000013209 00000 n +0000013261 00000 n +0000603551 00000 n +0001159556 00000 n +0000013322 00000 n +0000013366 00000 n +0000603809 00000 n +0001159463 00000 n +0000013427 00000 n +0000013463 00000 n +0000612635 00000 n +0001159370 00000 n +0000013524 00000 n +0000013587 00000 n +0000615981 00000 n +0001159277 00000 n +0000013648 00000 n +0000013698 00000 n +0000619742 00000 n +0001159184 00000 n +0000013759 00000 n +0000013815 00000 n +0000624070 00000 n +0001159091 00000 n +0000013876 00000 n +0000013923 00000 n +0000628370 00000 n +0001159012 00000 n +0000013984 00000 n +0000014052 00000 n +0000630938 00000 n +0001158919 00000 n +0000014107 00000 n +0000014158 00000 n +0000635461 00000 n +0001158826 00000 n +0000014213 00000 n +0000014277 00000 n +0000639146 00000 n +0001158733 00000 n +0000014332 00000 n +0000014396 00000 n +0000639275 00000 n +0001158640 00000 n +0000014451 00000 n +0000014528 00000 n +0000639403 00000 n +0001158547 00000 n +0000014583 00000 n +0000014640 00000 n +0000643560 00000 n +0001158454 00000 n 0000014695 00000 n -0000640286 00000 n -0000998100 00000 n -0000014742 00000 n -0000014794 00000 n -0000640415 00000 n -0000998021 00000 n -0000014843 00000 n -0000014887 00000 n -0000644614 00000 n -0000997889 00000 n -0000014936 00000 n -0000014977 00000 n -0000644743 00000 n -0000997810 00000 n -0000015031 00000 n -0000015079 00000 n -0000644871 00000 n -0000997731 00000 n -0000015133 00000 n -0000015184 00000 n -0000645000 00000 n -0000997652 00000 n -0000015233 00000 n -0000015280 00000 n -0000649267 00000 n -0000997519 00000 n +0000014765 00000 n +0000643688 00000 n +0001158361 00000 n +0000014820 00000 n +0000014877 00000 n +0000643817 00000 n +0001158268 00000 n +0000014932 00000 n +0000015002 00000 n +0000648072 00000 n +0001158175 00000 n +0000015057 00000 n +0000015106 00000 n +0000648201 00000 n +0001158082 00000 n +0000015161 00000 n +0000015223 00000 n +0000650348 00000 n +0001157989 00000 n +0000015278 00000 n 0000015327 00000 n -0000015364 00000 n -0000649396 00000 n -0000997401 00000 n -0000015413 00000 n -0000015452 00000 n -0000649525 00000 n -0000997336 00000 n -0000015506 00000 n -0000015584 00000 n -0000649654 00000 n -0000997243 00000 n -0000015633 00000 n -0000015700 00000 n -0000649783 00000 n -0000997164 00000 n -0000015749 00000 n -0000015794 00000 n -0000653222 00000 n -0000997031 00000 n -0000015842 00000 n -0000015874 00000 n -0000653351 00000 n -0000996913 00000 n -0000015923 00000 n -0000015962 00000 n -0000653480 00000 n -0000996848 00000 n -0000016016 00000 n -0000016077 00000 n -0000657161 00000 n -0000996716 00000 n -0000016126 00000 n -0000016183 00000 n -0000657290 00000 n -0000996651 00000 n -0000016237 00000 n -0000016286 00000 n -0000657419 00000 n -0000996533 00000 n -0000016335 00000 n -0000016397 00000 n -0000657548 00000 n -0000996454 00000 n -0000016451 00000 n -0000016506 00000 n -0000681573 00000 n -0000996361 00000 n -0000016560 00000 n -0000016601 00000 n -0000681702 00000 n -0000996282 00000 n -0000016655 00000 n -0000016707 00000 n -0000684433 00000 n -0000996162 00000 n -0000016755 00000 n -0000016789 00000 n -0000684562 00000 n -0000996083 00000 n -0000016838 00000 n -0000016865 00000 n -0000702386 00000 n -0000995990 00000 n -0000016914 00000 n -0000016942 00000 n -0000709874 00000 n -0000995897 00000 n -0000016991 00000 n -0000017031 00000 n -0000712670 00000 n -0000995804 00000 n -0000017080 00000 n -0000017123 00000 n -0000718853 00000 n -0000995711 00000 n -0000017172 00000 n -0000017209 00000 n -0000725478 00000 n -0000995618 00000 n -0000017258 00000 n -0000017297 00000 n -0000737861 00000 n -0000995525 00000 n -0000017346 00000 n -0000017385 00000 n -0000740957 00000 n -0000995432 00000 n -0000017434 00000 n -0000017473 00000 n -0000747237 00000 n -0000995339 00000 n -0000017522 00000 n -0000017551 00000 n -0000757049 00000 n -0000995246 00000 n -0000017601 00000 n -0000017634 00000 n -0000771281 00000 n -0000995153 00000 n -0000017684 00000 n -0000017713 00000 n -0000774411 00000 n -0000995060 00000 n -0000017763 00000 n -0000017797 00000 n -0000780649 00000 n -0000994981 00000 n -0000017847 00000 n -0000017884 00000 n -0000018257 00000 n -0000018379 00000 n -0000283180 00000 n -0000017937 00000 n -0000283054 00000 n -0000283117 00000 n -0000990433 00000 n -0000964490 00000 n -0000990259 00000 n -0000991458 00000 n -0000019688 00000 n -0000019881 00000 n -0000019961 00000 n -0000019998 00000 n -0000020079 00000 n -0000020203 00000 n -0000020462 00000 n -0000020821 00000 n -0000020853 00000 n -0000020947 00000 n -0000021980 00000 n -0000033116 00000 n -0000098706 00000 n -0000164296 00000 n -0000229886 00000 n -0000284604 00000 n -0000284419 00000 n -0000283280 00000 n -0000284541 00000 n -0000963269 00000 n -0000936748 00000 n -0000963095 00000 n -0000936063 00000 n -0000933918 00000 n -0000935899 00000 n -0000296307 00000 n -0000287653 00000 n -0000284689 00000 n -0000296181 00000 n -0000296244 00000 n -0000288187 00000 n -0000288341 00000 n -0000288498 00000 n -0000288655 00000 n -0000288812 00000 n -0000288969 00000 n -0000289131 00000 n -0000289293 00000 n -0000289454 00000 n -0000289616 00000 n -0000289783 00000 n -0000289950 00000 n -0000290115 00000 n -0000290277 00000 n -0000290443 00000 n -0000290605 00000 n -0000290759 00000 n -0000290916 00000 n -0000291073 00000 n -0000291229 00000 n -0000291385 00000 n -0000291542 00000 n -0000291697 00000 n -0000291854 00000 n -0000292016 00000 n -0000292178 00000 n -0000292335 00000 n -0000292490 00000 n -0000292651 00000 n -0000292818 00000 n -0000292985 00000 n -0000293147 00000 n -0000293302 00000 n -0000293459 00000 n -0000293616 00000 n -0000293778 00000 n -0000293935 00000 n -0000294092 00000 n -0000294253 00000 n -0000294410 00000 n -0000294572 00000 n -0000294739 00000 n -0000294906 00000 n -0000295068 00000 n -0000295230 00000 n -0000295392 00000 n -0000295554 00000 n -0000295716 00000 n -0000295871 00000 n -0000296026 00000 n -0000309682 00000 n -0000299635 00000 n -0000296392 00000 n -0000309619 00000 n -0000933367 00000 n -0000916286 00000 n -0000933183 00000 n -0000300225 00000 n -0000300388 00000 n -0000300550 00000 n -0000300712 00000 n -0000300870 00000 n -0000301033 00000 n -0000301196 00000 n -0000301351 00000 n -0000301509 00000 n -0000301667 00000 n -0000301823 00000 n -0000301981 00000 n -0000302144 00000 n -0000302312 00000 n -0000302480 00000 n -0000302643 00000 n -0000302811 00000 n -0000302979 00000 n -0000303136 00000 n -0000303299 00000 n -0000303462 00000 n -0000303625 00000 n -0000303787 00000 n -0000303950 00000 n -0000304112 00000 n -0000304274 00000 n -0000304437 00000 n -0000304600 00000 n -0000304763 00000 n -0000304931 00000 n -0000305100 00000 n -0000305269 00000 n -0000305433 00000 n -0000305597 00000 n -0000305761 00000 n -0000305925 00000 n -0000306089 00000 n -0000306253 00000 n -0000306421 00000 n -0000306590 00000 n -0000306759 00000 n -0000306928 00000 n -0000307097 00000 n -0000307266 00000 n -0000307435 00000 n -0000307604 00000 n -0000307773 00000 n -0000307943 00000 n -0000308113 00000 n -0000308282 00000 n -0000308452 00000 n -0000308622 00000 n -0000308790 00000 n -0000308959 00000 n -0000309129 00000 n -0000309296 00000 n -0000309457 00000 n -0000322857 00000 n -0000313314 00000 n -0000309780 00000 n -0000322794 00000 n -0000313888 00000 n -0000314051 00000 n -0000314214 00000 n -0000314377 00000 n -0000314540 00000 n -0000314703 00000 n -0000314866 00000 n -0000315029 00000 n -0000315192 00000 n -0000315360 00000 n -0000315528 00000 n -0000315696 00000 n -0000315864 00000 n -0000316021 00000 n -0000316181 00000 n -0000316347 00000 n -0000316514 00000 n -0000316676 00000 n -0000316838 00000 n -0000317000 00000 n -0000317162 00000 n -0000317329 00000 n -0000317496 00000 n -0000317663 00000 n -0000317830 00000 n -0000317992 00000 n -0000318154 00000 n -0000318311 00000 n -0000318478 00000 n -0000318639 00000 n -0000318806 00000 n -0000318973 00000 n -0000319140 00000 n -0000915397 00000 n -0000894066 00000 n -0000915223 00000 n -0000319307 00000 n -0000319473 00000 n -0000319628 00000 n -0000319784 00000 n -0000319940 00000 n -0000320102 00000 n -0000320264 00000 n -0000320421 00000 n -0000320576 00000 n -0000320733 00000 n -0000320895 00000 n -0000321052 00000 n -0000321209 00000 n -0000321365 00000 n -0000321522 00000 n -0000321684 00000 n -0000321841 00000 n -0000322002 00000 n -0000322157 00000 n -0000322319 00000 n -0000322480 00000 n -0000322640 00000 n -0000326277 00000 n -0000323933 00000 n -0000322968 00000 n -0000326214 00000 n -0000324171 00000 n -0000324328 00000 n -0000324485 00000 n -0000324641 00000 n -0000324798 00000 n -0000324955 00000 n -0000325112 00000 n -0000325269 00000 n -0000325426 00000 n -0000325582 00000 n -0000325740 00000 n -0000893100 00000 n -0000873133 00000 n -0000892927 00000 n -0000325898 00000 n -0000326056 00000 n -0000329377 00000 n -0000328630 00000 n -0000326375 00000 n -0000328813 00000 n -0000328938 00000 n -0000329063 00000 n -0000329188 00000 n -0000329251 00000 n -0000329314 00000 n -0000872339 00000 n -0000854022 00000 n -0000872166 00000 n -0000991576 00000 n -0000333885 00000 n -0000332768 00000 n -0000329501 00000 n -0000333262 00000 n -0000333325 00000 n -0000333449 00000 n -0000333574 00000 n -0000333699 00000 n -0000332918 00000 n -0000333111 00000 n -0000333822 00000 n -0000595891 00000 n -0000657612 00000 n -0000338540 00000 n -0000337504 00000 n -0000334009 00000 n -0000337977 00000 n -0000338102 00000 n -0000337654 00000 n -0000337816 00000 n -0000338227 00000 n -0000338352 00000 n -0000338477 00000 n -0000354470 00000 n -0000341761 00000 n -0000341201 00000 n -0000338664 00000 n -0000341323 00000 n -0000341448 00000 n -0000341573 00000 n -0000341698 00000 n -0000345190 00000 n -0000344049 00000 n -0000341872 00000 n -0000344503 00000 n -0000344628 00000 n -0000344753 00000 n -0000344878 00000 n -0000345003 00000 n -0000344199 00000 n -0000344351 00000 n -0000345127 00000 n -0000546105 00000 n -0000346274 00000 n -0000345961 00000 n -0000345275 00000 n -0000346084 00000 n -0000346210 00000 n -0000348371 00000 n -0000347668 00000 n -0000346372 00000 n -0000347794 00000 n -0000347922 00000 n -0000348049 00000 n -0000348177 00000 n -0000348306 00000 n -0000991694 00000 n -0000351303 00000 n -0000350414 00000 n -0000348470 00000 n -0000350722 00000 n -0000350851 00000 n -0000350916 00000 n -0000350981 00000 n -0000350561 00000 n -0000351110 00000 n -0000351239 00000 n -0000530439 00000 n -0000354663 00000 n -0000354215 00000 n -0000351415 00000 n -0000354341 00000 n -0000853347 00000 n -0000841358 00000 n -0000853168 00000 n -0000354598 00000 n -0000358487 00000 n -0000358296 00000 n -0000354789 00000 n -0000358422 00000 n -0000840817 00000 n -0000831071 00000 n -0000840638 00000 n -0000363097 00000 n -0000362698 00000 n -0000358653 00000 n -0000363032 00000 n -0000362845 00000 n -0000431895 00000 n -0000365442 00000 n -0000364992 00000 n -0000363236 00000 n -0000365118 00000 n -0000365247 00000 n -0000365312 00000 n -0000365377 00000 n -0000368173 00000 n -0000370720 00000 n -0000368017 00000 n -0000365567 00000 n -0000370139 00000 n -0000370268 00000 n -0000370397 00000 n +0000655852 00000 n +0001157871 00000 n +0000015382 00000 n +0000015444 00000 n +0000655980 00000 n +0001157792 00000 n +0000015504 00000 n +0000015543 00000 n +0000664901 00000 n +0001157699 00000 n +0000015603 00000 n +0000015637 00000 n +0000665030 00000 n +0001157606 00000 n +0000015697 00000 n +0000015738 00000 n +0000685657 00000 n +0001157527 00000 n +0000015798 00000 n +0000015850 00000 n +0000692639 00000 n +0001157395 00000 n +0000015899 00000 n +0000015932 00000 n +0000692768 00000 n +0001157277 00000 n +0000015986 00000 n +0000016058 00000 n +0000692897 00000 n +0001157198 00000 n +0000016117 00000 n +0000016161 00000 n +0000703499 00000 n +0001157119 00000 n +0000016220 00000 n +0000016273 00000 n +0000703888 00000 n +0001157026 00000 n +0000016327 00000 n +0000016377 00000 n +0000707742 00000 n +0001156933 00000 n +0000016431 00000 n +0000016469 00000 n +0000708001 00000 n +0001156840 00000 n +0000016523 00000 n +0000016572 00000 n +0000710774 00000 n +0001156708 00000 n +0000016626 00000 n +0000016678 00000 n +0000710899 00000 n +0001156629 00000 n +0000016737 00000 n +0000016782 00000 n +0000711028 00000 n +0001156536 00000 n +0000016841 00000 n +0000016893 00000 n +0000711157 00000 n +0001156443 00000 n +0000016952 00000 n +0000017005 00000 n +0000713609 00000 n +0001156364 00000 n +0000017064 00000 n +0000017113 00000 n +0000713738 00000 n +0001156271 00000 n +0000017167 00000 n +0000017247 00000 n +0000718053 00000 n +0001156192 00000 n +0000017301 00000 n +0000017350 00000 n +0000721558 00000 n +0001156074 00000 n +0000017399 00000 n +0000017439 00000 n +0000721817 00000 n +0001155995 00000 n +0000017498 00000 n +0000017545 00000 n +0000725249 00000 n +0001155877 00000 n +0000017599 00000 n +0000017644 00000 n +0000725378 00000 n +0001155798 00000 n +0000017703 00000 n +0000017762 00000 n +0000728733 00000 n +0001155705 00000 n +0000017821 00000 n +0000017885 00000 n +0000728992 00000 n +0001155612 00000 n +0000017944 00000 n +0000018000 00000 n +0000733149 00000 n +0001155519 00000 n +0000018059 00000 n +0000018117 00000 n +0000735170 00000 n +0001155440 00000 n +0000018176 00000 n +0000018238 00000 n +0000737334 00000 n +0001155307 00000 n +0000018285 00000 n +0000018337 00000 n +0000737463 00000 n +0001155228 00000 n +0000018386 00000 n +0000018430 00000 n +0000741498 00000 n +0001155096 00000 n +0000018479 00000 n +0000018520 00000 n +0000741627 00000 n +0001155017 00000 n +0000018574 00000 n +0000018622 00000 n +0000741755 00000 n +0001154938 00000 n +0000018676 00000 n +0000018727 00000 n +0000741884 00000 n +0001154859 00000 n +0000018776 00000 n +0000018823 00000 n +0000746483 00000 n +0001154726 00000 n +0000018870 00000 n +0000018907 00000 n +0000746612 00000 n +0001154608 00000 n +0000018956 00000 n +0000018995 00000 n +0000746741 00000 n +0001154543 00000 n +0000019049 00000 n +0000019127 00000 n +0000746870 00000 n +0001154450 00000 n +0000019176 00000 n +0000019243 00000 n +0000746999 00000 n +0001154371 00000 n +0000019292 00000 n +0000019337 00000 n +0000750440 00000 n +0001154238 00000 n +0000019385 00000 n +0000019417 00000 n +0000750569 00000 n +0001154120 00000 n +0000019466 00000 n +0000019505 00000 n +0000750698 00000 n +0001154055 00000 n +0000019559 00000 n +0000019620 00000 n +0000754380 00000 n +0001153923 00000 n +0000019669 00000 n +0000019726 00000 n +0000754509 00000 n +0001153858 00000 n +0000019780 00000 n +0000019829 00000 n +0000754638 00000 n +0001153726 00000 n +0000019878 00000 n +0000019940 00000 n +0000754767 00000 n +0001153647 00000 n +0000019994 00000 n +0000020049 00000 n +0000779610 00000 n +0001153554 00000 n +0000020103 00000 n +0000020144 00000 n +0000779739 00000 n +0001153475 00000 n +0000020198 00000 n +0000020250 00000 n +0000780128 00000 n +0001153357 00000 n +0000020299 00000 n +0000020349 00000 n +0000782950 00000 n +0001153278 00000 n +0000020403 00000 n +0000020441 00000 n +0000783079 00000 n +0001153185 00000 n +0000020495 00000 n +0000020532 00000 n +0000783208 00000 n +0001153092 00000 n +0000020586 00000 n +0000020624 00000 n +0000783337 00000 n +0001152999 00000 n +0000020678 00000 n +0000020730 00000 n +0000786573 00000 n +0001152906 00000 n +0000020784 00000 n +0000020827 00000 n +0000786701 00000 n +0001152774 00000 n +0000020881 00000 n +0000020926 00000 n +0000786829 00000 n +0001152695 00000 n +0000020985 00000 n +0000021051 00000 n +0000789815 00000 n +0001152602 00000 n +0000021110 00000 n +0000021198 00000 n +0000789944 00000 n +0001152509 00000 n +0000021257 00000 n +0000021332 00000 n +0000790073 00000 n +0001152416 00000 n +0000021391 00000 n +0000021476 00000 n +0000792981 00000 n +0001152323 00000 n +0000021535 00000 n +0000021616 00000 n +0000795442 00000 n +0001152244 00000 n +0000021675 00000 n +0000021759 00000 n +0000795571 00000 n +0001152165 00000 n +0000021813 00000 n +0000021857 00000 n +0000798400 00000 n +0001152045 00000 n +0000021905 00000 n +0000021939 00000 n +0000798529 00000 n +0001151966 00000 n +0000021988 00000 n +0000022015 00000 n +0000816495 00000 n +0001151873 00000 n +0000022064 00000 n +0000022092 00000 n +0000824044 00000 n +0001151780 00000 n +0000022141 00000 n +0000022181 00000 n +0000830319 00000 n +0001151687 00000 n +0000022230 00000 n +0000022273 00000 n +0000836854 00000 n +0001151594 00000 n +0000022322 00000 n +0000022359 00000 n +0000850093 00000 n +0001151501 00000 n +0000022408 00000 n +0000022445 00000 n +0000853117 00000 n +0001151408 00000 n +0000022494 00000 n +0000022532 00000 n +0000859767 00000 n +0001151315 00000 n +0000022581 00000 n +0000022620 00000 n +0000873231 00000 n +0001151222 00000 n +0000022669 00000 n +0000022708 00000 n +0000876250 00000 n +0001151129 00000 n +0000022758 00000 n +0000022798 00000 n +0000885745 00000 n +0001151036 00000 n +0000022848 00000 n +0000022878 00000 n +0000894551 00000 n +0001150943 00000 n +0000022928 00000 n +0000022971 00000 n +0000895005 00000 n +0001150850 00000 n +0000023021 00000 n +0000023054 00000 n +0000909263 00000 n +0001150757 00000 n +0000023104 00000 n +0000023133 00000 n +0000916463 00000 n +0001150664 00000 n +0000023183 00000 n +0000023217 00000 n +0000922445 00000 n +0001150571 00000 n +0000023267 00000 n +0000023304 00000 n +0000925715 00000 n +0001150478 00000 n +0000023354 00000 n +0000023391 00000 n +0000931198 00000 n +0001150385 00000 n +0000023441 00000 n +0000023474 00000 n +0000931651 00000 n +0001150292 00000 n +0000023524 00000 n +0000023558 00000 n +0000934599 00000 n +0001150199 00000 n +0000023608 00000 n +0000023647 00000 n +0000936747 00000 n +0001150120 00000 n +0000023697 00000 n +0000023731 00000 n +0000024104 00000 n +0000024226 00000 n +0000289027 00000 n +0000023784 00000 n +0000288901 00000 n +0000288964 00000 n +0001144529 00000 n +0001118444 00000 n +0001144355 00000 n +0001145567 00000 n +0000025535 00000 n +0000025728 00000 n +0000025808 00000 n +0000025845 00000 n +0000025926 00000 n +0000026050 00000 n +0000026309 00000 n +0000026668 00000 n +0000026700 00000 n +0000026794 00000 n +0000027827 00000 n +0000038963 00000 n +0000104553 00000 n +0000170143 00000 n +0000235733 00000 n +0000290455 00000 n +0000290270 00000 n +0000289127 00000 n +0000290392 00000 n +0001117208 00000 n +0001090589 00000 n +0001117034 00000 n +0001089904 00000 n +0001087759 00000 n +0001089740 00000 n +0000302181 00000 n +0000293506 00000 n +0000290540 00000 n +0000302055 00000 n +0000302118 00000 n +0000294052 00000 n +0000294206 00000 n +0000294363 00000 n +0000294520 00000 n +0000294677 00000 n +0000294834 00000 n +0000294996 00000 n +0000295158 00000 n +0000295319 00000 n +0000295481 00000 n +0000295648 00000 n +0000295815 00000 n +0000295980 00000 n +0000296142 00000 n +0000296308 00000 n +0000296470 00000 n +0000296624 00000 n +0000296781 00000 n +0000296938 00000 n +0000297094 00000 n +0000297250 00000 n +0000297407 00000 n +0000297562 00000 n +0000297719 00000 n +0000297881 00000 n +0000298043 00000 n +0000298200 00000 n +0000298355 00000 n +0000298516 00000 n +0000298683 00000 n +0000298850 00000 n +0000299011 00000 n +0000299166 00000 n +0000299323 00000 n +0000299480 00000 n +0000299642 00000 n +0000299799 00000 n +0000299956 00000 n +0000300117 00000 n +0000300275 00000 n +0000300438 00000 n +0000300606 00000 n +0000300774 00000 n +0000300937 00000 n +0000301100 00000 n +0000301263 00000 n +0000301425 00000 n +0000301588 00000 n +0000301744 00000 n +0000301900 00000 n +0000315699 00000 n +0000305636 00000 n +0000302266 00000 n +0000315634 00000 n +0001087171 00000 n +0001069750 00000 n +0001086985 00000 n +0000306286 00000 n +0000306450 00000 n +0000306613 00000 n +0000306777 00000 n +0000306936 00000 n +0000307100 00000 n +0000307264 00000 n +0000307428 00000 n +0000307592 00000 n +0000307756 00000 n +0000307920 00000 n +0000308084 00000 n +0000308248 00000 n +0000308412 00000 n +0000308577 00000 n +0000308742 00000 n +0000308907 00000 n +0000309072 00000 n +0000309232 00000 n +0000309397 00000 n +0000309561 00000 n +0000309721 00000 n +0000309886 00000 n +0000310056 00000 n +0000310226 00000 n +0000310391 00000 n +0000310560 00000 n +0000310729 00000 n +0000310894 00000 n +0000311059 00000 n +0000311223 00000 n +0000311388 00000 n +0000311548 00000 n +0000311713 00000 n +0000311878 00000 n +0000312034 00000 n +0000312193 00000 n +0000312352 00000 n +0000312509 00000 n +0000312668 00000 n +0000312832 00000 n +0000313001 00000 n +0000313170 00000 n +0000313334 00000 n +0000313503 00000 n +0000313672 00000 n +0000313831 00000 n +0000313995 00000 n +0000314159 00000 n +0000314323 00000 n +0000314487 00000 n +0000314651 00000 n +0000314815 00000 n +0000314978 00000 n +0000315142 00000 n +0000315304 00000 n +0000315466 00000 n +0000329835 00000 n +0000319302 00000 n +0000315799 00000 n +0000329770 00000 n +0000319970 00000 n +0000320139 00000 n +0000320307 00000 n +0000320471 00000 n +0000320634 00000 n +0000320798 00000 n +0000320962 00000 n +0000321126 00000 n +0000321290 00000 n +0000321459 00000 n +0000321627 00000 n +0000321796 00000 n +0000321965 00000 n +0000322133 00000 n +0000322302 00000 n +0000322471 00000 n +0000322639 00000 n +0000322808 00000 n +0000322978 00000 n +0000323147 00000 n +0000323317 00000 n +0000323487 00000 n +0000323657 00000 n +0000323827 00000 n +0000323997 00000 n +0000324167 00000 n +0000324337 00000 n +0000324507 00000 n +0000324676 00000 n +0000324840 00000 n +0000325003 00000 n +0000325167 00000 n +0000325331 00000 n +0000325495 00000 n +0000325659 00000 n +0000325823 00000 n +0000325986 00000 n +0000326150 00000 n +0000326314 00000 n +0000326477 00000 n +0000326641 00000 n +0000326809 00000 n +0000326978 00000 n +0000327147 00000 n +0000327316 00000 n +0000327473 00000 n +0000327636 00000 n +0000327804 00000 n +0000327971 00000 n +0000328134 00000 n +0000328296 00000 n +0000328459 00000 n +0000328622 00000 n +0000328790 00000 n +0000328958 00000 n +0000329126 00000 n +0000329293 00000 n +0000329454 00000 n +0000329614 00000 n +0000342999 00000 n +0000333429 00000 n +0000329935 00000 n +0000342934 00000 n +0000334061 00000 n +0000334229 00000 n +0000334392 00000 n +0000334560 00000 n +0000334728 00000 n +0000334896 00000 n +0001068859 00000 n +0001047525 00000 n +0001068683 00000 n +0000335064 00000 n +0000335231 00000 n +0000335387 00000 n +0000335545 00000 n +0000335703 00000 n +0000335866 00000 n +0000336029 00000 n +0000336187 00000 n +0000336343 00000 n +0000336501 00000 n +0000336664 00000 n +0000336822 00000 n +0000336980 00000 n +0000337136 00000 n +0000337294 00000 n +0000337457 00000 n +0000337615 00000 n +0000337778 00000 n +0000337935 00000 n +0000338097 00000 n +0000338260 00000 n +0000338423 00000 n +0000338581 00000 n +0000338744 00000 n +0000338907 00000 n +0000339070 00000 n +0000339233 00000 n +0000339396 00000 n +0000339559 00000 n +0000339727 00000 n +0000339895 00000 n +0000340062 00000 n +0000340228 00000 n +0000340395 00000 n +0000340562 00000 n +0000340725 00000 n +0000340882 00000 n +0000341040 00000 n +0000341198 00000 n +0000341356 00000 n +0000341514 00000 n +0000341672 00000 n +0000341830 00000 n +0000341988 00000 n +0000342146 00000 n +0000342304 00000 n +0000342463 00000 n +0000342620 00000 n +0000342777 00000 n +0000345400 00000 n +0000343854 00000 n +0000343113 00000 n +0000345335 00000 n +0000344064 00000 n +0001046557 00000 n +0001026587 00000 n +0001046382 00000 n +0000344223 00000 n +0000344382 00000 n +0000344540 00000 n +0000344699 00000 n +0000344858 00000 n +0000345017 00000 n +0000345176 00000 n +0001145688 00000 n +0000348523 00000 n +0000347756 00000 n +0000345501 00000 n +0000347944 00000 n +0000348072 00000 n +0000348200 00000 n +0000348328 00000 n +0000348393 00000 n +0000348458 00000 n +0001025770 00000 n +0001007305 00000 n +0001025595 00000 n +0000353060 00000 n +0000351919 00000 n +0000348651 00000 n +0000352421 00000 n +0000352486 00000 n +0000352613 00000 n +0000352741 00000 n +0000352869 00000 n +0000352075 00000 n +0000352269 00000 n +0000352995 00000 n +0000692832 00000 n +0000754831 00000 n +0000357742 00000 n +0000356684 00000 n +0000353188 00000 n +0000357165 00000 n +0000357293 00000 n +0000356840 00000 n +0000357003 00000 n +0000357421 00000 n +0000357549 00000 n +0000357677 00000 n +0000373539 00000 n +0000360983 00000 n +0000360408 00000 n +0000357870 00000 n +0000360534 00000 n +0000360662 00000 n +0000360790 00000 n +0000360918 00000 n +0000364441 00000 n +0000363275 00000 n +0000361097 00000 n +0000363737 00000 n +0000363865 00000 n +0000363993 00000 n +0000364121 00000 n +0000364249 00000 n +0000363431 00000 n +0000363584 00000 n +0000364376 00000 n +0000619806 00000 n +0000365518 00000 n +0000365199 00000 n +0000364527 00000 n +0000365325 00000 n +0000365453 00000 n +0001145813 00000 n +0000367561 00000 n +0000366858 00000 n +0000365618 00000 n +0000366984 00000 n +0000367112 00000 n +0000367239 00000 n +0000367367 00000 n +0000367496 00000 n +0000370140 00000 n +0000369510 00000 n +0000367661 00000 n 0000369816 00000 n -0000369978 00000 n -0000830173 00000 n -0000820377 00000 n -0000829999 00000 n -0000819813 00000 n -0000810727 00000 n -0000819638 00000 n -0000370526 00000 n -0000370655 00000 n -0000991819 00000 n -0000369645 00000 n -0000369703 00000 n -0000369793 00000 n -0000472215 00000 n -0000507341 00000 n -0000375384 00000 n -0000374449 00000 n -0000370876 00000 n -0000374933 00000 n -0000375062 00000 n -0000374605 00000 n -0000374771 00000 n -0000375191 00000 n -0000375320 00000 n -0000661639 00000 n -0000379043 00000 n -0000378663 00000 n -0000375536 00000 n -0000378978 00000 n -0000378810 00000 n -0000380266 00000 n -0000380075 00000 n -0000379168 00000 n -0000380201 00000 n -0000382969 00000 n -0000382391 00000 n -0000380365 00000 n -0000382517 00000 n -0000382646 00000 n -0000382775 00000 n -0000382904 00000 n -0000386147 00000 n -0000385440 00000 n -0000383107 00000 n -0000385566 00000 n -0000385695 00000 n -0000385824 00000 n -0000385953 00000 n -0000386082 00000 n -0000390455 00000 n -0000389557 00000 n -0000386272 00000 n -0000389875 00000 n -0000390004 00000 n -0000389704 00000 n -0000390133 00000 n -0000390262 00000 n -0000390390 00000 n -0000991944 00000 n -0000592515 00000 n -0000394491 00000 n -0000393913 00000 n -0000390580 00000 n -0000394039 00000 n -0000394168 00000 n -0000394297 00000 n -0000394426 00000 n -0000398086 00000 n -0000397766 00000 n -0000394629 00000 n -0000397892 00000 n -0000398021 00000 n -0000401532 00000 n -0000401032 00000 n -0000398198 00000 n -0000401338 00000 n -0000810452 00000 n -0000807094 00000 n -0000810273 00000 n -0000401467 00000 n -0000401179 00000 n -0000657354 00000 n -0000403260 00000 n -0000402813 00000 n -0000401714 00000 n -0000402939 00000 n -0000403068 00000 n -0000403195 00000 n -0000403713 00000 n -0000403522 00000 n -0000403372 00000 n -0000403648 00000 n -0000406327 00000 n -0000405749 00000 n -0000403755 00000 n -0000405875 00000 n -0000406004 00000 n -0000406133 00000 n -0000406262 00000 n -0000992069 00000 n -0000406767 00000 n -0000406576 00000 n -0000406426 00000 n -0000406702 00000 n -0000410769 00000 n -0000410003 00000 n -0000406809 00000 n -0000410317 00000 n -0000410446 00000 n -0000410574 00000 n -0000410639 00000 n -0000410704 00000 n -0000410150 00000 n -0000415267 00000 n -0000415459 00000 n -0000415012 00000 n -0000410868 00000 n -0000415138 00000 n -0000415394 00000 n -0000419338 00000 n -0000418761 00000 n -0000415584 00000 n -0000418887 00000 n -0000419015 00000 n -0000419144 00000 n -0000419273 00000 n -0000422155 00000 n -0000423534 00000 n -0000422029 00000 n -0000419476 00000 n -0000423081 00000 n -0000423210 00000 n -0000423339 00000 n -0000423404 00000 n -0000423469 00000 n -0000426611 00000 n -0000425904 00000 n -0000423689 00000 n -0000426030 00000 n -0000426159 00000 n -0000426287 00000 n -0000426352 00000 n -0000426417 00000 n -0000426546 00000 n -0000992194 00000 n -0000432218 00000 n -0000431300 00000 n -0000426723 00000 n -0000431766 00000 n -0000431456 00000 n -0000431607 00000 n -0000432024 00000 n -0000432153 00000 n -0000785720 00000 n -0000436057 00000 n -0000434786 00000 n -0000432356 00000 n -0000435476 00000 n -0000435605 00000 n -0000435734 00000 n -0000434951 00000 n -0000435103 00000 n -0000435289 00000 n -0000435863 00000 n -0000435992 00000 n -0000440288 00000 n -0000439968 00000 n -0000436183 00000 n -0000440094 00000 n -0000440223 00000 n -0000443763 00000 n -0000443384 00000 n -0000440413 00000 n -0000443698 00000 n -0000443531 00000 n -0000446780 00000 n -0000446975 00000 n -0000446525 00000 n -0000443875 00000 n -0000446651 00000 n -0000446845 00000 n -0000446910 00000 n -0000450344 00000 n -0000450153 00000 n -0000447087 00000 n -0000450279 00000 n -0000992319 00000 n -0000454655 00000 n -0000454077 00000 n -0000450456 00000 n -0000454203 00000 n -0000454332 00000 n -0000454397 00000 n -0000454462 00000 n -0000454591 00000 n -0000457866 00000 n -0000456824 00000 n -0000454767 00000 n -0000457285 00000 n -0000457414 00000 n -0000456980 00000 n -0000457132 00000 n -0000457543 00000 n -0000457672 00000 n -0000457801 00000 n -0000459418 00000 n -0000459227 00000 n -0000457978 00000 n -0000459353 00000 n -0000460953 00000 n -0000460762 00000 n -0000459517 00000 n -0000460888 00000 n -0000463877 00000 n -0000463557 00000 n -0000461052 00000 n -0000463683 00000 n -0000463812 00000 n -0000468308 00000 n -0000467939 00000 n -0000464015 00000 n -0000468243 00000 n -0000468086 00000 n -0000992444 00000 n -0000625982 00000 n -0000472280 00000 n -0000471960 00000 n -0000468420 00000 n -0000472086 00000 n -0000476118 00000 n -0000475798 00000 n -0000472405 00000 n -0000475924 00000 n -0000475989 00000 n -0000476053 00000 n -0000481414 00000 n -0000480122 00000 n -0000476243 00000 n -0000481349 00000 n -0000480314 00000 n -0000480468 00000 n -0000480623 00000 n -0000480808 00000 n -0000480982 00000 n -0000481167 00000 n -0000554393 00000 n -0000485716 00000 n -0000485525 00000 n -0000481595 00000 n -0000485651 00000 n -0000489480 00000 n -0000489289 00000 n -0000485841 00000 n -0000489415 00000 n -0000493794 00000 n -0000492851 00000 n -0000489592 00000 n -0000493342 00000 n -0000493471 00000 n -0000493007 00000 n -0000493600 00000 n -0000493729 00000 n -0000493176 00000 n -0000992569 00000 n -0000564129 00000 n -0000497456 00000 n -0000496894 00000 n -0000493906 00000 n -0000497391 00000 n -0000497050 00000 n -0000497221 00000 n -0000645064 00000 n -0000500710 00000 n -0000500390 00000 n -0000497625 00000 n +0000369945 00000 n +0000370010 00000 n +0000370075 00000 n +0000369657 00000 n +0000603615 00000 n +0000373733 00000 n +0000373028 00000 n +0000370254 00000 n +0000373154 00000 n +0000373283 00000 n +0000373410 00000 n +0001006622 00000 n +0000994560 00000 n +0001006443 00000 n +0000373668 00000 n +0000378400 00000 n +0000377330 00000 n +0000373861 00000 n +0000378335 00000 n +0000993987 00000 n +0000983054 00000 n +0000993808 00000 n +0000377513 00000 n +0000377668 00000 n +0000377839 00000 n +0000378010 00000 n +0000378165 00000 n +0000521253 00000 n +0000685721 00000 n +0000381927 00000 n +0000381736 00000 n +0000378569 00000 n +0000381862 00000 n +0000386399 00000 n +0000386002 00000 n +0000382069 00000 n +0000386334 00000 n +0000386149 00000 n +0001145938 00000 n +0000488637 00000 n +0000388602 00000 n +0000388152 00000 n +0000386555 00000 n +0000388278 00000 n +0000388407 00000 n +0000388472 00000 n +0000388537 00000 n +0000389071 00000 n +0000388880 00000 n +0000388730 00000 n +0000389006 00000 n +0000391766 00000 n +0000394356 00000 n +0000391601 00000 n +0000389113 00000 n +0000393904 00000 n +0000394033 00000 n +0000394162 00000 n +0000393409 00000 n +0000393571 00000 n +0000982148 00000 n +0000972128 00000 n +0000981974 00000 n +0000971564 00000 n +0000962478 00000 n +0000971389 00000 n +0000394291 00000 n +0000393733 00000 n +0000393238 00000 n +0000393296 00000 n +0000393386 00000 n +0000541088 00000 n +0000581042 00000 n +0000399123 00000 n +0000398187 00000 n +0000394527 00000 n +0000398671 00000 n +0000398800 00000 n +0000398929 00000 n +0000398343 00000 n +0000398509 00000 n +0000399058 00000 n +0000758863 00000 n +0000403041 00000 n +0000402532 00000 n +0000399279 00000 n +0000402847 00000 n +0000402976 00000 n +0000402679 00000 n +0000404189 00000 n +0000403998 00000 n +0000403182 00000 n +0000404124 00000 n +0001146063 00000 n +0000406055 00000 n +0000405735 00000 n +0000404290 00000 n +0000405861 00000 n +0000405990 00000 n +0000409350 00000 n +0000408515 00000 n +0000406169 00000 n +0000408641 00000 n +0000408770 00000 n +0000408899 00000 n +0000409027 00000 n +0000409156 00000 n +0000409285 00000 n +0000413404 00000 n +0000412508 00000 n +0000409492 00000 n +0000412825 00000 n +0000412954 00000 n +0000413082 00000 n +0000412655 00000 n +0000413210 00000 n +0000413339 00000 n +0000417431 00000 n +0000416853 00000 n +0000413545 00000 n +0000416979 00000 n +0000417108 00000 n +0000417237 00000 n +0000417366 00000 n +0000421358 00000 n +0000420909 00000 n +0000417573 00000 n +0000421035 00000 n +0000421164 00000 n +0000421293 00000 n +0000423671 00000 n +0000423480 00000 n +0000421486 00000 n +0000423606 00000 n +0001146188 00000 n +0000426939 00000 n +0000426361 00000 n +0000423815 00000 n +0000426487 00000 n +0000962203 00000 n +0000958846 00000 n +0000962024 00000 n +0000426616 00000 n +0000426745 00000 n +0000426874 00000 n +0000431006 00000 n +0000430199 00000 n +0000427110 00000 n +0000430684 00000 n +0000430813 00000 n +0000958491 00000 n +0000956494 00000 n +0000958326 00000 n +0000430355 00000 n +0000430519 00000 n +0000430941 00000 n +0000836918 00000 n +0000853181 00000 n +0000434543 00000 n +0000433836 00000 n +0000431134 00000 n +0000433962 00000 n +0000434091 00000 n +0000434220 00000 n +0000434349 00000 n +0000434478 00000 n +0000438230 00000 n +0000436960 00000 n +0000434657 00000 n +0000437263 00000 n +0000437392 00000 n +0000437521 00000 n +0000437650 00000 n +0000437779 00000 n +0000437908 00000 n +0000438037 00000 n +0000438166 00000 n +0000437107 00000 n +0000643881 00000 n +0000441952 00000 n +0000441503 00000 n +0000438358 00000 n +0000441629 00000 n +0000441758 00000 n +0000441887 00000 n +0000444959 00000 n +0000444639 00000 n +0000442066 00000 n +0000444765 00000 n +0000444894 00000 n +0001146313 00000 n +0000447976 00000 n +0000447527 00000 n +0000445129 00000 n +0000447653 00000 n +0000447782 00000 n +0000447911 00000 n +0000450825 00000 n +0000450118 00000 n +0000448133 00000 n +0000450244 00000 n +0000450373 00000 n +0000450502 00000 n +0000450631 00000 n +0000450760 00000 n +0000453634 00000 n +0000453314 00000 n +0000450939 00000 n +0000453440 00000 n +0000453569 00000 n +0000459347 00000 n +0000456562 00000 n +0000456113 00000 n +0000453748 00000 n +0000456239 00000 n +0000456368 00000 n +0000456497 00000 n +0000460886 00000 n +0000459200 00000 n +0000456690 00000 n +0000460434 00000 n +0000460563 00000 n +0000460273 00000 n +0000460692 00000 n +0000460821 00000 n +0000754573 00000 n +0000461398 00000 n +0000461207 00000 n +0000461057 00000 n +0000461333 00000 n +0001146438 00000 n +0000464012 00000 n +0000463434 00000 n +0000461440 00000 n +0000463560 00000 n +0000463689 00000 n +0000463818 00000 n +0000463947 00000 n +0000464453 00000 n +0000464262 00000 n +0000464112 00000 n +0000464388 00000 n +0000468540 00000 n +0000467774 00000 n +0000464495 00000 n +0000468088 00000 n +0000468217 00000 n +0000468345 00000 n +0000468410 00000 n +0000468475 00000 n +0000467921 00000 n +0000473038 00000 n +0000473230 00000 n +0000472783 00000 n +0000468640 00000 n +0000472909 00000 n +0000473165 00000 n +0000477082 00000 n +0000476504 00000 n +0000473358 00000 n +0000476630 00000 n +0000476759 00000 n +0000476888 00000 n +0000477017 00000 n +0000480192 00000 n +0000479614 00000 n +0000477223 00000 n +0000479740 00000 n +0000479869 00000 n +0000479998 00000 n +0000480063 00000 n +0000480127 00000 n +0001146563 00000 n +0000483517 00000 n +0000482813 00000 n +0000480349 00000 n +0000482939 00000 n +0000483068 00000 n +0000483196 00000 n +0000483261 00000 n +0000483326 00000 n +0000483452 00000 n +0000488830 00000 n +0000488042 00000 n +0000483631 00000 n +0000488508 00000 n +0000488198 00000 n +0000488349 00000 n +0000488766 00000 n +0000937473 00000 n +0000492695 00000 n +0000491424 00000 n +0000488971 00000 n +0000492114 00000 n +0000492243 00000 n +0000492372 00000 n +0000492501 00000 n +0000491589 00000 n +0000491741 00000 n +0000491927 00000 n +0000492630 00000 n +0000496842 00000 n +0000496393 00000 n +0000492823 00000 n +0000496519 00000 n +0000496648 00000 n +0000496777 00000 n +0000500748 00000 n +0000500369 00000 n +0000496970 00000 n +0000500683 00000 n 0000500516 00000 n -0000500645 00000 n -0000504226 00000 n -0000503906 00000 n -0000500835 00000 n -0000504032 00000 n -0000504161 00000 n -0000507406 00000 n -0000507086 00000 n -0000504338 00000 n -0000507212 00000 n -0000511216 00000 n -0000511025 00000 n -0000507562 00000 n -0000511151 00000 n -0000515098 00000 n -0000514469 00000 n -0000511371 00000 n -0000514776 00000 n -0000514905 00000 n -0000514616 00000 n -0000515034 00000 n -0000992694 00000 n -0000519292 00000 n -0000518613 00000 n -0000515267 00000 n -0000519098 00000 n -0000518769 00000 n -0000519227 00000 n -0000518943 00000 n -0000523314 00000 n -0000522865 00000 n -0000519404 00000 n -0000522991 00000 n -0000523120 00000 n -0000523249 00000 n -0000527347 00000 n -0000526681 00000 n -0000523469 00000 n -0000527154 00000 n -0000527283 00000 n -0000526837 00000 n -0000526999 00000 n -0000530634 00000 n -0000529995 00000 n -0000527516 00000 n -0000530310 00000 n -0000530142 00000 n -0000530504 00000 n -0000530569 00000 n -0000534443 00000 n -0000533940 00000 n -0000530760 00000 n -0000534249 00000 n -0000534378 00000 n -0000534087 00000 n -0000539058 00000 n -0000538684 00000 n -0000534625 00000 n -0000538993 00000 n -0000538831 00000 n -0000806739 00000 n -0000804741 00000 n -0000806574 00000 n -0000992819 00000 n -0000622257 00000 n -0000542988 00000 n -0000542351 00000 n -0000539184 00000 n -0000542665 00000 n -0000542794 00000 n -0000542498 00000 n -0000542923 00000 n -0000562318 00000 n -0000546169 00000 n -0000545850 00000 n -0000543113 00000 n -0000545976 00000 n -0000549396 00000 n -0000549076 00000 n -0000546337 00000 n -0000549202 00000 n -0000549331 00000 n -0000554458 00000 n -0000553796 00000 n -0000549508 00000 n -0000554264 00000 n -0000553952 00000 n -0000554104 00000 n -0000558566 00000 n -0000557687 00000 n -0000554570 00000 n -0000557987 00000 n -0000558116 00000 n -0000558244 00000 n -0000558373 00000 n -0000558501 00000 n -0000557834 00000 n -0000562512 00000 n -0000562063 00000 n -0000558678 00000 n -0000562189 00000 n -0000562447 00000 n -0000992944 00000 n -0000564194 00000 n -0000563874 00000 n -0000562624 00000 n -0000564000 00000 n -0000565754 00000 n -0000565563 00000 n -0000564306 00000 n -0000565689 00000 n -0000567473 00000 n -0000566965 00000 n -0000565853 00000 n -0000567091 00000 n -0000567220 00000 n -0000567347 00000 n -0000567410 00000 n -0000571388 00000 n -0000571132 00000 n -0000567585 00000 n -0000571258 00000 n -0000571323 00000 n -0000576424 00000 n -0000574584 00000 n -0000571500 00000 n -0000576101 00000 n -0000574794 00000 n -0000576230 00000 n -0000576359 00000 n -0000574961 00000 n -0000575122 00000 n -0000575284 00000 n -0000575446 00000 n -0000575607 00000 n -0000575768 00000 n -0000575939 00000 n -0000785687 00000 n -0000581569 00000 n -0000579821 00000 n -0000576536 00000 n -0000581504 00000 n -0000580040 00000 n -0000580203 00000 n -0000580364 00000 n -0000580524 00000 n -0000580687 00000 n -0000580849 00000 n -0000581012 00000 n -0000581174 00000 n -0000581337 00000 n -0000993069 00000 n -0000587912 00000 n -0000584338 00000 n -0000581694 00000 n -0000587847 00000 n -0000584656 00000 n -0000584825 00000 n -0000584987 00000 n -0000585149 00000 n -0000585311 00000 n -0000585473 00000 n -0000585636 00000 n -0000585789 00000 n -0000585952 00000 n -0000586105 00000 n -0000586258 00000 n -0000586409 00000 n -0000586563 00000 n -0000586725 00000 n -0000586887 00000 n -0000587049 00000 n -0000587210 00000 n -0000587372 00000 n -0000587534 00000 n -0000587695 00000 n -0000592710 00000 n -0000591581 00000 n -0000588024 00000 n -0000592386 00000 n -0000591755 00000 n -0000591918 00000 n -0000592069 00000 n -0000592232 00000 n -0000592580 00000 n -0000592645 00000 n -0000596083 00000 n -0000595508 00000 n -0000592849 00000 n -0000595634 00000 n -0000595762 00000 n -0000596019 00000 n -0000600404 00000 n -0000599591 00000 n -0000596252 00000 n -0000600079 00000 n -0000599747 00000 n -0000599917 00000 n -0000600144 00000 n -0000600209 00000 n -0000600274 00000 n -0000600339 00000 n -0000603670 00000 n -0000603349 00000 n -0000600503 00000 n -0000603475 00000 n -0000603540 00000 n -0000603605 00000 n -0000607574 00000 n -0000606995 00000 n -0000603782 00000 n -0000607121 00000 n -0000607250 00000 n -0000607315 00000 n -0000607380 00000 n -0000607444 00000 n -0000607509 00000 n -0000993194 00000 n -0000611415 00000 n -0000610706 00000 n +0000503598 00000 n +0000503793 00000 n +0000503343 00000 n +0000500862 00000 n +0000503469 00000 n +0000503663 00000 n +0000503728 00000 n +0001146688 00000 n +0000506597 00000 n +0000506406 00000 n +0000503907 00000 n +0000506532 00000 n +0000510197 00000 n +0000509748 00000 n +0000506711 00000 n +0000509874 00000 n +0000510003 00000 n +0000510068 00000 n +0000510132 00000 n +0000513155 00000 n +0000512836 00000 n +0000510311 00000 n +0000512962 00000 n +0000513090 00000 n +0000516398 00000 n +0000515358 00000 n +0000513269 00000 n +0000515819 00000 n +0000515948 00000 n +0000515514 00000 n +0000515668 00000 n +0000516076 00000 n +0000516204 00000 n +0000516333 00000 n +0000517919 00000 n +0000517728 00000 n +0000516512 00000 n +0000517854 00000 n +0000519479 00000 n +0000519288 00000 n +0000518020 00000 n +0000519414 00000 n +0001146813 00000 n +0000521317 00000 n +0000520998 00000 n +0000519580 00000 n +0000521124 00000 n +0000524735 00000 n +0000524544 00000 n +0000521431 00000 n +0000524670 00000 n +0000529206 00000 n +0000528838 00000 n +0000524863 00000 n +0000529141 00000 n +0000528985 00000 n +0000721881 00000 n +0000533299 00000 n +0000532918 00000 n +0000529348 00000 n +0000533234 00000 n +0000533065 00000 n +0000537534 00000 n +0000537169 00000 n +0000533427 00000 n +0000537469 00000 n +0000537316 00000 n +0000541282 00000 n +0000540833 00000 n +0000537676 00000 n +0000540959 00000 n +0000541153 00000 n +0000541217 00000 n +0001146938 00000 n +0000545583 00000 n +0000545217 00000 n +0000541410 00000 n +0000545518 00000 n +0000545364 00000 n +0000550667 00000 n +0000549534 00000 n +0000545711 00000 n +0000550602 00000 n +0000549717 00000 n +0000549873 00000 n +0000550058 00000 n +0000550232 00000 n +0000550417 00000 n +0000635525 00000 n +0000554943 00000 n +0000554752 00000 n +0000550865 00000 n +0000554878 00000 n +0000558896 00000 n +0000558705 00000 n +0000555057 00000 n +0000558831 00000 n +0000562750 00000 n +0000562430 00000 n +0000559010 00000 n +0000562556 00000 n +0000562685 00000 n +0000566514 00000 n +0000565698 00000 n +0000562864 00000 n +0000566191 00000 n +0000565854 00000 n +0000566320 00000 n +0000566449 00000 n +0000566024 00000 n +0001147063 00000 n +0000650412 00000 n +0000570932 00000 n +0000570241 00000 n +0000566671 00000 n +0000570738 00000 n +0000570397 00000 n +0000570567 00000 n +0000570867 00000 n +0000741948 00000 n +0000574280 00000 n +0000573960 00000 n +0000571060 00000 n +0000574086 00000 n +0000574215 00000 n +0000577233 00000 n +0000577042 00000 n +0000574394 00000 n +0000577168 00000 n +0000581107 00000 n +0000580787 00000 n +0000577404 00000 n +0000580913 00000 n +0000584762 00000 n +0000584571 00000 n +0000581264 00000 n +0000584697 00000 n +0000589124 00000 n +0000588312 00000 n +0000584933 00000 n +0000588801 00000 n +0000588930 00000 n +0000588468 00000 n +0000589059 00000 n +0000588628 00000 n +0001147188 00000 n +0000593286 00000 n +0000592661 00000 n +0000589281 00000 n +0000592963 00000 n +0000593092 00000 n +0000592808 00000 n +0000593221 00000 n +0000596450 00000 n +0000596130 00000 n +0000593414 00000 n +0000596256 00000 n +0000596385 00000 n +0000600387 00000 n +0000599720 00000 n +0000596621 00000 n +0000600194 00000 n +0000600323 00000 n +0000599876 00000 n +0000600038 00000 n +0000603938 00000 n +0000603169 00000 n +0000600501 00000 n +0000603486 00000 n +0000603316 00000 n +0000603680 00000 n +0000603745 00000 n +0000603873 00000 n +0000607913 00000 n +0000607539 00000 n +0000604123 00000 n +0000607848 00000 n 0000607686 00000 n -0000610832 00000 n -0000610961 00000 n -0000611026 00000 n -0000611091 00000 n -0000611220 00000 n -0000611285 00000 n -0000611350 00000 n -0000614945 00000 n -0000614108 00000 n -0000611540 00000 n -0000614234 00000 n -0000614363 00000 n -0000614428 00000 n -0000614493 00000 n -0000614622 00000 n -0000614751 00000 n -0000614880 00000 n -0000618118 00000 n -0000617411 00000 n -0000615155 00000 n -0000617537 00000 n -0000617666 00000 n -0000617794 00000 n -0000617923 00000 n -0000617988 00000 n -0000618053 00000 n -0000622579 00000 n -0000622002 00000 n -0000618301 00000 n -0000622128 00000 n -0000622386 00000 n -0000622451 00000 n -0000622515 00000 n -0000626176 00000 n -0000625546 00000 n -0000622704 00000 n -0000625853 00000 n -0000625693 00000 n -0000626111 00000 n -0000629951 00000 n -0000629317 00000 n -0000626288 00000 n -0000629627 00000 n -0000629756 00000 n -0000629821 00000 n -0000629886 00000 n -0000629464 00000 n -0000993319 00000 n -0000785654 00000 n -0000633220 00000 n -0000632514 00000 n -0000630063 00000 n -0000632640 00000 n -0000632769 00000 n -0000632834 00000 n -0000632899 00000 n -0000633027 00000 n -0000633091 00000 n -0000633155 00000 n -0000637089 00000 n -0000636640 00000 n -0000633332 00000 n -0000636766 00000 n -0000636895 00000 n -0000636959 00000 n -0000637024 00000 n -0000638567 00000 n -0000638247 00000 n -0000637215 00000 n -0000638373 00000 n -0000804460 00000 n -0000797176 00000 n -0000804280 00000 n -0000638502 00000 n -0000640543 00000 n -0000640095 00000 n -0000638693 00000 n -0000640221 00000 n -0000640350 00000 n -0000640479 00000 n -0000645129 00000 n -0000644186 00000 n -0000640655 00000 n -0000644549 00000 n -0000796855 00000 n -0000787642 00000 n -0000796669 00000 n -0000644333 00000 n -0000644678 00000 n -0000644806 00000 n -0000644935 00000 n -0000646171 00000 n -0000645980 00000 n -0000645366 00000 n -0000646106 00000 n -0000993444 00000 n -0000646598 00000 n -0000646407 00000 n -0000646257 00000 n -0000646533 00000 n -0000649911 00000 n -0000648685 00000 n -0000646640 00000 n -0000649202 00000 n -0000649331 00000 n -0000649460 00000 n -0000649589 00000 n -0000649718 00000 n -0000649847 00000 n -0000648841 00000 n -0000649013 00000 n -0000650365 00000 n -0000650174 00000 n -0000650024 00000 n -0000650300 00000 n -0000653609 00000 n -0000653031 00000 n -0000650407 00000 n -0000653157 00000 n -0000653286 00000 n -0000653415 00000 n -0000653544 00000 n -0000657804 00000 n -0000656586 00000 n -0000653695 00000 n -0000657096 00000 n -0000657225 00000 n -0000657483 00000 n -0000656742 00000 n -0000656921 00000 n -0000657676 00000 n -0000657740 00000 n -0000664691 00000 n -0000660863 00000 n -0000657957 00000 n -0000660989 00000 n -0000661054 00000 n -0000661119 00000 n -0000661184 00000 n -0000661249 00000 n -0000661314 00000 n -0000661379 00000 n -0000661444 00000 n -0000661509 00000 n -0000661574 00000 n -0000661704 00000 n -0000661769 00000 n -0000661834 00000 n -0000661899 00000 n -0000661964 00000 n -0000662029 00000 n -0000662094 00000 n -0000662159 00000 n -0000662224 00000 n -0000662289 00000 n -0000662354 00000 n -0000662419 00000 n -0000662484 00000 n -0000662549 00000 n -0000662614 00000 n -0000662679 00000 n -0000662744 00000 n -0000662809 00000 n -0000662874 00000 n -0000662939 00000 n -0000663004 00000 n -0000663069 00000 n -0000663134 00000 n -0000663199 00000 n -0000663263 00000 n -0000663328 00000 n -0000663393 00000 n -0000663458 00000 n -0000663523 00000 n -0000663588 00000 n -0000663653 00000 n -0000663718 00000 n -0000663783 00000 n -0000663848 00000 n -0000663913 00000 n -0000663978 00000 n -0000664043 00000 n -0000664108 00000 n -0000664173 00000 n -0000664238 00000 n -0000664303 00000 n -0000664368 00000 n -0000664433 00000 n -0000664498 00000 n -0000664563 00000 n -0000664627 00000 n -0000993569 00000 n -0000671337 00000 n -0000667773 00000 n -0000664803 00000 n -0000667899 00000 n -0000667964 00000 n -0000668029 00000 n -0000668094 00000 n -0000668159 00000 n -0000668224 00000 n -0000668289 00000 n -0000668354 00000 n -0000668419 00000 n -0000668484 00000 n -0000668549 00000 n -0000668614 00000 n -0000668678 00000 n -0000668743 00000 n -0000668808 00000 n -0000668873 00000 n -0000668938 00000 n -0000669003 00000 n -0000669068 00000 n -0000669133 00000 n -0000669198 00000 n -0000669263 00000 n -0000669328 00000 n -0000669393 00000 n -0000669457 00000 n -0000669522 00000 n -0000669587 00000 n -0000669652 00000 n -0000669717 00000 n -0000669782 00000 n -0000669847 00000 n -0000669912 00000 n -0000669977 00000 n -0000670042 00000 n -0000670107 00000 n -0000670172 00000 n -0000670237 00000 n -0000670302 00000 n -0000670367 00000 n -0000670432 00000 n -0000670496 00000 n -0000670560 00000 n -0000670624 00000 n -0000670689 00000 n -0000670754 00000 n -0000670819 00000 n -0000670884 00000 n -0000670949 00000 n -0000671014 00000 n -0000671079 00000 n -0000671144 00000 n -0000671209 00000 n -0000671273 00000 n -0000677513 00000 n -0000674075 00000 n -0000671449 00000 n -0000674201 00000 n -0000674266 00000 n -0000674331 00000 n -0000674396 00000 n -0000674461 00000 n -0000674526 00000 n -0000674591 00000 n -0000674656 00000 n -0000674721 00000 n -0000674786 00000 n -0000674851 00000 n -0000674916 00000 n -0000674981 00000 n -0000675046 00000 n -0000675111 00000 n -0000675176 00000 n -0000675241 00000 n -0000675306 00000 n -0000675371 00000 n -0000675436 00000 n -0000675501 00000 n -0000675566 00000 n -0000675631 00000 n -0000675696 00000 n -0000675761 00000 n -0000675826 00000 n -0000675891 00000 n -0000675956 00000 n -0000676021 00000 n -0000676086 00000 n -0000676151 00000 n -0000676216 00000 n -0000676281 00000 n -0000676346 00000 n -0000676410 00000 n -0000676475 00000 n -0000676540 00000 n -0000676605 00000 n -0000676670 00000 n -0000676735 00000 n -0000676800 00000 n -0000676865 00000 n -0000676930 00000 n -0000676995 00000 n -0000677060 00000 n -0000677125 00000 n -0000677190 00000 n -0000677255 00000 n -0000677320 00000 n -0000677385 00000 n -0000677449 00000 n -0000682091 00000 n -0000679827 00000 n -0000677625 00000 n -0000679953 00000 n -0000680018 00000 n -0000680083 00000 n -0000680148 00000 n -0000680213 00000 n -0000680278 00000 n -0000680343 00000 n -0000680408 00000 n -0000680473 00000 n -0000680538 00000 n -0000680603 00000 n -0000680668 00000 n -0000680733 00000 n -0000680798 00000 n -0000680860 00000 n -0000680924 00000 n -0000680989 00000 n -0000681053 00000 n -0000681118 00000 n -0000681183 00000 n -0000681248 00000 n -0000681313 00000 n -0000681378 00000 n -0000681443 00000 n -0000681508 00000 n -0000681637 00000 n -0000681766 00000 n -0000681831 00000 n -0000681896 00000 n -0000681961 00000 n -0000682026 00000 n -0000684886 00000 n -0000684242 00000 n -0000682216 00000 n -0000684368 00000 n -0000684497 00000 n -0000684626 00000 n -0000684691 00000 n -0000684756 00000 n -0000684821 00000 n -0000689225 00000 n -0000688905 00000 n -0000684999 00000 n -0000689031 00000 n -0000689096 00000 n -0000689161 00000 n -0000692825 00000 n -0000692570 00000 n -0000689378 00000 n -0000692696 00000 n -0000692761 00000 n -0000993694 00000 n -0000696073 00000 n -0000695882 00000 n -0000692964 00000 n -0000696008 00000 n -0000699802 00000 n -0000699546 00000 n -0000696199 00000 n -0000699672 00000 n -0000699737 00000 n -0000702643 00000 n -0000701935 00000 n -0000699941 00000 n -0000702061 00000 n -0000702126 00000 n -0000702191 00000 n -0000702256 00000 n -0000702321 00000 n -0000702450 00000 n -0000702515 00000 n -0000702579 00000 n -0000707309 00000 n -0000707053 00000 n -0000702782 00000 n -0000707179 00000 n -0000707244 00000 n -0000710261 00000 n -0000709488 00000 n -0000707435 00000 n -0000709614 00000 n -0000709679 00000 n -0000709744 00000 n -0000709809 00000 n -0000709938 00000 n -0000710003 00000 n -0000710066 00000 n -0000710131 00000 n -0000710196 00000 n -0000712863 00000 n -0000712154 00000 n -0000710414 00000 n -0000712280 00000 n -0000712345 00000 n -0000712410 00000 n -0000712475 00000 n -0000712540 00000 n -0000712605 00000 n -0000712734 00000 n -0000712799 00000 n -0000993819 00000 n -0000716107 00000 n -0000715721 00000 n -0000713015 00000 n -0000715847 00000 n -0000715912 00000 n -0000715977 00000 n -0000716042 00000 n -0000719241 00000 n -0000718468 00000 n -0000716247 00000 n -0000718594 00000 n -0000718659 00000 n -0000718724 00000 n -0000718788 00000 n -0000718916 00000 n -0000718981 00000 n -0000719046 00000 n -0000719111 00000 n -0000719176 00000 n -0000722628 00000 n -0000722437 00000 n -0000719407 00000 n -0000722563 00000 n -0000725737 00000 n -0000725027 00000 n -0000722754 00000 n -0000725153 00000 n -0000725218 00000 n -0000725283 00000 n -0000725348 00000 n -0000725413 00000 n -0000725542 00000 n -0000725607 00000 n -0000725672 00000 n -0000729289 00000 n -0000728968 00000 n -0000725902 00000 n -0000729094 00000 n -0000729159 00000 n -0000729224 00000 n -0000732735 00000 n -0000732544 00000 n -0000729415 00000 n -0000732670 00000 n -0000993944 00000 n -0000735807 00000 n -0000735488 00000 n -0000732861 00000 n -0000735614 00000 n -0000735679 00000 n -0000735743 00000 n -0000738378 00000 n -0000737540 00000 n -0000735960 00000 n -0000737666 00000 n -0000737731 00000 n -0000737796 00000 n -0000737925 00000 n -0000737990 00000 n -0000738055 00000 n -0000738120 00000 n -0000738185 00000 n -0000738249 00000 n -0000738314 00000 n -0000741345 00000 n -0000740701 00000 n -0000738531 00000 n -0000740827 00000 n -0000740892 00000 n -0000741021 00000 n -0000741086 00000 n -0000741150 00000 n -0000741215 00000 n -0000741280 00000 n -0000744817 00000 n -0000744626 00000 n -0000741485 00000 n -0000744752 00000 n -0000747625 00000 n -0000746851 00000 n -0000744943 00000 n -0000746977 00000 n -0000747042 00000 n -0000747107 00000 n -0000747172 00000 n -0000747301 00000 n -0000747366 00000 n -0000747431 00000 n -0000747495 00000 n -0000747560 00000 n -0000751027 00000 n -0000750836 00000 n -0000747778 00000 n -0000750962 00000 n -0000994069 00000 n -0000754063 00000 n -0000753743 00000 n -0000751238 00000 n -0000753869 00000 n -0000753934 00000 n -0000753999 00000 n -0000757373 00000 n -0000756664 00000 n -0000754287 00000 n -0000756790 00000 n -0000756855 00000 n -0000756920 00000 n -0000756984 00000 n -0000757113 00000 n -0000757178 00000 n -0000757243 00000 n -0000757308 00000 n -0000761790 00000 n -0000761534 00000 n -0000757525 00000 n -0000761660 00000 n -0000761725 00000 n -0000765404 00000 n -0000765213 00000 n -0000761916 00000 n -0000765339 00000 n -0000768186 00000 n -0000767802 00000 n -0000765530 00000 n -0000767928 00000 n -0000767993 00000 n -0000768058 00000 n -0000768122 00000 n -0000771670 00000 n -0000771025 00000 n -0000768338 00000 n -0000771151 00000 n -0000771216 00000 n -0000771345 00000 n -0000771410 00000 n -0000771475 00000 n -0000771540 00000 n -0000771605 00000 n -0000994194 00000 n -0000774735 00000 n +0000612763 00000 n +0000612086 00000 n +0000608084 00000 n +0000612570 00000 n +0000612242 00000 n +0000612699 00000 n +0000612405 00000 n +0001147313 00000 n +0000718117 00000 n +0000648136 00000 n +0000616110 00000 n +0000615790 00000 n +0000612891 00000 n +0000615916 00000 n +0000616045 00000 n +0000619871 00000 n +0000619551 00000 n +0000616237 00000 n +0000619677 00000 n +0000624199 00000 n +0000623707 00000 n +0000620028 00000 n +0000624005 00000 n +0000624134 00000 n +0000623854 00000 n +0000628499 00000 n +0000628179 00000 n +0000624327 00000 n +0000628305 00000 n +0000628434 00000 n +0000631067 00000 n +0000630747 00000 n +0000628640 00000 n +0000630873 00000 n +0000631002 00000 n +0000635590 00000 n +0000635100 00000 n +0000631181 00000 n +0000635396 00000 n +0000635247 00000 n +0001147438 00000 n +0000639531 00000 n +0000638772 00000 n +0000635704 00000 n +0000639081 00000 n +0000638919 00000 n +0000639210 00000 n +0000639339 00000 n +0000639467 00000 n +0000643946 00000 n +0000643194 00000 n +0000639645 00000 n +0000643495 00000 n +0000643624 00000 n +0000643341 00000 n +0000643752 00000 n +0000648330 00000 n +0000647881 00000 n +0000644074 00000 n +0000648007 00000 n +0000648265 00000 n +0000650477 00000 n +0000650157 00000 n +0000648472 00000 n +0000650283 00000 n +0000651970 00000 n +0000651779 00000 n +0000650591 00000 n +0000651905 00000 n +0000653427 00000 n +0000653236 00000 n +0000652071 00000 n +0000653362 00000 n +0001147563 00000 n +0000656238 00000 n +0000655661 00000 n +0000653528 00000 n +0000655787 00000 n +0000655916 00000 n +0000656043 00000 n +0000656108 00000 n +0000656173 00000 n +0000659903 00000 n +0000659712 00000 n +0000656352 00000 n +0000659838 00000 n +0000665159 00000 n +0000663316 00000 n +0000660017 00000 n +0000664836 00000 n +0000663526 00000 n +0000664965 00000 n +0000665094 00000 n +0000663694 00000 n +0000663856 00000 n +0000664018 00000 n +0000664180 00000 n +0000664342 00000 n +0000664504 00000 n +0000664675 00000 n +0000937440 00000 n +0000670438 00000 n +0000668518 00000 n +0000665273 00000 n +0000670373 00000 n +0000668746 00000 n +0000668909 00000 n +0000669072 00000 n +0000669235 00000 n +0000669397 00000 n +0000669560 00000 n +0000669722 00000 n +0000669885 00000 n +0000670044 00000 n +0000670205 00000 n +0000675059 00000 n +0000673487 00000 n +0000670566 00000 n +0000674994 00000 n +0000673697 00000 n +0000673866 00000 n +0000674028 00000 n +0000674190 00000 n +0000674352 00000 n +0000674514 00000 n +0000674677 00000 n +0000674831 00000 n +0000681361 00000 n +0000678470 00000 n +0000675187 00000 n +0000681296 00000 n +0000678752 00000 n +0000678904 00000 n +0000679058 00000 n +0000679209 00000 n +0000679363 00000 n +0000679525 00000 n +0000679687 00000 n +0000679848 00000 n +0000680010 00000 n +0000680172 00000 n +0000680334 00000 n +0000680496 00000 n +0000680649 00000 n +0000680812 00000 n +0000680967 00000 n +0000681131 00000 n +0001147688 00000 n +0000685786 00000 n +0000684948 00000 n +0000681489 00000 n +0000685592 00000 n +0000685113 00000 n +0000685276 00000 n +0000685430 00000 n +0000688940 00000 n +0000688620 00000 n +0000685928 00000 n +0000688746 00000 n +0000688811 00000 n +0000688875 00000 n +0000693156 00000 n +0000692086 00000 n +0000689111 00000 n +0000692574 00000 n +0000692703 00000 n +0000692961 00000 n +0000692242 00000 n +0000692412 00000 n +0000693026 00000 n +0000693091 00000 n +0000696607 00000 n +0000696287 00000 n +0000693284 00000 n +0000696413 00000 n +0000696478 00000 n +0000696542 00000 n +0000700096 00000 n +0000699775 00000 n +0000696708 00000 n +0000699901 00000 n +0000699966 00000 n +0000700031 00000 n +0000704017 00000 n +0000703308 00000 n +0000700211 00000 n +0000703434 00000 n +0000703563 00000 n +0000703628 00000 n +0000703693 00000 n +0000703758 00000 n +0000703823 00000 n +0000703952 00000 n +0001147813 00000 n +0000708258 00000 n +0000707421 00000 n +0000704131 00000 n +0000707547 00000 n +0000707612 00000 n +0000707677 00000 n +0000707806 00000 n +0000707871 00000 n +0000707936 00000 n +0000708065 00000 n +0000708130 00000 n +0000708194 00000 n +0000711285 00000 n +0000710583 00000 n +0000708386 00000 n +0000710709 00000 n +0000710836 00000 n +0000710963 00000 n +0000711092 00000 n +0000711220 00000 n +0000713995 00000 n +0000713418 00000 n +0000711484 00000 n +0000713544 00000 n +0000713673 00000 n +0000713802 00000 n +0000713867 00000 n +0000713931 00000 n +0000718182 00000 n +0000717862 00000 n +0000714180 00000 n +0000717988 00000 n +0000721946 00000 n +0000721186 00000 n +0000718309 00000 n +0000721493 00000 n +0000721622 00000 n +0000721687 00000 n +0000721752 00000 n +0000721333 00000 n +0000725637 00000 n +0000725058 00000 n +0000722060 00000 n +0000725184 00000 n +0000725313 00000 n +0000725442 00000 n +0000725507 00000 n +0000725572 00000 n +0001147938 00000 n +0000729251 00000 n +0000728356 00000 n +0000725751 00000 n +0000728668 00000 n +0000728503 00000 n +0000728797 00000 n +0000728862 00000 n +0000728927 00000 n +0000729056 00000 n +0000729121 00000 n +0000729186 00000 n +0000937407 00000 n +0000733408 00000 n +0000732958 00000 n +0000729365 00000 n +0000733084 00000 n +0000733213 00000 n +0000733278 00000 n +0000733343 00000 n +0000735299 00000 n +0000734979 00000 n +0000733536 00000 n +0000735105 00000 n +0000956213 00000 n +0000948929 00000 n +0000956033 00000 n +0000735234 00000 n +0000735782 00000 n +0000735591 00000 n +0000735441 00000 n +0000735717 00000 n +0000737592 00000 n +0000737143 00000 n +0000735824 00000 n +0000737269 00000 n +0000737398 00000 n +0000737527 00000 n +0000742013 00000 n +0000741070 00000 n +0000737706 00000 n +0000741433 00000 n +0000948608 00000 n +0000939395 00000 n +0000948422 00000 n +0000741217 00000 n +0000741562 00000 n +0000741690 00000 n +0000741819 00000 n +0001148063 00000 n +0000743372 00000 n +0000743181 00000 n +0000742254 00000 n +0000743307 00000 n +0000743813 00000 n +0000743622 00000 n +0000743472 00000 n +0000743748 00000 n +0000747127 00000 n +0000745901 00000 n +0000743855 00000 n +0000746418 00000 n +0000746547 00000 n +0000746676 00000 n +0000746805 00000 n +0000746934 00000 n +0000747063 00000 n +0000746057 00000 n +0000746229 00000 n +0000747582 00000 n +0000747391 00000 n +0000747241 00000 n +0000747517 00000 n +0000750827 00000 n +0000750249 00000 n +0000747624 00000 n +0000750375 00000 n +0000750504 00000 n +0000750633 00000 n +0000750762 00000 n +0000755024 00000 n +0000753805 00000 n +0000750913 00000 n +0000754315 00000 n +0000754444 00000 n +0000754702 00000 n +0000753961 00000 n +0000754140 00000 n +0000754896 00000 n +0000754960 00000 n +0001148188 00000 n +0000761915 00000 n +0000758087 00000 n +0000755180 00000 n +0000758213 00000 n +0000758278 00000 n +0000758343 00000 n +0000758408 00000 n +0000758473 00000 n +0000758538 00000 n +0000758603 00000 n +0000758668 00000 n +0000758733 00000 n +0000758798 00000 n +0000758928 00000 n +0000758993 00000 n +0000759058 00000 n +0000759123 00000 n +0000759188 00000 n +0000759253 00000 n +0000759318 00000 n +0000759383 00000 n +0000759448 00000 n +0000759513 00000 n +0000759578 00000 n +0000759643 00000 n +0000759708 00000 n +0000759773 00000 n +0000759838 00000 n +0000759903 00000 n +0000759968 00000 n +0000760033 00000 n +0000760098 00000 n +0000760163 00000 n +0000760228 00000 n +0000760293 00000 n +0000760358 00000 n +0000760423 00000 n +0000760487 00000 n +0000760552 00000 n +0000760617 00000 n +0000760682 00000 n +0000760747 00000 n +0000760812 00000 n +0000760877 00000 n +0000760942 00000 n +0000761007 00000 n +0000761072 00000 n +0000761137 00000 n +0000761202 00000 n +0000761267 00000 n +0000761332 00000 n +0000761397 00000 n +0000761462 00000 n +0000761527 00000 n +0000761592 00000 n +0000761657 00000 n +0000761722 00000 n +0000761787 00000 n +0000761851 00000 n +0000768563 00000 n +0000764999 00000 n +0000762029 00000 n +0000765125 00000 n +0000765190 00000 n +0000765255 00000 n +0000765320 00000 n +0000765385 00000 n +0000765450 00000 n +0000765515 00000 n +0000765580 00000 n +0000765645 00000 n +0000765710 00000 n +0000765775 00000 n +0000765840 00000 n +0000765904 00000 n +0000765969 00000 n +0000766034 00000 n +0000766099 00000 n +0000766164 00000 n +0000766229 00000 n +0000766294 00000 n +0000766359 00000 n +0000766424 00000 n +0000766489 00000 n +0000766554 00000 n +0000766619 00000 n +0000766683 00000 n +0000766748 00000 n +0000766813 00000 n +0000766878 00000 n +0000766943 00000 n +0000767008 00000 n +0000767073 00000 n +0000767138 00000 n +0000767203 00000 n +0000767268 00000 n +0000767333 00000 n +0000767398 00000 n +0000767463 00000 n +0000767528 00000 n +0000767593 00000 n +0000767658 00000 n +0000767722 00000 n +0000767786 00000 n +0000767850 00000 n +0000767915 00000 n +0000767980 00000 n +0000768045 00000 n +0000768110 00000 n +0000768175 00000 n +0000768240 00000 n +0000768305 00000 n +0000768370 00000 n +0000768435 00000 n +0000768499 00000 n +0000774738 00000 n +0000771300 00000 n +0000768677 00000 n +0000771426 00000 n +0000771491 00000 n +0000771556 00000 n +0000771621 00000 n +0000771686 00000 n +0000771751 00000 n +0000771816 00000 n +0000771881 00000 n +0000771946 00000 n +0000772011 00000 n +0000772076 00000 n +0000772141 00000 n +0000772206 00000 n +0000772271 00000 n +0000772336 00000 n +0000772401 00000 n +0000772466 00000 n +0000772531 00000 n +0000772596 00000 n +0000772661 00000 n +0000772726 00000 n +0000772791 00000 n +0000772856 00000 n +0000772921 00000 n +0000772986 00000 n +0000773051 00000 n +0000773116 00000 n +0000773181 00000 n +0000773246 00000 n +0000773311 00000 n +0000773376 00000 n +0000773441 00000 n +0000773506 00000 n +0000773571 00000 n +0000773635 00000 n +0000773700 00000 n +0000773765 00000 n +0000773830 00000 n +0000773895 00000 n +0000773960 00000 n 0000774025 00000 n -0000771810 00000 n -0000774151 00000 n -0000774216 00000 n -0000774281 00000 n -0000774346 00000 n -0000774475 00000 n -0000774540 00000 n -0000774605 00000 n -0000774670 00000 n -0000777831 00000 n -0000777575 00000 n -0000774901 00000 n -0000777701 00000 n -0000777766 00000 n -0000780973 00000 n -0000780264 00000 n -0000777957 00000 n -0000780390 00000 n -0000780455 00000 n -0000780520 00000 n -0000780585 00000 n -0000780713 00000 n -0000780778 00000 n -0000780843 00000 n -0000780908 00000 n -0000784563 00000 n -0000784242 00000 n -0000781125 00000 n -0000784368 00000 n -0000784433 00000 n -0000784498 00000 n -0000785542 00000 n -0000785221 00000 n -0000784702 00000 n -0000785347 00000 n -0000785412 00000 n -0000785477 00000 n -0000785753 00000 n -0000797097 00000 n -0000804686 00000 n -0000806986 00000 n -0000806955 00000 n -0000810672 00000 n -0000820112 00000 n -0000830619 00000 n -0000841105 00000 n -0000853729 00000 n -0000872794 00000 n -0000893681 00000 n -0000915824 00000 n -0000933719 00000 n -0000936550 00000 n -0000936320 00000 n -0000963857 00000 n -0000990968 00000 n -0000994319 00000 n -0000994443 00000 n -0000994569 00000 n -0000994695 00000 n -0000994812 00000 n -0000994904 00000 n -0001011519 00000 n -0001030788 00000 n -0001030829 00000 n -0001030869 00000 n -0001031003 00000 n +0000774090 00000 n +0000774155 00000 n +0000774220 00000 n +0000774285 00000 n +0000774350 00000 n +0000774415 00000 n +0000774480 00000 n +0000774545 00000 n +0000774610 00000 n +0000774674 00000 n +0000780257 00000 n +0000777861 00000 n +0000774852 00000 n +0000777987 00000 n +0000778052 00000 n +0000778117 00000 n +0000778182 00000 n +0000778247 00000 n +0000778312 00000 n +0000778377 00000 n +0000778442 00000 n +0000778507 00000 n +0000778572 00000 n +0000778637 00000 n +0000778702 00000 n +0000778767 00000 n +0000778831 00000 n +0000778896 00000 n +0000778961 00000 n +0000779026 00000 n +0000779091 00000 n +0000779156 00000 n +0000779221 00000 n +0000779286 00000 n +0000779351 00000 n +0000779416 00000 n +0000779481 00000 n +0000779546 00000 n +0000779674 00000 n +0000779803 00000 n +0000779868 00000 n +0000779933 00000 n +0000779998 00000 n +0000780063 00000 n +0000780192 00000 n +0000783466 00000 n +0000782759 00000 n +0000780384 00000 n +0000782885 00000 n +0000783014 00000 n +0000783143 00000 n +0000783272 00000 n +0000783401 00000 n +0000786958 00000 n +0000786201 00000 n +0000783593 00000 n +0000786508 00000 n +0000786637 00000 n +0000786348 00000 n +0000786765 00000 n +0000786893 00000 n +0001148313 00000 n +0000790202 00000 n +0000789624 00000 n +0000787085 00000 n +0000789750 00000 n +0000789879 00000 n +0000790008 00000 n +0000790137 00000 n +0000793110 00000 n +0000792790 00000 n +0000790316 00000 n +0000792916 00000 n +0000793045 00000 n +0000795700 00000 n +0000795251 00000 n +0000793280 00000 n +0000795377 00000 n +0000795506 00000 n +0000795635 00000 n +0000796141 00000 n +0000795950 00000 n +0000795800 00000 n +0000796076 00000 n +0000798853 00000 n +0000798209 00000 n +0000796183 00000 n +0000798335 00000 n +0000798464 00000 n +0000798593 00000 n +0000798658 00000 n +0000798723 00000 n +0000798788 00000 n +0000803193 00000 n +0000802873 00000 n +0000798967 00000 n +0000802999 00000 n +0000803064 00000 n +0000803129 00000 n +0001148438 00000 n +0000806796 00000 n +0000806541 00000 n +0000803349 00000 n +0000806667 00000 n +0000806732 00000 n +0000810047 00000 n +0000809856 00000 n +0000806938 00000 n +0000809982 00000 n +0000813767 00000 n +0000813511 00000 n +0000810175 00000 n +0000813637 00000 n +0000813702 00000 n +0000816752 00000 n +0000816044 00000 n +0000813909 00000 n +0000816170 00000 n +0000816235 00000 n +0000816300 00000 n +0000816365 00000 n +0000816430 00000 n +0000816559 00000 n +0000816624 00000 n +0000816688 00000 n +0000821421 00000 n +0000821165 00000 n +0000816894 00000 n +0000821291 00000 n +0000821356 00000 n +0000824431 00000 n +0000823658 00000 n +0000821549 00000 n +0000823784 00000 n +0000823849 00000 n +0000823914 00000 n +0000823979 00000 n +0000824108 00000 n +0000824173 00000 n +0000824236 00000 n +0000824301 00000 n +0000824366 00000 n +0001148563 00000 n +0000827345 00000 n +0000826830 00000 n +0000824587 00000 n +0000826956 00000 n +0000827021 00000 n +0000827086 00000 n +0000827151 00000 n +0000827216 00000 n +0000827281 00000 n +0000830708 00000 n +0000830128 00000 n +0000827501 00000 n +0000830254 00000 n +0000830383 00000 n +0000830448 00000 n +0000830513 00000 n +0000830578 00000 n +0000830643 00000 n +0000834160 00000 n +0000833904 00000 n +0000830850 00000 n +0000834030 00000 n +0000834095 00000 n +0000837112 00000 n +0000836468 00000 n +0000834288 00000 n +0000836594 00000 n +0000836659 00000 n +0000836724 00000 n +0000836789 00000 n +0000836983 00000 n +0000837048 00000 n +0000840705 00000 n +0000840384 00000 n +0000837281 00000 n +0000840510 00000 n +0000840575 00000 n +0000840640 00000 n +0000844296 00000 n +0000844105 00000 n +0000840833 00000 n +0000844231 00000 n +0001148688 00000 n +0000847762 00000 n +0000847441 00000 n +0000844424 00000 n +0000847567 00000 n +0000847632 00000 n +0000847697 00000 n +0000850416 00000 n +0000849707 00000 n +0000847903 00000 n +0000849833 00000 n +0000849898 00000 n +0000849963 00000 n +0000850028 00000 n +0000850157 00000 n +0000850222 00000 n +0000850287 00000 n +0000850352 00000 n +0000853441 00000 n +0000852732 00000 n +0000850572 00000 n +0000852858 00000 n +0000852923 00000 n +0000852987 00000 n +0000853052 00000 n +0000853246 00000 n +0000853311 00000 n +0000853376 00000 n +0000856922 00000 n +0000856601 00000 n +0000853597 00000 n +0000856727 00000 n +0000856792 00000 n +0000856857 00000 n +0000860091 00000 n +0000859381 00000 n +0000857036 00000 n +0000859507 00000 n +0000859572 00000 n +0000859637 00000 n +0000859702 00000 n +0000859831 00000 n +0000859896 00000 n +0000859961 00000 n +0000860026 00000 n +0000863741 00000 n +0000863485 00000 n +0000860247 00000 n +0000863611 00000 n +0000863676 00000 n +0001148813 00000 n +0000867398 00000 n +0000867207 00000 n +0000863883 00000 n +0000867333 00000 n +0000870723 00000 n +0000870532 00000 n +0000867526 00000 n +0000870658 00000 n +0000873552 00000 n +0000872845 00000 n +0000870865 00000 n +0000872971 00000 n +0000873036 00000 n +0000873101 00000 n +0000873166 00000 n +0000873295 00000 n +0000873358 00000 n +0000873423 00000 n +0000873488 00000 n +0000876509 00000 n +0000875799 00000 n +0000873708 00000 n +0000875925 00000 n +0000875990 00000 n +0000876055 00000 n +0000876120 00000 n +0000876185 00000 n +0000876314 00000 n +0000876379 00000 n +0000876444 00000 n +0000879808 00000 n +0000879487 00000 n +0000876665 00000 n +0000879613 00000 n +0000879678 00000 n +0000879743 00000 n +0000883039 00000 n +0000882784 00000 n +0000879950 00000 n +0000882910 00000 n +0000882975 00000 n +0001148938 00000 n +0000886134 00000 n +0000885424 00000 n +0000883167 00000 n +0000885550 00000 n +0000885615 00000 n +0000885680 00000 n +0000885809 00000 n +0000885874 00000 n +0000885939 00000 n +0000886004 00000 n +0000886069 00000 n +0000889435 00000 n +0000889244 00000 n +0000886290 00000 n +0000889370 00000 n +0000892497 00000 n +0000892112 00000 n +0000889648 00000 n +0000892238 00000 n +0000892303 00000 n +0000892368 00000 n +0000892433 00000 n +0000895198 00000 n +0000894230 00000 n +0000892738 00000 n +0000894356 00000 n +0000894421 00000 n +0000894486 00000 n +0000894615 00000 n +0000894680 00000 n +0000894745 00000 n +0000894810 00000 n +0000894875 00000 n +0000894940 00000 n +0000895069 00000 n +0000895134 00000 n +0000899701 00000 n +0000899380 00000 n +0000895340 00000 n +0000899506 00000 n +0000899571 00000 n +0000899636 00000 n +0000903445 00000 n +0000903189 00000 n +0000899829 00000 n +0000903315 00000 n +0000903380 00000 n +0001149063 00000 n +0000906877 00000 n +0000906621 00000 n +0000903573 00000 n +0000906747 00000 n +0000906812 00000 n +0000909456 00000 n +0000908878 00000 n +0000907005 00000 n +0000909004 00000 n +0000909069 00000 n +0000909134 00000 n +0000909198 00000 n +0000909327 00000 n +0000909392 00000 n +0000913457 00000 n +0000913006 00000 n +0000909611 00000 n +0000913132 00000 n +0000913197 00000 n +0000913262 00000 n +0000913327 00000 n +0000913392 00000 n +0000916787 00000 n +0000916142 00000 n +0000913599 00000 n +0000916268 00000 n +0000916333 00000 n +0000916398 00000 n +0000916527 00000 n +0000916592 00000 n +0000916657 00000 n +0000916722 00000 n +0000919348 00000 n +0000919092 00000 n +0000916943 00000 n +0000919218 00000 n +0000919283 00000 n +0000922833 00000 n +0000922059 00000 n +0000919490 00000 n +0000922185 00000 n +0000922250 00000 n +0000922315 00000 n +0000922380 00000 n +0000922508 00000 n +0000922573 00000 n +0000922638 00000 n +0000922703 00000 n +0000922768 00000 n +0001149188 00000 n +0000925908 00000 n +0000925329 00000 n +0000922989 00000 n +0000925455 00000 n +0000925520 00000 n +0000925585 00000 n +0000925650 00000 n +0000925779 00000 n +0000925844 00000 n +0000929734 00000 n +0000929286 00000 n +0000926064 00000 n +0000929412 00000 n +0000929477 00000 n +0000929542 00000 n +0000929607 00000 n +0000929671 00000 n +0000931972 00000 n +0000930942 00000 n +0000929890 00000 n +0000931068 00000 n +0000931133 00000 n +0000931262 00000 n +0000931327 00000 n +0000931392 00000 n +0000931456 00000 n +0000931521 00000 n +0000931586 00000 n +0000931715 00000 n +0000931780 00000 n +0000931845 00000 n +0000931910 00000 n +0000934986 00000 n +0000934213 00000 n +0000932114 00000 n +0000934339 00000 n +0000934404 00000 n +0000934469 00000 n +0000934534 00000 n +0000934663 00000 n +0000934727 00000 n +0000934792 00000 n +0000934857 00000 n +0000934921 00000 n +0000937265 00000 n +0000936426 00000 n +0000935128 00000 n +0000936552 00000 n +0000936617 00000 n +0000936682 00000 n +0000936810 00000 n +0000936875 00000 n +0000936940 00000 n +0000937005 00000 n +0000937070 00000 n +0000937135 00000 n +0000937200 00000 n +0000937506 00000 n +0000948850 00000 n +0000956439 00000 n +0000958738 00000 n +0000958707 00000 n +0000962423 00000 n +0000971863 00000 n +0000982598 00000 n +0000994293 00000 n +0001007010 00000 n +0001026244 00000 n +0001047140 00000 n +0001069288 00000 n +0001087544 00000 n +0001090391 00000 n +0001090161 00000 n +0001117809 00000 n +0001145075 00000 n +0001149313 00000 n +0001149438 00000 n +0001149564 00000 n +0001149690 00000 n +0001149816 00000 n +0001149942 00000 n +0001150043 00000 n +0001171759 00000 n +0001195784 00000 n +0001195825 00000 n +0001195865 00000 n +0001195999 00000 n trailer << -/Size 2169 -/Root 2167 0 R -/Info 2168 0 R -/ID [<0C97D45D411E72A60BD825BAD36788D6> <0C97D45D411E72A60BD825BAD36788D6>] +/Size 2735 +/Root 2733 0 R +/Info 2734 0 R +/ID [<1DE9D6805D55864A9314F6997A97E945> <1DE9D6805D55864A9314F6997A97E945>] >> startxref -1031261 +1196257 %%EOF diff --git a/doc/arm/Makefile.in b/doc/arm/Makefile.in index 5098528..d9eb8fe 100644 --- a/doc/arm/Makefile.in +++ b/doc/arm/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.20.332.2 2009-02-12 23:47:22 tbox Exp $ +# $Id: Makefile.in,v 1.22 2009-02-12 23:47:56 tbox Exp $ srcdir = @srcdir@ VPATH = @srcdir@ diff --git a/doc/arm/dnssec.xml b/doc/arm/dnssec.xml new file mode 100644 index 0000000..a678b8c --- /dev/null +++ b/doc/arm/dnssec.xml @@ -0,0 +1,268 @@ + + + + + + + DNSSEC, Dynamic Zones, and Automatic Signing + As of BIND 9.7.0 it is possible to change a dynamic zone + from insecure to signed and back again. A secure zone can use + either NSEC or NSEC3 chains. + + Converting from insecure to secure + + Changing a zone from insecure to secure can be done in two + ways: using a dynamic DNS update, or the + auto-dnssec zone option. + For either method, you need to configure + named so that it can see the + K* files which contain the public and private + parts of the keys that will be used to sign the zone. These files + will have been generated by + dnssec-keygen. You can do this by placing them + in the key-directory, as specified in + named.conf: + + zone example.net { + type master; + update-policy local; + file "dynamic/example.net/example.net"; + key-directory "dynamic/example.net"; + }; + + If one KSK and one ZSK DNSKEY key have been generated, this + configuration will cause all records in the zone to be signed + with the ZSK, and the DNSKEY RRset to be signed with the KSK as + well. An NSEC chain will be generated as part of the initial + signing process. + + Dynamic DNS update method + + To insert the keys via dynamic update: + + % nsupdate + > ttl 3600 + > update add example.net DNSKEY 256 3 7 AwEAAZn17pUF0KpbPA2c7Gz76Vb18v0teKT3EyAGfBfL8eQ8al35zz3Y I1m/SAQBxIqMfLtIwqWPdgthsu36azGQAX8= + > update add example.net DNSKEY 257 3 7 AwEAAd/7odU/64o2LGsifbLtQmtO8dFDtTAZXSX2+X3e/UNlq9IHq3Y0 XtC0Iuawl/qkaKVxXe2lo8Ct+dM6UehyCqk= + > send + + While the update request will complete almost immediately, + the zone will not be completely signed until + named has had time to walk the zone and + generate the NSEC and RRSIG records. The NSEC record at the apex + will be added last, to signal that there is a complete NSEC + chain. + If you wish to sign using NSEC3 instead of NSEC, you should + add an NSEC3PARAM record to the initial update request. If you + wish the NSEC3 chain to have the OPTOUT bit set, set it in the + flags field of the NSEC3PARAM record. + + % nsupdate + > ttl 3600 + > update add example.net DNSKEY 256 3 7 AwEAAZn17pUF0KpbPA2c7Gz76Vb18v0teKT3EyAGfBfL8eQ8al35zz3Y I1m/SAQBxIqMfLtIwqWPdgthsu36azGQAX8= + > update add example.net DNSKEY 257 3 7 AwEAAd/7odU/64o2LGsifbLtQmtO8dFDtTAZXSX2+X3e/UNlq9IHq3Y0 XtC0Iuawl/qkaKVxXe2lo8Ct+dM6UehyCqk= + > update add example.net NSEC3PARAM 1 1 100 1234567890 + > send + + Again, this update request will complete almost + immediately; however, the record won't show up until + named has had a chance to build/remove the + relevant chain. A private type record will be created to record + the state of the operation (see below for more details), and will + be removed once the operation completes. + While the initial signing and NSEC/NSEC3 chain generation + is happening, other updates are possible as well. + + Fully automatic zone signing + + To enable automatic signing, add the + auto-dnssec option to the zone statement in + named.conf. + auto-dnssec has two possible arguments: + allow or + maintain. + With + auto-dnssec allow, + named can search the key directory for keys + matching the zone, insert them into the zone, and use them to + sign the zone. It will do so only when it receives an + rndc sign <zonename> or + rndc loadkeys <zonename> command. + + + auto-dnssec maintain includes the above + functionality, but will also automatically adjust the zone's + DNSKEY records on schedule according to the keys' timing metadata. + (See and + for more information.) + If keys are present in the key directory the first time the zone + is loaded, it will be signed immediately, without waiting for an + rndc sign or rndc loadkeys + command. (Those commands can still be used when there are unscheduled + key changes, however.) + + Using the + auto-dnssec option requires the zone to be + configured to allow dynamic updates, by adding an + allow-update or + update-policy statement to the zone + configuration. If this has not been done, the configuration will + fail. + + Private-type records + + The state of the signing process is signaled by + private-type records (with a default type value of 65534). When + signing is complete, these records will have a nonzero value for + the final octet (for those records which have a nonzero initial + octet). + The private type record format: If the first octet is + non-zero then the record indicates that the zone needs to be + signed with the key matching the record, or that all signatures + that match the record should be removed. + + + + algorithm (octet 1) + key id in network order (octet 2 and 3) + removal flag (octet 4) + complete flag (octet 5) + + + Only records flagged as "complete" can be removed via + dynamic update. Attempts to remove other private type records + will be silently ignored. + If the first octet is zero (this is a reserved algorithm + number that should never appear in a DNSKEY record) then the + record indicates changes to the NSEC3 chains are in progress. The + rest of the record contains an NSEC3PARAM record. The flag field + tells what operation to perform based on the flag bits. + + + + 0x01 OPTOUT + 0x80 CREATE + 0x40 REMOVE + 0x20 NONSEC + + + + DNSKEY rollovers + + As with insecure-to-secure conversions, rolling DNSSEC + keys can be done in two ways: using a dynamic DNS update, or the + auto-dnssec zone option. + + Dynamic DNS update method + + To perform key rollovers via dynamic update, you need to add + the K* files for the new keys so that + named can find them. You can then add the new + DNSKEY RRs via dynamic update. + named will then cause the zone to be signed + with the new keys. When the signing is complete the private type + records will be updated so that the last octet is non + zero. + If this is for a KSK you need to inform the parent and any + trust anchor repositories of the new KSK. + You should then wait for the maximum TTL in the zone before + removing the old DNSKEY. If it is a KSK that is being updated, + you also need to wait for the DS RRset in the parent to be + updated and its TTL to expire. This ensures that all clients will + be able to verify at least one signature when you remove the old + DNSKEY. + The old DNSKEY can be removed via UPDATE. Take care to + specify the correct key. + named will clean out any signatures generated + by the old key after the update completes. + + Automatic key rollovers + + When a new key reaches its activation date (as set by + dnssec-keygen or dnssec-settime), + if the auto-dnssec zone option is set to + maintain, named will + automatically carry out the key rollover. If the key's algorithm + has not previously been used to sign the zone, then the zone will + be fully signed as quickly as possible. However, if the new key + is replacing an existing key of the same algorithm, then the + zone will be re-signed incrementally, with signatures from the + old key being replaced with signatures from the new key as their + signature validity periods expire. By default, this rollover + completes in 30 days, after which it will be safe to remove the + old key from the DNSKEY RRset. + + NSEC3PARAM rollovers via UPDATE + + Add the new NSEC3PARAM record via dynamic update. When the + new NSEC3 chain has been generated, the NSEC3PARAM flag field + will be zero. At this point you can remove the old NSEC3PARAM + record. The old chain will be removed after the update request + completes. + + Converting from NSEC to NSEC3 + + To do this, you just need to add an NSEC3PARAM record. When + the conversion is complete, the NSEC chain will have been removed + and the NSEC3PARAM record will have a zero flag field. The NSEC3 + chain will be generated before the NSEC chain is + destroyed. + + Converting from NSEC3 to NSEC + + To do this, use nsupdate to + remove all NSEC3PARAM records with a zero flag + field. The NSEC chain will be generated before the NSEC3 chain is + removed. + + Converting from secure to insecure + + To convert a signed zone to unsigned using dynamic DNS, + delete all the DNSKEY records from the zone apex using + nsupdate. All signatures, NSEC or NSEC3 chains, + and associated NSEC3PARAM records will be removed automatically. + This will take place after the update request completes. + This requires the + dnssec-secure-to-insecure option to be set to + yes in + named.conf. + In addition, if the auto-dnssec maintain + zone statement is used, it should be removed or changed to + allow instead (or it will re-sign). + + + Periodic re-signing + + In any secure zone which supports dynamic updates, named + will periodically re-sign RRsets which have not been re-signed as + a result of some update action. The signature lifetimes will be + adjusted so as to spread the re-sign load over time rather than + all at once. + + NSEC3 and OPTOUT + + + named only supports creating new NSEC3 chains + where all the NSEC3 records in the zone have the same OPTOUT + state. + named supports UPDATES to zones where the NSEC3 + records in the chain have mixed OPTOUT state. + named does not support changing the OPTOUT + state of an individual NSEC3 record, the entire chain needs to be + changed if the OPTOUT state of an individual NSEC3 needs to be + changed. + diff --git a/doc/arm/libdns.xml b/doc/arm/libdns.xml new file mode 100644 index 0000000..8861f2c --- /dev/null +++ b/doc/arm/libdns.xml @@ -0,0 +1,530 @@ + + + + + BIND 9 DNS Library Support + This version of BIND 9 "exports" its internal libraries so + that they can be used by third-party applications more easily (we + call them "export" libraries in this document). In addition to + all major DNS-related APIs BIND 9 is currently using, the export + libraries provide the following features: + + + The newly created "DNS client" module. This is a higher + level API that provides an interface to name resolution, + single DNS transaction with a particular server, and dynamic + update. Regarding name resolution, it supports advanced + features such as DNSSEC validation and caching. This module + supports both synchronous and asynchronous mode. + + + The new "IRS" (Information Retrieval System) library. + It provides an interface to parse the traditional resolv.conf + file and more advanced, DNS-specific configuration file for + the rest of this package (see the description for the + dns.conf file below). + + + As part of the IRS library, newly implemented standard + address-name mapping functions, getaddrinfo() and + getnameinfo(), are provided. They use the DNSSEC-aware + validating resolver backend, and could use other advanced + features of the BIND 9 libraries such as caching. The + getaddrinfo() function resolves both A and AAAA RRs + concurrently (when the address family is unspecified). + + + An experimental framework to support other event + libraries than BIND 9's internal event task system. + + + + Prerequisite + GNU make is required to build the export libraries (other + part of BIND 9 can still be built with other types of make). In + the reminder of this document, "make" means GNU make. Note that + in some platforms you may need to invoke a different command name + than "make" (e.g. "gmake") to indicate it's GNU make. + + + Compilation + +$ ./configure --enable-exportlib [other flags] +$ make + + + This will create (in addition to usual BIND 9 programs) and a + separate set of libraries under the lib/export directory. For + example, lib/export/dns/libdns.a is the archive file of the + export version of the BIND 9 DNS library. Sample application + programs using the libraries will also be built under the + lib/export/samples directory (see below). + + + Installation + +$ cd lib/export +$ make install + + + This will install library object files under the directory + specified by the --with-export-libdir configure option (default: + EPREFIX/lib/bind9), and header files under the directory + specified by the --with-export-includedir configure option + (default: PREFIX/include/bind9). + Root privilege is normally required. + "make install" at the top directory will do the + same. + + + To see how to build your own + application after the installation, see + lib/export/samples/Makefile-postinstall.in. + + + Known Defects/Restrictions + + + + Currently, win32 is not supported for the export + library. (Normal BIND 9 application can be built as + before). + + + The "fixed" RRset order is not (currently) supported in + the export library. If you want to use "fixed" RRset order + for, e.g. named while still building the + export library even without the fixed order support, build + them separately: + +$ ./configure --enable-fixed-rrset [other flags, but not --enable-exportlib] +$ make +$ ./configure --enable-exportlib [other flags, but not --enable-fixed-rrset] +$ cd lib/export +$ make + + + + + The client module and the IRS library currently do not + support DNSSEC validation using DLV (the underlying modules + can handle it, but there is no tunable interface to enable + the feature). + + + RFC 5011 is not supported in the validating stub + resolver of the export library. In fact, it is not clear + whether it should: trust anchors would be a system-wide + configuration which would be managed by an administrator, + while the stub resolver will be used by ordinary applications + run by a normal user. + + + Not all common /etc/resolv.conf + options are supported + in the IRS library. The only available options in this + version are "debug" and "ndots". + + + + + The dns.conf File + The IRS library supports an "advanced" configuration file + related to the DNS library for configuration parameters that + would be beyond the capability of the + resolv.conf file. + Specifically, it is intended to provide DNSSEC related + configuration parameters. By default the path to this + configuration file is /etc/dns.conf. + This module is very + experimental and the configuration syntax or library interfaces + may change in future versions. Currently, only the + trusted-keys + statement is supported, whose syntax is the same as the same name + of statement for named.conf. (See + for details.) + + + Sample Applications + Some sample application programs using this API are + provided for reference. The following is a brief description of + these applications. + + + sample: a simple stub resolver utility + + It sends a query of a given name (of a given optional RR type) to a + specified recursive server, and prints the result as a list of + RRs. It can also act as a validating stub resolver if a trust + anchor is given via a set of command line options. + + Usage: sample [options] server_address hostname + + + Options and Arguments: + + + + + -t RRtype + + + specify the RR type of the query. The default is the A RR. + + + + + [-a algorithm] [-e] -k keyname -K keystring + + + specify a command-line DNS key to validate the answer. For + example, to specify the following DNSKEY of example.com: + + example.com. 3600 IN DNSKEY 257 3 5 xxx + + specify the options as follows: + + + -e -k example.com -K "xxx" + + + -e means that this key is a zone's "key signing key" (as known + as "secure Entry point"). + When -a is omitted rsasha1 will be used by default. + + + + + -s domain:alt_server_address + + + specify a separate recursive server address for the specific + "domain". Example: -s example.com:2001:db8::1234 + + + + server_address + + an IP(v4/v6) address of the recursive server to which queries + are sent. + + + + hostname + + the domain name for the query + + + + + + sample-async: a simple stub resolver, working asynchronously + + Similar to "sample", but accepts a list + of (query) domain names as a separate file and resolves the names + asynchronously. + + Usage: sample-async [-s server_address] [-t RR_type] input_file + + Options and Arguments: + + + + + -s server_address + + + an IPv4 address of the recursive server to which queries are sent. + (IPv6 addresses are not supported in this implementation) + + + + + -t RR_type + + + specify the RR type of the queries. The default is the A + RR. + + + + + input_file + + + a list of domain names to be resolved. each line + consists of a single domain name. Example: + + www.example.com + mx.examle.net + ns.xxx.example + + + + + + + sample-request: a simple DNS transaction client + + It sends a query to a specified server, and + prints the response with minimal processing. It doesn't act as a + "stub resolver": it stops the processing once it gets any + response from the server, whether it's a referral or an alias + (CNAME or DNAME) that would require further queries to get the + ultimate answer. In other words, this utility acts as a very + simplified dig. + + + Usage: sample-request [-t RRtype] server_address hostname + + + Options and Arguments: + + + + + -t RRtype + + + + specify the RR type of + the queries. The default is the A RR. + + + + + + server_address + + + + an IP(v4/v6) + address of the recursive server to which the query is sent. + + + + + + hostname + + + + the domain name for the query + + + + + + + sample-gai: getaddrinfo() and getnameinfo() test code + + This is a test program + to check getaddrinfo() and getnameinfo() behavior. It takes a + host name as an argument, calls getaddrinfo() with the given host + name, and calls getnameinfo() with the resulting IP addresses + returned by getaddrinfo(). If the dns.conf file exists and + defines a trust anchor, the underlying resolver will act as a + validating resolver, and getaddrinfo()/getnameinfo() will fail + with an EAI_INSECUREDATA error when DNSSEC validation fails. + + + Usage: sample-gai hostname + + + + sample-update: a simple dynamic update client program + + It accepts a single update command as a + command-line argument, sends an update request message to the + authoritative server, and shows the response from the server. In + other words, this is a simplified nsupdate. + + + Usage: sample-update [options] (add|delete) "update data" + + + Options and Arguments: + + + + + -a auth_server + + + An IP address of the authoritative server that has authority + for the zone containing the update name. This should normally + be the primary authoritative server that accepts dynamic + updates. It can also be a secondary server that is configured + to forward update requests to the primary server. + + + + + -k keyfile + + + A TSIG key file to secure the update transaction. The keyfile + format is the same as that for the nsupdate utility. + + + + + -p prerequisite + + + A prerequisite for the update (only one prerequisite can be + specified). The prerequisite format is the same as that is + accepted by the nsupdate utility. + + + + + -r recursive_server + + + An IP address of a recursive server that this utility will + use. A recursive server may be necessary to identify the + authoritative server address to which the update request is + sent. + + + + + -z zonename + + + The domain name of the zone that contains + + + + + (add|delete) + + + Specify the type of update operation. Either "add" or "delete" + must be specified. + + + + + "update data" + + + Specify the data to be updated. A typical example of the data + would look like "name TTL RRtype RDATA". + + + + + In practice, either -a or -r must be specified. Others can + be optional; the underlying library routine tries to identify the + appropriate server and the zone name for the update. + + + Examples: assuming the primary authoritative server of the + dynamic.example.com zone has an IPv6 address 2001:db8::1234, + + +$ sample-update -a sample-update -k Kxxx.+nnn+mmmm.key add "foo.dynamic.example.com 30 IN A 192.168.2.1" + + adds an A RR for foo.dynamic.example.com using the given key. + + +$ sample-update -a sample-update -k Kxxx.+nnn+mmmm.key delete "foo.dynamic.example.com 30 IN A" + + removes all A RRs for foo.dynamic.example.com using the given key. + + +$ sample-update -a sample-update -k Kxxx.+nnn+mmmm.key delete "foo.dynamic.example.com" + + removes all RRs for foo.dynamic.example.com using the given key. + + + + nsprobe: domain/name server checker in terms of RFC 4074 + + It checks a set + of domains to see the name servers of the domains behave + correctly in terms of RFC 4074. This is included in the set of + sample programs to show how the export library can be used in a + DNS-related application. + + + Usage: nsprobe [-d] [-v [-v...]] [-c cache_address] [input_file] + + + Options + + + + + + -d + + + run in the "debug" mode. with this option nsprobe will dump + every RRs it receives. + + + + + -v + + + increase verbosity of other normal log messages. This can be + specified multiple times + + + + + -c cache_address + + + specify an IP address of a recursive (caching) name server. + nsprobe uses this server to get the NS RRset of each domain and + the A and/or AAAA RRsets for the name servers. The default + value is 127.0.0.1. + + + + + input_file + + + a file name containing a list of domain (zone) names to be + probed. when omitted the standard input will be used. Each + line of the input file specifies a single domain name such as + "example.com". In general this domain name must be the apex + name of some DNS zone (unlike normal "host names" such as + "www.example.com"). nsprobe first identifies the NS RRsets for + the given domain name, and sends A and AAAA queries to these + servers for some "widely used" names under the zone; + specifically, adding "www" and "ftp" to the zone name. + + + + + + + Library References + As of this writing, there is no formal "manual" of the + libraries, except this document, header files (some of them + provide pretty detailed explanations), and sample application + programs. + + + diff --git a/doc/arm/man.arpaname.html b/doc/arm/man.arpaname.html new file mode 100644 index 0000000..8f0d98c --- /dev/null +++ b/doc/arm/man.arpaname.html @@ -0,0 +1,91 @@ + + + + + +arpaname + + + + + + + +

    Y„öÆ:]Kþ`¨&g’×õnWŸÊÆlåô8Ô~œÁa½¤½ÙÄÙ0éß¹a ÂÖÀ˜h¨pÈ7šjµdjò`p"‘€EŒŠ“°fá­^³ˆx¬ÙØöšE´Ë)9·¤Ô1ôMRe—â±åÁ2¶<|ñØT#!DCå[Bʇ3¾( +ˆü"Š¤{'BEc„LåEiÇ3¢å Y=ˆ&Òñü¹D6u;iÖXûÖŽp5ów/ÖÂÙÁg¸:sNjYR0ß×Iµ|à†ÀË¢9¡\ˆy˜° õB^î|­ÝáØ¡æ•œ¤àå/Pú«—öP,Ë5Wgùh ¡yIýÞ@FÕœRjþö¢Fdôp¸ ïCi"= åò7wÎolƒ8óÇ«6‡]jw]b˜ÁE_­ëú«÷¡2Ô#¸Ž¹À¦yïïd;ÿ÷}Àd`gÈ!²4Sã|;F×î¨12Ó Ÿ¦\æOæ ›†gZ½#£‘¼:S£+÷·¶Ü莯p òÉñÊ9ÂMê3Þ ç!ÃIt¡÷$èºÃ¬éÂØh²9L9>À®R°Á®pæ™TZK)¤L=­Îèå2ZF(e.ï½ÜÖTÖØh ð"ã¹hãõÃ^ð0ÚÕ¬z³ÆŒ†„‘Âp¤ŒA*NÃf¥L"Rc§ªYÂ>›º ]'©P©õaÔñˆ¢DDZ^D?ŽP1¹zóz63€¢:Åk]>ÍõÜ5`Óì=ô[]Ê7¿ð$«£¶3õ«öBŒtój5ÔŒ9XÁ„ä`"-¬êïH/\žƒ±¥j,"¾zÛ—N‹F¦"ÆÄR*=Æ)èy¬¦Ã}¥†•½°Ã1Z<â½oeÉ3õ.à‹0º¿#Ÿ)xeŸýÕ¬qZ&"?O¥‹wl¹`¢|RX¢í¸R~˸™@fÜgŒ±‹:[…Ü–• ©f¾;åç–F¢aÌ‘[ðR—Jo%0Ky5%^”&»+ÐæÝ ¡ j LîÍÍ›„±ÓÌDÐeÏwÅp·“†áé[8o(V‘ðíhmân4… ߢAÕv™$~U3 ¿Lg—š¾tþ›X(ZÄ/³£i´Ñvq[<, ÌJJpTüNÆï r°‰¡‘MQM¾YBÔ“|'ç{Í$çÖÏçm÷#)%fDp‚×dž†üå‹n’¾at9d ‰öètã?A‹ƒÂû‡Â0“Ùk…¡YÖ—tƒÁ:?î:"l ihý¡h‚øAJ.÷AÚ ó÷+x+çà0%´½¼i÷ß±†Oƒ“Äî.áâw*ÅbMG3í©ûBO“ÍfF»Ñ'ý~ýbüÂÓOúO÷E*–þêKº5()ô%I—…‘ÊNHzòÛ‚~Õ+„<Ý*¯€«HJtôBÁÀzüãík¥Â×_sQ Ja ó77â6@ópÛÒÇ×î¿p„ʊѱôÎûVøcéKÔþøÃãî¢Ýµr¿€+ÃàÝʸ¨ÁW/‹ßxVn£Jè ĆWÚÅTnÎí †'‚§·¼¿>;ßr§– §"—²ô‡|®;D#'%ºÄ¥Y5äStd"9w0Àº°'è+^µ~I#=¾‚宧üit4yçÍbý†O?Lo(ÃÕé@Úû—Ð[Âb€Ho¤ËcӸ߭\”´”v¼j/\z½^ÿºŠ÷5C«êK-©½pÁþÊ>ôC) üuSzàŸOø¿D5üÂ,J…±V‡1  +au–z¢³(½¤¼ÿµÕSÒÿ:[)Žendstream endobj -1090 0 obj << +1598 0 obj << /Type /Page -/Contents 1091 0 R -/Resources 1089 0 R +/Contents 1599 0 R +/Resources 1597 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1068 0 R +/Parent 1562 0 R +/Annots [ 1601 0 R ] >> endobj -1092 0 obj << -/D [1090 0 R /XYZ 56.6929 794.5015 null] +1601 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [173.6261 273.4719 242.2981 282.8815] +/Subtype /Link +/A << /S /GoTo /D (the_category_phrase) >> >> endobj -1089 0 obj << -/Font << /F37 802 0 R /F41 939 0 R /F22 737 0 R >> +1600 0 obj << +/D [1598 0 R /XYZ 85.0394 794.5015 null] +>> endobj +1597 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1095 0 obj << -/Length 1945 +1605 0 obj << +/Length 2400 /Filter /FlateDecode >> stream -xÚ­ksÛ6ò»~…&Ÿ¤™&>›OnâÄnïÒ4ÖÝ—¦“HHâ”…;º›þ÷îbAŠTèæríxÆX,ûÞÅR|éÂ_F>seì-ÃØc¾ËýeR,ÜåÎÞ,¸¥qz"gLõýfqõZ†Ë˜Å–›ÝˆWÄÜ(âËMúËêåíõ»ÍÍûµ#|wå±µãîêúտלóÕõÛ—7¯èèÕÛ{^ß\¯Coµù×ûÄpã=ßÞÜÜß½Yÿºùaq³ôÛÀ]‰Ê}Züò«»LÁ”.“qä/aã2ÇbY,<_2ß“²Çä‹ûÅÏÃÑ©¹:ç_FÌD8ãœ,Ž=ú1 ¤Æ)*Ï«GçS§ëÓÚ \wõ_ZTyzAÐï°rßèêŠ0©Þ©.oi3ºª’D7 ús8g±ï‹K)N¢’ƒžÈÊÊV×¥Ê+Qžîb¤@­›¶Î«Áˆá×4¨uÒÕMV•ß,_xOÊ?3È¥¤cŒÍ©Ó£ÚÉ)´w„d1&bÿS•ÖÌgMÖjÎôgUsÍ’ªx6ÄåØS¡°p®,hX¡ˆ^êD|{:ZºB5àŠs†í²žï³âŠôÙU•ÑåÅÓhkU6;]«ÿG¾ÿ‡¯Ä¬¯þŸ}ÍþæŠdü©ýäÊæ¢Èªö ë[8ƒüùx¨šöc¡N[=µüotå¬'ùÈ“W¯…5 -]æùqdhîJj 6O:Œ›Ã%¤…*©òðH¹›aDLx·´\ß­jâ­?uÙƒÊuÙ–®É5€umÐoÈ¡Á ßÍ(æ@ïƒîÚÛ™Vur ¿«~U´4‡ªnôWû.K5aÛÊžê¶ÍÊ=mº#­›5<…˜*±Q$hQª¶«×—YY™ä]Jq—ÁÑ\ªÌ«G…²£5!nª=ß™x¿é“½¤Ê”€®yš¼ÉöÓðî1kQzÍa q½ÀhŽ@ú kV¨:ËO´mºã9…å°Á_[›l ƒ[ó¡fQte–˜PBŽÈÈïó< ¬ÓŒ®À‚žìïœ0Ü=T$VЈ³ÝÉL‚Ïg[®ñPäÚøšSDÙ A¨çFAb€*žËWïM4]OûÔl?ƒµÔÆ‘¬°´&Ž‘Û» ˆ–ƒêåæYÏŽaÈÉ›àSÉ°G/Îäºy6LÖÿ"‚q -u1<3ME¨­¦µkô®Ëé”ÂÈô},K,Å1U­ÆH¸ruM8Šû‰6CPÇ,Ôœâ>\xåPuyj•«Ê–RÞªñôÄg*?Œlå‡ñ™=bIQ:@²DC*x¢Ôµ„¾{ç؈á+ÈœL´Àì±kÙt¦À±¡$Ô7¸"ˆ!½I 0 >Ûj_«ãT™7¢u!'îËýºtJ˜í‰VŠBFHª­yÝQ×YeÒݨuúfô|sÉd„ô<5ÖI_>-žÏ"Ï(Z­À¨bhK{ªÚC¦˜8°ãHX¶Îo3’¹ÏB)zÉX–3cˆËÏØœfØ80zÀGSt1xc?šaž•¶ËVÇÖV&n옒•gŒõO=mÃí¬£aa‚»¾Õñœ¥ Ü0°4ì<ôú‚Üq´B†ÌRö“ãv6x£K]›LGuîªÖÖ¼‡ö¿ëMºQ‰mçïTVO-¹…«ybÊ€˜DÜ3²¡æ¥ô fÕùĽ¶Ö–ô)I¿·êY2S³°bÃA²K6[Ý>j]’2ÇF)Ý>è8òm…Çb7¾Ìž)'ü¢#1ÇÒ'Œâ!:Ž@Ã+IMUo3xd°çáãkø¦ö'À_—ßÑT.`Ju9ÌÏ“œü „gÌqŒ. ÷Ø`¡Umú1ÀH@€$ TtMk“S_ Í@Ô¿íÛªÇQFÃfr?ð× 7:çØe×][ð'ÄÄ&ý$þó„16xR@âg™?p;”"n3œÅÚùìI‰"¹ˆð8mpääÁÛS«iôÄÝí?¯_:÷·×·ÇÆmà„‡üp’ÄG†ÉÔJØVzöÛàŒ€Øb‰QCÐyDñ0;c†ô¥}[àÄÌÜ_¹­U“õ$TÒŽ*Å„óƒÕÛªµÄ-ͦ²¨B}Ί®dßU{ 6rËÀÖ†@Û¨._ 4ƒiÆæÝ|nóD÷ªâÎxÔ$R6dMƒ>ž6Ò²Žà€ROúøq­‡B%Ô½ai¶öëHDaoÜþt¿±wFåñÔOr¼ø;ÚÌhîÐRÿòÏuçß'½žÒH ¿ÄMJ@º½ŸV)t /5~×ûRõ?X†–endstream -endobj -1094 0 obj << +xÚ­]sÛ6òÝ¿BÓ—H3B€ ^žÒÔιÓ$=ŸûpÓv2´IœR¤JRqÕ›ûï·‹]ðC¦ß%ã‹Åb¿?`9 àOÎt,âT¥³$„¤ž­öÁl {o/$ã,=ÒrˆõÝíÅË«0™¥"U<»Ý h#g·ë_æ±Pb‚ù›ﯮßþ|óz‘DóÛëïK¥ƒùÕõ—´z{óúÝ»×7‹¥4ZÎßüýõO·—7´3ï®ßO”~!zsyuysùþÍåâ·Û..o;Y†òÊ DAþ¸øå·`¶±¸D˜=»‡@È4U³ýE¤C¡£0ôââŸÿèvÝÑIýÉ@¨0V +Œä@&q¤Š8T¡S`Ó®m]¿BA€ÚRJ‘j­ÜÖË—‹eóª,N´jl¹¦Õ¡Î«:ož—›ŠV™GØåÛ­§È6ö“¥Û—*© "MþOÇšßFèj—•¥-ˆDy,xõo‡+‘†ÊŒéxaÚªi<«§v——ÛN´Öcðï.gLÛ„0x7³v­°ÿòJ©!P˜T“¤çvgih-ˆVCYÛMv,Úsw“`ù0ŽfqølwS"5ÆL;ÛÒÓ[:?q&e(B ’z,âðî¸5TB‡AÂrtv “x¾Ë\$ iKæ`WyÆÛ‡z!ͼ:Ø}!í.kéDÞ„\s€½>®lÃ{Çöpdüû-= —­ÁKì YФ • [sa_€ç´D×Àß²*ÿ²t5äPóëÖïÔû¬@öðë<Þòt0üÍèç× P…¥õ +NØ5©q»°)$x ë±Ìöv-êc9¡qÈAʘ”1ó’/Ýñc¹‰¹ªþÝ~¬s'Ž]µU}ZH)ç‚´±ˆ’$öžž8úWÐRitWG +kü"YS•Í· <Ê&À=b¿*MÈ*£P˜TJ–`yœÒ[ˆP!GrUí÷.áG‘—î& ^Ôæ_ïL¿ÇÆ®oÚq4Á‡Ë“±~žÎ•úhí,:¸mÅiíšYB×%Å&J(©¢±ße›–òçy^PÂH£†LM…” m¼ +]¤)¸øÛ:´a?L¼k˜yiï òóõ÷ßÒŠt {- ÒŃé" Á[[Úš¥Ópy1•Õ@Û"2iò?±Ÿ3÷M›Õ-;ª™¬¾HªHž©Ï1NÞ´9–\Ö 8U–D¾VvÖªBI’nè:oV™ÛZƒÝÁQŒš_ohïTiQZË÷8mÂï*;´G26Ñ£:‚[¤/Ô¬ zûcÓùcrÎ(È?Ç+®ïóv7®BTܺà~$¢”„”ú”°Ü>7 €b9:ðÎpt÷™‚3K ¬1‚@gáT[?‘ø|v …Š´ìË(²ñ¡\qã‘4îëÂ(´4˜)•ÍT¾ÜŠ×w–0çþ˜5Šb¨ÀG¦EVŽçYÑÚ…œ×ôÅé hó¢]º‹ˆµ†zÝ”D¿²ÛÝ‘UG׺ÀºÞWë|s:Ëݾ  jTm·]Ö¾cÔC•—m]A@n¡Oó•'ã£^‡—ï²OÝE‚Æpà¬%å Ç뚥Û]ÎŒý´«³Æ>Ò E"dä›!„P“§e€´“½¯Œ4t:|Øýž× -RŸ³†—`µim†®!ÀQ›%ËÁ½¬M„uÚDxF°.Ðö@U‘ñ|ƒ"Œ„z ¬Ž{SEußÅ!¦ÓQìòGŸf}?‰MÉß&2x0NŒ½¬8Ÿt¤iÂ>6§Œùj t5œaÏ™P^c¸(ÈÂS*žÛ?³ý¡°NÐfÙöECMv"LVtì @drM¾å»ŽÁ^eËdOeø™!D¢#k®=¤/šQ8è†x‹ºß†>[:÷e¡•w6üÀîj²3ª<Ë‘sà÷}ßçF1]òÀÛW|¬*ñk{¬Ù9ˆãüÔ4am9Õ¾'Eæï¡Š¿Ìlè Ð=š>?Ÿ$Ÿð„ Ú|ÎL JS⣇ˆâyŽ S—^V»%ä{M®œ¿sS†tU`í†ÖüŒ€KÎ[®tŠ¬iœÑ0º3XÕ_NyF?½ŒkN;ÃúcýÞñÀS;ζí•öev87mø5Mk”ˆ“0yÚ´©P,5…xÖfwÓCäشﺒjí)Ä”Œ^ºSûîPGq>„}8m€-m]ÒK.îܦ#8¾hZ‡/M;ªU¥=ó€U¶ê¦}`éq#Ô÷µŒìz>IâQ#'H¤ÑO9‰€Nb]Wù9#¿>ð“ÿ§¬8ÓáÚ–¹ºRß•Ó?Ž¶i›Ç•:`÷Ë4@IÅÆ•Geôäî‚Ùg5þÜÿöÿD£zZÊÄ€Æp…´P‘‘yð_LÿEÆ°þ_x‘‹;endstream +endobj +1604 0 obj << /Type /Page -/Contents 1095 0 R -/Resources 1093 0 R +/Contents 1605 0 R +/Resources 1603 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1068 0 R +/Parent 1609 0 R >> endobj -1096 0 obj << -/D [1094 0 R /XYZ 85.0394 794.5015 null] +1606 0 obj << +/D [1604 0 R /XYZ 56.6929 794.5015 null] >> endobj -158 0 obj << -/D [1094 0 R /XYZ 85.0394 418.0047 null] +434 0 obj << +/D [1604 0 R /XYZ 56.6929 520.4669 null] >> endobj -1097 0 obj << -/D [1094 0 R /XYZ 85.0394 382.2497 null] +1602 0 obj << +/D [1604 0 R /XYZ 56.6929 495.6849 null] >> endobj -162 0 obj << -/D [1094 0 R /XYZ 85.0394 223.9723 null] +1607 0 obj << +/D [1604 0 R /XYZ 56.6929 178.7136 null] >> endobj -1098 0 obj << -/D [1094 0 R /XYZ 85.0394 195.8278 null] +1608 0 obj << +/D [1604 0 R /XYZ 56.6929 166.7584 null] >> endobj -166 0 obj << -/D [1094 0 R /XYZ 85.0394 149.2124 null] +1603 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F22 953 0 R /F21 930 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1099 0 obj << -/D [1094 0 R /XYZ 85.0394 126.0612 null] +1612 0 obj << +/Length 2418 +/Filter /FlateDecode +>> +stream +xÚÍZKsã6¾ûW¨j+W"çæØò¬S3ö¬­­ÚÝ$Z„%ÖP¤"Rö8¿> 4(R2%Æe¹jì@Ç×èî€Ø€Â?hI¨ˆ‚ADR&ÓÅ Ì îã ómFu£Q»ÕÏ““Ÿ.E8ˆH¤¸LZ}iBµfƒIòëðü_g_&ãÛÓ—t¨ÈéH*:üùêúK"LÎo®/¯>þçöì4 †“«›k,¾_ŽoÇ×çãÓÓ’<÷=츼ú4ÆÜÇ۳ϟÏnOŸür2žlÖÒ^/£Â.ä“_§ƒ–ýË %"Òrð”°(âƒÅI ‘uIvrwòïM‡­Z'Ú…_@a\ŠÁHhH©÷‹CPÖg#‘”»£Ž˜¡§ÐêD*B!»Ñ g-°@-„„2"Jpá”2-òß(å3‹ð–àÊ „Qœö|Ãõ*®Ò"GhmIf0¿ŒWešÏð#Î_º:ezXLMi+É®ÐB¨´çþ6~G”fe— fy@ï-@ߦ¤FïõòŽiZZjÊûôsƒei‡ì·{š÷ªþÿEîA«Vq^‚¤GÚ鸦˧¾Òëݤ‡m«5ùcÙÖ{`L5á\öA ýhÆÔ6Äźz'ŒK“'‡Ñm¦ýƒ«"ˆ˜*Ò=èª("ZªÀ–Uúð܋뤆ïúfruù¿-¿_Ó"Û]{VÇ<Á‚¾ÀªtH"Ê|`uþ²¼/[ñ±Ëå¶Mýµ)«òž­‰ O` !P†Wt‰úžȣн›1”$ +FÑu¾ˆ«éBU¤ŸËxflìcŒ;®µÐDYsA³º:@J¢€ûVO±ïsÇ÷–ö¸þ LS™Õ"Íëb0 +mGŒ‚nø«­¨;Íâ:^Û.Ç#‚Èd,xš§6â ôP¸|Mìeóe4vÿ¼\(§À¡Ê¯á15O å6 +«È7f­h4<ÃpЖ֡lL˶Agòa–Ö¹r½XÄ«güpþÒ8+ ß°˜ÍÓ5—"L»; „0ª7¸ï5%® “µ§qef ÏCÂSº Í·ÁŸÌÝä„ldàK ëÒ{02,)Ñþ ÌMÒ+6ÄŠ¬¾\ã*1+Gw~´Y4HÌC¼Î|—iÕÅÂZÑƼЧ—Ià—B°zû®³¬ FD Î<ÎssÈ·Lòmfþ¾ž˜q"µèõÄLRôĹ©žŠÕ×^¿qíÛ¡Îì:‡¼mk2ßs觔(®ûˆ•¢áÌ[÷z™€iôŸXžÁs¦S„ eáÕšÈwŒ—ÔoBôà%#N¸Œ¢^£ÒÂÒªŸ3-=AzŒ³sbò´.¬™€WÇ+˜@{GÃ:b„kþªý^‹ìE[D!ˆC|êA[Ã(4À“,~•B€ïCùni¦–Á:Üžšj?ë>Ðí΋u–Ô‡_L7áÊ9cÒåµÏÀWB€çWÕz n?ÐÐŽê蜭uÇ ›ÙD›Žˆ§Àø«Ýõþ +MhÈ6Œ$ÇïúvaÖÇ9ÿ‚™(ˆ$Ìd#Ã727M=Län|Ž}Þ|µ»Ô…˜“¶˜BF£¬ïÛV8®åv û}~Ñ´;Ÿ›éWg™¶æ"-­'n,×f·÷¥lƒnoõP¹Ë ·;‘ë²zŸÚóKY¥y}· 5ÛÖÐliÞliæჲš);j€à6;×÷O—AÛÏì X: ­ ¢ðÏþ¡¸êÃéˆqŠŽüùCç¶xz"æ[¼Xf†L‹öruéüaq—t{èpÐðРìÅ ¹©ö :ÂA;cw;$¾1ξ+0á@È>b)tD(ç¬ #8'«þø}•ÛÛézO±.¾·}.ÛÄoÆðïr~ËÂqË™3”8Ÿ'ò²p÷ÒPò§Ùî'PíÅ÷A"8惄PŒHŽz=¤ƒlG)$«IZ.í…A?½÷ ‘€m;>*¬Ÿ{ò¥l¸Œ§_MUnÌÛ[l.U!¿(’u†¼æ…±nÓ3¯ß¶Š‹m’Öz^òþ¤[™-”ŽûÊp\ƒ +"Òû|'¤ L*¼OrXøôï¼,a¸j4&wW_^Ö¾îÙ®™ñ±lDH¢Õ«Ì®–Ø+JJƒ^?€¥ ï¾3àj#ܺý~ê“{ò2ò›½´h"´Dµôqs i9Ý~Nµ‘\Qç«ll¼(ð¾k*~{ÜàÊZó´x4 ±‹˜»y²)¾®Û\„ XYŽ9`ÉÈ-l¾À{GP«æE¹õFâ£y§ÝúÖzûÑòÀ–iiãm~×MÃÁcjõí*á°%½_5™™9uŽŠ<뿸ش·Ç 1tBx{9pùTÌJ¬i‚](ê`¹yüh0çŽT.g¯AS¼i{èØõ/n>Ÿ]¹ßJ„îA™KU?„…­(Šßxâ{¯z±PW÷§^ -©íØCqÇ©Àë³l?za@‚€Ögä4ßzƒ† åoN ÿ‚WVë{Ìý¹yùK œ¼ÐäöïЖê߶›JIÈ•ü'ÅW”Ý…ÐAo(ù»?Ai~Ÿ…Ôºõ^½u‰@Ñ< +í¼{lñ ¢]@¤ÐDZRY7kMþ/ÌŠpendstream +endobj +1611 0 obj << +/Type /Page +/Contents 1612 0 R +/Resources 1610 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1609 0 R >> endobj -1093 0 obj << -/Font << /F37 802 0 R /F41 939 0 R /F22 737 0 R /F21 714 0 R /F39 899 0 R /F48 953 0 R >> +1613 0 obj << +/D [1611 0 R /XYZ 85.0394 794.5015 null] +>> endobj +1610 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1102 0 obj << -/Length 2252 +1616 0 obj << +/Length 2956 /Filter /FlateDecode >> stream -xÚ¥ÛvÛ6òÝ_¡Ó—P'!‚ ÁKsúà:Nêî&›­Õ}iú@I”Ä”"‘²ëÝÓß ‘2}Én|N 3ƒ¹b¢cg2›$YÄ4z²ØžñÉÖÞŸ ‹:¤°õãììõ;•L2–Å2žÌV=Z)ãi*&³åol`S ÀƒÙõÕûi(…ÌxpñÓù§Ùå/0ÕPáüí¿¦BˆàüãÅå[Zzûñšï.ϧIÌ~ýåòzúûìç³Ë™—¯Á -÷õì·ßùd GùùŒ3•¥zr ÎD–ÉÉö,ÒŠéH)©Î®Ïþé öVÍÖQΤŠåˆR¤SŠÎX¬¤2J™m -8èáâŽe‹_”5Í;‡ñ™sYxä×ï"Ñ#œ)&E„ò Å¿mš¶!þ/ÙK«—ÿ±Ý¾¼É;» ˜H5S\;`ƒH‰àcÓmÊzM¼—å~*Ò Xt•óЭЉL¾š†Šó`~莦“P&)Ót -Á2­¥a7ÏÛ"Œ#2nQ/še±¤IÛíI¯šªjnýô³”ш&˜K&*vª(î¾9¯T,Cï $CÊ]ä5 æ…•æÏnŸ/:'ÏÊè ÙҌ좽]Ì8¯-.¨ÇŽòÖ~í¡69©Ò²Xмû~ä@¡H&R'Rqp°0-ÿ=}©/¾¼Ïþñ²iÅ—¯<—_–ç?ü0rl>¤1sò÷Õü€^µd2UNcßÀSDŠEOªú¾¾¼~Ö³‡Ë4K n'¡Š àxâ“`r -ˆ…àC^òŠÈ½/êbŸweSëLjŒÖžÊT2IÅ=‘hÝÂËíÎ ÀrúìÁEŒ ™m_àñ–h³"è¼ìZˆ!õÃà&!ž †a¦ƒç?¿¾¸º²„I[˘D£ÉM^•KŽü¡0Tépÿg®yÞ¶‡-y ,wNUQ¯» ˶wÎ4ت®ÜUƒ³¥¥Oa‚ðšÔ“ZÁ pÚÅ°Û·»tHX µÍ@¤´oš‘S 5æ‡[ãF(˜­É7Š%óÄzt^µ Š‘sè8 þ¨›Ûš†>ª`L\``¸Àw?Mƒƒ…uJ+‡õfÄE*™Š³ÔFÐvK.1⪣Qâc´Ùu+8bYå¶#†ë}¾µ"4ôuǵÂz€‰óDJäY)Ôˆ¡n—y—#Ò¯˜ RPûREŠ./šÝO>>â¯Á†.Ú¯ÁbÎZFNøþاÓÈ (RP‰ž]ãŸiL~šj°Å]cÜ`Ä€í¢Ù3. _h<-ž|èà=7OFu»köA¶¸p]¶[»aÓª¥ãJ0tc,´"ñ¢é`áðb×c6âÎïfŸ¦ÐE¯lfl7vÔU±Û4uaçE·xÜ4Ê›FYÓ\Õ«f¿1N±¿¡Ð„‰QR*Ó‹©EÒôòϲíLŠ{Ê@WÛ| –$<¨wG<•Rä"Àt7cE=b<δÅÂsŸ’Ș҉êQ")彘A'ê*×1a®ðî×’.0 ~¬¨'ÍJé:€¥omœ'à¿}RÓZÛíH –Z0εSCoÁM½‘=†rÇNÔŸŒv‘,Í¥T“|Ó‰boÑo$ òã„ή˜Wëf_v›­Ý»Í!äb©ã7%b kÄýâ;Úž0¤ëÄ_oÆ}ŠN"ú=Nt’÷#kåü6‚Bd>åÓ4Ÿ77ÚWŠàº¤Z `ÛóúFÔÞõ™ÈÓAyÂÑöÑ fò¥ãÒmr‹V€ -Á îÛJA—ŸÄ‰~ŽýC<,ñú©ê¦o›=¦%b+Q¾ÌçÔ»+iªbõ Žñ „/å]sd­{#ÝÛ€h:`¨ ÁµÐÄuPTB@íÕÁÓžßh‡}ãQíÀõ+I| QepXàQbom(MY“e]Ë¡­rpà°œ×uùo“æäh›æ5–¨„é {Wb©º„€cK°Û¹#Õ¶ùÚí(×5yT‚Z:¥Ä;õ«±pD/U<¢NÀº\Ýј¼È ïl=ÂêÏÕê1$CâÒa±WÓ`96hüb‰ž'’#ÚEµnO©Øcâx~OD°üØÝéŸÛ D¾ -B#wo Óù¯mq¿>Yúl^Qï’aÅ4… @çž­iû¬&¸c¥æîä'Î/ú˜öàƒ·1,wf48tö`ÓÌÜÐûýŒ½äúÇœtÐìB/ÚÑ”jÂñ¦ªûáF€²»Z%š‰8z2 2è ï­Ñxëƒ}‡3@Ÿ´ÍXssúÆëoËÜŽoÏñI‰€ã"Ö˜LÅÓi:ž±¥Ñ÷º¶V‘Ši­ã¡_#gÌ%F›3X}Ó±ÙC?—(èw”ûqƒû‚ðÿ”rüí(J˜JS9þ+ þHá{„ -é=ÉÝo.÷Eÿ/~¶ÕAendstream +xÚÅYKsÛ8¾ûW¨jKWY Aðé=9;ë©ÄÙu¼sÉä@‘Å +E*"Åóë§_àC¦wf6‡M*a£4€F?¾†Ôƒ¿jFn”úé"N7ôT¸È·gÞâúÞž)³´ƒ–ãQ¯Î^Ýèx‘ºiäG‹‡õHVâzI¢Å''r}÷$xΛw7·oÿsuÎÃ퇻ó¥zÎÍí»k¦ÞÞ_½u¾TI¨œ7ÿ¼ú×Ãõ=wE"ãõíÝOÌIùó‚Ðûë›ëûë»7×çŸ~>»~èÏ2>¯ò4äëÙ§ÏÞ¢€cÿ|æ¹:MÂÅž«ÒÔ_lÏ‚P»a µåTgÏþÝ õÒÔ9ýžr•êÅÒ¬Z{q]^Ãu…ôU„>Yv©¼ÔUðÜN軉'ý¥øjt) +¦I¼ˆÃÔ´¯éRLQ·Ë¢l³Ue +TLòG“@9qÄ°Ž~×<‚V½Èùz0ûÒ´Üè6Y‡Tèl²o†y+cj¦ÖÍþ\%NâytÃc­ ÝUY)cºûÈDq0¸Xv©”›ÂÁh}š¦NWnMsèZ°­CçaS¶ÜÁßÄiÖ­,E¼~òÆ0Aû2Û¦“­Ù3{‘T7ÝÜV¦¬QqèÜß¼a¬'@*ròf»«Ê¬î¸ãW/ôP5²ê˜=µLóÊÝa_‹´È¹ùp¿œ.È^óþú-ß×è¾Ó–Û²Êö̤CóšUœáj€Õ…L†SË|ótÓ–Mݾ¤b+Ö$XÇžsÜ J¥ï‰©ŒO :*Ž<Ôè±kš4 à’¢X;·2™w2³ò‘ ¥h/P#>¬B·ÅŽýv¼Ü£éȘ€C†ßáê¢ÄÚ#°×YYÉÔ†¿¼ßv×b"²Š­³6!| Ú„†& +5€TÑÔ¦tîÎï íò|$‘(W'N……ÄÖ´mö(Ü<«™Èª¶aj%]dÍZƒŸƒ*™ÜeùÓYm;»úk#ŽˆÆžjQÄ®Ùwl‚i0R"ô¯ÉÜ€[7õ’M¸bêÀ¶¦ž›9ý‰~ÀÚMs¨H×)y¼ö²3-_$°è~à[ÀÝî·emxû*ðë ¼ÅnÚÍZæmfnzØ!† ¥ú0³`e>6¤—~‡Ð±ã5¾™Zî”´ƒ˜_òù¸Ä!¶yØ®ÈÏBÙ"|×p‹f¹kÚ²+¿É¸Aû§·¥Æ¶’1oæUÕ“„çqLOWÇÄ8<×Ùv6ˆëÈU!¤u,+pŠ6Àá:T)©9à´;¦:ÞbFzÂ.•ï¹¡öâéÑÛC¾Á»Šú Ì­L¾~#‰ûðe[Bl (¸-&FFÅBêbNÝàc{´÷Ô›n8Ê)Á1:&q8H2 ‘ÖW ›}ek€xGÕóó*kÛrý4Ùl‚ÁëFILeòåc¬Yüò±c£±4°ÕšéÉÉaT¹]Î%'¾C:K(>¼~üoYU  îó!d—t;‰5ேR" ´úû³ì~™Þzs¯Å§þ®&&Ž9Îp<ƒ¯ ŒÝ@¥ñb Y~ é q5€ÍÅrÀ_èpNìÅ'€î›e7¢¢}!^ìÂÉ&@ð ôã@™ö¼ù¡«áóàÍ¢Õ õ]_ùq¨ìp²çyßÌ´ž–f¿oör9o²Î<6û§™àà!uÓ@$óê)vLÝÄïaàDþs‰ˆ/½PÆæveÁerü¶;“—¿zžŸS`ã¾pI [”´ +!#¬ìÞÀßöJM‹™4ð‡óÔ§<ˆ +ˆ”à·Ü:n„ „Ħ9r$‹S7ðÓÓ@Öo =0eþ ²°áPuÜI€uàœhyhØû\€'*J0dTqVp×BkØÙ/7°#DÑ2uÄñxtÍ÷ ’†q!w¼º½{uæBx&ëÓBn~©“Ä›ã3X‚àÐ4«…$\š&éí—؃wHNηɌrqþ1÷r$¾ãîŠðrh¯Dámá·mROr=¶23—¡E:™„-7Ÿ9;ÔâI •ŒCLj*vÉ–?‚­NâÅvðב1u=Æ$ƒ¶¶X µàRæ(ß*©6¦Ú‰Åõákbµyvhÿ”Å®­Ÿd‚)²C·iöe— ¸“!>Gk*§iY< +z^ï À¦Ïç- 쩃Bµ×+&Ãò"üwY¢¬a¿[‹UF2\ö-ïºgµMuè¨l¥ñ¶ÊÓ#óã•´¾™¸÷gJ…Q*¥ ‰¾@›^hÕ4_„*¿˜¿&|H©IœÒÎÖ¦ÃH†^J@ \lZçÝãñáêÀ!sy fãº$Ö„Í°óåHøÅœì½YCLȪKÿvŠðü2¾øºjÁ¤/“ ) .Ë +J”Kï¢Æ2oÄÜ=­²„ì.ÕEV¬xØR)FG ã2õù0ƒzMz,CÏI$ 2ÇFL>h©F Ó“²‡äMÕÈ“T‡Ç“w®Øɘqjª=ËšêðFÓ(BgŽ40É`Ü&¢šñΩid) +†ãõ*¨^úëev «Ô¸6 +á :)rP3uV1wŒr°“ŒTeìÄÆv‰€çN…Ã(Àcw_ÏËü^ …x¤ÈœgLÊ»qÀÇ6ü¹h&n¤6Ø3Pã8LúxÏõ­‚£Ó<ˆëj-ÞÌ埬A‡µmã¦Fy Ù½’±1’Ú>Ñ “!Òfø>Á½ÓÑšµü¾ÞPõ” ìž”ÔÍ?¶Qr‡Â×¾Jj­œÞó±C^û4•©Ô=..i*ÈÞî:nXyÛ¬Àç°Q~ðÓJR"vŠACrÐ}ªÄpÈ4–“dc íl¶6A /”—œf•­¨¾ÎÊH*ÅF†u…o&Ìꟿ¨¿Ø„FÑk¦ñàãu-ïù_ÎñDЬLV0‚!ôŠ’¤É!¥ˆÓž]šœÔ}á)²/¼'õ=æ!›j¦§åÇÛrM¦˜Íøl* ™PbÙIà˜:¯ Ö*˜O5|Û¯‡¡ú€öjO/!­ôŠ7Àô‘G x§µÆ)?A@PUÖMûä˜h ¢d/Œ—X¤ ¯³ÐÇÜ ¶§&‡H†¢v0’رà–"‡2Ý\•ƒaÁ·õ,ú²¡çBXÅ6°¹#@Ìcvì¾Àý­©…-Ƀ(3))LqWoT¦ørG‹ ®G“ÉG[ýÙgºÈõB­Ÿ=ÈJÍ4@÷‰IŒ²æcØ)Âb@^NÇ ×Tù•AäžÚ)ÈjÛm¶/³UYŸHGYä£w={=êñR^è^ü¿ÞzÀuè&Qþ…÷+;ãÅŸñ¢™ŸöAÁܯx)“°Ä}ýáïw|&ûwêX€wlKj¹«³ãOLµçäOa³e7³îIÑžD7òÈù ,á³* ÁD$¶w[ŸLËVÍ7!%£Øå`n3‘Ô—gûBƒÁ±dhÛMÛ XÞz¢/)«ÄhG¸ìå‡ÍÑ%þ˜]žçÆ~”à § ö‘Îý° ÿDÓ?ü3öð»PûÃäØ°äáRã¶Q*8ôžýÈ®<×בoG¶þ;H'lendstream endobj -1101 0 obj << +1615 0 obj << /Type /Page -/Contents 1102 0 R -/Resources 1100 0 R +/Contents 1616 0 R +/Resources 1614 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1068 0 R +/Parent 1609 0 R >> endobj -1103 0 obj << -/D [1101 0 R /XYZ 56.6929 794.5015 null] +1617 0 obj << +/D [1615 0 R /XYZ 56.6929 794.5015 null] >> endobj -170 0 obj << -/D [1101 0 R /XYZ 56.6929 691.7741 null] +438 0 obj << +/D [1615 0 R /XYZ 56.6929 510.1455 null] >> endobj -1104 0 obj << -/D [1101 0 R /XYZ 56.6929 668.7722 null] +1618 0 obj << +/D [1615 0 R /XYZ 56.6929 482.5541 null] >> endobj -174 0 obj << -/D [1101 0 R /XYZ 56.6929 579.8329 null] +1619 0 obj << +/D [1615 0 R /XYZ 56.6929 117.762 null] >> endobj -1105 0 obj << -/D [1101 0 R /XYZ 56.6929 549.1878 null] +1620 0 obj << +/D [1615 0 R /XYZ 56.6929 105.8069 null] >> endobj -178 0 obj << -/D [1101 0 R /XYZ 56.6929 502.9124 null] +1614 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1106 0 obj << -/D [1101 0 R /XYZ 56.6929 474.9173 null] +1623 0 obj << +/Length 2444 +/Filter /FlateDecode +>> +stream +xÚÍ]oÛ8ò=¿Âo§5—ß’®Oi›ô²Ø¦{ivq@®(Kq„Ú’×’Óëö¿ß ‡”%GNÒ&=„äp8r¾)‹ ‡?1I ã*Õ“8ÕÌpa&³åŸÌaîíð8Ó€4íc½º8øéDÅ“”¥VÚÉÅuVÂx’ˆÉE~½þÛѯÇç‡SixdÙáÔX½:={C”š×ïÏNNßþv~tëèâôýÏOŽÏÏ^NEb¬—žÂž'§¿SïíùÑ»wGç‡/~>8¾èÎÒ?¯à +òÇÁåG>ÉáØ?p¦ÒÄL¾À€3‘¦r²<ÐF1£• +ÅÁ‡ƒ¿w{³néØýi.˜FÁM bköoK[pØÖwMÊâØ$;»N…Š™61Ê„'LÊ­H´è‰DhÅ¥Ì$:VIåd².š6[·x7?HÙÇ[‰ŽaÄ»¸)§°KTm–WÅšúõ5µ³¯³EÑP¿½ÉÚÐóKÖ‡"‰Š¦^܆…íº,òþä²n äv› +ÁRc¤Û¶)Ö°HÁ#$lxê;~ç³ ‹mj=¿y½ÌÊjäXš³TÃÚ¿ëª5c¼³œ3+“‡ž5"=¢«XŒvÂn£0íæ(8HLá ;á¦ò¢-f­‹x0ÊÚ1›¤ˆ!IPò!‹T)S’Çà·‚âÎc¿l¨Ý2…#ŒJÛ誠1{E郱̤*½Ã6Ò2ºúJmVa« "Ýf‹2'`_íRûeYCèÙq³h=Ú5µ‹ºþ¼YÊcÉô/HMÕ<÷”< ÏÚì*s›ÃÃîÑ›W_ä žàP…ã+ÙÉxDdYX†5ƒ@Zä÷˜TOWŸ+˜ý“2%F>ÌL*d +©»‡ +4i½~œQ)-;£Â¾“/´H.4·Þ4Úª‚PjI=Gj7Ø9BÕtLV³zSµ^ÄÎWZT#ׂR€Kö錷aÕXŠ˜Æî3O3«aŸ ÓpÇCûT2ŽÞW…Ï$S˸±;!uV/—˜Ð)­AÁœöB,X‡[ÐýÚ·æM´© Ô4»ZxĬÊ÷ù"P~»{½Ä…gY†ìfN_¿û•zw·`°§³,šQ95Ùüž¸Ô×Îç2"eXbÍ·ØeX±ßˆ¸fiˇŒHI¦M¢¾Êr¨ÅV³"oCöÑŠ°ÝTÅ¿VÞ«ã¸ïv¡ë«Ékãlªz8›ß4CÌ'Ψ¸ÐB¸`‚mgI8 ,{)ELq'b +gveÄìÁ´Ôö›UùˆDµ/¼§)ÄVÇtÌŒÏ'VìÕ1øÏ„µå>üŠ‰¥€•_=ÆQŸdåbãeEojœ«4)*—ÞS"¸ïwpü¢ö"p ‚ZŠSO. “$Mz¾< +׎GÅ}!„ðŒ@ïNçOèý)@] r+³äÎi:¯öÚñŽ. ÙÔoeÓ¡†q¸ˆXG.#±¡¦Æ^^V{B7Ù­ŸÌª¯¾3^ç÷Òšm:?«]›7ûµº¯.OSÁê9µ@\<¤ÔÀBœÆ”}\—U~ ûjo-TH÷ýF‰BÄPµ%"Nwp6´Ùhd­ÛlAŶ´¾Œ£ë!‹.ï °¹™ß`‰Ùå"®Óñ½iK÷î$V„?ª<3àøÙÞýÿ±ßS±‚ É*е,U’^[ ù ILGoÎ>|8~M0WÖdxã {-eôûa +GÒõR¡ZØ›œby«;×±ÏôprWâ8é%>sN‘0Ä;ׂ³‹r9þ`H¥Ÿ1Túa;ê– Ôù¨æ*íyåP\%ðñ +Sm8ÒÂo[Wø䉽›lµ**ê—cÙÈ4I>™?.>x¥$Nö«{_‘žË#nþú’€kbï|Iø¾UaS¦b ¥,KâD÷¿@Üù¡8 É4ž`>Î$Wº3©Á}†Ï$J@‡“A¹wÄà‰¬‰òâj3'Ø¢¸- ÉÁÚHQS¯ |SÎ1íćí˜oé4þåÙX 44Ê<Áö¦n<½eš°Ööy4åXñØ]­Žðz>wU L\SÀœKŠG¬³«\|ÁãRf×ûp|~:ûû åèôFµÍå„ÚR¯*æàn=|'/GP³Á‡xWP5žÌ?Þ¼wtzæ¡Ûç ㇎М&sgÑ= +=ÎG<@xñ`aü?hÕ÷IXÿ%,˜„u'a=.aÿV-ÊÏE@ö쪾õÝP«ÿ¾Ñ1Š]õ‚2¼íùÝêN¾zË>¾È9öØS!½£BlL¾>%,1´WÅ,Û4þÁÊešØé½'bzw¡§­*¬§6/¯«™{©C û¢„“^H¸¯_ç–.]ݬŸ¯pwUÌ»qpaA*®Ð\OlÜið{¯ø©Žóhñe]xæ>´Y[,é ~ë]gËe6Vã ‚§,Ö{î¦ãqî)¸%f½o^rmˆ²b q5R&ÇL%!Çh†üö¯ènàƒÅã@+ˆœÍêêzd+™Äô>”â\.Š¿Ž…R µ³HÔÐÚý}â‹ñœ*…Ê~`&—„±(›¶¨¦(@ZàšrõÉåÅnp¹ª×mÇÁG½tÔcÁb%†Úzùmd\Øæöà?_†¡«Þ†Û Îp[_¶½Oxµƒµ|tUSdkôÒ½cSò‰ª»k—÷OßÏ9½š*¯[/$ª†§ÙŸ/÷ýêÒ$ü©ÂÈoxg…OþEÄöç"m ‘ã)F—Šx¦s#v97P›DÆ#¬ÿP4rËendstream +endobj +1622 0 obj << +/Type /Page +/Contents 1623 0 R +/Resources 1621 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1609 0 R >> endobj -182 0 obj << -/D [1101 0 R /XYZ 56.6929 277.7919 null] +1624 0 obj << +/D [1622 0 R /XYZ 85.0394 794.5015 null] >> endobj -1107 0 obj << -/D [1101 0 R /XYZ 56.6929 249.7968 null] +442 0 obj << +/D [1622 0 R /XYZ 85.0394 220.329 null] >> endobj -1100 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F41 939 0 R /F21 714 0 R /F39 899 0 R >> +1625 0 obj << +/D [1622 0 R /XYZ 85.0394 191.1908 null] +>> endobj +1621 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F22 953 0 R /F21 930 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1110 0 obj << -/Length 3204 -/Filter /FlateDecode ->> -stream -xÚ¥Ùrã6òÝ_¡·•«" ;OžO29&Y²[©$´[ÌH¤BRöx·öß·/ð©8U[®2€Ðh4ú¦ôBÁŸ^¤6P&‹IVi»Øì/Ôâ澺вfå­Æ«^¯/¾|g’Edq/Öw#\i ÒT/ÖÅ/Ë7__ý¸¾¾¹\…V-£àrecµ¼zûÏK­õòêÛë·<õöÃGî¼»¾ºL¢åú§›k„¨ ÖEA,;×ß^ÿ|ùÛú›‹ëuOßøZ$î‹_~S‹®òÍ… -L–ÚÅ# T ³,\ì/"kã!»‹ÿèŽfiëO¬I›†É SB½Ð:Ȭ '\±Y›ÐW`G`/WZ)¸ÒÇ÷_ñÕ¿uOÜy·®àîÕfãÚ–ûoêªkêÞN G¬W‹UY¤#Bÿúýdkª—ùnW?âö4\¾ÿQ`EÑ\êt x]+ ªàN“W÷NÖw5Ãn·íÁmÊ_• -‰6XPV³_õ!Ï°!!AÏç‘w]EJYÚÅ -liEiï_cñ¯×MS7íËN“mN–zäýnYÝ3ŒŒ‹Ž½½H/øÐßÃÒœý&Œ6yÅ‹ÅËwO¿Ä­îÁ5ùŽ®áã4èa–.ßßñD~öÁÖò)-‹ -@H‡U]‘O%ë9òFr‡¬úcÞ 4 [×a}}€ŒüÝ7ß_ßÜðàWeÕ]ÝìóŽÇ=ý0¡ôXîvÜ»Ì|Jwlà*‚x»‘YÖ¯€$àR¸sWÖ€zP°"û&÷c§"æšuµ@O¦Bo!C»ôm>&M ÀôÒÐîËvSWÏÜ›U 7j ÜzÂíˆpØxlխ̺ÏÐü²#ó -ã/]²Ú㪊…â£gÞqlzÉ4±Ã}Ü&ž`xæ GKæ2!´(`:q76,-09–œðwƾ°Üa\2Ú=’XÚ!c}­«¸=VŸªú±â]è90?Ž›(e6#\ÞêÑ¥ d)!„Î#’cf8öXv[Xe´ „Ž\ϨQ¬„ð^¬y¸© ÇËZ× ŠšÛ×Wo1)Az†¡Íy‡?BO8ÞƒÐ?á Q¼[8ƒáù9‰È»c†Šá¢¨¨F%Ë¢&Ì#…BÐC¾+Ñ5!ŸCñs?á3l>ÃÜ­@z>T£‰\@#ΪdÂY˜Ϊ„8;£ÎÄçÈ"ŸcÀbq“"ÆboÌâhPL쟰xØ=°r“Èò,\¨ÜËmYøÁ·|_\Ž‘]6Q…l³çf*™©žÉZy&kÅLÖCtųD˜öï¤{ÉR٘ų†Âbí…W³‰À˜º~ÿýõ<"Ë:9A.=•#ñÍ:s%N€¯Åï`9íUKúA¢ˆ¶›q|„°ó„ŽÇE!jÛBœEæðÀƒJJY -xLÙ’WOÜ!N'º/$»hÁ5/ÿ·vD 1kF Ñïk™µâø0VóA±; -?ü°F{{õÓúk‰ƒû5´ÓG ¨êÊ ¨bØF¡N!YJ¸b xÉ|„ãã_9 A1ºIƒ8ɸâ0Zž¤Æ6ò 6»Æˆöl¶yU¶{†ÞÕ ÃÞü?ÐËos÷®rè%)^Â%âзùÈÇ`ÌFBtœ¬Âd÷X3Jo•Æ¨l¢ŒâÓÇQûû›Lsƒ=q¡ÐÖ %ÄçÜ ‡´'ö},ˆZf€ÌVýäQavYŸÑ¼Rö’½ï©ÄNÌ”¤'Ù‰‘IOŒLæ5zì\ðBBâ±õ×åè›y&%±¨Bñ<Ǥˆ@>{kŠMžß/ËÅы׋uêߟ©¤ZN[û*“qúº°÷,…Û¹Nf'Œ 7äáË>Ì ôTÒn}¹Cù¡¬­/õ†JÊ+:4AƒÞMò…y™UZ¿hQe£9‘6– &µXQfƒ‰CJba¸Ù•¤}Ø'[ -möùå« -òO£½ƒ†œ’Ÿ€º(õ—è7“ò3áE€4qw”„Á k¢MÇ'ž*?ÈõMIÕA0 -hòZŽ.Œ¤÷†Ó{lˆ¦,\®Æ!/U†ôneµf…ÍP¿eÀ,B4ƒžÀDTøÃÙ²“X¶á²!!àXLûp5Á„¶ËÑò1y³ÁȤqV 4ô…Ϭ´Jå;ä -ê!ä”o8‹µlª¦ÄË«»Ž¬˜Â4’ ô¼û‚+(·ìÄ`ã!o ¬)9¹X\Ê -ç\%î eÅ%,ŒùèƒH–¹ O+@C›}é]tLôǽ¾¾Â„Ì +Ýç|#ÑÆÔðöHvëã."uóJ™bÍØþ…0ÇúE'¯O–ÿÚ:‰ŽR.“N·HºÆxUøïÔŸ“…FÅx‰¼Ô¦fD¼b¾õLäøO&±Cd‚`/… àì'‘z.?Gž–‚¶€ŒäÁÉn²7$©">$&P¡ §l‹ÚŸÆûRâ‚Dþ±Ï=SÖþDš$Æ :˜#w“ NÀꆢ7¼ýðñãõ^;9Š ôy,—’0&5‡–a¹ š|1ĉR6ݼ“Bk¬ìaî'47“[†™ÁîõŒ*ƒ~±åÞáx»+7_‚5x`3 -0ÿþ†Mhb&C¼_—#ügWœBëÆJ·“gçP»× %àû¹Ÿ9—ò·ùÞIÈ«Šìºùv!ú/'í+ï—ˇrçúˆ£|HpÒõŸpTeÿUfø˜ìËøýÉ'šÙj (½áj$Xý)óq¢av¨C©´šh\x¡ê/†Û/‘*/,’\ÆHÙ Cž/èî¸eêM$Ô’"Q[ EðtéÒW#ûÓ€eî‰ÈG¾:áS_ßµ¾JCLëø®sûÃIο«Yºø›dñ¥_t›y -®!μ Óå»áѧÏ=ÄÚ%¤ˆ«I9xýæGÙÓÉ'®};­Wôc€–ÀG|'Ÿ]מÖáKaW×;|–‡ƒ´!.–zÙi êÃK!bþŽ'îð™4Ê$A˜j³UíÙ¼àh”ísŽàÜJŒ ðW 3Ÿ²Tÿ êÿþ±Éðëš( Lšžù&Ùc†Yâ‰BÂuvJyÿ«”ç¤ÿWuJpendstream +1628 0 obj << +/Length 2008 +/Filter /FlateDecode +>> +stream +xÚ¥YYsÛ8~÷¯Ð#]µB¼vž2‰“õÔŽg×öíu¥ëž^?ëß8—uÑMMœ´Î‰øµK×3öä¨`|ËL&*2†n7NHŒ„DÂâHa,(CöUI(y‚Y0RÝÞ5_ +/kjôm½kÏEì¡ÿÈíÁœ!ê´2÷:Ý>êÖ.7ôLËÎQ™Õ—Z )=Êb½éŸ4þ%†5Ó”VÙ 0‚@’¾÷øÖ‡ðP‰d*ñ‘¯˜ïG!Ö‰ÖÚõ‚ˆëQaør,Ou'çH+æèFgK4Zü€Åœƒ¾ +°Nu‰ò D‡~Æ1S!‘”Ì¥š…ZŽ¥Ž½;Ò…Ö$Hz° „’7UúLăaø^µ+ûb[Îb‡Ç,R òÿ€'d± Õ!x:²³GOQ¯Éä¤â(3­8r¨âÉ?ý†Øy±BÑ• jJ Â*FÓlP³Õm_èŽQè3ùò•ž‘œq‘¸¨‹®×õªy¹òY4×4~àu[¸é?4h>ª#F³"Nšç6þŽdoÓþ(·mÚ¾£zâZ¿I­‚~SXù¢ëu¦;‹ãþ‚u²fÑB*™&nh=!¼<Õ"énÓìÊœè4Ëô +nþ±ÓW›zÆ»\£nè‰ÁUXÑ}¢ò¿`·‡#™D +²à„wÎ4Û, ¦QÈ€«ø(¶¦*úÞ˜ÂÑ:õ9OEY… bæ°‰TÛa즳˜0a5‘Ófk“â Xƒù¬’Ðbè±ÐOs ¦Ðÿèh2ö½‡¢Î;")Hío|¦ô(‹sá0¼i"ÇÞ(n& +Œ›ÖŽ³lM}¾º!w…ÎMHÅT »3Í4æÎ=Ü!¤4B[k"¬_Û¦î4 AÀý’^¬ ™®oÏco—Q¥LS8­V¨3RUZ×&NìËŽx)=ꦭR«‚&¤}vŸöÙÆL2éZpe&C‰4Û«jÀªšbÕ÷{Nßçv‹…å\¯RÓ$CÙGÊ}…]az'¡CƒYLãlˆúQh†ÄZÇ­iM+º¥YÚ†'AÓY±o‹õÚZËZÀ½„Jxë´Í63]à &•R3] b>¡—‹Ç´ø¹*1©œ± :ÃÐßgÚî JLÓÃÎðA÷Ù‡Ö4 ®f $ •pj|žx—=ùn÷±Ç"×6Ê”´— Õ¬¨ÓüEò`žçM•ÂD°nS@Œ4Ù2ÌËv«ëÜ9“·a@–i_> endobj -1113 0 obj << +1631 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [418.3461 611.3335 487.0181 623.3932] +/Rect [491.4967 730.5319 511.2325 742.5915] /Subtype /Link -/A << /S /GoTo /D (dynamic_update_policies) >> +/A << /S /GoTo /D (lwresd) >> >> endobj -1111 0 obj << -/D [1109 0 R /XYZ 85.0394 794.5015 null] +1632 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [55.6967 718.5767 89.457 730.6364] +/Subtype /Link +/A << /S /GoTo /D (lwresd) >> >> endobj -186 0 obj << -/D [1109 0 R /XYZ 85.0394 769.5949 null] +1629 0 obj << +/D [1627 0 R /XYZ 56.6929 794.5015 null] >> endobj -1112 0 obj << -/D [1109 0 R /XYZ 85.0394 749.4437 null] +446 0 obj << +/D [1627 0 R /XYZ 56.6929 769.5949 null] >> endobj -190 0 obj << -/D [1109 0 R /XYZ 85.0394 597.4103 null] +1630 0 obj << +/D [1627 0 R /XYZ 56.6929 749.3309 null] >> endobj -1114 0 obj << -/D [1109 0 R /XYZ 85.0394 573.0707 null] +450 0 obj << +/D [1627 0 R /XYZ 56.6929 523.534 null] >> endobj -194 0 obj << -/D [1109 0 R /XYZ 85.0394 410.9267 null] +1633 0 obj << +/D [1627 0 R /XYZ 56.6929 498.8411 null] >> endobj -1115 0 obj << -/D [1109 0 R /XYZ 85.0394 378.8211 null] +454 0 obj << +/D [1627 0 R /XYZ 56.6929 429.268 null] >> endobj -198 0 obj << -/D [1109 0 R /XYZ 85.0394 204.765 null] +1634 0 obj << +/D [1627 0 R /XYZ 56.6929 398.8008 null] >> endobj -1116 0 obj << -/D [1109 0 R /XYZ 85.0394 171.4256 null] +458 0 obj << +/D [1627 0 R /XYZ 56.6929 365.2487 null] >> endobj -1108 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F14 740 0 R /F41 939 0 R >> +1635 0 obj << +/D [1627 0 R /XYZ 56.6929 337.6865 null] +>> endobj +1626 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1121 0 obj << -/Length 3252 +1638 0 obj << +/Length 1135 /Filter /FlateDecode >> stream -xÚ­M—ã¶í>¿Â‡¾·ž×µBŠ¢H¥§ÉÎl²I»ig&=äã [ôX/¶äXòîN~}¤%[“M_û|‚$€ø -g~r¦ó$/ÒbfŠ,ÑBêÙjw%fOÐ÷õ•dšE Z ©¾z¼úâ­2³")ò4Ÿ=®sÙDX+gÕOó,±É5Ì æ·ïîÞ\/d¡µš¿ùææŸw÷׋T "’›Û_K)ç7ïßÜÝRŒ"àíÝ͵Éæ?Üß=\ÿòøíÕÝcäp¸ )²÷ÛÕO¿ˆY›ùöJ$ª°zö"‘E‘ÎvW™V‰Î” -˜íÕÃտ℃^?tR*R$©ÊÓ ±¤r&³DeÐ9”‹.`R­ƒ\@BD¹À–``:§˜-Ò"‘R~Ä›Ãó¾oŸå~S¯@&E>/ýÆ5}½*ûºm×®ñ«Yp€¨›u{Ø (ꎾû¶ëêåÖQ«¿–óÍáZÚy{|Ú0nÃq²·:êþ™Z? -ˆqU WEž(e ì§ .–°îå&AÐÖɤ0¡D¢Ù"Ó ÝTÛÙBÊ,&õýîSïšvÒ½T>¯ÜÏB¤«°™Â^é{ÿö jž ¥˜”q)â2Æ•M5à;5X£`j/)˜¥s+PT®[ê¥ë¨I2¢•ž+O”qöcÇ4 Ü»’‘™wõíàßÛÆuIaÁÜ<ý»Uû+wÀ¦ž÷-¡;×â¸'DIÍ° Ñ€=¿Ô‡KLT*pCÞòÔˆ3uîPãþ=kÆõnϨ` ÂîŽ]OÈ%Ï·n·Ûö£«@È™1ó¯Þ½¿%‚b,Rx·©ã¬u¿ Ìp‡r‹ »n·LÑoJ^lÄ4H¿"Úº „5ٓů\×ñö#óf<‹û´ß–uCSåqª];$ª\_ÖÌØÒÁ>¯‹tîwjYk0ëv;e«²sÞªóÂÛ”?*™•,KÒ \•Åfâ4×ÑE¦˜¤Ý³-æ6Z7}GpIŸõ8ñжF-¥yFÞÉËC¹s½;tx´ž¿o{G]$e‚ ‘¤I2¿ë "\!úÕ={KEñÖutôµMl¦ôؼq§–Ì(eUBÛO‡ˆíá׺y"lÅK®úöðLýíálÀw{·ª‘¯e Y>Ÿ]*$µz¡ƒFª)è$•6i--3äp¶Û!sÁª‘)8{W‘l”‰É ‡Žº :NIš|"ü®MMŠC’ã†6<æÂM¥…¬Ç“+IuÎÎ k*·]K¸%÷Áº»csŠd@–qÇU»ºc=” ´Ž:½É‰öå=ïä¿h¼Ì¦ÞVD†.G2/0mÓíê~Ê¡µâAÎ KÁà—ùñ¯|(UäN9,fà -ËþÈ=¼gÀú¦n*ܦwòˆ~&4ÇZ5fŸ×¡žµß JjÇc¨U¹/9–+>x]»ýàxlqÂçô‡k;g¥ˆyíýUÙ—xì¥1{C'‹ b˜. -dÏ ¸fŘ6Ýrˆ\3rêl™"ÉrkCñ0íí²L>ÍyæþŒ³ÊmÝS´1à´·H¶‹’K -™åÃPûÖ»,·>,(1ú\;Â{¿„ß(J$A Þû)ÀpÈLµä@Ÿ©›ã$t»:¬”Η“9ѦÀl¶Ûgj¯ÚÕGñŠ¦á‰üŒÖ{ÕMÙôïQ•¿"C=EMѵ5,”1]¹l?D V{ëæl˜à÷´—°¦!‡¼ú\XåÛg&V’óç¯]Ù@ï}?ÎóœÔ²i(cƒgŠË -ÒíÜlPUÓÁ¹^À¾Ÿ\31cš!uåLòóÝøÀPúáwØÒ÷‰8>É•½çÂÚ$—fìCÑÛ@Z2LØ°Íòˆ=LŠ¾»ô£¡Fì÷*Eºvz<{6ˆ,^*½}¬}ºRŽJPPÁŸC?XÎWýp…×SFYâ éžós04æNêÀä(€ÄÍ3#É<œ|¯ ž· bžÿ81K MùÁ1ÐAnDP¡I._Oy]ôÞV…¡õÏ{†¨>8³ÊÜ&…ˆÕÔß¿¿›0F¨UZ_øš¦£ÀochÉ+;6ĤՓîä­<ÒÛ³UQ¿»k*Ç pR+ ¦_ŒQ%ÙyþÕžex«³úÖBµ}j!¬nvÔ„Ê ,uh%‰ð?§i¶ƒ½–”É!Ê5øÖ»ýÖ£=ÒjH°àu¿»{|û7ÙÍ6P²¶ (Üä„ñ†3ÿpóðÍ|))""ª„¢ßB‰ÆLÛ…³(écr õt?ZìÌK¯‡®ü2¾*á­*$¦>/Jܧå5a^Ö_“„Âuü%OjT eÁƒ -£‡!tìF9ø™EIßȹG.é {cS{‹÷ЈËdÚÉD}]€(1B«ò”~ôAVÄzÃw¬òÅ|Ù—WÇ•«¾œžÌER@-ÆâønÌ×_…Е©Êt‚Ú˜È[Lž%‚ìQé €j/i ®´%¦c<­5ß´œ „=Éütí">Ê~°? -«ðF­|¼§v°ôå? KjzóC /Ÿð2'AÅY²ùS?ГÐòì1xao?¤÷[öJ>Tevp56s™ÈtÚʧìǪ$·y:¸ÂLÍŒ<–n¸š¢…)Í2¡Þ¼&Œ$uX4òÜjžG_ôáàNׯ’áš¾>Ì KÈYz¥ËbØÊ,Gdx -¾!'D ^6°zq_΃Åxrr%€Åéhù‚7‘Ö$& î,O‹D¤ú$a´ëGœv´4çL¸^Kß„ÅŽïþÖ$åzšö¶s\n!–Pv¯€Å\çeyɸÇ=f®M‡Zÿ…“æI&äÔæ&Âè£Gû!”þ*"Äb¿ £­ó 'ñ;”’) ºaÛA,—Õ†oÅù  ØóíÝ¡÷7|Ø‹¢Y!Zö甄¨ê5ŽZ»Aá:\‘}OJ­ÐÞ•<sacá8ˆ…‹©øŠòÅ :™Ïg*·ùüúÐî¶åÒm'TX€KͤÌê \ü²! …ï“¿Ì ¤oß@A_ZÓl»å=o¨ö¯>ž.gL0l–Gº½0&HÍ <¤4XÞœ8G:.çßõÑË'76Ë®ÞÕÛòK• q‚ÄV韭r`ÃÆÃ\Zy^äP|°"œXSþ¨ Ñë6í7ŽØ%SÖ Ôá>¤–/Ä­dgiC ƒÉ€‡?‡«í±¢ Cû’[S©J”Ðê3‡Þ$yaóÑ©ïh•c‡+\J2C0÷¿¼{ÿæï?ÜN¥õCªaÄÙ;Þø´¶û³ÕrÊÕòxš˜rÆ"üGÎgÿ_53ú³ß§ç42Éÿ¾fæšó”ãôlSøܤ…qÝ܈·|qw‡¨›¨:i†á=Œ§ø“¨pAw~à—¡â­ªÐÑÿèo@ñ?áÒ–ØŸˆ&E>¬°±+llàqê¤Q˜`<(ٲ뎻8KmÅOçHè딂ÞCý;8\8tÕd0ÉÀ•ª|PC'Ÿ+»¡–Nt‘ŸbèÂ@ðGü ªˆ r¬çÊ­Ëã¶gu•áat‘ËRç·Nù–‹Ë<ÿýPB>‚N¥Áð–aôˆô¹›ÎqÖžL\ œeuçÑ„®Ú‰ËBý)™ŽžÒ¿ÇY%œ­p;€pP'¨qü~öJ´«T/j7á—ý)ç‚ij‘Ÿ”Œ‡^^ÎÙ Ñá%ãHž1û^¹Ðÿ<éíL’\ ÐœQ/²T&™ÍÕÙ»tÛ¬?ç6ÊîìÐ×&VÄý´wˆQ|êï@•Ø9Šm¦b7iò¬Û®ä™Z‡†+V(Vú*,pŒØ^’C.Õ‘ç-zÚCM†(•ÊêSÌQÔÃ8ßBë•/ÀÆ\Ę y‚û ;×ȈiùM_ÊüM0Š +eSÆeÕžß<é»bÓ4Ëñ^.ÿž£O¦PÙh¸VróMÆɱ¾½€9®ä5GC«ƒ.z¶¹)þ\™g:°F„çqÏe.U(2¬«’¦© håQH®R¥fì~§¢ÑRî+µ8[¤sŽ¤SÉ@›)1i4àgÊ8:µÀZጢ,U{^ÈxôŠ×;·ÞÐ1Ù}¯ÁZ(n1‰Âj½vñ Ý_m<è™c¹ïî%[]ü@΂o~ü˜xI0}î®R^oE[]Œ6¬ïh—;ÇÅ +¸Z1U`å‚„X$PÍ ‚Ks>´V¥÷ôO`‚rg¿l¨ „jn¾ò;ÃnQCrHE\ÚéÅb>ªz/{y%²TU|—ž; +Š:£Z­À/µ¬ÅºÇG´®ÎÔeö9Ä¡ êQäézH¦ü»^;ʇ· ¤Êsæd¬tYõu¶Íˆ=•+$°¸˜ÞK¢Ê´#—Ëüûl3Y”‚¼¤j†š·tMã SŸ{ïD|á¸^ÛI™ë™ùñV˹–U• ï>E;1Ž&¦ëûNu@æ8µ2×›¾LÊ rΞ{yuÜö:ôÿëíšœendstream endobj -1120 0 obj << +1637 0 obj << /Type /Page -/Contents 1121 0 R -/Resources 1119 0 R +/Contents 1638 0 R +/Resources 1636 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1117 0 R +/Parent 1609 0 R >> endobj -1122 0 obj << -/D [1120 0 R /XYZ 56.6929 794.5015 null] +1639 0 obj << +/D [1637 0 R /XYZ 85.0394 794.5015 null] >> endobj -202 0 obj << -/D [1120 0 R /XYZ 56.6929 769.5949 null] +1636 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F22 953 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1123 0 obj << -/D [1120 0 R /XYZ 56.6929 748.4014 null] +1642 0 obj << +/Length 1187 +/Filter /FlateDecode +>> +stream +xÚÍX[“›6~÷¯àÑîŒT]‚Ù§ÍÖ»ÝL³i\÷ÉõxÈ»j08 oâ&ýï°Y v·Óñ–ÄùÎwnÒAØ@ú‡ fAË!ŽÁ2„™á­ÈxÔkw\¼v/ê[o¦ƒo)7èXÄ2¦Ë +– ‘mccêφ$p¤ÐðæýÃíýÝï“ë7‡Óû÷#@ÞÞÿ2ÎÿÝM®ß½»žŒ¶Þü|ýët<É—¬ãÍýÃOùŒ“?^ŒoÇ“ñÃÍx4Ÿ¾Œ§{[ªöbDSC>fsdøÚì·©c3ã‹ ˆ‡«É(d&¥»™`ðÛà𲚉6ú#H¨EhâŠm-¤¡8s E Í8 ¡¡ûI<[`ã¯Á:ŠU’ÏËéÌ"‰Ê‡_åÏyj¿&0†c¤Š˜¾-B…ùpVåÿäzQæ5m®ïÇ"I+WyOçªÕƼºf\Õüy#â-H¢Mì‰|æÄÐá?¹6©–|ô=ÃÃÜ”p¦a!7)ËPÈ— + +  gk[RNÌFG”&V•W,/tc`\çIwÝU¿}/˜qh#“©‡A‡s«yoœµnóÆ=²í<;àY;d[UÚp°U©šçQ%ˆêŽ;Í^ @/·VÐ^Á­9`Æš[»c®']K†˜#«;ÝŒç#ûðì˜m}az|¾èóghÍa¤är |¸ÛÝþåE¡Ÿ4PjEèTKeïߘ ì¢ÅœBj:Í Zcyº’ʲ|¢w0$6ámîT‘æêijsLÜ ‰@ŽTûTÔ¬JS[ئÈ6…–~ 7x³+Nö€ÖúÅúw)8ÐsԈȯËÑ#Hä_âŒFæOòPÈ¥xúo‘¬…×á¨ñ"ÝŽKvŽ„î'ÝKä—2Ø5„ë­Œr½O—h÷á†2|g¶ÄOÂÕGáªõDKÅ–®'Îe ] t?%½ä\­#~Ûnw.ó«¶xèÚ(ßí UïrãD(Åþ®—+в™ã ÏZW+´,Ô–;+W(œñ…z®÷ÔQø¨œÏ•Mä#ÐÁ—¾TÛÆT(•æÝkL¦;ÓcV%aä×;þÎ…VEIŸ®Úħ šîp)ƒéÅkÃ+ÚË_|¿[^~›ú<·m²¿º%¤ruK¸ M[ƒ¤Rs™yÄ|w|Lý¯aGendstream +endobj +1641 0 obj << +/Type /Page +/Contents 1642 0 R +/Resources 1640 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1644 0 R >> endobj -206 0 obj << -/D [1120 0 R /XYZ 56.6929 549.4516 null] +1643 0 obj << +/D [1641 0 R /XYZ 56.6929 794.5015 null] >> endobj -1124 0 obj << -/D [1120 0 R /XYZ 56.6929 521.7105 null] +1640 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F22 953 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -210 0 obj << -/D [1120 0 R /XYZ 56.6929 231.5025 null] +1647 0 obj << +/Length 1337 +/Filter /FlateDecode +>> +stream +xÚ­Ûr›8ôÝ_Á£=³¢,.Ó§4uºél“nê>µ ²Í#Šd'ζÿ¾G08$ÁnœÉ ç~Ó‘°aÁ6|bZN06¼`l #\,c ß> p‰ƒ*$ÔÄz7¼¹p<#0×vé¢ÁË7-ßÇÆ4ú6<ÿûìótr3B6±†®9Bĵ†ï.¯ÞkH ç×W—¾Þœ¼ñpzy}¥Á7“‹ÉÍäê|2BØ'èí’×ÿLôêÃÍÙ§Og7£ÛéÇÁdZÛÒ´[Ž2äçàÛ­eD`öÇe:OŒ;x±L¶±Œ‰c’±ãTdðeðoÍ°ñµ íòq|“ø¶×áÀ1n8[¾ŒÏðH`ºŽíü6B®e E¼DðŸÆéÉ]Æ44ݬç,×ë·úq«lÁc3 Än2YÇ)Ê9—¢I݃n#Šï¥ 3žÏRþœ\ܤÏr¾£N=¤çìç† y"µÌ•(ÌHd4d§Q8-r&VHÆë#@ï_I¡‰ÌwG±Àõ8–EK‹ŒçR¯âl¦^zÐÐ(ŠeÌSš EÎ׈näêÔxò +i¸:&¸í£i<"¶« ɨ\ÍRZy§gp - RXU·l&2®Ðšf‹ ¹"˜8>ñq"¤=üOÑv¬Áß-buzé—~Ì¡^~ (¡aM“§ÿÕqR&Ì +»fI,ʬùÝà†[ê}ùyë¢ j'¾¯Ø+:Û1ÕÉ»4 +“˜¥U³;M›ƒøª˜¼šqì>L6{5õÄfQ;§ðVɬW‹ 7¹ˆ· 2%Ùõʵ–)“¦›u†«6îí3*©€Ë·UÚ×æ‹)„BžJÊÛý rå9á2Ù°Ãâ9kÍüZ€«ë«ÉQÕÃ@O´‰²Fëxn{~ÔÌû“¶Ót½„-©ê¥ð?“¤ÊÔ¬¤ôm“°›ç»„/OmüQ,èìŒ,“ÅìÙ£;¾}6vM•’˜*ÔÉòõÕ£3žÂY/ãIîZìÒ¨>ì—0>¤­M‚ϳ6ä¾Ù¤k´ˆJÚ…{IM‚öó»#䇮 øøæÂÆFmöB9aìÁyÜÓmu»€ÝÂpã™Ú…¾Lø"©dkh^úõ=ûnYvZ>4zñUÐ%+eÙ£=ˆ²‰‰¢EMW¬V¨qþ‡ã¸€¬p* 3s\ÓuR≆rŽ3L ¼jµÉôs™ð¹Ú=Ôzo¼H®žã᜕B ·j5ß駺¨1õrºŠK²kZ"«á˜æ¥œbŒÐ«éÈ¢ÔÆíÌS‘u\wHÕÃB#U¾]nrª½«¾)HÂ@—ÃË…Ê”<ö‡L*åZJ‡c]ßôƒ¿ìY––wèÙ¿€w@ ÊZVíD%pžðð‡^ÞÅê0«0´: Ó¸z ¡ÑŸ•ã –â© *‡˜êV©ã:ɪSø/¯ö7{PŽïÛõ½TÛ+–kúvàUJ)ßr¨y}ËõXõÿÿ±[Lendstream +endobj +1646 0 obj << +/Type /Page +/Contents 1647 0 R +/Resources 1645 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1644 0 R >> endobj -1125 0 obj << -/D [1120 0 R /XYZ 56.6929 201.1114 null] +1648 0 obj << +/D [1646 0 R /XYZ 85.0394 794.5015 null] >> endobj -1119 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F39 899 0 R /F41 939 0 R /F48 953 0 R >> +462 0 obj << +/D [1646 0 R /XYZ 85.0394 122.4687 null] +>> endobj +1317 0 obj << +/D [1646 0 R /XYZ 85.0394 92.1609 null] +>> endobj +1645 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F21 930 0 R /F22 953 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1128 0 obj << -/Length 3056 +1651 0 obj << +/Length 3032 /Filter /FlateDecode >> stream -xÚµYI“«8¾×¯¨è˸¦º0’X£cÞž÷¯Ý}À€›Å¼NÌ-@Ùõ˜yýbbÂD*•ÊåËT -ƒWÿÀ«"r,“eNUïEø/®çaÿ(rI÷âÑPJ¡y2¬tŠ=öÖ-¶’”˜d ”Ì8§ýÁóгâ'¹7 tÏ»= 3½ó—…8%ͱâl_ªˆÅ6:Å–IÌÁnI-ø€Ãa„Ô+€˜)vM‹„RâXéL*.HØõÑMß Ü8‰ô$Œb6{q‡ÍÔ£÷!â9AP„Ô?ÝÆ*.ð· pªœ¹û^äÃ(—ëFl3#Œ˜nñ! L7° 6¼Ä)‚˜í7-Ø -ˆ$?2&‹&O3Æ[ƒlc=ažDªÌ!QQŸ]ùévœ6Ô}d€auzœÀ~Œnlx]âTÊ~YF¼Ì¥º‚×|›-Vò‰âe–Ï$ÎKžçKµ0 °Oq3µ¢³ùËØnˆ}Läho*,% Â*êÏÊ7ˆ âp1©£ÝgÐú"! ¤\I*ô!P„Kú!ÅÜ!rõÄ¢8Ç|Œ¦(_x† =ëžkâ°7œéA|!0¢SîÇS!6 b1Û¯äMýÌÿ'€ -8¨Bðý.áä…bÆMŠc‘HNP}–˜êKhTrŠ,dÅ%<|°´ð ‚ñ­|©X)nO,܃nÒ2‡i$ð„BRÂÍJW‘¸³jŠ_ò(§kšªdÆ ±ÚÔÛÅHôP G$"˜À>FÈ&0Gº¹g陊¬L…¢7r ¤z`8¸¶e˜¢†‚ÿf#/(4©LFe%žŒô¢hÜm¨bŽ$ÂR-󃂑N…yélŸoeEÑ -ê¹(q²$¡GPsXÏm‘p•“å\®@Ù¨âÆB’¤çìú±Ò2òŠT{ìà’¸gÈ–ÑØÇÆ“IÌ[rœ.RèS=`èèI&=Á)/VºØÏ–¤L$NQœ0>Ï öŒL@õÄgD·CÚ‘~p\ƒÁ>3ç õ†£“µPÔòÌpD„JÚa:õy.qgÁ{>AEù‹ØÀIêC Àš#,üûƒŸ’©/ÙM^?ÏübZ–ŸéF‹~ZW—B^M3‰Zà“ˆúòø ƒÂ—S>¯×¹±xœº€&uËC±ð= Ym5¿œPÈ%?I(,Rδuxê5²‚\„pþg‘ÓQúŠlv<ÅFän2¥)8ðÓŸ™ÝMí§µê™9ÉO?34N$ѹ‚tß']gçî‰`¥E⋈BŽYÍ)¸L² 3¤=4&aÂHø4r·7F$­½ž¤•,e Æç…º™Š¥Í<žb].™Lc‹i4gÉ@?%¸†º¸Z¹ç”+Mc2k†ŒDÔx*³ @õyïp° —$òW'çù,Èìh£ÄìPÐ&T¶,Pzh“¤’m±V -÷¸än0’‹:zÏ€¸`¼ÒíàºÇÞ—¯&¦ÀÇ#/ ÷l‡¾…cNÓ“L°pâ3’Jæyá…t:E®jÓä”JŽ³Î,6d±ç -q;œ°òØ*ƒ½fõIJ¨fûãËœÖ4A)¥íÙ‰è•óîG}ê~ˆ§$¦W¦'©L[Ü{æ!RƒC6»±ŠNß¼(n©Ìv)/(x”Þ4EûƒÂN"}"Ƹž2¤†â3sâË[’Òh—r0©ô쌺a=Ò ã÷ÚKz 3Ý‹S³+§ôY -‚HÚC²†vG¹ŧ'zz¹úzYÇ`?na}ös$„D¤ëû'Ú ,ÕÍýôÖá»±•1)““*“=[ñ7&âF¦pÊL/xnr˧iErøúýåðx¼Kg·¼˜+èrÈí ¿ ¸3ù®lHø®÷Oº ãö˜ÇWzˆ°Ÿx2—é”H®Ï¤¢r²€ØÄßéDº‡‰IH*&ÛµØá'Ò›*XžÊ} —3‹ENÄýÔ3¬á~a’¡(³zzüR¬„K´èƒ ¶í¼×–&Í—·•n9n4¶]dx“MS×.ÓÎ5jî¯E¸>ImytïœØÖ²ÌÉ<==\ÝPí«0«{³Òò–]³!ÜWíÃÄÑ«ÝàlÔàLõ×ÎÞœL0Ãr«bî–Òóû^p_¡" ßopyöÞbX©k£ûô¬Zº¿Sæ@µš»jOŸ'«ó¾ìâºrØ­lgû.m^ä÷ö¦~/ÊùþkA¥6Q€\ÿ&T«º<›”7V½u;ˆîB[.¦®´ôÃNoÓT§ÆÑ=™ïÖÞy9Aý"ËÞl6Ÿlö– Ú£ÎÔ5ý.ZßjžçËiw³³Ê‚8힌–\fâÎÚö“£$ÙÝÐïÞ %º*ÛÙÜ’Oªº¸k=ì£w­;×Õx ùocUž¾÷º3í06ŽPžÈ •ç¢3_§F»ÈêÁñbÜ…Ý긮ÃíØ´¯£®Õ¼_›TM×µn½þà¾l¢_~Ë¿[±ðþ4Èá#L ´)ähq$ƒð” ¢Ïj÷·8çºè‘É^²o‚¯©ä‹æO%”Ç$?{ÁºêþÛéÛ -3DL3¤riT*úuÔ7&ðÊ·6ã¹°°ÖU)lÔ—ï?îKbwãh»hÖzeâœÆzÍÔp"/}¹Ñ¢•êníÆé(Ÿ×å{s=3ÍÁâöÞYßO1ïÍÉÅÞ5/Îl -DQim„Nw¶Ùc¨}åpYz;¾á.QXÿ6÷w­¡ vo_2fÝÙ¶ì×äÖy{YµÊU ÂfP+B†¹A·sC[¸]îCua{ý½¼ÛlÙ³îÙ´VÅfOžjãÙ½ºgñµ°ÉR<;¸i³V Ô¹ÔV¢Ó]Kµã·«_™¯GwmͽºAôŒÈ^–»ýFÓ,šèžÎß„c§v3O®Õ:íO+Ô–ýŠ1y¿º:d&íÙèì—ÃÛb¢TegaÞ‡ç ÈÄiMs¼Ö]Ý•gÕ7I9CmÌ«þÞ?ƒö|DÚrvgàfí7'üTÙ—ñ5 Êâ³™#ßñ!×|Têõɨ Úp>Sá”Ûöpv¨Ž:hÚ÷‹qšýÊË ”ñqŒÇã -S—|K¢_ü6ŸGïnÏijÁ y@­p1îÍÚ÷nÔ™¯ÑݶohqhÒ~J_ð$¾¯Ž›äl8¾=®)µ{7ÜõË ¹R¿Y¶ôԧ͊]}hNù¢0߆m©jâËûjmÞ½U_owš[¡/˜·°Ûvîæú6†›Õ8ÚÝÆEJ½*ïÕd}ÄýÛªÛj­¬É™í<ºîÚã¥oía§y|?ã°ÉK…Öâ\íUÇQ£Z{ø In_{£&wúß»‹ø!ArÜÎtnæ.‹ÝÅ~‚ b¡cg2[$™bš ½Xí®øâ=Ìýx%,NèÂ)ÖíÃÕ·¯£d‘±,–ñâa=¡•2ž¦bñPüÄL²k ÀƒWoï_¿ùñoïn®<¼y{J̓×oþ|G£ßÝüüóÍ»ëP¤Z¯þt󗇻w4[·oî HF3Dßݽ¾{wwÿêîú÷‡Ÿ®îY¦ò +¡ ¯~ý/ +û§+΢,Õ‹'xáLd™\ì®”Ž˜VQä Û«_®þ:œÌš¥^ý ÎdK¥ô)Pg,ŽddX”ëü°íI®§j»¥Ñ²¤ç¡+ v"¥`‰ñ"‘NÂÏ!…S,bJø˜rXÈTÞ÷ùj®à_y¼¹’ˆâòî–gû©N€C–e±šï³Ý6OÝu¥q°íTûmIoUé&ú†žÝ&o¯EXŒÜB«ú½[Dr˜a‘÷ù2ïJ0¸ÖÜÁÌH˜F›ÜlUowjžê)!PÈ"Œ4Dœ¡¤,ÓZÒaZê€-¢`ùLO{Ä/áMfÁòиZÓs" ¼9a¸É-°ßØA—ïì¨Ù—mÞWMo °o¶ÕÊî¸nZÔ>©¨k¶\ddàsæóº›ã$%hø•Ô¼iP œ°¼Nƒdª}„çŠÚ¿MÜ žšÁ0Â!dWîšöÙ.'¦ëªåÖ‚«ÝÞlÒe@j&¤Eéú¼/weÝwh•B"]CÿiS€½WÆͦ==Aým[eG½ó©KeÏOàý¶Y‚qž² žžè$ûƒjKX*ѦG¦ Ó OÏœ”Ž¦JÄæÔRñǵˆ³4åbƒ4"ÉþPò,KÓÔŸ:Âb8%ibàœ¹(biœfãÎȤq]Ï)ÆŒK'ÈhhÂ.PH8Oçqk´´ïƒÇBbcM‚lÊz\î1¯²Z Ù”ŒÎ@ +!„Ãêʬ…È®š™|°nKü¸hdudK™f'qu 1ø?ì!:‡ÐV:Íâ–&Ô¨™VdÅ#ètVKt>·ÏÓõks2¸°9"o­v +»`ÔVa¨&o|[›¨…ç½Ûap£±;ûœ"Mêæ³CÃWLÝ\ é OÍa[ÐpYÎ×æX# C¸äùÅ-&ùiØ‘ùNäaÈ”ñ&¥YÑÔå<«Y?OR‹×´‚L©ÿ&þå–™œ6ÄN²—;{²_@´¼]V}›·–S4^EÁ!/@5:;Ë›ºC2FeÉx¬[„R‰Jaë.Úâó;OÔË$ƒ–ÎÅ18‰Õ‡£Eçy±Ê‹ûÒCMCa?dúÕ¶Ìk0¬j8ƒÇ¡7š’L¦°øImŠºëÊU˜¯Vå¾ËOûªõÖæYÆtª¿–,°X¹ë°H¦œIˆÂH†Jb<>j wù' + aßû4CŸÅ#u®‚´4ôH®¾H/†¾Ç_CÈuÕg_¢‹SmüÈŸ-³ +_£ …^”º­?—mÖMØ5ù9Vá´t¤]}–\Î˳û¦7¥…r>|\(ëÒ_Z€+è4 3"v–ćÎ.ÿZ:rd@¡ú•Ï'¥´YõÄÍ4öGžè^T6ÖLbÔâC ?°…õú´ŠWTÅëñŽo,áC•H[¸p,Ü"Xl7d) Ì7+J 8µ8ÃԱݲœ„ŒÐzžˆé‚ôœq'P&¨›@­J­}÷mœ¡uO–Œ°×{™mÛp`sŒ> ;¤² Üoì(gèDÍnØ”–,”ü>)vùSGÂ.eÝÙ!l=]ÑɃòÑ\#¤¶CJ1붻õa‹§‰öMOPÓP¥"È‹]Uƒ@3Ô’(xagl†Ø£-«-ýþ™¦¨æƒÍêî0–¸ü¤Íüö¶*m3UÙÉ£ú£žº°í2jÊ6…ÆKhu×^§ÁÁ߆Ùq¸z9î¥}×ûRpÆ#­/_ïO±Î_ïX¤‰<^ºíœ%ÐÒôòÎɳóìfŸC& pͶ¦šAjèìÛd˜ðRØ¢ªÈïí3A©WÔ®ÇÓîN ‚ ~/Št©µnê0_šû`‹»Ïû åmxUæŒg´Nï%¤6÷6[×Làš%/ºT‰”¢¨ª¢ ï¨ d¾(תlî£Cjh†JS£¸B#8!)1܇!$°mVŽM˜"ÿ‡Á®1õ¡R¤šktóÚúýÁN‘P{Ѽd÷9r{sÍÇÚƒ/÷ëˆ%Yê.“±g{ÆØßÑÓÞ©'gäŒR¼YBîÛ#gKÔô +î%y=][ÁÔ`M^Z``¨£ÏŽ&Žî?=Šˆâj@žLóð±X–$.±¿xI£dÄ¢$>ê?Éâ”8f+R2XÓW!¸»w%Ü"9\£šy20·÷mo®o¡¨sãÙ@Ìo- ={K€“K»Î¤"˜È<ÑÎ*Áv1PM±Îª wýP>‡gƒ•xÿ¯.ïî<»Ï‚•”P\éh¾=]Œãýë¾lÁév°xÏàÕŠ&{(’KSYÍY¹:Œ½>7ui¾µHå:8~r`zšq<Q÷‡åÖíg‹M08Ž”ÎímßV†tîùåî?”Ï4‚Ééõ‘òöº9Ôäb‰)špΗæõÔ1O»AŒÎ™r@P\˜ÈdÊZO âUí"¨PÃBé“­À<@“åØƸC´úTÆžíû±TO¥0E/^Ò‰ Ê0N›øÚ´˜ÝÁx­07]žh’¥,Á|IÁbYÕ…­ì‡™™§žï>Ë?j‹ÔÙ6¦­‹Ã÷Ä.h°Æï4T›Ÿ^ƒ¥ñð­²+;¬þσ¦%ÑC¿ÆL28'ÚðËQbÄ9#,§uþ¾,BÔÚ…PM`:.ô +‹rÂÀ,L$ ü]É„ +¿<9ñfžš_oÐ$}ŽH‚MCß3RkŠÍ^ŽW^›¯>È +K/(1ºäÒ[»+Îü(&Ò Éâ‘žŸÿófÆ_©„Ei*ýš”IÊT +D,S¨IŸŽýeÍ)ëÿ)”o#endstream endobj -1127 0 obj << +1650 0 obj << /Type /Page -/Contents 1128 0 R -/Resources 1126 0 R +/Contents 1651 0 R +/Resources 1649 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1117 0 R ->> endobj -1129 0 obj << -/D [1127 0 R /XYZ 85.0394 794.5015 null] ->> endobj -214 0 obj << -/D [1127 0 R /XYZ 85.0394 717.5894 null] +/Parent 1644 0 R >> endobj -1130 0 obj << -/D [1127 0 R /XYZ 85.0394 690.1986 null] +1652 0 obj << +/D [1650 0 R /XYZ 56.6929 794.5015 null] >> endobj -1126 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R >> +1649 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F53 1303 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1133 0 obj << -/Length 2753 +1655 0 obj << +/Length 3894 /Filter /FlateDecode >> stream -xÚµ]sÛ¸ñÝ¿BÔŒÅàƒÉÉ“/¶{¾i×ö¥—{ EÈbC‘ -IY§Ìô¿w LgÚÉ]2c,‹Å~cñƒÿ|«Pe"›%YƌdzåæŒÍžaîogÜÒ,ѧúéñìݵLfY˜)¡f+W²4å³Çâ· -³pXps÷IÍ"fÁïwwïç2  qsKãO7·—eóçŠÉàÃÏwW÷„,«‹ËOsÎypqûáÊ.¸¼} àúêbžDÁã¯÷Wóß9»z4ñµåL¢_Ï~ûÍ -Pú—3Ê,g{ø`!Ï21ÛœE± ãHJ‡©ÎÎþ90ôfÍÒIëq -©Ä„ù"î™3˜åRÍ’8 •ÒØ/ CÔXAÂ,Ž…Au×éåB×ùS¥ç ÅXpÐÝûï¾äUYä}ÙÔ'ä‹( SÁ·ŠüöŸ÷oO%iÈWÿ“õ¸³,Ž¦­‚&À4bâm^´Ž/ ºǬÆUŒ‡±àÑ`d!fƒ9V3%B™€ðJAdJNF¾E] eÆ -¼bÜÆR€ä†â#c¸*\Zx²D$0²0ÉW³¯3²(Ë$y°Ñu´A¼»ÙˆÙeÍ<¥ã…ÏÙ(¥„9o@ûKT`m£SSC`ˆ$ šŽiЯ-âË\°@ãŸCGSUÙõº Ù²väeG=—,ø#ßl+MSyk9½ÌE``AbÊ(njÂoóv¾ˆXЗË]0äåù‰mÓô„òıX©j 8 -h -MoÓGD* Eš¥3?~,®0‚ãLA`)þcQª\ä…êër'”Dêþ¯µF‹ ÞÃÕ‚ýÜÆoc@©<ô‘×ç´sžÍV·Õœ›rÙÔŸÏ;3© t—Ö]°šÐ]S½è–0û²ªü¹ëeïv:8 Û붣V´ífÊ¥]ù\Óž)P­¬ôý "¹#p¿.—kWyYÔ74Z+hˆôÅE$(@ĵߵµ=ˆà`‰ãàÓ5ž7?æGº°¬J]÷C†\”Œ‘à÷ºÛ6ugäK£`“°Ò¥1qŒ“ÎÎ7-d+L–}§ÁÂyEH8ï` Ô*“ËjW”õ³Ý°ì:ø0“"ÐlKÏ@î¶)k³¿Ý¬/¦ÎŠÞÞì© Ç!¾èÎþQ:ŠLšÔ&ïÝ,Ù€Ëïï;mÉLñi°Zà®uO ÑáV#?äµ[{€±/f4ZIòœŠ<£‘‹˜å²1k­}½X({£¬.Z×Í®²‘¶Î_lÈ,ÕE¹„\ÅòÂRªj€v§0Âhrœ£mpo(%4³ŸYÌîP臚–ˆÐO¸ˆž‚³bBº¨D”3.°&BôXèà÷yua¡Ðt[Q$´8kwÉiµ1°uNè› eSÇ^Þ -ASþæåÈ?Í°Cø+oG(¦ˆùx> >ãQ(#%üë‘Pq˜%‘r¯Mà^ÆðµéŽ6í¶Û¦ímW¿~iûWôÀp•æ1(†\-1Æ «9ÌSAGÜ;šÈÍMp·ë‰2 -'-@È£i7ñ09(+3@unj @&sQØN×.¢äz=3.™TMóe·í&_’núÓ[R^u¶ëÝu¶­éíæ.e®GÞä_,ù×nËñÎæZávžÂ‘_ÍuS»›Úé.Ë|K[¦ƒ>t½Þ]¿ŒäצT ‰¦ÜS[^Âê{N·Pë>Àg4XŸÁå·#DS'tÿ"-Ý… Ã¼e<¸¿þ@ÓКH‚ -½N–Üv€¶7giˆ»¬ìjr‡ó)ï—Ufï ‹®,4!º!¬áƒ®“Þ0žð&ä>·ÀÑEǨ>,Ù4/ÚnéÝ£’!cºR%pâîñ®ŠwgS•à2»ë×M[öy_¾è)uœ+RrEêbT`µn_ì[|ôÃãBÕäöãõa"UÚÒÚŽŠ¢ -¾É¼é`rNBV€®T·S˜šøŒlÞ:¤}­ ÅcÃYw‚õ´ç¸ç9ºUBó2>eؤia»•Ù3 ä§tGÚÁ÷…òŸ2¼ðœxœ ;–M,å–¡¡5My©¢äàdóÓ^ySîEÐ }QRWO3æô+Ÿ gíñDXáLs¨L%)k*0²Xkª¼2ó*¯LñᎠj8Ë­ -óv›OÔh¡ë]‹fF:·ïÙÐæÀIŸd’9oE°×&²9`ì*‚¦*¼pN1³ý´~--8tÐqæI ÷ aÞ‡‹/I‹Y”$ÁG³©ÙÝ6íH<ꬄó @MXŸP»à‰–*ë¼=]•?éʸØ…',L’T‡)öD¶à«8øR7ûš@ªÊrí»¾…ÄÓ[rð9U…§]OX¯0ŤŒƒ\À_Q4»Ýg‘†ÞLZ6øÖÜk*Mñii‚û¨1,Æz}¸ýøÏÏo¯S½¾»ýå‘?¿ÿðþóûO?¾¿ÞˆÌ/ý >Üþ×{j}üüöo{ûùúßw½zßeø¾‚+|‘oW¿þ›¯ +xí¿^q¦lfVÏðÀ™°V®WÚ(f´R²¿úrõ8á × ÓŸQ3™Lg(å@‚C['«ÔX–(©œ«^Ȧ몥ßÆssüZÕø­‹êx-²u¹ëšã˵b ŠÒ ²Û.#zÌû‡l]7Dü^•Ïý*õd½ß8—ûzóA‹Ø2•,Y +/‹ò:(‹Í×ò¥eÛª.hÈäMA©5~HƒÒ=WmG¬6*Mˆ'W!˜5F:Þ/?½•&¡M~ÌÛGj5÷ôKÒBß…Zu~ð4§Bø=µeA­çª{œy#a¦•â±¾ËÌkÀ¾*“HÏVþÞ•u[55ÍEY°3äŒ8©HAiJÎ8Ï´r‘½ˆ¹¸P +|Ýbóû=l÷di¡RÆe/¯¹Îâ@GZ2®aSF«ß=¢’•ÊÖÍSçT¡Ù®£mÛf_v%›Ñ¥µLÂñðºD³ÅÏyKSО!©ªé—œöeDèúmŸÊ]uÿâ‰hÈô”wd +C^ì&YF­ “J%^˜±J'rƒ™&,rb¦Oî€5ÇüÀp)½¾uv‘Eç—­íøM?xn˧ü˜ws 2¥Œø#8[ÖXÏ:„V¡S§¾,Á@ÿ‚"Hð2žzªw¸qù¾ê^†ìz{ªö'Õ—Ù+pµ‘Þ^‰ å¤ÓЖÇï -xëÅ#‘$Še`cOÄ€iù@&¡ƒ³»yhÛü©B—ÔåÛ³s‘ +¦sY€Èt.Áȱ1(ŒE¸s6(’õÏŸ0Ôò’¸¶w¬®íì~O­#¤ëûæH”_¾lî¾Ü~ôýOJ‹ÑgëÛ{?šN´âéƒv µeGsæuáùQ7´} x<Îõ؈½Úv,Š²îª|û©%…V`»5@`±îТµAàÁEèñ²ÒÃsµ÷3lK¢äû}óì2C&rýB$‘(‡¼Û=RÄrNħcU盛(–_3˜%Û£s ¨ïh–M#r¢³WlrÀuÁ(×Ô*wǨکeÂØT¿"F`šcd™–³T¨ÉáLº`ûv§£;òø4Ýq¤ÑÖ¸ÖcµóÍ®ïÎ7µ›Ó¾ v~B(ÑU;ôkŽâb©kÑ"ßNeÛ•™!è4M56Ã-€°>¸Ã˜þ, Ù{¸®Ù5{†®<iòºÛûÁMM­lýsyÜjZê3ô3•¢¸ðÎû¾çÕ>ßî½î d²S•Œ^#Àg¹v*tŒlÙ5÷°hAÍHÜåi쾪è4 +Eóž¦ã‹ò>?‘‡}zŨƒNɽñØ©9à|¾Ì`¤Éɺ)»ÝÍ×ãÖ°ÞÉN#¼a‰!ÂÃN;õ¾1Ñë}ÔŽOÑ?B;úGh»wV‰rÞ ¨ãXÔòO­óØìÂÔó!`µ v‰<'¢gðcŸÂûƒU÷*­í<²C¡ÖÌlÐ{hìoRj¯Ålˆ4`ið[i¾ûôåfa+f1[!&²V4‡Üݹž6§< àvo“¬ï®­\7$Ù©õ"†³ôfuXÉŒ’a¦A´ÐÜ0—5·( Jel˜æpj½ýåû¶¡Ö6¢ßUÝ÷géÁoï†n{Œê) 'ñÁíÿÌ]¾‘œI V}Ñå¹–]~äŠêëu4òóZ1a^Y;0ͬ=òó:c€Æ'‹Ó1¼æpíüéÉ…éÂAkãQ±  1"à·–šhÛʤ®‰Ð>ú$Ò&¿Ž­‡².Ç4¢O²FJRR‚ ñ`w?¿ÿïÛ‘)ôNø—ËNÝ+øT1C›×vl»}ÞcM2Œ5.ú:‘ @ž@õŠH–ñ4ÉbÖ·{Ìëç1yâÒu\ï¿P£9Òr‘àì1OÁe µ(Û*êÕñ; -È›)2£×öɾ´Âá@$SD,[xû7¤ Á932MÆ +¢}†ŒÛ'FÐrÛÒ~lŒ¶Ùf(°ƒ¶¶sU‘&´ KØ‹„ûÓ|_áŒøIO7W#=ëÌ„²Âά-«Ò¡{ZôA MjÔ ø¤|~ u‡7¡âÀ™Ê„‡6ŸB†ÀdÒiI%}×HKÀ@Z‚¯%h-h VäÑÅW4RËcù;5ŠêÓ³ù*ŠMbe^Cp4ìÿMC&±.iEáMÛÑ›íò¶lßÐɞϞ7Js¦…š N‡3‹Kh ¼I2³2ï“ ¤’ÿÑ)85äÃÞ +Äã‚$‡“€mXf‚Ǻ©7åï` 4LdlOÛ~*»ÞW_}rĽPé#O. œ30 «µ•¤Â(™Í²l¾¾¸‰3n†SÎø}‘1# ãŒla˽‡˜À˜É`÷ÇXÀå&c +¬Õ¡Ë‘Ü®_šâ`>¨,Õ£1¤÷8Ãõx,ßóc€5è€ûJQbà¯ËGBözª÷eëÇÆUƒ/¥$"c™L&¾î ‰ íÿ0hT<œáË€aȵ "W\qg+yúòÒifiy^ÇSãµïBÕ÷ 1ØO—3o~*÷ûƒ;M! ‹/§iû2©ÇtŸ@Z@D:Nì%áêÛ„Þ€‡bGV‹EïX{Rð + ƾ y&À™ÎHôã3µ6ŠÀùu`’õÞ'&­Á¼ñ½q5²èÌW<€â­ZN'гoòÂSÂO§í¾Úù.ÛDâ±úNªªW´î)Ý;øX¯ ¯± ÛØ[¹,Êc媞”ËûËÃç/œ²[?Œ¢å  F“`ƒÂ_ðå˜9§¾kúqnœcñÔA^.Ù¼R-r-ŸºÈå€J¾{,7ýeÇèÜÁ¦'£³/pÍ,?:y`¶‰äéx}ª ûœÚ¼ÆMrõŒÁÞ¼k&iËeí)&òJ’3亠½Àå‚Èéð´¨<˲䕵ÓÌÚcÕi–i9Yü. ±a­?9k± Ð{W…D|‹v2¨È!ämÖxxG™´ªºíŽ×Ùú´£ÄgÀTø߶¡¥¢ ÕÌ&Øt¬ ªPªb;žd Îêý4-îkŸÓ;ª +UíNEŸ"l:¼˜n°Âë0ÈŒ\f—ªÄþiìgÜ §tæ0’NiÁ$j.²[d³ +öL+¶pJ¤…ÙRuù ˜–ÏH`rõòÐvy¸³ÚµKg=‚µö¢‘é\†ÑYI,K2!GBøHÅGŸ\+ –‘ñxTD1ˆn8ŽÕö¡ o†õOmþàÇõoëçiüb5ýï°BÅ)E­‹eˆ;•™Ü­ý9Kæ +N™2ó[2—ce +”78[K¦b8ËŒ~ÅTz¦ ¦â™ÜÝ]U,€5©tzqáÈt¾ò8ÑVLŠd´òÝüµ)¹Ò´÷š½+Íæ\iíÃÝÜvþ2×WìwÇ#áö]¸Ûż3•t£Î{¹9G{®Þ/÷Ü_5Ÿï¹æ˜ÇZÄ/bJÌꬤ#7ÇS}ã,ƒþe°sé7léaA2f_ж뿻—Jù ~mé.. Ÿ ` 13ö îi=O÷˜wÔ÷œc†êh QÚ²öãÛê¡Î÷mìöЋv^î‘™Y»8Uׄ%2®i¡gxM ‰ƒ^¡Ä +Yg2x Ô˜P˜˜«› ìÙ\_¼:U‹x¸¥!^DíëÓ™¯©gÆåo@wZÅç~!ùh–<ïõWŽ@݆»j™0%ÒÉe5šjGŸ½H¹]ã…Šk®TàsÈê’~vëá=üx>4ßñóVxÐù>·§3Ítª‚›YPœ„ÌeÐ6]:ÐE¨uפâqiw@¸ô‘¿ç øú2䵿u“è¢`#ÏÌ…^徉9ý\½½¬wû&~RR‹¢9Qšío§Æ]V/8O‘*ÈTí+Þsȵì>#—ÃNx©‰ùâ’Õ†AtI.K¹fDùðŸ€GÇ"P 5fh·jøí®Å:pD›5á3¸ð3–Žú¿°„¬ÊØ‘wÔê 1ð°›\ˆãÍÔ+ˆHÍú p˜“ r‚p]ÜmÂf{ŒÙL¿«šdÖ4ë$ßÚÆš¯KštX—üC·Ù\’)H•ÄÊó²a+ÁÀ*^3ì×Ã\½ + ±ªÃaã.Š¹fd׈€é‰ A‘Žë!F€'‡¸7Q$ÄøÇuOŒ8ó§'g­ï E7¢¡_Ÿiû4Ó0þ×eZÜøbÑ\‰:e\s3—jáñÔB×øÛ!BHÇŽ‘Šsúþ"ºG*‰Z°Dдàbl‰KÒ°Wè}<¨G×ÞjZ\q×ç½ðÍ•z½<ņ„£NP^lçÝ·—½#ë£EQ¶»cµD‰‰ÅJÓsa“Ωëø°¢ÆçåFîMÏ~n·Ó9Ý÷£å®‹ßh&L3H=Ï2Y¨Ÿs1åììDž‹Lgºè.ð{×4y¥(3`ºðE¨gr_ÏTu¥ÂË1Ð^\=2/?åh}Š€©FÀ”ÜRszŒ6$Uà×Ûáta÷âÆá dv® ¥”êPÅõQ¯ŠÐ·}™»‡ȩ̀…é>òáU#!ÈR¿”Ѩmø•é"@ÜÝ© _‹ùª³ÁËLÂ\Q·m¹Ûì›ækÞ¢ +fbÞèòpe–Çï¬Ç2ƒ‡ˆŽøI¿çûª omffÅŠ ™’/= +8¾]^í[}µ¾"D_y}CºÑW,ø<´m/—n–¾Ù‡ ÚÏØ'üõ¾éOÏßÿgüâ6ËnMOX&m„BÁM:•<~ø.úÿ—[> endobj -1139 0 obj << +1657 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [349.4919 62.7905 408.4801 73.5749] +/Rect [250.9056 106.0844 314.5963 115.494] /Subtype /Link -/A << /S /GoTo /D (ipv6addresses) >> ->> endobj -1134 0 obj << -/D [1132 0 R /XYZ 56.6929 794.5015 null] ->> endobj -218 0 obj << -/D [1132 0 R /XYZ 56.6929 285.3652 null] +/A << /S /GoTo /D (statsfile) >> >> endobj -1138 0 obj << -/D [1132 0 R /XYZ 56.6929 250.4165 null] +1656 0 obj << +/D [1654 0 R /XYZ 85.0394 794.5015 null] >> endobj -1131 0 obj << -/Font << /F37 802 0 R /F41 939 0 R /F22 737 0 R /F62 1062 0 R /F65 1137 0 R /F21 714 0 R /F39 899 0 R >> -/XObject << /Im2 1051 0 R >> +1653 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F41 1208 0 R /F21 930 0 R /F39 1151 0 R /F48 1228 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1143 0 obj << -/Length 1018 +1661 0 obj << +/Length 3489 /Filter /FlateDecode >> stream -xÚ¥VK“ÓH ¾ûWø°» -÷öÓÜØP[!›ñ°àà;Äà×ÆÉ üûU·ÚÆ™1Ãû ~I-}ú¤jæRø™+BE"Ý(‘DQ¦Ü»Ú¡îgØ{ã0{&ÓS/SçÏ×"r’„ÄÑÒg‚ÉÑg±§i™ãZÙ£ÌPtp>;fUUT¸pj­œØ–z$½Y«/`QP/k†Ñ¹©Ê¯Å…éåEgÕ²Sa=Y†ÏØë»â®üH)/ :òqˆ VEs*Ñ€%"£ @7ðec7Phä+«uéPV0 4LñŽoYÝUÅ Lˆd’8ŽãÖïvë7šÏ!ÕÈ][“¹mòƒˆÃQçá.I±ôtàƒ^ƒ#l‘ßÆ‹û )&>Üô”Òk÷Zbƒ² ½Sg]§³ Ç˜j³Tö¨Ø´'\à©ë¢É‹Ü”´ðÖ{k†£õ™5”5(‘Bzkr$Z(åwñ°fð VO9y1þM2ª³[åé0“.èJPï\‚ymu±Ø÷` ',Œ‰1ƒ¯V¢¡Œ¬Rfé4Rp±êíø̉T´¡c4Ÿk¦An²ºx¾elÊÛÛÂÀÖ:;ýºgü{(4ÐÐœ+°jLéɹC™ÙÍ‹êÑ ¥Ýhìz¼7wêD²ñ˜Uâtm•jçÙP°zÒ—P$ßqŒë÷ű/rc5ô¾œ «¨4¸[Gf¢)fV4“z©ˆb‰°I,»dÇ.#3€)`B̆ƒƒÏP1šûè‹N‘^c¶Ÿ«“ETz ¤*EF¶“ècc'¹DlßVUû0æâ¡=Wö"ìší}™&j ‹$À1DÏ&åa€³¥1r§2ÜÁñ~èh¶`°dÇzyÒ6g -žœµð|c -‰”ŠÌ˜ x(`hÿ¼RrùÇä–ä ™™qr‘ÊÇ´`„>÷CùÅp“R÷ßpÚ~·éN§€"Jäq3Ÿ{@uë'ÅÌ[‚Žýà·_.?u2""ŽùGÉ{ACó$œ2Ù=Ÿ8O]ÿŽ|ƒKendstream +xÚ¥ZÝsÛ6÷_¡·“g*š ~Ì=¹±’K¯qz¶Ò¹NÓŠ„,N)R%);î_»ØER”ÜÎ%“X,>¸ûÛ/PbæÂ_1SÄ^< cßQ®P³twåΞ`ìÕ`ž…eZô¹¾_]ݼ—á,vâÀ f«Mo­Èq£HÌVÙ¯óÀñœkXÁ¿û|ÿþã‡/·×¡?_}ü|½ð”;ÿñÇ%µ><Ü~útûp½‘ówÿºýiµ| ¡€×øþãýQbzœYôaù~ù°¼·¼þmõÃÕrÕ½Kÿ}…+ñEþ¸úõ7w–Ákÿpå:2ŽÔì:®#âØ›í®|%åKi)ÅÕãÕº{£fê¤ü„ëx2ð&è‹ž#á¨8V³PÅN =i¨Ûôf—™ó»~mðunÞ{^oR:¡°r;'/,œPˆ`z±ã ß?s@bZô¹Ìù<1¥`Ë…;6:­«ªm_]×+ôxï‹øòþ–ibÿþ« +¡œØ­ °ÚjPºÏ÷I»-“éEójCÔvË>ßØèúY×DÌ»}cÉé¡ÎÛW¨¯¬ïHƒmEä—­.‰’—M[_GóCÚêŒw`¦¬âí¤¼Ý²û¢]Hß‘®¡,œX)ϼZ]f)ÚJy? +d€…îüã†æ•UË ìuš£töQHÐÈô&9Ì—ó` +©œ@Ä!ïBÎœ GŠ¤D€÷70 k_9®¿CÛÜ<'õM}(oŒnX¤èw'N(”r|zÃ#~u•û¨Oàf{xN,…@ÑXý4£ÆCw–}Ñç?…ÝɪxG¶O˜àëEŽ?râXÈÁNáo¹Þ8ÇéjxÔˆŒçI‰àóÚt¦}R·yz(’šè¤2Èò&=X{l(@G†SH‰0vÂгò'D-öU‘§Sê +@]lZàÝé²ý‡EEÔÇžVßb¯¨Òd +¡R:nìZèT{#t`CK‰È9µt°»Ê„ö½y »„T†„d]Zë ó†Z´šæÄÄY‡ê¹ŽRÑþôÈtÁ2ÓÈ›76„®PÄÑÅÝ;¦ÓíP’ UÔߟ|,ɯaƒ£|ìS˜Šñ?Ø 9CƒÂ°“DRç$íbB´\ß瀳s1ÌCçâúvEÙ ˜Ð1:‚m¾zžoÀ² ¨LÈôdYV6Èx6$ª¦M#Yƒ=¦ó´L# &ÅÓi0„p­À~/mÞ1î> …¦®Á`{£@_È9l^AÛî°KÊC²QŒòÒÚ¤<딇äžò"×ÿ|CL,òŒXŸ“â ÞÒZv¶»$]4ÛD€F}¥¨OêòCãð¬ ,ãÉ¢n²§C ;ŠŒÆ‚›´±ÌëågÈGùèd€«ÞÙÎC 4©à ïÐçº.Ëõ÷²­‹G8f[§g˜Ì¶‡ lËSýl zD|+Lu̶ ÍÙ´l¶M"ù]¶¤„Ç :œz#e[@¢d” Ac:áEŒgC< ƒT‘¯†8œÌ‘@Ý"˜~@úcÓÈ…l`…Æ °†’d †Xüõ¸Æžø«5Œ]õv`Uq(†Õœ—ä /p ¡æõt›äECËkb§‘¨ÅPY©ph05¢úAì(Ì.MŸë¼Ñt\x€}U·ãMCå€ã—7µL›’C´(ýá¦d$n4ÿr÷ÓÍêÝOÔ1GV8/»5VÃHm-¯-‘± Ènˆ•”$bªóç¼|"9=3µÌ:êÝý#MÝS=ÝViUð^u²AgŠ9òÍYQÂh FaôX±†€U4x¡ã„ªˆó¦°C[Ú.ÉËâ•ie '4%» +mŠ/€¥ÕM ¯ðOè=Á˜áИ7D2’›ü©ÔÌügUêÍQÅlT†sÏ vL[S€6¹ r }¡Á`€¶4ÁÊ8 ST6ŽØô7$Êõº»Éw!>{$£^_‘œ*WP’e¶Ïù ö™Ø#à¶&ßr{"îoñÇ!¯É…ö9oÃ!("µø’0l™@ê."¡½EíáèúZ̵eÕ߶ɡiu†-¤Anr áÉm^¨ìê¢çÏdÂÔœ¼Ø“öúxmÍ7  Ÿ²Û©X‰okhÖ!ïe}Të è`éµesÐ!Úïˆb0Š`G-ã?_òF£ÜØÆ„‘÷ñ c‰°æp§ýÎøÂ+K”_˜+ÛäwÝPS›p´Ñik¯† öî˜2 (ô!_ † È˼ͭãM«µôt¨{%~Q%{v{9ÛÅs¨º=ìÙ›ç;ʬ» ¥çSÉiØå›ÃºÙƒ`©OL¸is6@² +9i^}®óA ã2iN­7º®u¶xB$žDt¡äåý;®‰ £@è(ÃۉƗ…^l 2’ó"oèÞØÚ×½¦"ü–Lb¤[øÃ`*›;Ð×¼Þåm·ÒZoŽW=¸'0ôDV D¼3ÛÚ³$Y–Û’¬J†£ÔadÑÕØ»>£~¾ñOè¨_ûhöàÙ4X»ûf 6ß`cÝXŒ&%/ÍÒR®‘Öýçû%Šç,ÌàM¡h‘oÀ¬Ïuf—±ùªjÁâ ýdìlQaŠ7›Â¯pB^>EÇ5qŒñý¯'¼`xŽÕ5f 5!Y¤ŒÀƒo/ ©©ˆnbn„JÜs^dõã]Cì(â¶Ú¹ÐϺàéæ´ GÏÈ^:À ûáŠðJ'ã+ãÇIdb1µïÃMK‹CÆúF›qº ‘Áȼ{¤Û2`NÕ‚¼…ÁŽþ¦H%\ºÂçšGwI¦‡#œ¼Y »yÑï3#¯ô‰É?©$i˜–nuú{ӑߙܴÝ]ûxrtyÊÛ×a>¹­s9V¿ôÜå XÌMà-±'a«±^»BÖšMŽ]v6ó]^$µqþ¾o‚M81¸p1§Ó %Eo‹¤Î-WOiÐÓ»½·_ù2;³ª²¢ö‰›õZzÈ|úúÈÉór0<ÈA&TÌ.s ®ŠÏÍcŽ}oïáûŽ áÝW'>8jÇ-J&=¿ïÑL Bc{ Ï§õéÓ‚vž†ø ónù•>Ž™ahþˆ_á~!~yÄÿyOªð‰ûÓ—Çå—OØ¢’ |ihòKjYJÉyìH |W@pÎýØO*¡7‘îÃ?^êÿþ!àñW’~èÈ(ò¦ëH?‚EøPø +*:-˜øƒ§Gÿ—âƒhendstream endobj -1142 0 obj << +1660 0 obj << /Type /Page -/Contents 1143 0 R -/Resources 1141 0 R +/Contents 1661 0 R +/Resources 1659 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1117 0 R ->> endobj -1144 0 obj << -/D [1142 0 R /XYZ 85.0394 794.5015 null] ->> endobj -222 0 obj << -/D [1142 0 R /XYZ 85.0394 769.5949 null] ->> endobj -1145 0 obj << -/D [1142 0 R /XYZ 85.0394 749.4437 null] +/Parent 1644 0 R +/Annots [ 1663 0 R ] >> endobj -226 0 obj << -/D [1142 0 R /XYZ 85.0394 622.33 null] +1663 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [80.6033 659.1254 149.9876 671.185] +/Subtype /Link +/A << /S /GoTo /D (dynamic_update_policies) >> >> endobj -1146 0 obj << -/D [1142 0 R /XYZ 85.0394 593.7503 null] +1662 0 obj << +/D [1660 0 R /XYZ 56.6929 794.5015 null] >> endobj -1141 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R >> +1659 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F22 953 0 R /F21 930 0 R /F48 1228 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1149 0 obj << -/Length 69 +1666 0 obj << +/Length 3661 /Filter /FlateDecode >> stream -xÚ3T0BCS3=3K#KsK=SCS…ä\.…t œ;—!T‰©±ž©‰±1ƒEV.­knj©g`fA‚!ÂVŒendstream +xÚ¥]sܶñ]¿â&O§™ ‚ÄíNgYN•Ä²+«ít’_]¯¤K¯”ËoÎ/ÞÓHB?§Ÿ.>œû·Ë“c/¯Î?]ÐðåÙ‡³Ë³‹Ó³ãUhUë%S8°àÃùg}{yòñãÉåñÏWß]ugž7ä×£‹ ŽýÝ‘¢ÄªÅ|ˆ L¹ØÅ* +TE~¤<úrô׎à`Ö-“ŸŠl ¬43ŒÃCp¬&66†XoÛ¢®šã•bùo<Ϧ­@. ƒD)éðvuÝ®²¼ÌoS\°ª«ò‘å¿­Ë}–{ +îç«,ÿêƒå}î›Üì›|¿ñŸÿyçv^M¶&ir$f àϪ#­†XN*2œQ« ·ÌŠ&½.óUZÞÖ»¢½Û4SB# Øϲà‘fXË1*0ÖFcÞ o:^¶wˆ–Í6_? !óŒfÞ_|ùrvJ“vÝ\Úòo•Âu^Ö/Q¬ÒMvE|Ü—m±¢»Ñ*°±ŒÆj±av"ÓPaœ  s"k©@´¤iÓ6ßäUÛ¹¥»ãÐ.sþ(áy†,†bùÉ)"ŽÓ‰ØÔMKPw¶5}?eIе'¶Ý–;¤b‘TVó¼Š °žQ1å¤R5M¾^•uýKÚYþDÁtÄuô<Ö #Óà4#£Ç<üã.¯@ ±\6yûõÌEÆ*HYž^£biü‚­»¶úpÚ‡î€û´,²´­wôùzAPÊ¥e›ï*Pü —›¼½«3&R÷4X9CÃÆáX93Z­"4’ïÏþI0©Òºv¿™S0¶˜d ÞPßÐoJ?¿×•3)¼ôú¹á.Å„°;¨ê-°_•Õ›´`Bc[„å×î|bìÙv“e–çÛ”ýéÍAÜqgO¯¸9 +ê„| ôwFô;Võn“–w®ø>!4ÐÜ]ÚÐD™ß´4ÔÑø%¤¹}ÕîŽírß´yÆ;"ÝhBÃMŽ®Ôã¯Òj}G2•UK¶ê­:¯2"ë‹òÊ1xèêhˆNŠý¼ÿá8‘Ë¿Ï©Ìü¦r‰Òõ[î·^è»É©¸á_Ö‹5èûè†éœ,NX CŒGB;ÆÃ0\‚Æ6\žßÐ0Ï›žkü˜r˜žnC()/cÅEø'¡DSlŠ2Ý¡cuäëfùòŒ_ÿåÐŽÔ;o€fxXÁ ÷–YÙ%8# vÿ æ’¬`‰ö¼×  Û" øe·ˆh&>‰@‡Ñ0ËWC ­(QKÇg”8¹5±¬‰’ÀêÄo’î=Òˆ°Œ‚ÅÎêâÈéiE;\]ü•å7)dú€›Ü»k„ýoÐpn€^p{DuzîPYnlmJQl'´7²¹Ð œ³Z’ëêÖã9OŽƒŒÞ¿ØôñŒ@ï9&HiЕÓT$z Š×›'ÌMœ¾ÀoÓ’ +:l·¹W`é”\HŸ¹Œsdä.|!×E•@~.c ¥ˆ¿ºwsÑ3Ðõi=M6C%Âøy,2pXÖ)3ßÞ¹2<§€4i×:Wƒ‡œÕôR”H&cU§;‡”$°I¤Æwþœ@z®bÍ@&lÒöf0ä ‚”ÞØ?dX„ÅzyBä×õö‘èc(ÆÒrøݤ禨@*e‰WŸ¬™ˆAš‰ƒT "”€ƒÞ³Yàò†×û©PÕ2!¦_ß°Å@5EfÆ¡Eâhm™§  Ó…simÉkûxˆ@o¬>8"ÿ¶-ˆLƒL&‰ó¶‚óX2Ú35‘¼T&ˆáz_¡Ê€h”fL IŽêµç½~¨PLáû†Òº «Qãåé±ݵí¶yûæÍÃÃ.(šu@Fyû¦©Ë½«:ßdå=±ŽË‡ì?´ÌÏŸ¦©±4 úD«El“@IÍ©1Mÿ²ðÐ÷OÓånåj¸Ô¥Ë#žî€Œüy.m +LlM§¸¤ÆP-?ŠDX¯PMÈ“ãüž4,Œ}¶ ¥ÖoˆRÌ]k( S¯»W$2TC{ªUÍÞÔû +=xoS08V|@'…„¿>-›šqëͶ SCn+í,|$QpD¼—Ü¡’$ÒcyÆëI=6µË¼|,\Ð1zé²Nƒ¾Ò…£(Àˆ;,>7Ùl\fˆËÊåT’÷ùÛ<<’òÂb´î×½·Å¹³Aq5Š|ÙÕ›8ôpy ÐwÑtÈKÁ±Ô¸DËLŸŒN€(¬œ]\¸4Ń„v…N&eiƒ|ñéêìí̱á°ü#ˆK#ZáîDB>wR° R\è5§¸¾ž g:0æÃÂàŒ+;L¼ÆÉp—ðt×ÛL²¬Ùõ[6‘•²ö…žÚëpãÃä¬Þ®óÀûÝÓ®‡5AKó<Ö £®G"ÁNøø‚vƒj(Íò®ÈwÔ\ZØÐàÃ]±¾#¹%È ~@q&et= w2ÒWT·•»4ø&ÍÀcZû:à41v¬C¾†•Ikéõø1ŸÓõ¤¹Ì ¤·†Š‹L)û +k¶á8YµÂ›5@ézoç„t¥jò]C®îµÎyÔNF&È K[!æÏ,EŽVzª¹TÒLj§‡v»vý +úþ…¥*ä8\úÔX8‡ŽCN×߀ä”ú†®«¥¨#IÁ(æj HE‡ª€ˆHbÍm,ŽHÒÉŽ›Â²;€ñqS(îë9œd˜žïæz +é̵câçãV»seôêç´`KÖû{rzÓj#„’Wyg¿I«ôö0=š‘Šžt|¹¢œ¥¯Œbõ‡Ú‘J¿€e5ìþ®Ûâ>?ì CpdheÏûÂÖ3¾Ðc1ë:~âû@|*IÌóÛvX3ûŽí@£3P1MIè‡ýu Z2 Q,ž\_`Ý6³}¨ã0zÉK ñ˜hè mÚ¯E{XV4´Á>]Fðùçû˜òÇ4Ë8%iræ¶å„óþÑȯû|WÐtÌéŽCÄ(çì2ñXZD“4©÷<:D'¿‚IãȤAŒæËåyK³.±ü¢j}‹F[¦rÍT9D#~E3ëºú×¾Zûiè“;€R¸ ×FÈehdz¢ÐLÚ¥ ¦0¦·R¥iI¡2ÝLŽ¤¢0¥¿FqLâ å6”«Mr•‚«ã<Å= +mËçqó¦Ë_Æ&ç9Éf»=§ÿ‚—½öÔA+ôaâwé=ã•yuÛÞñ0µìÅ2’ìLbáË€Ò xÞ¹ÿ+– ï—2±­O›.?œò¡äl¯ñ$Ë +¼_Ü4 f‚¯ôv 7.Î?ëàäò3fä'„B‰%ÎQXEèš[kZ™MP¿¯ï„Ø‘txª¦ßÁ ¡¦4Ž¶WPkdRÑÏ5i! N™ôRØH=bÕcƒý°oë*£ÈÅêäýûËÄöM‡ÛüauJAÕaíÿ ®/k]]ö*“—¢3³gL>6bFþ[ìØ>£ØóQ^çüßBÍè$m:Ñ#}H¤×‡Dô>¼>ÈP=ч¤{„Nø~‹Ûª{ûbMÐl<Ñ +–ŸŽ±DÞîwÛšð‹?ÖtžˆT& ÕæNÎ:™ºq—c¥]Ó÷5“íþ¾f‡Éò¤z¤áª®V›´]ßu„§#w¶™2vÔ7w=®ý®on=IGë5Pì4»Kt(ܬ±ÛÝOúf·‘•w·³æ„z‡Ïè† +KÕ©–sÐÄfÝR"§o0Ú7Ûµá×=4<v‰ Ó+œö € +'ph—%¥UÚ?ãÃpW~Ìå—6ã‹À)¤ƒOW*Y~óÈ]*h=}-C—„¸d@æCR&†Ãä@ÌûWóùFíÛƒ­9x5 ¹m2Ø6ÄT×+sFÜLræ+Zá ÓÄKÙIÑ\CÁmÖýÕ +ø6«&Ï‚¿SS‡þ^WE³õ¾èNùÿ-iÿ‡¶±/jå|ã :°ÛÄ@%Sλ?:}Êú} ûendstream endobj -1148 0 obj << +1665 0 obj << /Type /Page -/Contents 1149 0 R -/Resources 1147 0 R +/Contents 1666 0 R +/Resources 1664 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1117 0 R +/Parent 1644 0 R +/Annots [ 1668 0 R ] >> endobj -1150 0 obj << -/D [1148 0 R /XYZ 56.6929 794.5015 null] +1668 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [278.4002 485.7209 280.3928 497.7806] +/Subtype/Link/A<> >> endobj -1147 0 obj << -/ProcSet [ /PDF ] +1667 0 obj << +/D [1665 0 R /XYZ 85.0394 794.5015 null] >> endobj -1153 0 obj << -/Length 1913 +1664 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F21 930 0 R /F22 953 0 R /F48 1228 0 R /F11 1442 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1671 0 obj << +/Length 3076 /Filter /FlateDecode >> stream -xÚX_Û8ï§È£h\KòßÇöfoÑÅ]±èÎ>]ïA±•‰P[ÊFöäæÛ)JNœqºE€˜¦(Š"©)³M?¶©‹4M¾©š<-2VlÚá]¶y†±_ß± “"-r!àeet[ˆ:-j^m¶×J>=½ûðOÎ6ýFÓò´ª+†Ó2X¢H«&«ý„§ƒ"áOŸ¿<ÕÐã_úù0žþã«r¶åQ+ËS‘—þûØ/¯£_­v¸Üσá*qz˜úQe'Gzk¿OGµ{âWr¢æ‰ä(Ï꺰C§\ -veÒÖNϬ—ê¼g¸rÞÊ.ÎèŒÈ¢h¡Á¾¨îý<æBh%ÒËÞ:z³á˜èáhÓ»>HÅôÑhÇ L8[Ú,²j¼œ—D>Õ/…T¿—T„ ¬ñØ€0š&îm´Ù­4DÈÞY¢Bž¼è.ÈÜ&ò0§5¤RP¦†³à÷öÆ'çSʯ†í°ÓF^b ®Æû+ìY‰Óò¸ó†_Ž;oDHàJz+ÞI©!úê`Dñ:™Œ¡£ Q’â™ÞR-ÅãT!pº Û&ƒè¦H,xÀ·Üór>0“³äÏÇß·;é”ßCÍmk{È@ÁD4¤I¾qž_»ÊÏ_î9×*p -M&PÄqíèÙi7jÓŽ4¾§YyŸ"A¦͠ì‚d,"û©ì±‰kkÒ;¥)ÏR^Š:”&JÓ×9*—“²,Jן©IW؃È!6Š‚OÆ¥KaäÆ¥ÀÐU§½l†¤(.sÝ«Õ@BÃäf˜R‹eÞj1-£O.拪‚#/`h~>)×­lS€³†1Œ•ô ´ÅhmsV݈jµ75‹Êš5ß²Œ?OdoÀ7*ƈ·ö2Q¥ z¦k{WÌåU*ê*¹Ž ""!Ú–•ÐMåLÜ žqQ&ÚK¨#¾ºÔ7ÍŽÇ$%£(–qÅ‘`Wm¾œµO^˜9ÈïŠxp:¯çB£àFGBÚ/땱ˆ¡ZkÛµƒ²“íw„¼æº¨ã[½$x(ƒƒFlBLÀ{‰j8K [|ﶪ,}­UP[>é®S‘ÿº–vY•òZ\Âòâm$s–ò*/£ 6*,¬C:ç ½"åEžéjl?œ|BèE éɸXú -q¿–D"mX• ‘¹ÈjmËúÿ@CH®2#¶¦È²&RØš8"u£´÷Dí¦ñŽÌ~§¹G@ 8È°€¿¦¯Ðžt–æøúê¾QCJºoæ°Ù²(î Ç<Ž,üˆ5kõ46i]WMPº/Ÿÿ¨Î ‚oœ»p7ª2ö·¸ÅÓº*#¼Åð`' C½žu¼?\: jº·3äŠÅ.…îÙ|˜ëãц›À¥Yé›Îe<¨õÞd[°4ÏËòÇ-Jµ¨{È‘!ètE1‘RDPż´î¡bnó‚%ŸT+)wð0Ò£Tç‚KÏXx¸¿_OIŸN@a&`ËêY‡ -:åô³¡&Ä«»Û†ý5é˜âB€û}Ye¡ødÉ °]B楖x¬†Í@”üizT(þ¶Úxe訳vTn3o-òÁa^¨ª1ü8Háã=ô6³¶µ{Ó‘¡š»hW”P·Šj‰v¢æwЮ„Z[Š´»ƒhM 5ƒ© º¡s?‡+ì -ïp,'èñ+)jä‘jåQúk ©ï¯‘ÙYºÝÕ¡Eâ¦Á§âÛð´â·I-§Ñ;ÀÍÍ$b®»Ö¬Ý‰ÜQµ㩺›{JýÐà4;,ÿ‰f`¨º ‡W$‚7€Úù«1[Ë/¥nÆÏX «Eš Q S£»»·ž;šWïP{“øÄDN)ój=u”ö¬ÊùßC;»òÕ]Û Ñ_;Œ`ÝÄF -q…7ÉGb†N0bèKNôJ… $ȳÈBÏ"g¥O Øêåýµ G’^—=Ys{}ñJE½Ó6l`‘“TÈ‹«Ã}%­JüŠÆ‹ŸêIÙmS:_Óß Р*çóýÃì(š´ªŠúºWy÷ËÓü-1~!EŠß×¾6F‘íE†>5.NF¸áb¼¸]mþpùv¹ÿ`)iendstream +xÚÍZÝsÛ¸÷_¡><"ø"&OÎ}ÍMã´9wÚÎÝ=Ðe±'‘>Q²ãvú¿w ðC¢ä䚙ƙ —àb±Xüö‹”˜pø'&©a&“ÙÄfš¥\¤“ÙúŒOîàÙ÷g"ð$‘)és½¹9{y¥ì$c™‘fr³èÉrŒ;'&7󟦆IvøôÛ÷×Wo¿ÿ뇋s«§7oß_Ÿ'2åÓ«·º$êûïÞ]|8O„KÅôÛ?^üùæò=2AÆ›·×ßÑHF—#B?\^]~¸¼þöòü—›Î.oÚ½ô÷+¸ÂüvöÓ/|2‡mÿpÆ™Ê\:y„ÎD–ÉÉúL§Š¥Z©8²:ûñì/­ÀÞS?uÔ~‚3©Œ1 = +™1-¹œXm™±–,˜ÏVç‰á|ºYÌD&Ýü›.‚¿t¯™I&Œ{)L°8ðRÈpÿŸ×h P)‘Še¸{?¯£‰ÁèWWWÙ›W¯^f&®‚3@'¹$B°,M¥Ÿ7[•EµmÚäÕÓÁZý9ëüþ¾˜¦ü!ìêõsÈÅÇÙj7/"új‡É¯^-àï‡?ÿ_÷d\±f·X”ã\bIF·Mó_^ÉþÁ%`i+­‚9)ãV©úÂ0€¦oêzUäôýý¶¬«æž‚Y!Ì$u’q)Ä8SÒçòh(¡Þry0­VõcRÉ¿êª8X_(p #²Ó +´\#È>žUÆúÆ@…· ² v}Vð^äYžH³}q–eJÚÀóâGÜyrK×͹›îªm¹.húC™œ¬È8ãZé°è¦šÏZ‰¸àˆšÎ=ÓqF½!þy±*¶Q‡ñµ`¢PFô—"ræVfDxD•²Ìê,ÈÈ©ŸÞ, BÞ¼Xä»Õ–nÊfä,Œ_. ó«zì(‚"q‰c0Ö3­{ÅÓ &áÝv™Tçõ:/«K1 vjí–épñ!~Ó\êÁê£ð͘U­ÅO¡×õÐ+[ôr‡Ô$ œHm#$..Æä:–YnK„7·x²þš¯ó§@7Å–«+¸þûwïß]¼½¦»Í¹pÓ¢¹‡¸T4AÁ⡼傮¨¨Ò›‡bÓ®æ¡*´`Òº½˜YÕ7—A*Ûî =…;8Çz + pÊò¡¤jiRáy‡TçÆ‘* ®X—šO‡êëhm´.¯9]f˼º+hÉ…7H½¦'¡ôÊyE "Áß?Õ» ƒ,H7»¦¬îH˜é)Øò¿&µz5'wüîúG"šz±} â^ЭÄ:"¢*Š0o[‡iEôëmû`ÄjX„8§>®G=\;Ã|§]¼ÏuÜÇ[. +o˜ªfù¶Hê*)>ÂŽr•e +ªÓ:´\#J ö«%ÓNf Å á,Yû„Môcîœq<2<ê +TG,ˆîšÈ¢ÊoW! +Ï–ÅìWÜ-0Kø³-Öõæ‰Ø¡Xø5.¤£|<´Ç”áÌ!‡.Êãò®ªƒ[@Ä4ÐßO^…]Ä`ô}±µÖûó¼âÍqƒðOB]ïÇÂZïAÐt©†çµ¬qràÝäU³(6AD>£ìÞDÑ4Œ†Æ„3/<Ê|€U`AH!{å7ˆ/熿úvDFü4!fzK+îî–¡‰óÁ÷ýT\ :ÀŒæ@}tWVàó¸!äéŠ?Ãç'¤‚)!F‡Ã1„Ô…–yCÂæ¥Fðƪ¶c­pxfxJh°TtVR†°ÞÀ+Y×<ÝÊ;§°ÿºšÁHáA•ŽƒyXÂo!1+ 4uäõPe¸z@ ±Ä·U‰Ž«åco ¨/½ïË).³yÈW/è¶ö "UÄêl¿óÃX&[/‹|³½x&QÒXäUÌ¥:úFSrº¬ï‹ÅŽê^¸ï6!óË×P¡@Ì`Ÿ>ÇCtÏWM(!šÝý}ÈçMkîÌAÍ/o4êuÌô‹½ +%ÁÔ÷tð_VöNÂó÷Ñøù]¤4ŠYë>³‹œ$Ò¦ÐL)¬gB¡B¬íÎ!¡»ØwuAr¿!–Ìé,6´m哹PKc8 ÃÐmA×½ í(Å„è5¢Jê ~l»æ‡²xÑD¦Lp—ö2º)§ÚêüH/¡21<‚«‚b¯ã^Ð9E]c:õC:ÄléZ?P H‚á‡`¥ÜÇѦœÔŽw«ú¶Å_u ¬¶Ÿpʸáy„ÓϪ;ý¶ç†èJ)$BÊ9‡þï/ë¼Ùú¦40=´ÈbŸÝѶ¯@?–>¶øQ¾€ªwÛäë÷7o¯þA4¹ào»¢ <> "o”Ó-³Ê‚§î§Ÿyʃ)0lkÞ†í ƒ×CeÐË»;¯­ ç€D°‚ñ‰´D—FºÚ­o#«¯ÖIœ”ýÙ^3"QŠ+õC¼¡ºÉsBÔ@ÚŒ¥ 2 n ¶«ú±mlZÈ„ÅúÍ*X¿\ ûé¬ãëâ@76K½â¯ª 1µK,óYx0ˆQm7# yÓo÷·Ó«ãêSLš¡º :ÜvºQ S¯V±z-ê”ZʶgUoÑ #^™0æÙX¡Rû bÉQy:c2Õv/Úf°Švnmý› ³áX€ò–€+¾/1¢=Wñ=,\›í…ùÖ¤Á2£"Mèö2ÜÞ¾Û­ò0ëg)u§VSž¿¦ëb"r^€8 HÆÎ}Ö\$;÷Þ”>öÁ år êʧq BƒL7 d ÃNí‘D!…dn>«®ÐŒóˆ„âã}Ùõô°NÖËçó2ø®^Ó#úc8nƒßŸä0õ‘Þ mÔå{Kõbñô\]dÖ‡|ð%/¾äUè˜Ë +¬y}¢+½y1e-“F?ïøY¡mpcÉ ‚épÂ]7D¶è5 *¿Ã·›c«s¦œ6ƒÕCnTÐEÙlÿü}Þ4wÆ|-eR¥bOCÍ[½´èôÒ¼Õ‹žP ­ù~¹çRüÖ]‡ƒÄÔ‚˜€Çö +s ÝkSð¦â´Ãì\ôw$²Cq,ª†ôj8’Í æ„V-¼…òÉFG'·Ž‰7¡«äGÜMiÇRןänI;iØuŽ÷¢{qvhÜ4eÎe±*=Í”RvûÏ]²Ì¼lðasX¸XÆ¿³˜õà5E¦àЙƒH—Ÿôõ[Y(GEš ¿~ÿ¾YQ^ì=ªÍã +qÆPT÷”@ƒ~Íù™e”ÝD*ÊzxßþÔs_±éô´™Ì&%£#\Â*{ÀÕųþ¡h+ñsݤ¯ÿÿf4¾Vw.û­¬ ”ørüÕUkdÍO9ùžPˆˆü½B?®@áŒo–Ç¡ý vDAÔ¨ñ:µ¾¬í¾(B±iÆ=c<éð—)úÄë5üˆÔUr­y:‹=~Ùo-ÕSâ+6I©æSá¯+´“§«…¡µF`uÊZ==¾bkqÎ 7úkqpºL=“ðŸÅÖ '$5Ò¯ÛXÎ1“ +uÚV™„úÍfÏ$ð#¶ú„xÕSâëµ”Å/Fœ¶”ãLºÐ6†’ù÷ì„'ö”ùRë~±÷ÿ(‚ð³‚3ʘB~½á“gõS¨ØýŠS[¨þœ/”¤…2Ä)‰¿"Òñ‡lüðƒWøEcàê©þ_ì¶Aendstream endobj -1152 0 obj << +1670 0 obj << /Type /Page -/Contents 1153 0 R -/Resources 1151 0 R +/Contents 1671 0 R +/Resources 1669 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1158 0 R ->> endobj -1154 0 obj << -/D [1152 0 R /XYZ 85.0394 794.5015 null] +/Parent 1675 0 R >> endobj -230 0 obj << -/D [1152 0 R /XYZ 85.0394 769.5949 null] ->> endobj -1155 0 obj << -/D [1152 0 R /XYZ 85.0394 576.7004 null] +1672 0 obj << +/D [1670 0 R /XYZ 56.6929 794.5015 null] >> endobj -234 0 obj << -/D [1152 0 R /XYZ 85.0394 576.7004 null] +466 0 obj << +/D [1670 0 R /XYZ 56.6929 636.8504 null] >> endobj -1156 0 obj << -/D [1152 0 R /XYZ 85.0394 544.8207 null] +1361 0 obj << +/D [1670 0 R /XYZ 56.6929 609.3387 null] >> endobj -238 0 obj << -/D [1152 0 R /XYZ 85.0394 403.9445 null] +1673 0 obj << +/D [1670 0 R /XYZ 56.6929 172.736 null] >> endobj -1157 0 obj << -/D [1152 0 R /XYZ 85.0394 368.2811 null] +1674 0 obj << +/D [1670 0 R /XYZ 56.6929 160.7808 null] >> endobj -1151 0 obj << -/Font << /F21 714 0 R /F22 737 0 R /F41 939 0 R >> +1669 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F21 930 0 R /F22 953 0 R /F48 1228 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1161 0 obj << -/Length 69 +1678 0 obj << +/Length 3726 /Filter /FlateDecode >> stream -xÚ3T0BCS3=3K#KsK=SCS…ä\.…t œ;—!T‰©±ž©‰±1ƒEV.­knj©g`fA‚!ÂVŒendstream -endobj -1160 0 obj << -/Type /Page -/Contents 1161 0 R -/Resources 1159 0 R -/MediaBox [0 0 595.2756 841.8898] -/Parent 1158 0 R ->> endobj -1162 0 obj << -/D [1160 0 R /XYZ 56.6929 794.5015 null] ->> endobj -1159 0 obj << -/ProcSet [ /PDF ] ->> endobj -1165 0 obj << -/Length 3113 -/Filter /FlateDecode ->> -stream -xÚÍË’ã¶ñ>_¡K*šªŒ7ÍiýØd}p{o¶«Â‘8#ÖJ¤,R;ž|}ºÑEI´É(U.Fw£ŸÄ„ÃOLœa\y=)¼f† 3™¯ïøä ¾ýõNDm3Z)ø“ù:3Ê1ãd1™‘|ýñî«÷RL$gÖJ3ùø8¬e ǼÒ~òqñóô›e¹é«íýL>µ÷¿~üž¦iV¸Bà4KVx?üð-A{j¾i›_8—O»mÙ×mCƒ?VÕ¶jæUÄ('žy+mDhªÂÈ1BeBhæïÅ´¡ñº£öa{/Ü´-«èêu½*·ô§o±5#´î/Ðj1]¶ÏÕg`µÐÓ7øÅMûepUXü¡æ±z&| u¨2RÓ>æ¨nÞ ãȪÌ›Èj·›/Ú™i˜ íçºzîØýL ›(†Q‡Í%èÓ:$cøŒßVUDÔ-ÛÝjAýçvû)öê~IÀÄ®¼‚í$Æ™uCí~yâñAëSÄ°n£x2ŒÍÛõfUý€–K—±bO @´mÐ4ýeÝ2ã8- -Waƒš)m%ÂÌ ™æLZEBµL€ap~ƽ¯Wq/¿£ÍïòI:pH^”ïÛÕª}Žòâäv -©YÕ]O½`ùÐV sø·ëª¨ý’XP»ëÓXu¬,óݤÔ_´ó.>¿Eúï¾û8øoAè…žh!™å^¢óÿíîç_ùd±âû;Δwfò 8ÖwZzVðB¥‘ÕÝOwÿüg%:PˆŠyÁÕy -h\±›f¢š%žfÊÁ¾x燈v œ0“)¥ÌDsͤæEؾr¾:–‘‚9«üð „$™wÎå™ gc”!:à€D´‰œ 8À‚¢|D]QÜxè¡Ê)ºØdlµÌ9íâìr±ØV]w, -e5¨.·’DBxEÊLØcA€š/OHô³ÚÝ’Æ„ñ -‘šC^¢@È º[”ÔsŸÄÝÑ-*4Ý}þ}x¡ C»ONm´cÐU.¹½¨¸GË€ p¬N¥à‚ÛaÇâ3@˜„œo26ž×Ù#Z¾â Þÿ‡‰[L5½bâÊÁŠ«Kº-4ä©…V{àW›yÂ8£Ì©a¬‡dfµ[À¦K +ÞŽÈ„ñ‘N2© -{Häí¶–Y@ªùîjcöÐ…¶©bgKí8K<^ôW:žr‰zsbøàÁ¬7Ü¿ãѨÂ@üçâTÍr†4ZG6Þd8uÌí³™S>5eÞp{;>ŒWøÔH;Ö€|n¶Õcý{†Se È ñè,§*|‚ý˜Unß@qz;VÆk¬z˜¯Å‘稹¸ýjbsf¡Þk·v1—F[Ó‡Î8“rHˆwª@3·:F¾šñãlŒò”qYj‹fžÀ.¤+ô`‘)‘}CygWU'j -&1èI Û§ u~M ð§4)Ú1^¤ç§j¾Ïˆ!чTÿX½`Œ(Ä=''$Ô*N± ÕH>ÀŽB×­l2¹/G™fœ °PÛx ±éJ€5  -2Æ­®¯¶Â+Þ0¸/…Ö=gb”Œ»Á!hgAó1S:Æ/ ‰4¶¿BgK —â—PaÙó~]yÅ8™ßH@¾‹RÞ@"jÕX@ç"X™JÖNgC÷ šY¹Êðl3ÎúóÞp%º¶·âyÀw‘gÃj­óœuíà:<ÓÎeÏe³ø*ëà•cZ€EŸÛbé=D<n]k¦¡¦x½[Ogc”™mæPÞq m ¡»ÝöWSv¶ÅÈ»ÃV)Ï;cù -h4:‰[q=`¼Âµ®•úë3ö¼pÃåÀ Ô^VØiÝÌW»E…ŠiÎ|3‘]8~½ÑXQÎDzLe=HF}Ü7Pƒˆq6F™‰î*ÓÂíNòÈlATq®ðãcµ| …ˆ×EãJQß²R×À…,®2È…Ñ&ð¼h×eÝœD2åYám±‡}u,Kgc”¹h&!e0GTž;â–q<3â™ÔvúÛî^€‡SFøÛõ[:ªÔfú¼¬Ã ?×álù1ŒÄƒI/4]q@óí?Ñ8’ñ†Æ1b§ú½\ÏrGþ›t<ù‹”:cPÒ5رdŒ/¬¯ºží÷ãˆW°>ëlŠMˆó‚ºŽá{°!H€K}E]%L°Z‹¨®=nì9u`o§®c”ÔõÊj^¯ËÕuý{È®Àëâ%…¨V»-ÔM_=¡g ãŸËÕ.$ið…Ç)ûÓs‚‘ÆЗ®Ú”Û²'xØ -”]—»Íùb¿؟¡©°¡k8<Óï2§r<¬3Ék -©rŒjæµò‡•ñÀƒÐx¼sÐÅmJ7RF"OMÐѦPî<ÃSâsøŒuV×þX7ÿÀU¡ðòZå" PRïƒê>{ú?ÞîôŒòÂéÿ‰g’ó£ÓÿwP÷˜~øÇg»af¸„ìâ%ñÐåè©çá²3| K ÝýýTø[ç{ÞU0%„HË¡r»Tø~iÖ“0ÎÆ(3Yƒ|ŸC61€]öC,‚j¤¬¶iéîì‚=Œ4íVö0ÜW~9ÎaÊ9‹\`É|í>LBÍì¤2Ñ"ìy‹H€7´ˆÊK1&ñË-BC‰a±gÆö®]»äÚ÷œkG2=Ð1JÎÅÛŃ{û–Ò¹Sp(: -'öuð8Z¿›· CHU™îá|éAæshQ‰P¼××ãÞÍcoY~®°ç¦åú¡~ÚÕý }À£/­ê-uÊüo<»ÓŽþ­w]D÷På¢à¢î;N-xœZ¼L¤v³¡»ÙÖ%¾4©h<,z¾¥™äut¼× -Ÿ6ô’fŽ&û@d !{A¹I1ùO!&Ó¦¤Ø.ªU½®{z¥ƒòæ|ú¡§ou„Œ7Ù<­^h„d;o×àçÄ^x‘!²`H¤òf®“8ÄQL;„KÅ0 ›ÕÐh³[WÛzNÃõØ­ñÂ2Ð@¥}x ‚€tŽ4ËîExoåâ[%hCŠ-ñõ¶ÿ—O,ÓP¶(E×Ç/ƒÒ›"Ÿ*zMä¦kŸ³yûè ”BaÖøH j+>~ …ëŽÚ¦¥¶ëËfAŸ4²!rNC€ &fFar¼°^äˆ C&d)ät¾ÛEñ÷°ëØ ôA¹},õãÅ:‚]Õͧ ëd·bؽøâixGäA4» ¯T ¤†£GévkªµTfÖ·³ 9=?>TýsU5Y–ÙaI’Lè µaó@yÞ‡òˇ ŽÏ–ÞDÆö³U;/WÅ(-8õyrxk\òy•ãàï²ge ò€`T/U2uUØ$V*û¾œ/C"Žíà~‡2žØZ¨U:¬i*ž žÎ×ãã£2RòñwHÂþE -²>Ÿ2˜ÄáÎG9ü)¿²ÁrÔ™½ã7àã~€ª;'è¼UðB4²nÃÑ2–'ÁN;ú3Þ*ü?ÚªŠª•YZêð€rõ\¾ÄE^í…ºbYS¦iM5<¼ýøñíÃÍo¿º}ŒgžWp…ùýê—ßøõŽý÷+Δ5úzœ kåõú*ÑŠéD©ÐS_}¾ú1.8uS§îO +ˤµÙõ\%̤°Æ€ê„Z!µQpÛÚ²TIo[ÊÁm í$½ÎTIânû¾íK:¿Ê{j5ív×Ô¾ÿôx÷þgjo¶7ÂÌڢ캪y¦¾ª süä|‰D˲èËõ<½à3bÀŒL4KlšÁ E•×»§2--3Yf<;‘g\ƒâdÎdD2­žh>¤¢ûSÚ¨pÇeþ¥œW¿ïÊíËñÞB&RÒÅÍ#ÕÄî#é$Š -Æ»ß5p…Fõ7É̼_›€´ÜÍÃX»é«¶¡Ñ²ÉŸjwï0ÐUë]÷$*xîW%QµO][—NîÐýÃýgjÐ!Eÿ²ñ£w?þ¶¨²ÙÏ7BÀˆ æ·*¨˜äN+˜ÕZ:æ›òk¹%X´¥×“Ázî90Ù6ge›¦–e™’—e;¤:/ÛHåd[öÅjþ\ïÊSÑr˜ššË{Gª‰ÍG¢U oxÜý‘$˜šƒÓlû¼ŒàÂUªH Û_<´@œµ$f¸“«2*õæ28à<å|öR851“2¥Ñ¹9E¾ëœÁ¤1ÀUWnI–ØÙÒoÞ÷åzÓAèt;’J@73ÊŽu‚x‘ÖÌœ/)»vçŨ·hÝΪ§ßEµh¾óíUþÕOٯʆZEÛtýöÆÌv…×zÎ|±¨ðžgÃÕò>§VΊíí,±¹¥K§¡pMþDb(Æ‘+ÜSù©%-áaî}bîŸaÜwåï:‰u“†Tõç F€¾qk^1˜Õƒ TxÖ_9W»n5ÿO۔ݼmæÝj×/Ú}s̉ä‚ÉDÚˬDª ^F1€CÂ13ÿrrWJ‘ˆ•’³&_—AUq üVõ -v%õy +«¯NEpìóÝß?$ µ~¥EëwÀ07¤rªn¿ÌȱªçÍ‹›e³ˆñ¯ŽZûmÕ—Ú·à E¾wQ.ó]ÝG:œ"˘*ñözQ&ÇîA–ÚDø©M;á Â^ ¸:Kç"½¬cCªó:©pÇU§¨ó¢®Ê¦ïN<³þ\d RMp0:¬Ná´VŒY “VY=3¶÷¹ï¬nĬå5©¯_|ÿzS—k`mÝuø™dÐØÂèðŒlÝ‘„5Ÿ›6ú ìx‚M^Ž§[ЖԘÙãÕ$ÝK2Æ…GºW¬ª¤°œÌ°Ö,p|*#P£gp|Ê& K’Ó&„s¤b©§/‚rN‘1«dX —³nSÕòåˆå~ßR£+7ù6ï}7ÉeÒ:WB&ô7ßõ«yómÑ®ójÊ" ¸ +Æ­ûôi¶%g‰Œv‡"œØÞB,ÍB,Ý. ©¸™#œS—%™‰w5m \¿¶ž¤‚øVæ‹óF ,Þ|) ©.e rro»~Þõ€Óº¾*N232ir™H5ÁÁØ(Ai–Yp2ºCttPz<†Á_ ¿”åÆ»]AQ~gpDËvë§~%ð M<ì8%E`,†ã— +˜ÚhYÛ¼ ‹›”ŒK‘•j_õ+ïíïC²4r®£9Ág¥d†Q®w^Öšó’ö4È#ZIÿóêÛÒ¹£ùSÞ¢c0r›&—$Ç ú¸X8p*9 bhSŸ:d.(Ö0qãÖ\I1»ëi¾óÝØðØ—ôK‡›†ÔŠöpP°Ïv]Q¸Nf‚lé!§Ÿ~›7ˆ|udµnŸI „–È‘:ÒÇI"@=v†é 4îš‚bj„ƒ©Ðùo G¯Ïg¸ãØÈwFˆ%þ@jé'Ño”ÓOà•…dÔ5@{„ O›²{°"¿úÝr zÉ_Ú]€¦AséÚÀT!=´»þ¹=Ô +NÎ7D½?[÷†žw]9U8€ +œH¨l¶íWÀФ°§VV2Iú:௞D&L¥ /ÛÛ€ê‚Å*gsUS­óz¾õYÆ©wÍ€CÄ—YˆT<ŒƒoÊ bÀwˉ˳€3MúB¹„r¡³tÆ Cn­gбm(Fèt”WuDâ}¬xVX¡ªkšÑ6õ õA&GÓlèHË廹‡é€ñ¬=ªRô«€8® ðžr0%ÆÉ"¦”,*’ÅŽúý•‹ab‹º©ýû®:d@ò+×¼dÏÎÆÐÓÔ峫8ÕWÌ +Ÿ]† Ô£»‚©‚MÙä!]ç/1¼PÉîk¬ñ•!'Ù.±Ê×ÁR—G^Þϼš¢ŒG‚=(®“ÿCž¡2Î4W¯„¹!Õy³‹TÎìàDßyá²ÆÓ'˜²R_f RMp0:lš2•)3fÁKÌjxЦaÓ« «òCÞÕCˉÓuxÌëÚ°I?ñ:*Y 7Їꉎ×@”ïîß~¼%cÌ(‘˜A uìÔà¤"}­ZªäQ·Ó(è&‚*4B€°f‘û5œ DX£àuüÍ>m”×ûü¥ kl+J½p¤l–­¯#uG»ŽtT¸q…¢ˆŸÚ~5†`ëÀ¶/»@’-#i,Ô,^àf«ÂG« øÌçÏ)²HYª¬}E‘T9P‘uõ˜7ë¯,Z]Þ7RMl<6ÖŒ¥6MÇ;O ÁÄ{1jHÁ´Ð&V04§N z9¬Ç˜ŒÔFi_E Xl—?£Dp$z\ê\P‹œ³# ÂØ¢ý`$–‹R*à9êrÁT߶LËäË9সš«¼faáë1ÅRèÜ=KMâ +]4¸}¾¦ÆÃP.~>œ0!—“u‘¯Ï¡ž‰¼%LœTç‡Ùš7§Õ¹@õ +§«yž¤†‚²1„Hòã½q¸_Å!”NG5$n®<•?]¤DÑ~çWw +ÃÕ‰·"XI¥MÔ‘csù[á0¹RI()&Ñ `ûPZL°nÛôúÇ’¢„b4õó§·Ôøè\kº õ"¨7¢“ÆÏw‡‡_W7âHx€%²$j +CÌ?4GŒg3s 'š, 8‘.lîÐÚé~©f™Ž5WqµÎƒ¹‹Á³Ê¡v@ +G°»½žHŸ1aW”tº(¾ì•ÉÏ„op ›—ß6uUTý—IÆŒäÙŸà2ð&#¿J¾'tŒå¥‹Á#ðR{à¤Mi‚æ‰RØ]¦3êQåœ@TÕI6ÈŽÑMßRb” czÞzÄÁñš\´ŒhX“oöê…EýLÈ ^Ö#¢É”³TêdgΨq1Òe8(Àˆ±—D­§’~]Ù1š±ÇZ80m\XBÄô›¸€2ß4ÓJN°æäR^,þ*wدªbEÍ«,®…ïºð ûv N¦»Ä $ìŠñ$㸪£siìùëJ3ô1‹è¶eJu˜¼owõ‚š>ý2Æ][¹Ä/rzgl [Âp¿Û6~ +U˜ý°am/¬Í¬ò£•ß0¾}„±®”ÚÅÅÖÓ#C*¶y·: »D†…(þJItHuvEªƒÎûvÞµùiA_æssyûH5±ÿ¸l˜@2b`Òz \—Á:ú6|¯%¹ñŸo@£X•ÅlZ¡q0¾Vë¨ÃAdnÙÃïÃCWö4;ÆTDèb"6\Ld~¶ûÞ„â¾K‡ø,_¦ª_£ ï'DA•‡ýtŽ,0pzyȤç>.cãìÿôp÷áîc4=ç~ñªoÖí6›–Ô×oi¿¢m° HÙ—TÁtã²OÊTJ‰’J=ƒ*›aJ¶vï:°ÛǸPðÓ³Ïíº‚’Šv¶j÷¥OÕ}ON3QÓ± K×øòÊÇxt';lú»F¸E¯±xU-ôL¥R1UÊÜKxt§Ï»m¼Pæ_xá°[,3¡´Cäû°ªŠÐÜôís'Ç,èP6ºèîíD]OU£ ß퇽îLˆâ€M‡…̼®J"c;8 +Ó!mŒÔÎ&ð“4´‰óþ‰ %©~Å? ¨.ø§@åÒÛ²Øm;t´Ç¾IA'qqëH5±÷øÛ à†m~&jÃÿd9Ñ% N‚VRiCø:<‡–¬Œe¶²ë;¢òàŸîàMÌ+¢÷_…ÈC­¦øZ#î¿m±ÂM$ùJ$*qXdßn¿xÐŒŸüMWMF5@Nx_B–’7ÝÞqÀ“à'´ðÅ•uˆÖ ŒŽE 8Û†¡C¸å‰¿´!aO<)Vé3öŽ&Ô´t¾x¡‘/ôË+Ϫw4BÍ=Û“¿G¾žñˆžóa÷N>" ŸÙ8aQ½ÆõFx˜¬7•ãk×?¡ZŒ2Dÿõ£ŒþHâ·N}?¸@sŒ/wRf)kˆÇY&b°¥êT·Ð ú,¸ï¦÷É‚ÖLH}ôB:¼oG¦gôf®]ÓÓ³gÒP¦>!ò¾óPZ~×Ñœ"‡˜ÿWÇz"ó`ZýöM¹¿¼ÙSéùÑ´ö‚ÈóîܧµJ³dºÀÊc™øþìöðM2dwÊœ{ù¬ -1Òf)¼ýô¤‚¢•g&³ Öÿ r8-endstream endobj -1164 0 obj << +1677 0 obj << /Type /Page -/Contents 1165 0 R -/Resources 1163 0 R +/Contents 1678 0 R +/Resources 1676 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1158 0 R -/Annots [ 1171 0 R ] +/Parent 1675 0 R +/Annots [ 1680 0 R ] >> endobj -1171 0 obj << +1680 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [356.2946 363.7923 412.5133 376.6291] +/Rect [182.6146 300.8791 231.8861 312.9387] /Subtype /Link -/A << /S /GoTo /D (address_match_lists) >> ->> endobj -1166 0 obj << -/D [1164 0 R /XYZ 85.0394 794.5015 null] ->> endobj -242 0 obj << -/D [1164 0 R /XYZ 85.0394 769.5949 null] ->> endobj -1167 0 obj << -/D [1164 0 R /XYZ 85.0394 576.7004 null] ->> endobj -246 0 obj << -/D [1164 0 R /XYZ 85.0394 479.565 null] ->> endobj -1168 0 obj << -/D [1164 0 R /XYZ 85.0394 441.8891 null] ->> endobj -1169 0 obj << -/D [1164 0 R /XYZ 85.0394 424.9629 null] +/A << /S /GoTo /D (notify) >> >> endobj -1170 0 obj << -/D [1164 0 R /XYZ 85.0394 413.0077 null] +1679 0 obj << +/D [1677 0 R /XYZ 85.0394 794.5015 null] >> endobj -1163 0 obj << -/Font << /F21 714 0 R /F22 737 0 R /F41 939 0 R >> +1676 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F48 1228 0 R /F39 1151 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1175 0 obj << -/Length 4063 +1683 0 obj << +/Length 3742 /Filter /FlateDecode >> stream -xÚÍ[[s#·±~ׯ`žB¹L,î—¤ò°q´>›c¯[©<8.Ÿ5’¦–äÈœáj•ÊO7nœ!ARŽ˜ªSªÝ1@hôåC£‡M(ü±‰ÒD;î&ÆI¢(S“ùò‚NîáÝ×,¶™¥F³a«?^_¼y'Ìħ¹ž\ß hYB­e“ëÛ§š0r èô«ï>¼{ÿõß¾{iäôúýw.g\Ñé»÷ß\…ÒÕ7Wß^}¸þ~Qá¦_ýÏÛ¿\_}ÞéHäï?ü)Ô¸ð8@õû«wWß_}øêêò§ë?_\]çÅ ̨À•ürñãOtr ëþó%ÂY5y‚”0çødy!• J -‘j?\ü5¼õ]K ”’Í•˜Ì¬&ÜhuxØ0…acQ9bŒ²;£Î´%šQÜj çÛ-‘l°%FgÍÄ-¸ð;Ò<îòÄ¢„sÛf/` -ÂÖ–Y2KgCŠû³s”(¾;½ÇvÝãß¼ã|Жq(C`«·+”;}ÿ|šA¯ÑÒ#¬ŽV›åM½.ŠX­Tl¢Æž^?ÔŠÄÆÊ“ qB¸Ø¬éÂdͲéëÛ0ã¾ •4þ|X_2;m7÷¡æ#Ô—H{2cRÌ#N)î©>5=6efú©Zlê.”oêEû„E;e”ËPÙ??6ój±x?ýHuׯ›y˜‹ÓêÍ%›vu(ßÄöajóºë`œOe} W«fu9TO«Ÿ* Ô¶=pTجUxݵË:4˜W@ñK(s:­V©s_¯›îchñªèÿ}ñ[x°ðzþP­+˜÷:þ„n£³sƒ(3Ýt¸@,ù9) ~>.ªyýÐ.n=!€Ï®^Ôó~Ôv]­nÛe(?4÷³¸ïÈÅÛ?PÉ®–IBÁˆûVc_g$è„K;™9E´dâWL=™Í8Qìû1»¢#Viy®äfg³+CŠ‡íÊhzëú®ùü2Ë"õ–Ep7]ÕýS»þ*»ÇzÞüƒRî¥ -Þz©^x÷m–X)“]Ùg0ŒX\çÙ8”)ž`‘€´è£G<ªnoKÖŒ \ð•a¨®àaïÚÅ¢cñäY,@káY8Ó-ªî!š/ï´«¨×ì7Q³%òr”$PèêU¨‚R(Dó¯Û»PwÓô](5«Ü16¯ûeÕ}»c¥^_: -JÜ,Ð@ÔõŸA—[ÜKÃ<5|Ve‡â„“w”[Jœƒ.Ú(â¤f¯ÞÑLq6$¹¿£ÜÂ.Y@6¹Ù±5DSvtY=‡·àŸÀ#Û´Ówí:Tן«åã¢þ2b;ÊÞÉFJŒ›7¶4ž&ÊP6ð‡H·Ö(5±Tì8¸¤yû£ -À hIó „â_ÉCQØ䈣ËTY@ -´5[ËÒs¥ŽÓN¤Qx ìqô?O”p"}ÃK,’ÒŒ C˜ç,ñHžq3V¢ ‘ãqKûↃ&öÐãìQ ]öä²4‚6ðÂØ ­‚A° -ø"Ìx¿ÿîÕ`r0³wÏOàï -<âíïçð¢Y}jŸÆí˜îO:ôèæí£G8øUÁŸ.T$ñÛ±¾´<(nbÅVA xkû‡ª%Ä3©.v& 5OÍb‘è÷ó‡Ø¬šœ•LÝwaOî‚‘Z†_Õê9ütƒ¡4Ø¢àä¯ ™<È!´¡,”ŒÇÑ•„³È–õóîšĘQÛv¯5½‰àlH±7À¸¡1ͯ¹-B àƒË·%Ì@‰4h­QU àé@Iz5Uxt€ù#Úö¿qócE¸qáìÕ7ÑØeØX­ÃIÀ+ú5,ôì;8K4í*êR=߬›>?¬SCi}ìê”8§NiIŒ>®R -À… ÒžR©Üîl*5¤xX¥Fó[4]ÿ¥*Cc_BYBMÛU+Öá¹lƒP´wšŠäå -ŒBƒóWî|œÉO°F ì—:æMÙÜDñ«ðçl¥@ÈáÝØ.#lÇêe3oíª õЀ Fxð‘6Õ«Ûèué6TI"©#*´ÎsiP -⼜dêqPƒ8œßœ9[SJÃRaG1éBŠè®]ÍVõ}Õ7ŸP65 ->ƒcMxÛ¬úúÞ‡'àž–RÜDkBdb{,Â7—kDPø‚†º´‰;˜&6Ü)$'5 5_l:˜žÆ0Ô*Üô=Áa¬ù¼~ì«›Αën -¯–ÍýCjï6k0äëPS— Ì6þ¥ÂqÑaoý¡0oa½Ÿûð£‰ùé¡™GájÒ«ˆ‡Ð °ÁÞ½Nþ«6šz!âÇ%Œûx† aŒªسÒpÊpÀãÜðÕV:œ )îÏQN¤…#Ðh†Ðc–Pf - íô—M ”1éˆÚ¤mÇꀖ±äczðŒ1=(ùè >Ãyƒ££P;3í6‰FÕlünüC÷fé£o–Ϥ¯»žlñ×îj4C­7ÃsMY;|.Kº2ù”†D?ã‡|j ;já–¹ƒ; -:A·|"­$Z‹×Gh3ÅÙäþ®J´0Ìl>¶©ñ@žÞþBለ‹+½S±'Å€U(u N†C-½'Š³!É‚$cxÕ›šÔÌ+rûTZ3H†Ìqº~Ó£ @ -s–Ö*hîžm­™â‰µ -°CŠÁ’FkÅ륓 þM*‘œ¤d|ÿpqÐÜ ²Ø" Ť¬D€S;†g9ÀT`$@#nÔFbdÀ -ŒÔ”ÏÏ“HgC’¥˜„€Éi¾ù¨ÐHE“Þ¹Býô1áý%ÊÙÖœ)žX³Ð°f£ÝxÍG…gp}£¼%ŽˆŸ–&Êð£z# #”S}¾¥gŠ'–.€-‘/Ùn ó‚Ç6;Fo¹Ao/%hE ˆ-¥ÓE4ùc— ¡ÝâÍcj,?&xië…C7y=*ÏgC’%áÀ+ ŽÔìÅ–/Ìàtéo~pù㛟‘k6Š­Ý®gFcÏpZŽy’4¥!±¡tS ¼p}(\ˆPß*ÏêXÜÄñWK£T -¬ð#ÂÒ Ó³÷³ £©X{Ž°Ü¹Êw.&&ÐAbÖŽ|‡mbþôÇT炈y2 •Z±2<àHÝÜž>£'@ -ào6ž8Œ¶¾Úì&Š³!É‚Ù0ØÇÜì$@'OKÃsȹn+0~¥¨þ54s—Cç%n ÁÇÑãEôa"nþY<.¥†ç;. (;.fXý%Ç%=ÂNFúü0ˆóbª·ƒáÑ.ž6« ÚŒ¶qvà°rÚ¿`(0”‘C¼D©ïªÍ¢$–`©¬Ì™d{­Œ[†·E/¬QùV{»"@g¼¸ãpXq9Ö³ãg ‰âlH²à¸Å‡•›Ùsn‰dl|qó˦î<ª„¥í¬t†’\!ü6ae¾Ûg‚®ÌÎ]ï²úÜ,7þèÆðSÕ,B|Ñÿ\¶›æŒåÊwdÖ`g½w)±Ó/-àò‰µ¥è´^ VÅÙd¬H Ø _nvŒí`SœÌ -’ríð"›pôŒ#f=ð{‘t£Š¥§ªR̓òÄ»ö>uõúS½ÞéÞõÕºqÖÝpnqk@y¾‹9œ‰yYÂæUŒZ·xñwÈâsƒ½¯o} ÜN»yµCl ¸]ÿ®`8@6°?É’ýo.jE¤æ;²Ú®K‘ A8¸ÉtCT æˆ¥Ùˆù;Gaåôc³hožûº+a*%\æ>ß šA× &¶|ñÄ–õ}'žß NÔ;Fœ«œÿúõfxÿâÞ79F¦ÙÎ6m§/D> €|( u(zÑ'‚Eßûâù·Yh©Íù¿’Dp -ÚŒ8‹Áµñ.pÃ\bŸ®šîN N!‚š æP³‡yãKΨ ©ÐCËxMU›U×ܯ°ÔùÒ¨0 D¬x/DyHvkͬ”ÚHI0×¥™¿bjïJÚMÿÖÅ º½8‹A¼¤_âÛ5±ŒêmšSØQ-1ØÅÇüͦé¦î²]K×Fm4PÕ]½H©0u?º‡ ŒŒyÏh)ÓánŤ ÷JìøßLŸÁc®ã‡âÃr F×Ѐӟƒs)Ýõçvg»ëR<|×?š_0ÃéÁBm!3Î5¿LñÄ},Øh‚«¶–) '%’¹ -ÇÉ} ((º™dàâ^좀Ë*§2¤Ô™üuC{2;-‹Öä>Aè®ä‹ÀÒ³œ»Ü¯7õ9Å—æ -›¬s짼h "”IŒ)%F*fùKY?ä:{£JÛ•UåfÉóÝ–z³Ö•5 ÆA÷RÐ@[l_ ø8þ7÷MYwŶÎ*j5›b›ueSÀv´»ü7¸rÎÒ8´´–vëîËãíÍ©ž-—[Ä[´n°jš¯»]‚‡¢ppUÛàœÀB>`!ך¥F(@…VE—¿„Ïð…`‡ìV†)n¸Ížš×‚Mä…³„s½H8Ì+sb (BÑöò9ýðPˆv»Ê…ŒLؽm +~Œó„E\Ëóè{¨üÃõr¼O=&à¡è:+"2J`ËÖÕw•Ì Kt;Ž½í WEú Ø[Ià ól×KAâé%É!´e[ÔKªÝ=PIò7¶\¶ôiV5žè}Ù½Œ&N‚‡/W6þÖ +aÈ…f\%éXWÍ–$«.žAx_½œÕí¾Øzñ{|qÝËb•íªŽe;Ã+JœðÔ‹WÝÌðÊã'‰ðy{ ÁŒ0ú[¬•4Öøšyk¡Œ0éøô\ô]s¹ªÿbFLÎV&iïl±Þ÷v¶©`’­NôñDÁ[³£ ê +5Ô¬ôC¹,ÛìÉJ=4nº¹gTl²-ˆò®Ê¶4akØtl&žŒ‹½‡šA?öð NŸ#ü½t‡ƒ}›o˺4«EL õ‡TQ£cõÎ0-ôœþyøw–<÷[5PqÆ“á^Íj ‡z‡Œélçe-Ñ”êQ;‘4dƒªNTm7/hàp —â,êhŠ{,fp¶Š5@þ×HÙñŽ¥ ìyZÊÐ×bºs@ÿ9!óàç×;™õ[EL&̈øüv÷@çi˜ÌuV¾$DÛʨwrC¨ÓÖC!Æn[d]˜Ó),kÃv“åÅôdœBè“òódôP3tŒ¤M*‹(ⲊÜ>Ô÷™ëÜÙ‰P%¢ Ç%& f¨ÀËuöµp=VrUt8!c'eW³Žšy¶Ý–Ù³û‚ÆðHKm<ÿ"„"Ñ…ÓâÐGƒÃ‹"€¬gTN¦ }^fÄ_2“Ä~ă‡EG×K¶Íòâ0i4‹ â…aDn˜‰ó™€$ Úl]P×Þ^›@Å2†2jÒþÚªMÃH—=Q¡„iñZ +oAŒ$¦ÂØ*Ë˪Ä3-µ«&[Ò Ì`ou “NñX£#”Cm7I¡âǻ۟¹oph[/YèѽÐþÀB(CPP빨ñ–†dÁå. ;såÝ#•viP~úò@•µ½R*ì“ n¸!¤¨|j0+5G%ÔNí?O(Ùùû_Ïì?ìªéS[ÎÒ¯ç;·„øIÌàØ•þA)¯d(…Ñ:\.B2påGLJºØWeís†Y¿½Ç¹ÅÝ /< „RóæHUìhŸj7ξAßð{ã“üi`-ø/Çä¿ ¯mÖn´-»]æÄ>³1M]vùøî†`¾Üb&ÉÞ&Hzî_ŠÀa]ƒ³Ò0@S ܾ¼Ø:˜Æ]AHO2ŽoÝMvW»+I;As:(\˜#¢qS”nR—ŸêéqTÌ,¨­¬‰úÀTmÜãè{rc .vµg8ô­›¥½Ó(\ûévhq“;?\uWòÀ&ÙèÕŠÖÁUÕ6(;e¯Mé¢#í·P£D’°Œ†6^ÞÏÆ>–ÁFŒ…Ûp/d0âäúÚMbçnCeí~xÕâ§ì¨$¢`Ó´miŠØ]ü¾)êÖ Ù­š!z+=³ ^sÝk˜¦ò/öÐa­ÙUΕ[åØ—mÑ«Ý’`vbÙgÿƾÿXí²™kâç JU(~ÏðV7)ÅXa¯A³ˆƒÎ,b5k¿¶T[ѧƺ;ìøü•G/4,ÌÊãyiÚÎÙõÑ%’”,1©¿ÒY5 s±¼YÏÝP¥Lk9¸õC²­Ø"Ë Ä;¥ ßy8gB Á˜ŠåQ0vˆ*ÕɈ­£(à•ë¬¬zÒ뢛»š’œÅQŸÞF,–~¼‹Û®éò§‘_ÄÑ *옼ŸÁNô"WîZ_\Áy;l9:f½— +q#g´Çˆè’8Ç¡j7ÿX(:ì‹SEw†å‘üB5©xÇUTò"?ìúZ7ûÚõ¯ÖâÚ;®f÷Œf‚[{úæ¦é­04jûnÃ]w /†•¡TÙ´ˆŒƒ8eírd~l#´8D0Kö±Ê(N“¦Væo)ƒó¬Ïé»ë‹–8S‡w½}”‰ýÎ6K{–ïa êëÍRX[n{‡ÆU¸—Q0020àŒ¨–.ÝdŸÏh!O×ÞÔ•²½®¿o˜5=>Ú–r Bã JiŸ!ÖVT°eéÆÊ®íDZ‡Ú— ,!-‡÷82&/Š½ô¡ýW2x-‹ý Â,þªƒsù¦Ã%Š˜ŒºÐ¶Ú{'ë†f®†#Å)ÏK:ùáÁ +¼›Ý^k³ÿ€ªIŸhÌwÛ–>˜d)œœØø±â°{å‡(iÛÅàQÅ€‡ÓeϧH˜´Ž“£pø >ÃókÕ<ÞÂì³mM±4Ö`ÿ²çbV˜ÎqCf¸ö'‚ùã&DºâÔK‚„qÝÛÇ,‡h’xÀ•U^ ¡B,SÂÅÖƒ‘¶ÎÕ~:RLå™tóÄ“g3…—®3'á¨ñ§ßC‹« š‘§óÆ +ï> endobj -1176 0 obj << -/D [1174 0 R /XYZ 56.6929 794.5015 null] +1685 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [180.4479 508.2615 244.1386 517.691] +/Subtype /Link +/A << /S /GoTo /D (statsfile) >> >> endobj -250 0 obj << -/D [1174 0 R /XYZ 56.6929 165.9801 null] +1686 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [265.4578 462.9269 326.6578 474.9865] +/Subtype /Link +/A << /S /GoTo /D (server_statement_definition_and_usage) >> >> endobj -1172 0 obj << -/D [1174 0 R /XYZ 56.6929 136.242 null] +1687 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [367.5441 462.9269 416.2908 474.9865] +/Subtype /Link +/A << /S /GoTo /D (incremental_zone_transfers) >> +>> endobj +1688 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [280.9692 432.1776 342.1692 444.2372] +/Subtype /Link +/A << /S /GoTo /D (server_statement_definition_and_usage) >> >> endobj -254 0 obj << -/D [1174 0 R /XYZ 56.6929 136.242 null] +1689 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [277.6219 401.4283 338.8219 413.4879] +/Subtype /Link +/A << /S /GoTo /D (server_statement_definition_and_usage) >> >> endobj -1177 0 obj << -/D [1174 0 R /XYZ 56.6929 106.2766 null] +1684 0 obj << +/D [1682 0 R /XYZ 56.6929 794.5015 null] >> endobj -1173 0 obj << -/Font << /F37 802 0 R /F41 939 0 R /F22 737 0 R /F21 714 0 R /F48 953 0 R >> +1681 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F48 1228 0 R /F62 1352 0 R /F39 1151 0 R /F14 956 0 R /F41 1208 0 R >> +/XObject << /Im2 1341 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1180 0 obj << -/Length 3096 +1693 0 obj << +/Length 3806 /Filter /FlateDecode >> stream -xÚ­ZÝsÛ6÷_¡Î=Dn,˜øà×õ)uÖÖÉ%ÎÜÍ4”–`‹cŠTHÊŽçîþ÷ÛÅ.(R¢å~Üèàb±X,v¿%'üä$ E S3‰S#Â@†“ùê(˜ÜBß÷G’yfžiÖçúöêèôµŽ'©H#M®nz²$‰œ\-~™žýðêíÕù»ã™ -ƒi$ŽgaL¿½¸üŽ()=ÎÞ\¾¾øþûWDZ™^]¼¹$ò»ó×çïÎ/ÏÎáDÃxÉžðúâ§sjÿtþóùåÕûã_¯~<:¿êÓ_° 4®äóÑ/¿“¬ûÇ£@è4 'ð™¦j²:2¡¡ÑÚSŠ£÷GÿèözÝÐ1†:a¢â Ù³  ”Hc%'q˜ŠH+íLxggQ`ãS¾ öè‘Í‹Oe¶²⿹o±¨mÓ|Zeí|ù©È›–èÿ¥ÇÇ ”hÓת¯ÃLÆ"Õ¨«s±r: å¥PÇ3ÀÐïìÇ PeÞæUIæÎÊ5>4Ù­e±ª'6˜@7X(4NÞ+ÐíX&SÐÆÅzꔤ&jê¨jšÑ×u¾Êê¼x¤×McÔj+z.lkëU^Z<ŸwâçUÙ:YUA„›ª¦Æ=ˆ¬6<_cë{ËÕÚÖ®°ŸÓq:½ZÂFÀÊp-RŠ4 É6=%aÒ¢©¨µ9–SVQMó’žíÒŽØ— JizVJ¡™èž,Ô÷c ãÝIaU0Èćgí¸ö§lŽ  m¢á´Þ6oÙ6C‡.¨ƒ‹·÷†-V{öûȇû¨™T,b&Ϙ©ÇuÀLžëy3šµg¦ÝiÇÍÔŸv×Lk2&­/[;åÌõÛé j”Uëþ ©`>“êôSõ¸˜Ês=oªC³öLµ;í¸©úÓf´twÆ8“}w®Åµ \o9¿_?nƒp$õ@î1FúÜsG sWrX¢wÓÎSS8xB˜æ Åû\O[¼ãzÖâgÝZ|oÚQ‹¦íÒÛýÌæýv/¬ýéÍm¦ÜÙ™‡¼]Ú¥ŒHbú³c^ŒíM(”TÉïÞ›Î#†Qö¦Çu`o<×ó{shÖÞÞìN;¾7ýi9J 'ðâì…-çEÕø1>³\×@:÷ÀúiEx -e$EßùödÕš>h¸£O+Ðã6#E€Èû ­Œ…ÍpøÑ‹ý2/²UƈLã‘[ßQæºß¾zY c[GŒÖ ‹|Qoá—Ö~QÐBmHÚGð8ˆñádÄŽRV¥%ÒqxAGQͳbY5-4Š'שÜ2”¶mð…ÈœÂÎÜ«4‰A³Ÿ«-šÐœ_;ŽòϦfA¼l:3cãšûnª×)ïFÚ1¨·°Í¼Î×[Ü»‡I0¬\£‹Ñ rO'a«0B÷ê`tÄâB/.òy9šÂîn&®²…Ýáó¹Ä‹ˆ +o¨Õ<–m6oó9a4Ç}Õʧó¢ÞàŒXWySCE–;’i“—óQÓ4v¾©ó–Á9èí Ÿa§ŽÙ©{¸Ýt¸ý>+òEF Ò `;ú|µié…¶ü–ücGDFt5êðð|ë¡r‘€¢},#4w07‘ÓKpb°c“Žúq·µX\0zÀhx&/C»lÐxÈ vŽM—*Ú%•%›[^hß™Õ|ƒ{å\{Ç(üsiѼ Y·9¬íÞÂβ@pæIÔ.2‚žœ9æÕjÍ¡¸ Š³uÂ(L¨·@BI=†CÉ#‰ySñø6»³íH,ǽøN¬ñë ;OŒ_Ø2·ÝøÙX¸ PÌÛ*<«Lºzõ‘SVôîäŸP»SªÇç&E\¡ƒÔË·ÍŒ6R‘ñ(—<ƒÂ1¿+uÂÊ¡8î¶{_ Â8 Òjol=j¢DÉç„%ûÂÆc6„JÂäÏÈ›góåØ5e¢EFZ⸞iõvšþ1©pŽ”Í ¸ö¾¼È™$PKÚzeHËpxºnÖ~§+sÐÝB‘èáî“°ä^lóЭð0ÞúÐÑ×™*ÄÅxë]R¸[Vض&i¥[m0Q¤S‡›5dˆ`Á€AÓ]:#tÑô}¾Ê‹¬!¥ôÊ=qá‘D"Nõﹺ©…D“ÃÎWPS=@„ÖœÑ>4¹F‹¶—ÓH¬èÉ8 cF_¤ -/^,Ý "áfGä*Cða_ð€ž¼ Û ÍÏ ÙŽ]Ñ?U/¡=FÑÆñb1œ±°H71·eŽç< o¬¼à!«m)#´•,²´ÔèŽOš€žžëÕÙOé|-“Ý æÄ|bÙaã8@ØcŸž0¥:F”éš}Ⱦ%'ÝðA†–c%УK ø™äÔ «@òŠÅ!×KÝ{­Nû!•E]ÖFUêQ¸"S¡5Pˆ/÷3/y"²P½B°?& -§ßZöa§Ú Ÿ<A¤»–³¾6^“™79®í2»Ï«È3tÁ®íΠ/Zëî^Œefôh6×e^çnØ®LuWZ^z©–ŒZQjÅ‚ÚPIŒúýušÇþž¡.Á«lá¿2ñ¬PÀ›†%nÑÕÁ.p±î"~–É}›«6Wî2*tÎùºò¬_²Õº°n–”K¬L¦c-ҤðR(¡O•ù«23ýŠ:ªú›±üÖI˜‚–.U7–Þ¶ VR!€D,Ì -K徃ÿ° $V >)J¹•š·U †XÑ+gP©ºä„<.ÿÁ¨¢ªî6k"ÒÀ=½\b•j?¡ÉY©K- Ýtú¡¯BdÁ¹Ô]¼~EÜ[SΔJ¶‚G`N,’T›^°~qÙYÆìô -œ…ËãkЈºÜE=<1z\y íþR8J«ùƒá=v6lLžá|â?Û‘$qºãçþÊ"ó7Õ¶€¡Ù¾¦¼™ñ5mÇÜ»üá:ù®~Ó‘lç?BûOÐgÕj[½Ç®/Ïuæ/šÆÿ&å[ªN¼4$Ž.–|Môî›1s7ý;(ƒw6cp¹‡^]ûü„-8R[Û¬éÆÃ}ú~Ü`ö®ATw?Å^}hÍñkU n7µ¿úç"ÞƒèHN¯ŽS<~\‡›  ‘Nkx²ãÜÖ¬©nˆèò (˜û.‡êþ„¾ú¶KwKÝt·ÝîÆžŠ­ebÎêKáì„Ÿ/_žP^ªê± k–¶(N׶î®Rq9£õ½,nÿ£ „déû„‘OûÄ©Ó€¿±Î¤ˆ&oûÚuxë÷:®Üq…¡ðÏŒ´-ØêÜÉõzî’žg$8%‡wçdezôSþ†¤B„b©ÓS’û—õzùrìŠñoÿéØYqûÃåÅ¿¨å¶ÚË+ù¿-nçŸøâ¤C¶ùòt{õ—ÿÓ³ýt%…N5þ ICbOT{¥ÐZ*ÝÕ¼ûóϾêÿ®4~»endstream +xÚ¥Ërã6òî¯ðm媈K|'OâÔîdvÆ©’h²¸¦HE$­8_¿ý_¢šZû@ Ñ~CêÚ‡u„žoÒà:N/ôUx®üëGûþJ ÎÖ!m§XßÞ_ý󃉯S/tt}¿›¬•x~’¨ëûâ×ÍûÞ}º¿ý|³Õ¡¿‰¼›mù›oï>~Ç”?ïúøáîûŸ?¿»‰ƒÍýÝOüùöÃíçÛïoo¶* ÌײÂ+>Üýë–[ß~÷ï¿û|óûýW·÷ÃY¦çU¾ÁƒüqõëïþuÇþñÊ÷Lš„×gèøžJS}}¸ +Bã…1R]}¹úÏ°àd”¦®ñ/4‰&:^a Ö*ÚAt‡©mˆEÖe7[g®šæ©?¶Ð ÓÍCß14«Ú†[ç½­y1Ëú‘Áý‘ÝÞÊŒº=Û2˜™ts¿/[*eõ¾í³ªzaà0±°myºQÉÆB„ÝgÏes’ɵ[¹Gß*å¥a¨éYßí›SÙe]ùl·M«ãEµöô ÔPNÀës—6ÆFÞœžwµm[6»%V–ï‘2l3×°U +:P%ý¶·Þ@aâÜ Rø ñO«`ƒS•ÙÔÙÁ2`  ´ Àê¦Þ +Uý©…CщáÞžJ"°vLËd–¬i€î¬c¯û5x°UsvXBBv´r‹Ž+Ö/êŠ5¦ÿÕÔö¸“lJ”íÃ&§ƒÜ­v²Ðrç\v{æïoZýñœÑ9 AãCïìé”Uˆ€PµéeiqhM#Û2e’˜)î|tÇ+¶ °jv(6)M‡b¢¦7Ous®¹yd"mÝqŸV¯H¯¦kyá&^Ê~o¾”un˜Nå´ˆ´f~ÀwÎ LyÁ¨–Á³à€=¾É•+"©Å;ŠB¡ Ѓ¼aû\V·H>L @>=TÒ"îÃ÷È[>—… Ì)æ ˆ æHMÌ‘QÚKRhû¬ÀEQveSgÕvwj["Ü&Ó§Öl;ÌŸwŸ‘B&pR70#íÑæåo¾¯má¡°†›»ºílV[t¤Htqsgð!ÚcS<„秥ú|ÏÖÂÖÍìöŒ.åç/·ßy gËG÷M_Éb¬‡Ì³¾]AV=°&Âo¸‡ƒØ™– +›3Þ#`Á{2KSƒ';Ä?úÑÜ"”mÉÔä šªÇ›™‘”ƒ¡ô.ÜŸïù!xf°úž¯ýxÝÝ ÒvŠÅÞJ­¸û sȺ|¿=dÇ£-¶ 1' .aA†ö}/J‚ôm:¬B¦‚¦ýЋ¢ÈÌ)¹Û±LÉ”f/ ý@ú… [:áØKN%P“b’kHØÀ÷îÓs çD@Š€HPàØ|/-Dn‰ØãzaØú©*ÛŽäo«´†ÈÁ„sekç„ÜwZn…UJZCÑ‚ñ"‰#«îqÔ•æè¤ Î– °RHðŠ>gM­<7§'FgqoúZ02þ<ÙSm+§¸%c§d~I9rš´µ½Q›|{Sq" DuÛ5Ýå£E¾ÿÉÙ캆ØÕ¢%N•Ø2ý-#£+?q¯ JìpÉöƃŒgynÅHmf.Ĉœ`«mò'8Œí¸Û·²™ÈÕZ5^’…kÚIèÂ7?áCÜž‰•ñÙÃ1+™‚1ÝcÍ“ÒÍè!ç짎O>Wüî²²â1¡5…Œš³}æ¸ò›5o’Æ^%Š….¸Xõovîšâ!4¯Mõ< +¼ î&fX¢¼º‘¢8G)…®Q>pÊYæÖ.ƒH·Ô(ÜcìX”mÞô§ìÔ+&5 ´gT¾mR§X¯›Ô ŽŽ±ê80ÞfðÁó®fA‡ +QWMô6!Ö +%3+/ÀöÎH`ôÈ%h3 ‡cz€dÏ )œ`—lIâ­”ç¸õ j:–Ù œÀîÚh4-̸ŽS/H#gÈ·[[ãnÛ]‰ŒÚ²Å4F{iš…ÁߊØéÈK “‡Ó¥ÁÆ}ÙBC^0x-=«GÁ8ç8ddÜ S•5†™DHwƒè¼øù¬ +ˆd'á»·Õq±›r$gŒ)±'Ö; q :µ;ÈÒä¡oò£ÍÞK¤€Çò™M)´Z<73á[ªÊ…ìo8V€Þ媃 é‰ µÒmøû Ã\gÆ)®dŒmàâ¢ò2g4\r;”+)†“â!h†pf?€4m×.õ\ô0íN–}ydžýóh9+õùeÃÙ2)‡›ÍûO?Ë +µ@öÐЃ0´!Œlûƒµ²Oà ÿh"ˆÀà &hZW¢ì: >¬Ü½ªxšªNgn Š‡®Ek~Ñà K5ä")&\ìǫ́*7dÅJã:œ¤¿®¹2Ó¶ôéíH’YWJD £³"»î½f7{çiË¿,¿ò°’ñä©HhHᡬÝK’›8®(ˆpÄʽ%¹G%ao:°p°pò <`»¿BIWÎ$›]k=›Sv*‡(T,'+ÈyKØtÊ^Èæî^ÝcÃ’×î‡2\] eÿÛ˜aá›ÓÄ3c%HŠƒi,Xíʆa©yèJž¢— ã™4Š&N¥rÁƒJŠì$WkóÚ7‹ãWÐU"¡%ÞAl`ZîTOUÒ>ïK²îi¤wø +!D!á‘YR>ü<÷’ôÿÚßÌtendstream endobj -1179 0 obj << +1692 0 obj << /Type /Page -/Contents 1180 0 R -/Resources 1178 0 R +/Contents 1693 0 R +/Resources 1691 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1158 0 R ->> endobj -1181 0 obj << -/D [1179 0 R /XYZ 85.0394 794.5015 null] ->> endobj -258 0 obj << -/D [1179 0 R /XYZ 85.0394 731.767 null] ->> endobj -1182 0 obj << -/D [1179 0 R /XYZ 85.0394 703.7216 null] ->> endobj -262 0 obj << -/D [1179 0 R /XYZ 85.0394 229.6467 null] ->> endobj -1183 0 obj << -/D [1179 0 R /XYZ 85.0394 201.8883 null] ->> endobj -266 0 obj << -/D [1179 0 R /XYZ 85.0394 144.1965 null] +/Parent 1675 0 R >> endobj -1184 0 obj << -/D [1179 0 R /XYZ 85.0394 118.9605 null] +1694 0 obj << +/D [1692 0 R /XYZ 85.0394 794.5015 null] >> endobj -1178 0 obj << -/Font << /F37 802 0 R /F41 939 0 R /F21 714 0 R /F22 737 0 R /F14 740 0 R /F39 899 0 R >> +1691 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F48 1228 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1188 0 obj << -/Length 2472 +1697 0 obj << +/Length 3567 /Filter /FlateDecode >> stream -xÚ½koã6ò{~…~¨½>õh?ew“4Åí¶Í¦8Ú§È\[¨,¹’œ4ýõ7ä•(6¹"@ÄÇp8œ÷ŒÙŒÂ›©ˆD)Ogq*‰¢LÍòí­aïì€9˜¥Z†Po/ŽNE¾;YüzùÝÁÉeÿ–𽌠-óß~þ•ÎVðìï(i¢f70¡„¥)Ÿm¤DI!üJyðéàÇa°kNòQÂEÄ'ÈÙUJ"Á…c rà -¥tþ^ÿB)¯Š®¨+|jV­pðS›­µy/`åV:[rIRɤÅ÷®ÞnuÕµxh›Ý:4»Îòöf£›KæWºMÖáèfStºÝe¹~AáiÃÏ µ¼® ýë}“ /0+¥&†tC,‹I*x‚Ä.Û«„àpØS.„˜·]Öt¸qSt\ì6¶»©q%ßdM–wºiqãè ®ÿBmˬÝÂ\!:Xce™jÀ4Â;ÞáŠÅ§Œæy$¡ÁbÔU%ó·:Ïö­î_ÆHªÚP -Œ4žgžÑfoÜ•ºÓ¥Û\é²ØÇW8uTÐÈœoý™þ‰† _°y>Ï*\9p ÈaëêþRÃXœÔ•¿;ÃÏ®nPVv÷³ß½‰Û7•Eå´¢vŠ`n0_P'ìí¾ìŠ]éà̉öŽäã±äùHò\0ó¢ªîpçÊA`1ĉù©½Võ™aç¡™)T³ü¹.Ëú¦¨Ö8-ÞéuV+%hz@KÑ›Ç@ßO@œ©¡ìКô ùMë,ëÍÑ×h½’­74ˆ#{‡"iG°Cb)ЬßØ s°q¹1ï‹Àwø¯½Þ œ ™¡‘«ùføq"Sš{aÛe‰ÃÝ=Œým#œý£FÌz×E³ó*¯›F玜¬ëôv×Oðk´ÆªÁCOT’DEÉ1ŽÊ`©_ -ðö‰rü´û„V5~˺Zƒ³uDûGÜNPé€8ÿjî„‚%ç1a2HÄS’$qŠ¶öÕW½µÉ4´6˜9%1C§Á0B 6ãgí¡ÀÏšùÑ~C?kÑy‰SŒ^öR°©jïÑÖwîÑΨÕhg·¹m—S–WäYiüad½ŒñÈ"1X¿‹Þ‹˜±ufͱÂi–[#¯Ûçƒï23sñøŽöGý*¬m²k[WnPÖëáÌàwab]䄹M8ÌCë,ß «Þ½zw‚^+ô6V$ÊØhaƒ–ñ–Œ:oið¡·|Ž:Bí|™oY2nqhoŒ¸ö9¬ð×ö¦îÞŒ0âL_ëÊUï×w¶ãp˜7¡BþÂG¼Ú®Ñ×E½oï›ëDØܧ.ËÐꌡxIìtãöœÕNëo뽃ÀðóY7ƒ-=e·½.„æ:!lH!ˆŒÀPKéI²X0”Wûí•qböæb]9ªúü4´pô’‚’–Ç ÷ùB¯³Úg·ÖîÃÁü¼8³ÈÚq -ÞÍ'ŸÈŸ¿£÷±cÅ?«ö<¼õÓú/^ ôSµ–H"¢€£Ï*¶'iªät±„&œÄ)•ãÂsp¹¡?1F5µ1’„ªd¨ÉxŸi€ -Dœˆ˜E3 ÀÇ•eÑ¿›P¨ ƒڠQoøüÂþ‡¢4bóó~Ìçgwy·Ð´L€ *µ…éìwàBʤ(Û×\± Gç[1{_ÃgÁ3=âeˆÙ>3 - Jv€‚ûeL¨ÀGþgÁ$<Ž¤C¼4c[$V!8hõ¶ÈëÒ” fj\¿ù½€Œ©õ7 0:ô9x¶vGM £¹Cž¹û|p´0{êìn‹ßÛ·´M„‰sQ½/MWÒúSœe8ýsÁ”‹Ç0ÃÚÓ,™!fh—f'x‘9]T+°(}q·ó`X €­Œ`Á]3TºöÙ®‚ÂB³Ó“ ˤÉ(%Jâ!™IA¸¤ì ™Éˆ$<Š{kmê²}†äòÒYEÛ·s{ã²]¶ãîß•îùë˜~u;dóxmH&K©)@|*ÕT«|‚8¨RÒHxâö]QÝí‚16D†{^Æðÿ§ ƒ/Ó'd($Ib†©Z^{¿ÒOŠÐÁµ#ôߧ™ÐóZL{}gEcÈÓeôӌҰ³„ßôí“ kw:/ ƒ,Ï"j× $¯Àílû<‚¢2;Øy‰\ -ßlzÅoÞg5¾ñå6ëåTÛiоíCÕå§ó³GÄpâµüÈ×Wib$ùãÒJ¡b¡þ´P¯×æýM^"†|Âæ>0rÝûòƒæÚº|X¼6ó¾Qa ¿} ç,,"ØB1¿µ±y‹ >W˜ˆ3ídRïe°áuEõŠ–¥€V%žðF±"4UPÊ›F?MÂÉF”ûq@¦$Š"ßfÂá>ZðƒQ,m½šLÀ¦‹60¿Ø¥qÆQëM·¼Ñ惎º´ÚaVV™KЗ Ô0"½ÓÓß¿`*:A?W$‘PíÐ-“€Ê>A7=¬00^&] ž04±?3NÓ©_®éìÉàöÜßɇQ‚{J¶[–Å ‘ Š\†#‚Þë,ùÔT@úÿ|§ ˆendstream +xÚÅZÝsÛ6÷_áGy&BñMðÑMœž;'g»wiûÀH”­‰Dº"Çýëo ðC‚¤xz3Ï„àb],~ûˆâœÃŸ87–Ù\æçY®™áÂœÏÖgüüú~:g™¦C®ïÏ~x¯²óœåVÚóûÅ`.Ǹsâü~þÛÄ2É.`>yûñæýõO¿Ü^^dzrýñæb* Ÿ¼¿þçµ~º½üðáòöb*œ“·ÿ¸ütuK]6ÌñãõÍ;¢äô80éíÕû«Û«›·WÜÿ|vuß­e¸^Á.äϳßþàçsXöÏgœ©Ü™ógxáLä¹<_Ÿi£˜ÑJEÊêìîì_Ý„ƒ^?4e?m3R[°¤b™i# – <™æ,s¼72 H9r¡‘çUÓ”³iYŸWåî’…äÌeb0$%¾ãJÈ—ùB挒c®HòT:9ywswwõ–ÚÍöé©Þ´ô²¬Pµõ©™æ`Vî'ªŠu9lC±Š³<´ As;ù¥Z•M$•AJ[ÓpííaÆä* )›„‘±\É(âMBWÃT–ŸRT1Ç¥\ŸËÇâkT,Âs¹Ï ñ¼ŽUÝâ”çS%%LM…`¹1ÒÏÕÛNFfôrÿXRc^.Ší*°,›„!„s;k¿Ã®3ö®¤ZôsáÔq8¹ùãÀùk±Z΋vYW{V–åâÐQ:®„£åj°2‡õŽ”ˆV*ë íVþ=jm¿,»¨6™˜ÜÔm™˜€%³,kÏãwf¶3ÝÄŪ©IÙª,ç 5Û@úÖè(tìãéX¦ÁOG˜LãB‰äb(GJçåà³\\7Y”³vùµ„%+®&× ê#'†FRÁ9Ó‰hÔ:Ý \tâ©TªH0ópûð}ÙÐs¾lДó×iä8³\GŠm›ÒI*–c®ùÈûUÆ8â"Øš2)jªò|B{>‡y´²“¢š#ÙM +êíB¾´› 7Ù6í´¨fõ†Ô€^ Ø]¨kƒ[S×aô_uH4Nå ”™ÌIœ-e e5“ö•×¯+؇ìá$jz#?´št„go•«ÉçmKä‚Ñ"ÍíuGõ”¢Ú«Õ ½ÍêêwÎåÃÖ©œuÛ,«‡(!á´&‡¢ÁƵµRΧ_Ê—”!,gÜvàÅö'œj‘ƒE1OªG&vLw¡i‹¶\—U‹X¯K Tñšý<œ>`%*çÙ‰ô1à:’>"× 6³YùÔNËoOË EßQ +¡2sî¸WBÑ’-ØÅr1VäÒk€QUL¼rŸ4ˇªhšbz~,+êýZn–‹Âtô Hì ĤÕ²ßCìíý^’{U<³âóAßM\îʶõŠ!JÚG@¡U?… ŠÔT,È¡©»œt0sh©b’[•¾xÚ÷™³ÌºÓ•˜v:BõëvU•›P¥’ŠþIf|Z/ô^´m1ûÒD­ÉrÒÙã¨rFmÇ… +þ¹-7/«úaWpž1k\~\pdJí'—Ìjˆ¤#ÉwOå Àë×!yaƒI*'ˆš=Ю½y¬·«9uø¼Ž´¶Ø´å¼›%UI ELÎÅéSŽë>\mÚÆçe‹i'eÓÖF˜ ¹31ˆW¦+l=rAY¬ºi `ˆiH9à$Fíæœ%fŸ[ûeÕµ¨ f†£`"l[nÖËÊÛ Þ?¿ìLðܺ¬fR/vXFÏ ”?Ô 3a8ô8Õ9ª¶L:˜;Ã݉xmðhc­>ü×äG.”8{,g_¦†f/J 8siyBxÇ•>>»Â!6z,þÞ‡0¥ó.„©°cHÃ’‡(¾`JØ¡v³œµ¡Ç_èš=›bÖ¢û j# S‘æ¥j‹oÔ‹ë•›¶X±ózMmè ‹6±2„"\j½›ü etEéÄ׆?Ô¡ƒjhTeû\o¾øËsŽæ u™‡)0›Õ~¦yÈd6¤Ø·Qm»m |Dg€I›>““÷É2(ãÌ@©  D¶yL9XÏ6$„œ)¤K¤.S¹Æ9&µ‰!kQ,W©Di˜ÎÅà §`î´êpÈò,²6+Hq©Dh †êRÜÿBóçbS¥'RË„æ^HQ5Ïå¦ àƒ2Òäf'&ŽÁƒ1©Ï(nðÐËïÜðämd©³ 8M…r߃L'vÄ%‹Ù‘0¼êã#TUõ&¹PÑ©|TΞäWŽW4Ž9#\%(Üʉ?ex?”Vщ É«ò¡Xí±nÚààØã#Ò×0O¢P¦^z ’“µáe`mà»}ÿ–È°OadC—š8)‚Ð0ùºž/§c·”Á¬˜îÆ©Š¦†€„YùØ&;Ñ}÷d"™Â[Çp€~zZQðÈ4ÅÛL…è„ú¹òah14"uAÏË7Ôu ÿˆBQH~%B€jIXRX'&×-q…[Ø«¡‚Ú«á·>ª<²TŒÛ23Q9lFRðZ3¹}G7Õøß%‘|‚‡çÍÝjÜ}¼ ­¿†m"öÝ^3ù7½ì¯G9ã×ãÇøõÈÌâz.Ä„–„ï¾ö=­U"NºÇ y½'šˆÏX8˜ê8=4ÂÆamC­e5_bõ2ÌE:â3ÌZ %¹¨ ¬êúËö)HXŒx£sÑÆš]Xü첚‡rmê»ë›éå»w·ìòöÓE.=Ô<ù“Ý%yO]×7÷—TÊ 8ˆå'ŽC®ÃUÇÕ»Ü|û4ÝàÍ÷Ë*¼»Ï!½U¡ãJè0¾?5,Ë ”x‹J ë¸¾@vHeؤ‹¨,ßö °ÕÅ>OåŽï üóe¸X$†* Æ°…Ïî ò>ƒ7ø{!hÇÉɵ5™³cÌ7庨ZÀª¿ +’ÒLÊ?·>ŒKK c$1ê¤t¤>É€ki»Cò¸:€Ði³îâø»“6—“á܆ÚÔM³¤£.¼}-VÛ2,w7õ‚dïD¡“±Lu÷Y–3åLˆ®zM^Mz Ô¼9ÏÌ /pñ’ÈÕ{ÉúÛÞ;‡äÅÝqÁ‘)!x|àÖP&€.#ÉÁ5¤Qƒã¶Q±v¡„…ϱc ‚yYlš0¢2.º‰¹ Çõ§ð:Ÿ‡êßç +‘Ç«?5¬–T8­ª4Bá8+é~°ûn„‚4B(Õ’ygüÝ“Ì·C;Ü~·JoíôIØB±¨OÁV™ÿ¶2· ã‰Óòë0l;®¶ÏËÕ|Vlö¯5¥eš‹ãâ#SBüÈhJÀI5–OÇe©tã§èöŸt\Æ8<2 `‡&ÕÁШêjJ!>Ž%¬§/d¸à¤IƒÄűñáêFç ’‘#«›Ã`@¸Äšo]7>.CÕ·z.^ 34á5²Ð#8NˆâŠT‰ÝÚãnÛ?2,žÛ +ªõ¦¥NF‡ÆpÅDYíì‘nv¼jõfÙ>®I1Xz'*Á•¦B¿4ˆ÷¯da9áJ^‹î—7\Zž÷y:}^îf(‰¡ +ðràÈ&UKÿE@ãÕo>>¬Åß•x¸ŒÍó+Фâ€óݽ†®VâqL2+L>ÎÜdtük¶!¨ôÀ°¦>ì¾àæ:ß;î¾®#î¹z÷]Vmù»û²ï¿†)nŽËL ùcÿåL:«Æ +|*7`[*Ž×ãNu1'ý쇭^KÏâUo¨‹~>å„°?Bw-D àèG‰XäÕg8x¿ÝÁ†\Š g]ò¢aP%*1L|JÉð£¶f:" x/©I7b Š829; UT[«mI#öd$§(¿-›0” ­ðüŽ-Ý}ï±:GëÐ=Œ³d.—s¡?uÿ0uåËU‡_(LÞyxï€v1 úüVùø =h±E”_oÛi½è¦ÉÓ$Ò¶I˜ãBèáÝÿÔKô³î ç¿Ê0ƒ eu®ƒU¸˜à•¦ä‰½Ãΰ~èŽËâçrU?µ­Ÿã‚aqÐêÂÅÀ(ÐÓŒâa›C'T¾®ŒELŒG"_W ¤¬fáz¥sh²£fP§˜¿gÈÓ?üŽ/\ÓÝ—Ç‚üɯ†ÔNƒqŽFÖ!×áÈÚq ëùéÌå÷>’LçN—ßq%‡Ö "j®Ç$œÊ™‘<–‹‰è¿33Úd£Ÿ¨ÀÿÂ×m&þæ$¬8ÞCøœü4ø«¯^;Ï6!~Øt¤QÙ™Ñ1Â…{" ¿½¹üpun>ñÓ&gœG­ƒPý<†”b™•êuçˆC âøÉ©:ñeåë¨"W¿aÍæëQT—™ò˜Rc`Ji÷HÁ.Š!¤lü²ÉæR@ŠÊT„éîÚ!Ãú d]W6ÞàôÝ„+›®€¼‡+#vëöÿ3®,Z§¾×íyŽ|ŸB<DÁ1Ký½ß;4="¸ãÙ“<þ­S!ˆÌPôh§µ> endobj -1185 0 obj << -/Type /XObject -/Subtype /Form -/FormType 1 -/PTEX.FileName (/usr/local/share/db2latex/xsl/figures/warning.pdf) -/PTEX.PageNumber 1 -/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] -/BBox [0.00000000 0.00000000 31.00000000 31.00000000] -/Resources << -/ProcSet [ /PDF ] ->> -/Length 557 -/Filter [/FlateDecode] ->> -stream -xÚm”In1 EOPw¨u€$ÅIg0²Êľÿ6¤¤êV5 oʯÅésÀóή¯ƒÖ×O²Î Ž¢‘ÿ¨#h8Çùø:„5?ùÆ [ÄIÚL’~”F Ø PÈùYÌÀ¹dˆÐzZ8å±Ýƒ²ÙËò‘–Œ€f¾Å(ÌÀE#@x˜oL Û¹[ƒ±ñðù -ä -6\>RgÈbÏWÖ¹j[†› -WŒÏ¢®{6;»²þFÃÇñ÷ø]š¨)Õ/Ô¬Mu;pk;Ì©Ëdh<åE–ñ¬AÏw³ð¬±±Nê¦ó¡Ä½t•‹ùD„™Â²]°Ä(‡;„ ·åŽ°Š­r²ÂÙÄLûˆ T¥Í¡誋ŠŽt’¹w_ =Î]ˆ‹=¦uSä÷—ä"ï±yl±‡µÃ-ËkHsŠöreOÚ³êvg›<7ºt,‡Ýe—;ãÒèЭ/I…B÷&ê(ýê³ö󻉨YÙ¹Ç,çkRÔšÚ'^ m" ^˜h±ÎW9AVªy­Â©/fýÆ"•œãûFy-Sng \Çdª¼˜©Æ¥†Í}B©•µŒÎ$âw1.¶&Øíþ²C¶O–ÃVç X×9g¹E{îÇ< •ãóP)!ÍZÜÅŸLÞª~ÑÔ'¯UâXLµüc“ÅXsЖõÚ¯½˜Ó’~òBL–§èªÆ¹O¦ºNZ_[Èü.øšŠû*]3QôçÇñ!Ö-žendstream -endobj -1189 0 obj << -/D [1187 0 R /XYZ 56.6929 794.5015 null] ->> endobj -270 0 obj << -/D [1187 0 R /XYZ 56.6929 769.5949 null] ->> endobj -1190 0 obj << -/D [1187 0 R /XYZ 56.6929 749.9737 null] ->> endobj -274 0 obj << -/D [1187 0 R /XYZ 56.6929 282.0726 null] ->> endobj -1191 0 obj << -/D [1187 0 R /XYZ 56.6929 250.2286 null] ->> endobj -1192 0 obj << -/D [1187 0 R /XYZ 56.6929 191.4593 null] +/Parent 1675 0 R >> endobj -1193 0 obj << -/D [1187 0 R /XYZ 56.6929 179.5041 null] +1698 0 obj << +/D [1696 0 R /XYZ 56.6929 794.5015 null] >> endobj -1186 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R /F62 1062 0 R >> -/XObject << /Im3 1185 0 R >> +1695 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F48 1228 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1196 0 obj << -/Length 2134 +1701 0 obj << +/Length 3339 /Filter /FlateDecode >> stream -xÚÍYMsã6½ûWè¶òVˆàƒˆääx<§fœÄvN“©)Z¢$f(Ò+RV¼»ùïÛ$ʦ,;ÖTmù  4¯×´pøƒ4a\Ùx`lÌ.’Áh~ÄS{w$üœ(LŠº³~¸>úö­2ˬ–zp=éèJOS1¸žþxòËõÙåq$>Ôì8J4þp~ñ†$–~N¾x{þî·Ë“c¯Ï¾ ñåÙ۳˳‹Ó³ãH¤‰€õÒkرàíùû3j½»<ùðáäòøÓõOGg×ë³tÏ+¸Âƒüëèã'>ñ:âLÙ4¬ Ã™°VæGq¢X+$åÑÕѯk…Q·´¿X*&¥Uƒ(á,b÷®´‡]}VZ´s{ÓHˆ„©D¡Kâ˜qË7.‘¢ã!3Ò&“X¦•TÎ'ó¬ióEƒØÀ|ÙÏS&bƒûàÄqþ;ç²Ê›ãH™d˜áO<¬²y>&IÐä:eÑ´4cR/HTT£rÙuº4޴˯²òšš2»ËÑ"ØŽÇl’Hgÿë*'—®7ÃΨ̖MÞ°‡N¸a©ábÐæu`++Y"´DaÂ!ý'afÊå>ÿ©Â:HêÛ }†ÿFuÕ.ŽE:¬K„ͦÃiYßd%¶í°Éwù‚ä0]=].²Ö¹ '„}Ü ç)l4yÛÐø8Ÿd˲m¶ÝF÷Þ…:ªng¹o6mÖæó¼jŸr[C¹-„ÓóU†»Ý@K¹÷ÖžTíñpïušÇc<_´Þ×yä!wí!ìxaF?·¹s}´v3Èn²¦x -üÍ©^ÔW½2:™Àö€¯­ei¢cBÒS1j¢Ñ,«ª¼|Vúƒ,ã@Ä ˜h N˜Ï—U1ò.p¢ ÎõÚš~§yKl4Ê7hpöìÚ+cÁ¸„ÌL{Rr}lZ´ž·uÍ6çÚíÕ.^ÿÇWJ -»ïNi“0k:~»X›0Ž¾ä÷/{Îð2@jL‡n=õß\\]R>hÇÔC]”¯¨ºÁcµQ Þ¶œÞ–»"_½IŸqÜZ+‡O×±è°À‰ƒ§,Ží¾GY'Ød’nxÊß×>ZÇšC¶a«ûè/®±tmÑß¿·*"¬`±ÑˤaÜlÓæGôYqÍRiÁj äÀÙñ‹|T¨æŠH>~=Ë{’®° `°Þ)e=Õ´Ç{Ê0¥ÁÓ4)P¯.•˜¿ws3§à„W~Í…¹½¯xZ£Ñ2¨j”o^õ>>ÀÖ–­ÉóCZ2má Œ€? -Á‰‰`% ¤â"pT’¾«`¯ŸÙ|žyºwÏËñ-‚,`§@“¦_/êýÇ‘ÂðŽl1úl<^À›øyžµ£ÙgW5àÜèÁdÊð}ßw0°!†ÈÑþîáäž½¡›WlÈ1ZhüÖdÓ¾»ûऻCI¤!”p÷ž$àkeºv¡jšbê8\ìJ,üiîç7uYŒ¨G¨b é…›Vù_€’ø‰[¯‡SC`¡ZV<žû­¦D-¡U„ÆF÷„*…ù–!·‹¢àž:Pp‘§TÌd*Óm·Öë–M.´É&h¢MÍw`”àÃÏŒ\ý¿)THð'Rówžð“Ó÷ ü -¶.5 ³J·ñEÝ”xfV J;€P²e xcp ù‡ (/¯ãÆKBΓxU´³>gRfù:Ñï A‡p“c•„ÖÑF…ßx¬' 4?& Í|5#fŸ¥³Vµ¿?‚Õˆn-VDb}´Óډ׉%¼EÁ×)Ëz•{ñÆ{à&Mjœ…™ÓuÑI=ªn–EÙFEõÝÃNˆ˜c$dYÈGJ<ï5‚ª^óÒרoU°ƒ”|ù3E -¨Ž0 vr‘(¯‚bFKŸK«ûž ± -è{¡ÀkŸ•þ¾ÌꦷªFæé¿kÌk)„bZÃøWÁ,Æú^©=˜A"H¹¡ø®úy× Uõó0ës(ÌX ¯1“XÝqµ3…Õ°ô|g”•xúàfdW¼ÑFϹ‹IDO(‰´m2nXè^˜DÑ -‚*oWõâ uŠªÍ“ Ž†Uß'¥6ä抶ùžë@òÚ‚7xèF*ùKjè°b§ç¤Ñ,NíÞhXð -³q]•·Íó]'lì 4”‹y! ¢!!§º‘ý’Oqlí/OÂøjVàSŠœkPF®éûŽ;ËйBwrãwF߯jÇD`)ihÚ¸&aU·Ô¸%¢páRŒýŠŒ~VŽDC£…A¿nœÃ6ó¢êý¸L!%c¯Ô=ô’¤Ì+P2mg õ]£=@MôÐÚ -zGºÄð¼¢±féØ$+A0Êšü›Þ/A†ià’ëªd·«£õÜ­²©æÝ„·¾8ÁvhzÛ·ùZÞ|C²? "Æö¥õJ,Neªº¶îÈ(1§ï54s÷­í^‡×]±Í­}I™{xb! æ‰Lð?@ npúÌ2W*°ß¨­”Þ)~Âÿ°D -Utb75ò%ûìOŸü_XØ)°3ñdd£eSϸu‰>Ò ¸b-µ±{Ùíg^®ó_R!KLŒ™™X%NÅ?ý)í é§Õ~—ÛzÑ®uo:Ÿ| Š„4 Éy_µIk1´u$÷=1¨ÁøµØƒ¢ÔïêTà Oõö]|„ -clkïEqYú“fPgP µªåü&÷pÖ«*4»âé¢^Þ>¿èDûL{x_¤}¥{ß_UÂb -€öÒÊçþgvóokp±JÓ_Ö×Î…–+ñ(K©”%©4=¦ÿüÑU&endstream +xÚ­]sã¶ñÝ¿Bo•g"–‚lžœ‹ïâ&ñ¥¶3æã– ›s鈔uʯï.v‘4e禗‹°À~/%f1ü³LG±Ê“™É“HÇBÏ–›³xöcÎÓ,<Ñ¢OõÍÝÙßß+3Ë£<•éìnÝ[+‹â,³»Õ¯ówß]ütwys¾:ž§ÑùB§ñü›«ëo “ÓãÝÇë÷W~¾¹87Éüîêã5¡o.ß_Þ\^¿»<_ˆL ˜/y…Þ_ýpIЇ›‹¼¸9ÿýîŸg—wá,ýóŠXáAþ8ûõ÷x¶‚cÿó,ŽTžéÙ^âH乜mέ"(å1ÕÙíٿ‚½Q7uêþEZ&él¡“He´íË[Ž£Xí-L;I!Ã-K1uËž +oùO»mu³h›bÑuÕøÔBÇQ–‹lÖ_új‚Ùã@heF‰! ÿ~´5\½óí¹Èæ¶Ûmëò\Ìë»î±Ù–]Ñ•ÏQñ¼¶áÍOkŸšºµ-¡º†o?^âÝ–4Ï[Û1Ù#/xw÷aš5!xD¸àRPQ. žVD¹ÖÄ;m½lÜsE +t<…eLYÓ“Àé@¯­]veã‰z‚dp¡ôV!‡~îÊ®‹]ÕñÊ-27´4I$Q!bÇãÁz¢,’(OTÆ4Ñ ugJó4Jóܼ®x}ªÓŠ¨&o±,–p±ú™ŒMg¯³¨&ø9KÀ½1d„ÔOäÉY(QëD®æ᎚†o}M#2”Ž0¹Ó7Ä£¾ç´ '~tÚæ0<»'k™ ’5⽬‚TE"‚’—œT€Jšì ·Ó§zEúž +wÜ=­ŠÎ.@äËO‹Oí§‚OÁSˆô Õ ƒÓš82¹ñ@‚WŠ%¤”vò@„“ÁØpô¹¨vŒ7á.5“Ê"£Ó7ìÎD¹’†i¾‚å´ž»{`üÖßß~OÀ}Éû—Ì®=%è“= _ÙÎn7emIe¤4cb9tZÍ~äÜ:Î=6»Š½Ö=îZïÇöä©z°µÝ‚a8ñöæöêCKð¼!y¹àÝvd8ìØšÚ:ƒ;-´¤ËÉ‹–u±-«Ã9 Ýý˜ÜMY´åCí6TZ!Ç-A¿Å:î‹ŽÞÊÖMÉzûœíŽÇéz ë€®ÐXKÐKá9ƺ7½aZàe´ ­»’'ù³õìOœÉ$‡[,+K 0y<#Z‚ðXÇ7<A$3Üp@ _Â𥩫A,L\ˆã ìÁ¶¯0úíõí÷—ÿ!øæ dp(R¤Âmf wJBOö3F®ØÌ¿kööä[î@Hk?¯l jž8Â"GQ:qÁü¥±I¡#'â /çlM&™å˜íØ_¥ðW3ÀËCM±Ý®¾&Þ–Çz7 G¡pj«¾éå#Ó+p®2t*E„ÙÛ°à¡]_Ô+B·,‹ 'F&t˜G^¤§‘n€ d¢!”ž“ÖÏß”U±.ÚQHyt•€¿Ë÷ºª[0q§Ç,Xañç„<aæÀ6–ÍfCÇ ¬ÊšýéĤ§`×­5«ÒIP!ÄN³c×É´ + G:Õú/øë¬ç¯3§9GÿÌ7»¶£ ï-= Þ·²…êö -)¡Àqï¥4yMÐV4ZT˜%>nh„¶|Z‚A„’bÙDBÚ‚èËÊŠ™ixÓFØ™ö? 2éxÎŽ<èĉyKœœC¿ø¡'»eÏ6(›r~µ„[CÆZ¿äaÒ¹?ˆ*à>1ü‘·*Û~ÎýÇŽõ}ç ²{Ö #6¶ûj<;x\¾¬ªaüëù€+v\¨;ùD*•ä˜¤ª7é>ÕéT*PõÌM —rÎ~œOåêÇô 6Õ›ÈM¤R3b„ë8ç6È«èãÍ¢«WS¹*¸I#Ù¼¦ÒÂÑÞ™‚Ê1øô¢ï4ï$Û½ãdÊîSe2˾,M“*„QØ ¸5ª$`Ésø6º—£@mF9 +¸ÁÇwÃù” çˆ9Æw7Ãé)ŽóŽ †²A7b‚IŽ«†¸0Åu7^t£ÝÙ“D‘|Â@$e2÷IB½ì%ïe`øB[äœ!@Ì{MrÄqžÀäªËM öWeP”õ +ý¢\Mߧ¡dl"K»ßu#wRäpq.ÛNC]#i¯šŸŽ¤Ô,Ε8Iaæâó”€zšÜG®¿@1êG±‘é0~AW!•‘Îý%U¥» «õÄb"‰L’¤_dö=Nì«^.-ºpÍ/í\A†(Sùv†({f~201ÃÁig/$°go8ûÕ+ÎÞS!‡Ýö°è–O‹­]omû8Õ®S +üñ« ª Æí:%ôƒ»ó­KP—C>ü®9ùxäAªŒ|U \)Éœ˜ß½û‰L…qìçoZuø².Ê +)…4â=eH‚›À8'#èÿ£÷e…-µP7†üÕ5ïTšý×Û*Ùj"ÒôÿÑGSie(ÎW5¢OuZ#Ußg`‘m]³(k‚ÇœÈXDª’×Y T¼ô-ã4’ñˆ—‹ªÂÖ‚9ÖþJ‚[9ÔŦ\Žõ@Pí‰Ãݶ¨Û’óvÀ“5í7Â,xò ýPb¸)#¡Ø¹ré¯ôža¶ÈSì‰5`W%—ý™™ß£bgèFe©»Ø#Íš†9—6½\ÚŒzÁ-&¿R’‡¥%QÝ Ôîè}Rã\–e_æeqʱ W<Èb3¥Ð ¬4d[E¡áFXžÓ~*\ñ,KÈ_Ülˆ–R…4@—fHÉQU*Ÿfà¤9G O'»B§,3’-w{õ縘Àõíå;Zy$æTBr*!C–Ð<[^á¨yøæO7ÑÄá|ŸƒÁÞVÕd…zåZ©ï1¤¡5âò´–pȶrm Úéœz)÷ «Ú†0µ]Ú¶-¶^›ÑtQƒý4­ýÓy.ç7?Ò —€½ó¾àrªé|ªà££Jýµ"´,vØGL#í]qÁDÎxàY„YÍöØP_‘µ¥$LÕ_£oR)·Æ®:¢ ^’¹ýü¦e—Tö¦ ×fÄ™ÚøL'kÆ—% ­ §«]sgðA‡;œë]7èpŒu´œo(ˆÛüºA‰a+†S²-ÀôÊî¨nˆº·®ï¨eSÿÇòa*SweÄDšKìEy—Qì LPÜ Å0[îàoÊÄqdâØ»ò±oSÖOÛò¹ðgáv i¸O?!ÓñèóY±D….ï± +õ*|Ö­¨J÷>ˆͶã6œÁ,¾9×7uÊÆ¢D ~ÉÂÔ×á%úP8&|§Ú~îx‡r3•Æ Bž]MÜ¥‚t"KÔ8‡íŠmǹähÝ…Î"•Ç·(Lê&â·lÿ/@81¦Eûb»âJt´%p&M$Óc²ÂY»)Ül Ñ­‹%¥OŽbY°žÝónÇü©IBÇ“Þ ®háÆ‚¼ìb_®XAè+Ÿi궯ížgØí³Ýº6¾ðr_í–ÌhŠ9ѨþË)/Ý<»FTâJ¡O-ô$?ÑÙmí\`QRñ®ø#“Ïw,]¶³Fèž' ÃøÉ7¬îÈ(ð˜Åâ¤íλð$2|€V<ÝU<Ï“nxžj‰tÒ°ýL9•ÏMqUãQ]»Kkwµ-ìK—¡‡)f^5Í'‚vOD㮩t 7`ñšx—¢>ì ²?¼«D²þõ” ¨š%äg<ƒš&¸hSO©{lZö›Çô'~Ö~['åÉßøˆòÕñª±crwÙ£ïóu»Ëûú¯ã‰N‡O&úB(üL›¾žè÷©N'ú +võ¢ä“"ÒFä¯o¨&v¸{™FZ+5Üšz +r‰ÐdÏé;Ñ€³±6ƒÖ»ŠF\@Ë}%ˆžã!3\UºnsoA2@ØÍStÍ(=¿ ¼ÿ‹›O}ˆU)ž6gG».·m7á%vì•Kt{ymgQl9ô-\3bΖ&”ö V¤þcA5SþJ*ü¯tã»@ú4d–^  #ˆ´7¥Z™)˜õ¹þ[çéXmûûÀÞ- +í«iãCªL¹ÎŸÿdÚ'¥‘‹ÀQ²ËLç†m±©ßµ¶Zƒ¸‘„ÖÏ‹wF†{÷Ýê±pÒÈ$é ßƒ\>Ùe‰—DeAèé<wl‚k½=y§Ït‰Œ“Œ¾¢ eú-˜Òþ€kÂàâÐYúŸ'vü]•V–øm„Æ(“¹ñL¹LA9×HèLš Öÿ ?íWendstream endobj -1195 0 obj << +1700 0 obj << /Type /Page -/Contents 1196 0 R -/Resources 1194 0 R +/Contents 1701 0 R +/Resources 1699 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1203 0 R ->> endobj -1197 0 obj << -/D [1195 0 R /XYZ 85.0394 794.5015 null] ->> endobj -278 0 obj << -/D [1195 0 R /XYZ 85.0394 585.0446 null] ->> endobj -1198 0 obj << -/D [1195 0 R /XYZ 85.0394 560.705 null] ->> endobj -282 0 obj << -/D [1195 0 R /XYZ 85.0394 491.9365 null] ->> endobj -1199 0 obj << -/D [1195 0 R /XYZ 85.0394 461.8226 null] ->> endobj -1200 0 obj << -/D [1195 0 R /XYZ 85.0394 384.4846 null] +/Parent 1675 0 R >> endobj -1201 0 obj << -/D [1195 0 R /XYZ 85.0394 372.5294 null] +1702 0 obj << +/D [1700 0 R /XYZ 85.0394 794.5015 null] >> endobj -286 0 obj << -/D [1195 0 R /XYZ 85.0394 206.4979 null] +470 0 obj << +/D [1700 0 R /XYZ 85.0394 227.0652 null] >> endobj -1202 0 obj << -/D [1195 0 R /XYZ 85.0394 171.8379 null] +1703 0 obj << +/D [1700 0 R /XYZ 85.0394 197.3345 null] >> endobj -1194 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R >> +1699 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1206 0 obj << -/Length 4496 -/Filter /FlateDecode ->> -stream -xÚµ[_sÛ8’ϧÐÛ)W ó”Í$sÙÚÍÌ&žª½š™Z¢-V$Ò'Rñø>ýu£” Û[É•HP£Ñhtÿºæ |¡Ë¢tÂ-ŒS…f\/Öûlq }?½àaÌ*ZMGýõêÅ_ÞK³p…+E¹¸º™Ð²³–/®6¿-ËB/[¾ýùãû?ýúéÍK£–W~þør%4[¾ÿð÷wôöÓ§7ÿøÇ›O/WÜj¾|û_o~¹z÷‰ºÊ@ã¯>þH-Žˆ~z÷þݧwß¾{ùÇÕß^¼»Jk™®—3‰ ùŸ¿ýÁXöß^°B:«÷ðÁ -îœXì_(- ­¤Œ-»Ÿ_ü3œôúŸfåÇY!d)2|Áyá´3 jW”RÈ$ABaŒ-×];º]O«ü¬gL´ÍÐt-µTí†^~í«Ûe3ŠÉ–±ÅJ}&i³®¶qŸ °4m Æ1‰…sjŠ!©0®™“¥[nêõ®:¼ävY÷Ò„µ`C·£!ëmÕ¶õ.tµ^×ô<öõ†z®¨¥èaj«6û¦múáP Ý¡§þHa>’¦e.V%+@«Ìb•öïîj B2,Ͳ»Á§õ?ò mµ¯©©¯_ëj^3 ”_úf“âÏÆÕawuÑÒð —';ßÉp¯Tð¡Ý¬3› dÁ¥±aÐqhvÍð@ÔQ Äwæ[wû=(I` -ú½X¤p…TÜF¹r$e"Ö‡CS­©¥íÚÕ?O»ûãnjzCrØ ?!)ÂÛTŠ8=è$·…qÜøiß´Ip]Xà8,²ië!# ¯–‹©Þ¦ IÝðÃ.›ž+ú¼zû }÷ÝúK=Ðûô«n›ö–ÆT¡™ú»zÝà„ÝÌœ"UÂÑבå»SË$•+³rQ:VaÄsl“€Z›·L«Dq5%ÍÎD­4ì²3|œ9¼ë9¡ -^0m?#ÏßZ./Š@i0Êt÷»‰ Q|BJ›‚—¥™‹ ÚlD yXÅ+X¸”Ëûm³ÞÒéQЯ™²s«²®PVÖz{&,hZøþðËWE-Ý!µ”ôæ𧩠£„¾pÀŽqaÔEÁ -0òVXž“õäš®&ÏÅ -ºQXî.ŽzLª²pLE±‚ÕõCÔl¼"7Ê £¤òÿ3CÊVƒUŸŒúiVÁé=4ýxç$^èAðM =wÁ¬ySŒ²ïéIº £âFÙå}³Û¬É‚oÂfŽõià´@–s -F¨­×è\¼—ÓHÊ;%E~Zªõº¾È×i°·jBà ==[øB^ð?zGLz:#K5jOi ½tbÙQ?Y3úÍ2!J*×ÍóD¯'ÓÀQ\ 7ƒ†è#o”Õ梪ri ر„“kKðߪª‘àjJñ\U¹â`œ'~LWUÁx©ŸÐU6 yý:矂ip ZvCÂ{莠ZÎE ¦®Ý=Њø\´ÎRñ$ —qÌí¡;Þå=¾3)ŸP÷p5|¤3þ|„¡¨‰¬»„ý2¾ 4ø!4Á B´R}‡$h¤¸š’̘` ¸Þ‚¤Ò°gc Ö¬S -0%ÿÁÄaTôð´ü[LÌXIL—ªœïpFHà,¬³r¡ ¼“ýÍ"ŠôV‚ç2àv0|‹ƒ.B üF+å †²ËwùÛ³Ô3X4æ.+fo¦o¾×bÁÇW‹Û±Ò=½\øB«2•"0;rÉ Þýõ†Q Ý÷[m$øøjskÀNW{I÷ à=J/=­7Zo-qý=ë?ëõÑû -ø˜T›à‹ÂÜ(,x1'€AÆ%(Ñ纾TÏUVLK‹ë£¾Ãí‚^>å*ÙÓñ$‘©d§Q¸Ôß>Õ{r{F,?RùÊÈå4·ÔúvÆ?tz²ö¦õ³¸@묓œñ~V;N£ž`¶¤à|ÏxnÚ³Y¯k.øs%–Æ?5ÿ]ïÎ)n'é@ÌW: óJõ„Ò¨'ø8§6qð&Æ‹°5M‹ ¥Ù«®»ã@} ‡în!„Þ˜ÍX ­ØÈÕ¸4ÙÂŒOy¹'2²¬PFžä“8xn^ õD®1ƒ˜1- @ÊϘí¸7ylÁ|ˆø¾úBlá:‚½6àkÁhŸØë®ï›kŸà’lKC•wlðwK$¢oð“ä%¡;l -´[zŒ0' iÆÌ høKã¯]BñE‰ÞR¡Rºp7 :`:o}ahÜѳb®§o±A@"ÒÃûîð%,5Z^`Wö$µß,W oU.YïCl÷ ?5œ5fÊéÔþŒ(Gâ€g‡ -Ú¥[,>\VÉíï@¯ý)ÁQG–hßГ$„¿´ÔÒ^‘¬œ, ¦ƒf¢:=-.œ¼ú›0¶Ï-/4%£É“.â(I"èÙ6·Û0º¾¥×ÔãM®tÓJÊtí˜/—ÿíæ1ŒŒz‰f¾o¼vJJ×݆iãabç)'Œ;ÓMMWÓtØðÒC¨ºnf] -oD„«Tþp`J“FЕ±íŽ» 5¢É£·œOåë—0­×*<ù«!R&lußøÒ͘ïî[zI lnfœám§~K<¦»°¬s NŠIŠ~á]Ÿ^á¸cÊKd¼àÉy¨>çœ@ôÄgè$HjEºõþW2„—y†YÇh _ŽÞûj4¢Uh£C6ÛYª+ä¶VO€-ˆÀ_é´8=!š¥²<ø£C&Θ©²Â‰ä7÷š'¨ À„ÐB ST±h€åﱑª=T1üÆðpGÆ]—pÚúfL¤«åmG¡¶ ë–àKã-Ó„ÛÞ &䲃µ‡%ãâCÌåT¡ÐBŸ×™œ,f|æœ}ú:—J?&Ø^ÑÅ à6Ln“™e[S†Î¦ùgÐùÉÆ-€?ÍŒ—GŽ¡¯_%­EÂm˜9y‡j!w>Ÿ£Muë}jd>`…*7“蔊/WWá†Ò$¯ã 6º°tm÷Ûp+k4M,Úg¬üû=ÊUb”Ã6MXžN3F—øA@ôUâ ^- '†«9Ü"0“¤Ëgdw¼p)Ns¯sú…‰ Òeiru‘f¸ p› ýaWdÜûrêZ(ÇÊitú/0+©HWJ„¾…³²Lÿ£Ã?ÁÙ7uö`~:T í\X{ò¯.‰⪛fW£õù!Ç‹œèÄIù Nþ¿þáéŸ#M(1&Q™<ŸÔˆõêƒw2šwx™ÇírRE‡Îj8}×5‘Ü=Z½ˆu.?@áœå7r˜®Ûƒ›_wÀB»å'¦ö¢ µ|;žÉ°cÍò¦Z£S€¶~vmÀLÿ#©‰ErŠœM&ð²QØ= û&^W#3%mdê¡;—Tâ°NÎÝòý¡ÂÞ2 _JöØB¸…Z}æCð«É©ùBž1Ë÷±µþ³Â Wèj‹\ÏÒŽ CLoN±'l¿;4_½ËÁÄ?tƒ‘Ep‚o±¸¨'B³„dèßÃføâ¿å -IX‘”2W‚`É(|ó? NêP3‚âBMÅØBY ˜Â•Ë³úIúïÂsÖÿb]+endstream +1706 0 obj << +/Length 2753 +/Filter /FlateDecode +>> +stream +xÚÍZKsã6¾ûWè¶rÕC<’ÇÉŒ'ëÔffÖã=l%9Ðm³†"Q²×ûë÷k4@ñ%;µIªR®2ÁF£Ñht÷×%þä"¶Âf*[$™q$ãÅz{-îÐ÷ý™ô<«À´ês}w}öö£N™È¬²‹ëÛž¬TDi*×›Ÿ–V(q ÑòýçO/¿ÿ×Õ»óÄ,¯/?:_©8Z~¼üÇ·¾¿z÷ãï®ÎW2åòýßß}¹¾¸â.ëe|wùéS2~œzuññâêâÓû‹ó_®8»¸îÖÒ_¯Œ4-ä׳Ÿ~‰,û‡³Hè,Ox‰„Ì2µØž™X‹Øh(ÕÙ׳v{½nèœýLœŠX»Xi#RÌ?oe))Á”Ä™°ZéÎÊJÎY9p‘•o›ÝS¾Û»v¼`YlY/úR'sw\3“«ÞäRJaR›gÿúP¬ËŸ£H-ÌŸÉåþ¾ †Z^~aB¾ÙìÎeº,Ú¶ãi˜å¦à÷C[l¸…Åt ¬ŠÆmÊú.`469ÈÞ·ù¡Ú3k9ž¹Ø>쟙V•­çú9Š£ÚÏK³@òŠ ¶E¤i¢a )²8Vn]½É1R +ÏjDYì“L…ŽmæX?TÅ *^®óšyÕ6Ür‹¥®¦&{ÝØ*¦6Ÿk¸i¶yé»nò¶lß ­#ˆ­š§n6¶l4îªæ&¯ºÞ‰~ÍþlêÖjÜꢡœ¾V/›Çb·+7›‚Ô°féÔ=çÇc¾+ gnô5·L|ÊŸ[ì™F8þûoLg³€±-öLyÈwûr}¨ò¿ó‚[ær~"üÃ÷–·´Ž[¶NQ·B„™ÈÚ¥³ :ïóÇb¸>ÎN9§‹©HðŽâÎ$"Aˆ@B/àxxSWÏoi?wmÙšT k2éGÞP¦„bHXoüø?ëfÏÞZ˜ûl¹ÓÅ8Ôµ¡ EÁÅÂDYF1Ì»»7®zAßñ¯ú¦A?•ë‚¾X“û„ü¬„J& +eø(4É=×kjL¤‘bf«°2E¹T»„k£¤¤´B`¢(Z~8äÕªÝçëo¼†¯ÅîÑ'ÐÑÌp‹Øãäôjm±x.—ëÞyç +~á´¦5¢ºí±3oì‚…ˆUN9Š(>O6»=÷ÿý©Ù}ëËoõ†ßhnGº©Š­Ÿ…"”ž,._ßç7eURŒ’°ÍÁ«GÉb&î«Î*.šÉßN'ïŸÜ(JðíË/fèÏ Ø!üäÜ„Æ}ÓzY[èVÖ…˜ µ‡Cii^ÆÌ>×iÌì¸h›nWíqëØ©3!í/ª˜fT §AÁCÈ©Mìí¢]Öù6Éžô¡(q9ÿA—·¢ð„máþ|½7S'vÓpoì·Ì‰v΄N·g笱4éÐ1ö»¼nÉ(µÛ ü¤@’R&ÕIæô'Í™H¨LT +ä-#=@SÛœû··jPo +¦äpe¦8­A qQ=†Ž{Ïæ£yJÄá½QZæÖ /ïOLÕ²ôÏûœg¢Ä-Ž(ì¶hx3{þ–ŸäHÔÒKçMn©*sÎ^ÇOÓ¼_d:UæýqŒ%±P± C¬¹\Uƒgálí×r¨+Ú·¡ˆw!ÓÌŒ Ð{ˆ ÏÆÃŒíÙ‡b6÷l7EQàli§6'¢|Ýl·Î³è¥báEeX!îæR·JQW&‘õ ¤­õÃWfÆñŸê`Ž®H›à€¶ï9<0Þõ ñ¾©÷»¦z ºAF±õL¨AA.Nm®zÐ{ã;½?ïwåzïÖª;nJ¶¥QGa®”6ƒRš;\†>rz,(~=@8×z¤Ês»/¶TŽÁ­¿Nk E”"ã(Q‚³Ê˵Cǿ꘦½©ÜaíÕà”BN³$”¶j ÏLú÷\¯hò¿Éb$áÌ„Î;q±Ï˪úð}ó4Œ‰–Rõís@6(ƒÍpNÞRj×i,ë¸\ÓQ`…ú‘4£˜ÔB"›½<{Ç53ýð˜ + Ê`úáPÉåÓ}¹¾§¦rˆà©]aDt§2Ÿ|üaO¿Ç°¿/ý8G¾`V àÔòŸ'¹(ï›ÚO€’§¾ +ñùIц•Îõ8#âÔ«”¡Nð I­-ª4ä幓¥"K2ŸˆÆÛ1²¡„–:%¶ù3Kçc"µnü|mg× \Uçu›ê µBia‚`§÷tv¤/›Ä3ppä!|†Â ~©¹FVòöBºL2™ V:ìVá芼îųj&(Îm´ìN¡4æÃÁÈÒÚ‰êTŠ$¨f¼¥ð°]ä5Ráí¡¢wÃàæã‡s$n’Ñ‚¼[&ѱÌ-_&Ø”núÚÛ¤7#ü;^Qà¥ì×ìGÐ霟ªbPsö^Àô•7Úpštþ[ÊirQŠ•“YHÃŒVeéËY¨Ïu: u\G·ðìf’\S›ìåÉ;®™Ù‡IÙ^Z=œ~˜…Ž>Œš¢ËBf]ý˜…R.5±ýÆ„&ܘä»gîúðé+w1¼Âqg«àŒ²]e7²ËœR¡¤•ýl B6à¨K‘[")g®f°ÍƒA—êðœÏ©‚,“½’" T:“!TuòƒuÑt‚''gOt?œÖE¦‘H”ÑãL@#^¶™Ãq)§‰À G¬8ÕÃ8½¼ݲü¿ëTã&éW†(ÅfUºÓ’ •"ε®RÙßrMŽ¥i:Ê4‘˜OËâqdùf1µ +Úa+$*g«úqØy!¼)*Ÿk•¡÷×ÁŸz†BYº­ŽPwiyÃ>#ÁÊå5þ«åäŠ>µ„¤Gº¥î&zñëBÚ²L3S¯íÖz´#¼½ÜªÅ‡+Zôå¯ú’Ý¢Iz^©´°ØD±6VIÃçGkç“tdX>¯ÖùúàÜvpRËè»@H·ph­Y¿ø+oÈ¥ç±È¤#u8[ôØCå5š5ñ,c3T•.ú{÷ûÜAcŸm! Ž_9~Ÿ³ú ÷Ì]§km^)‰•ÞhýÊ'‘Žk”tW\ï ðH‘3@»¾ä)®x¤6’C †x¤x„fլݥN&ßFtê‹š]àaÏíÂ`=0ÂÏ.¯¹tÖT±~ BK/ç¡iýG8¢S±âJ[â@ÿ†*ãë$Cu'rl½t¾IÊB&¤f— é…Qô,k*‹]W«Û|íN£ž^ì@ü7‡=7è>á(ξ +,þ³gis×9a®˜ŠÖ'uº k>—×ÅT¾+CAõ­ßPúùß)XçU´§Û×Pb 6lþ£á·¡©'ŽÜ±‘É &|5BËA½C½ôP/õ)xUˆf”»¯`½GrìùIÁ^v`/=ØãÙ{yì¶b9.û°3$'£›©ß`·$±öDz{ñ§áþ ƒÿ©·Ì•Ò(¡M¢þ¢e>I¥¯TIé:ý#«€Ôˆ,Ué_ô¿PdXeš¨?²ø“Q¿·U=ПÎ_øD´9àwÿ6ãøÓ¨¦æц†n‘u, ËÿnÅž¼’ l=åÿ±H¨Oendstream endobj -1205 0 obj << +1705 0 obj << /Type /Page -/Contents 1206 0 R -/Resources 1204 0 R +/Contents 1706 0 R +/Resources 1704 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1203 0 R -/Annots [ 1208 0 R 1209 0 R ] +/Parent 1712 0 R +/Annots [ 1708 0 R 1711 0 R ] >> endobj -1208 0 obj << +1708 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [55.6967 480.2482 256.3816 492.3078] +/Rect [339.2005 701.7636 400.4005 713.6638] /Subtype /Link -/A << /S /GoTo /D (rndc) >> +/A << /S /GoTo /D (zone_statement_grammar) >> >> endobj -1209 0 obj << +1711 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [268.5158 480.2482 332.4306 492.3078] +/Rect [455.0966 503.2689 511.2325 515.3285] /Subtype /Link -/A << /S /GoTo /D (admin_tools) >> ->> endobj -1207 0 obj << -/D [1205 0 R /XYZ 56.6929 794.5015 null] ->> endobj -290 0 obj << -/D [1205 0 R /XYZ 56.6929 769.5949 null] +/A << /S /GoTo /D (address_match_lists) >> >> endobj -1043 0 obj << -/D [1205 0 R /XYZ 56.6929 749.0409 null] +1707 0 obj << +/D [1705 0 R /XYZ 56.6929 794.5015 null] >> endobj -294 0 obj << -/D [1205 0 R /XYZ 56.6929 209.5509 null] +474 0 obj << +/D [1705 0 R /XYZ 56.6929 686.5799 null] >> endobj -1210 0 obj << -/D [1205 0 R /XYZ 56.6929 183.9497 null] +1709 0 obj << +/D [1705 0 R /XYZ 56.6929 663.4862 null] >> endobj -298 0 obj << -/D [1205 0 R /XYZ 56.6929 147.0778 null] +478 0 obj << +/D [1705 0 R /XYZ 56.6929 548.1865 null] >> endobj -1211 0 obj << -/D [1205 0 R /XYZ 56.6929 116.7981 null] +1710 0 obj << +/D [1705 0 R /XYZ 56.6929 525.2522 null] >> endobj -1204 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R /F48 953 0 R /F14 740 0 R >> +1704 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F63 1355 0 R /F62 1352 0 R >> +/XObject << /Im2 1341 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1215 0 obj << -/Length 2349 +1716 0 obj << +/Length 3489 /Filter /FlateDecode >> stream -xÚµ]sÛ8îÝ¿ÂÊLÅòC¥ÉS·›ô²w›½K½OÝNG‘[³¶äµäd|·ûß$HY²ä:½Î’ €ÀlNáÇæ‰$T¤Ñ\¥‘”Éy¾™ÑùÖ>̘à =RØÇúa1{{+Ô<%iÌãùâ©G+!4IØ|Q| -ÞÿíÝ?7W!—4ˆÉU(cüpwÿ#ΤøyÿËýí݇_Þ]©(XÜýrÓ7·77÷ïo®B–Hû¹£pfÃíÝ?núððîçŸß=\}^ü4»Yt²ôåeTAþ˜}úLçˆýÓŒ‘&rþJXšòùfIAd$„ŸYÏ>ÎþÕì­Ú­Sú“"!2ájBœÍ#©”| A™’Xpa5h„V Jið»> xÛ¬Õ]µNÚ]¶Ùd;#íÛÛˆõ.…ÎCbšXb–@Œ”¾”Âÿ1ûæ\Ô¨$ìül½¬we»Ú fÓîÊjymñ©ÇÄ‹nt¾Óí-œ¤û×5ò:”HJJ¨¢¬“<¹ ùú7JyU¶e]áLVüÚdKíŽáS*Qö”ÅJw¼‘8%qÄS@öj©ÌÕ£ŽŒ%2¦føiVpK, táÆ 5;v»¬˜xªwìÀ \B‹wúJÚh}jåU$æÀdÌa -” ö†‹»å‡žvøah_à1]#øG£ö G`ß#n¤$à½é€›‘“tX—xQ3<€"2àõÖ®œÞò\l£P”$ŒË¡5櫬ªôÍæŒNYÄà¶c5iJø%vØá},Ë)Í61`r8IAlóHz¤ÍçëçŸPòš$¨,Æ(Q±0ÊJH"hú Å È|Í_'ŽØ„¿pyV!Pçù~‡`æÖì]r*ƒ¶ÞâÌZ?Ûû2øO$ TWÆõ–û]æ4 “ffíjG¾¬š²psÙ„L‚J"¹òB=—úe* -ÀK¢¨<• -*žÊàïúÐà … ÆŠ€ECÄhaB—0œáä QÔ1wJÁ£rAãiDGo:ª€G_ˆ5$Äÿ5NáI€$N&‹ÖêªÀMc–£3”cJ»\I"˜Šspkí®^7RÀó™˜gæÔn¬6#0Rˆ røsb‘˜I5—qL"•$—ÜØã‡ý Ž4¢ûJW– ZÁ¬O~ìÌë#jÇÐhXØì÷jÚ ‡¯¤Ü‹™¹et%XÀ¡ J˜ q.*Hqb`îC(€sHˆâx.#xZ"•¾&#ã$M@¸É|,ì(†}’VYCÖ¸$Q*£ãɆŲ˜ò"ç¦(ÅcÒ <£©â*ø½ª_*³¿¨@³fÓU¶Ñv'J‡”áJQo²Òí7Xí«ò½^paªj˧dU¸ipc,°®Éƒ»§ÑµxôôŒkÛë“`‡Œñaôùš£Â% -I}*ÔèݳÞMy)dnŒOwÇ0BäY0í G(Ÿ¢·«Ì͸Sq¶îG-ØW.»À‰Iî-]ò*²êÇaâŠyiþ&kó• . zl^Ñ~lY—Èr¢•$ €7¸7‡LTV{à•ΉÀ°¾Êž5®=j]á\' ÀN˜Äff­ ËbGÙ‰š¨ÎÊRuÌÜýØ¥@txñÇ”tËÝÚ$ÇJx·>֧΃‹¡(•Xõ|Ÿo;‚aŸâ„kÇ‚ÐTõ>ïÚÒ ÄN£Æˆ2£nóÁ2a¼Õ\¬Ùê¼¼böÁÖ Îù R—²=¼Íöà à±¹Ë@,Q¯&pUȪ‚{¸«ÂíÛo·õ®m&ê·*FÊ(ÞÚj“åá¦A4K8U]°“”²f`)AUÂ&HAi µ¼¸D*9!Åy4A,6¸"úV¾¸ŒÏ“ßJL$“œ½Ç]Zêüä„PEò„ždü,= ]±ÆÀHö¡OYà"†•¾Å˜hÎi°¸J)Ä (+˜ÇW:‚°Ñ¬Œáq)WMâ‚3#ÄÁ㧳í’4Œ0íw@h*7û "UûÍ£ °°`3jy ÑeW²Z²¥_°¾Åùp*®äÓBÀò‘Z¯2ÃØc^+h²$ÊN!?f‚ŸZh˜Ð m+F”ð¹!è-‚·ùLÔŠá‹» -û'!K°˜Ä0GxHâïŽXž^Ø#8XÌK¦,éŽÅ'ÔFŸÉtXÉDöb–Q+^kÊ-»P»kpë.Éï]ŒÛJûo¶n Õ6àzB¾Áb6Y"žç-”bd¾.ÛÌÆ4<Š…GDÉ™^ÊX”v½ Ôõ‚ÖõréÌùé„aÛ§#rì€1ÙªiÓõ¥ý„]‹ 7ø‚éZ€ÛwRØIŠHOåÚ¡o³v…»':o¬.d „GGZÞ_ ü'~öպܔö.Cèó”ƒ:úMùo=‚à…ëï 'år§6‡TÙ‡¿Þþv÷÷›·wq-éz9“¸?n~ùÍV°ì¿ß°BÚªœ½À+¸µb¶½Q¥,J%eèÙÜ|ºù9˜Üuæì§Êª(…Ò³kmeÞʬ`%Xma+*)D´²à9+)´r½Ùt/‹?Íþu±¬—ëfºn®A[&åTˆRD¢7°h£ÍX‰OOͲý•1Ñô· )ùüeÝ.×Ô\wýà{ëý-¯æ¿@Å›^°ùÐQçc3ø»»þ¥ÙûçÜsÝ–®†µÁ-QQÊùû\÷Ä`’éB*]§¦BéÙBj6FÀúyaË’VÍ8Y»¨ +ÅTåGkQ¹RÌwÝ@¾ñ Pp—ÑFô ;Rfß,û¾ív™éŒ*ªÊÚÉt‡ÞÙ ZíCœ÷ h°̼iû&3;çÓÒ¨S[d¦ÔV%SŸ356äü°Û4}Ÿ™v!'Œ)LL±á¸n(Á†_e´Ð +‚ ã© KsB£uëˆ5èZÖÙµ[€j°ã®Û5¹É„-˜ÿO†KFãj›×Ý!Âô«æ¡>l¼N¿²’åŒ/¡]É0ú¦[Ö›]3ô_ÁSVÒ5úIN1P^0 pz¨í Ê«BTb‚aT¼8 >Îh€–àçB~F©Ôù`¥²ÁhAÈÅ£ +",à²Q*£Æ(U`™ë1ŠG‚™€$cSo½ZQDê{Ô€ Ý{lŸꊡ»¡o9`wEÂj Eî¦ x³Ú–Ü;3 ´Á¬¾2 XD^ ñ#$þ:S“â”k¢ÉÛÆ‹¢W9ÑÝ«o×ùEBò‚+VMÑ™£Ee¢/Õ»UìÍëˆíÜh¬°J?WÐ"'¿×Dê\ƒÔ™™rNˆ9 {(} +c.§O \2ñ¹é“©òâÔD? xUŒñ±)½BèÈÇ”ãB@6@œK9\;å*“rð©‹)Ç©¥Å(失èbrvÄ°¼’\R©óÞ¥2Ë¥à ©¡]Ô!Je”S]ÇùX‹±ËŠ˜Z¤ˆ©{'©ïºÔâî-—ÍÓ@Sw…ÛÞ]‘Ø*æ² +Í“lâÈ@ø‡¡èNŸ›M&šœÏ*›ÍIVAmÏÁAÂvK”W‚w*uAê‡ÃÓªN÷<ª„$ìåÙ£TfúJ ÎR‰ñüŽQ9† ±{cìv!v£{ÐÙî·í@ío_wõ¶]’À·>Q/-20nO½Ûºßþ°ÚÞó»H¯aÄ98§¥Ðäá׫ÆQè9N Ý é1ÐíVY;þÐ õëzˆ‚ÝK»{¤þãˆp뾦`ˆ¼zçuXûÈ`€½~À¥B:ú›êýOnal’zŽ8ƒ¼Ýõˆgwχ½¾9ÁŠþÌŒ*g%ìà èæþqF j¢ü"}à5§ã:Ô4Ë¡ ®d +y¢†½Š¨ÌH›äF©k:hYHŽž“ê@ryd¨ÛÍyßUÆBª·WBy*uÞw£ÔÔw ÎK½_!P¦Æ` ˆ©®.+¥2šŒŒÁJðÞtY§n¬etch7†æÑñ"º1\ïÈ£CûèÆxá܉O%mêgï¯ô«Ä$|;ÏÆ×å]÷}C×d8Ôkå”ÁÒCçE×^Æ ât’Ü$/„Íä—ï +&º`\&ÿo …Œù ´kþ'Ç}dal¸Ã4|°)*ÔÀ~Ê+K‘:w^mÍÝ]D),ÍWj¼³ +b︌–OAFA2n]pR zžš=Œ´E²ÌÎïn­˜w$Óìêû—‹S+“Fþ‚„]Þ}xÍÙÉÂþ©rÄ ³à†uÙÑKö¦… [°ìWgM+ãvif ü>¼: `%í¹Þ¨ +çù£/°­ë]Fu,L0#Ì_{Å‹¼AxM™qE¡µš ›,/7*XvZ€‘H5`ÏWºXv‡ ù‰ÒÑê° e<–‘'ûià1È8Y»[⻵Á3>g\c4è¶M˜e¿‹Qi Q¥~¼°á… ^”Ìè+žH]ð„ uôœ‡fºåµ…ÕåéƒPfúñ†W‚Y9žÄ”•(«Ã¦gÊJè#SÆþÈ”ññ†¿þý4®Î€Èq½ˆ_ëèîæÚK¥…ÊÌ©_YªS:扄ÝÊ•~FØJL:Ó)W¨w»ô&¤ pƒ–£™ð›Te¨O§ðwXgˉBžEšì 9“’…5<Ôû½mv®:¨xœ!khºó/¸ À¨§CíÛ•ÛBœ×ÆT…Àläó°>,51l'¹áfÌH.›Ï²xæ¼ò!x£wÏqië|ÉóB+ÐD‚¾fqÆw畺’Ä¡óž„pÝ÷ ënsZ¦ÇËÓ™ÓiG+ÞÏ;)U +GÞàgÓöµºcZ­ ›3j5ÔˆLO¿Ñ–/LŠ¤¬)’#¸HŽïqN?ÂÁñCAÛZìðt›ç&¨K[&XšÕjì³TzçœÏ=˜~Nk•I6%…úôÄÏEü€ˆÃû&-‰âaòÃÐùùîÎ!ót3$Á ”a&9>ãìø]Ê•Ã0á"ø•ô’J]i¢2?›2ô¢†¿ZuÅ«Ë*D©ŒSÄj-ùX‰q5_˜?®puéÿáì› ÎN1æ4/*DN¼èv‹g•;ºBB­Ò/1œOOªÓÿE`1—ª‘¨ºÑHHíܶŸïèeŽC +¦Ã†3ÐxåôÌ…¢ 4¹yˆ)¼~€ṁÕ¬F­}÷ñ+nŽ¨£—Á–Ñr–MYK(ŽŽãØC˜d[ÿÙnÛ “زˆ…™Á¯òXƒ‚U|joC˜¤ü¬]f|- +XB@~n‹5Ú ‚i<œ“õÞDš>þáæxö%³šÒˆ ‡_÷Mdññsz¸ ÉÆ2­‘ë\-‚âqêí‚3¼‹Põ²É}!Á°:_î ),Xdkñ!W¢ÍÜxêö®Èly(ˆZjE<æ\lûLåÆOR¨÷xHgÓ/å¨ÐôJÝ÷¾ò4f©ϤÉ$–Ÿ¡†Šå+ãY6Æá&½NV¾ˆ²£W@l2KÔ °NU~ÆÐJ,eêßµP¸å¤_šÄ¾ªÒ™4Ü_EÁŒK\Ëè0RüWl£* #!£Ð×hþ9_ŽŠÂVU•ÿnt\$#ºH8ÒN•3hC¢-È@¹m¤¡mÓòÿ§aðŠ†ø……žjèRõ9z£’Àaýa¾žcQ§‡A¿aÿ© 2yrxÁ ðT>ÞŒŒÜ,l y»ì*N +ˆdÞH9&OF^ãzÂÙÌQ¸”SÂxfþ{ŠX +ð#ãLNe1ÿÏß2?ôV†óeKàj•°&(å‚£™j^ʪ(+a2ªÿ‡endstream endobj -1214 0 obj << +1715 0 obj << /Type /Page -/Contents 1215 0 R -/Resources 1213 0 R +/Contents 1716 0 R +/Resources 1714 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1203 0 R -/Annots [ 1219 0 R 1220 0 R 1221 0 R ] +/Parent 1712 0 R +/Annots [ 1718 0 R 1719 0 R ] >> endobj -1219 0 obj << +1718 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [406.6264 617.3695 456.8481 629.4292] +/Rect [213.0783 507.6843 261.825 518.4687] /Subtype /Link -/A << /S /GoTo /D (tsig) >> +/A << /S /GoTo /D (dynamic_update_security) >> >> endobj -1220 0 obj << +1719 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [140.5805 606.0819 196.7992 617.474] +/Rect [398.1622 385.1227 446.9089 397.1824] /Subtype /Link -/A << /S /GoTo /D (controls_statement_definition_and_usage) >> +/A << /S /GoTo /D (dynamic_update_security) >> >> endobj -1221 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [103.6195 562.6731 159.8382 574.7328] -/Subtype /Link -/A << /S /GoTo /D (controls_statement_definition_and_usage) >> +1717 0 obj << +/D [1715 0 R /XYZ 85.0394 794.5015 null] >> endobj -1216 0 obj << -/D [1214 0 R /XYZ 85.0394 794.5015 null] +482 0 obj << +/D [1715 0 R /XYZ 85.0394 131.4374 null] >> endobj -302 0 obj << -/D [1214 0 R /XYZ 85.0394 769.5949 null] +1720 0 obj << +/D [1715 0 R /XYZ 85.0394 107.8521 null] >> endobj -1217 0 obj << -/D [1214 0 R /XYZ 85.0394 749.0225 null] +1714 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F48 1228 0 R /F41 1208 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -306 0 obj << -/D [1214 0 R /XYZ 85.0394 668.2594 null] +1724 0 obj << +/Length 2819 +/Filter /FlateDecode +>> +stream +xÚµ]sÛ¸ñÝ¿B}:¹!ø$€äÉ—8©o_Îu§Ó¹»Z¢-Ž%R'Jöe:ýïÝÅIÑŽÓkG‹Åb±ß¢˜pø‰‰ÉX楟X¯™áÂLæë>¹ƒ¹'"âÌÒ¬‹õýõÉëÊN<ó™Ì&×·ZŽqçÄäzñó4c’>}÷ã凋¿:;µzz}ñãåéL>ýpñ×s}¼:ûôéìêt&œÓw9û|}~ESY¤ñýÅå{‚xzÑF1£•JÕÉßN~j vfÃÒQù ΤÊ䈥 ñ,SR~Ú¯våfUàI_tð5g0ò° "®ÊfWT³ºŠ˜]ÊZ2g]Âlvù®XÕ®!iåÛSá¦E|Y­êÇbWn§Þ¸ø=_¯ˆ¸î²1s nÜ.Ž+ÜÌ2Χÿ¢‡a³Ì½¥·¿EjÀÔLæ]¹©·; ©tÚŸ(—b:’ƒ·×"ëшvRœiI7ËÕ +NšSTùÍ +`Õt·,XåëjŠíC±%(ò…0â !F䶎(-…‹Ï4“/$⦉KH¯ðÍOójñm:3Âê[‚äÕ4i1í>"Öu>_–U¼ä²¢gUìh²£Án™GPµ£ª8(mÖRÇÛ>P¿¸MÈ#z*Aû¼þf5M 4›b^þ¹,¯“ñíÅÀ8Þ&Œh ×ñE +£p]™<-»øü “xvÅö6Ÿ v–f-zÀŽ†_/ÇlRxÆ3}tØÙC6r^4x¡r½Ù•)…¯ütß ‚ìj‚iÜ~‰À Ý嘰H¥Z € ‚¥M—婘ΗZ­PaUªî ¨éA.ÙZ××´²š×벺#Yþ¶/¶e‘®œöM‹rÏF•êË¢ñ7¼w ÑäÕ—dùã†ßY„ËmW±à¦yœØ¥«íík-˸NÚ‰ö‡¶70‚e+—MŒÌqÍ BŒdÞ97`f-ÅY—dˆ=ö„õÌ‚8ìLf¿ƒ 0)1 %þwL¶¿Â$à0Éá~{L¢nÜš4ÌÛÌE“{íÞNÏðÀ±gZ‰žôÒö }‹È¢ v$3ÅXÔET ò†ºÓ)«¤8iÉ&ßBl%ã€ÐÌ4ì[GSÏïƒ×U.Ú4øð<!ŒÐhÔZ4½öݽŠºªì´Œ´"‹0"A1‰ÝÆ —‘\½)€Q2Axm¾€¸Ö4^æ‘NQÕû»È×Ù狈¹ßWÚ‹0¢sAÏâ!Ÿþ o­lžö a~ð¹#¼y]ÁêuCÐ €^}xG¥½ê†ÊޜѶ˜°x8s'ÉC pQ8€DêÐÐR +”>…é.¿àîsJ‡cA´s a?O¯%$ZQ°®ÂJBÅ£s„DjÑI°0‘ =QƳ,!-C…„!íž7Å2@_–¹>?±¡\@y3v°CØ¿MjϨ[>ÃÔP’ÑÂH„Ô! ü»r¾_Ã;É1:rC-ÅÉ9&28ÈWMMX7Aú_Iòœˆ…–B뛂–…C†uÑbwáƃi«„×1Sþ„yvEí³Ÿ‹Äìáp²˜œÐë]Ô¢,æ1Ez\ÀñvÉ,Š¦¤•‘0)F'‹ +’æo¾ s¡ xý“ÿe ñ¤×´¢E&¯™ ·Ø*R|ÿ¶Â[¦´r}MëñÓÍü;Ñþù¢]ø\!9o7îÍ›×J¾ßá%•„⦭$u©’@P«¢ Z 0b !˜š"$(€ DS‚¹¡)Á$zÙÇr·ŒÄü*1Òsk4Ôý&ZÀƒc\”xÞDñ ¯ƒB#„xÃÑ€7D"Ç‚“e„„=ƒ˜pfC‹Ñ¼~§©ÞÍèpX\Òšr˜£SÅ}‚JÖ‹£ _õì(–1Çw}êå´&]^ç÷Å3ÅH[4Õ"áVSæû”újîû¤}TuU|ƒú† ¦Å“Õ›åæå."“ÒU4‚ܘ>ªæ´L…‡8ƇƒD  V”m #¢(u+J-™Lí«ULÔ‡)£Ð˜ƒFfgcç´6óFw+Rd´Bª§9P‚HÓשǶ~é Ô2¯ …&šè#;+ͤ1¶³3‡ú>xV£ÞÛ1ùL3eý³‡ÌdÜH÷B›’!Ycj>+¬{ûYÄŠþvI—ˆ°è @ÒLNËR^L8Tº8q²mí˜àNö¯`QÜæýØÈ9Ð 0™É¶Q)@{ÁSp0›Ÿ lVzv¨ôŽÍjç¸nÍH% :Aòóê»MÜWõã7¯šGÂ¥Z×äô +%t+eMHjUÛðˆÈ,.©)·@hŒ:-͘”u‘­yJ³¦ÞoçÅÈg-z?ijU/%‹E”ÊLßq†â â¥õ8FqÍ>¤y0Û ð™±”J BÛUØ¡«€Ø5‰`1qV_RƒqÊÄIZ|H5¤{Ê®lƽ_j‡t½£+5U­w긡0´%Ë´'tL JmLÄøókŒk“8ÚƒnËæ>;¨Uð ^.ƒø¾.w;òÒ$.œì§ˆšœÙ°! ÜeÌýñŒ‰ƒO½¸<{ÿþjØ¡€ó2©@ðR*(ÕÍnP´gŠÔ‚ï݈¿.¾Ý7<—ÿëNH :;ˆTÄX`80ƒ¦Ø¡;ÙÏÇ{©cœi—¢AªÀ‡ fñÿƒgôâ÷m +?®(ÊÛÔF *UuP ¨v*ª:šÜ‚M×kBØ„"tG/Õ~}SD +·A7Z\¾”ÿè=îö‡ +€î]ÑßSB‚· Ø~iUE  ›Øà•4`bKÕ§F‰·©¾yR‡»ÕF…./ñe‰¯ÐÙˆ¶Ó2hS ~¥ˆ(UB)F“Ô˒U“³=Û/63jÜ_”ãLCÉÔ1éÛt]Xº'ÞlÐHš`·Fu÷ËfQl’3ç‡b{†3—Ú YQR?L¬()S͈ú£<ÔƒóÕ~šP8IAÖ7d%‚Z{DŒ¢¸Kœäu¹øš=6[9Ž Â3oûd[qQyð-ýnسò#Rö é^û½+ŠURFÚ)®þ ;!ÕtÆÅ^Î!^ô3p+Ü=+á™2VÐ{2PšÖuö ñ¿È7c=ðËLeÒôÎßcžJ÷C ÈÏŒô +–@„Túàö&I¹;mgSzÈê¬Y…-i›uQb&¬bÏŽÙÓŠiücøÿËÝ0‹‚¡“ö¨ +‹;F8ñM^ T´?F”E2)Ú +%zž—Ó¤Þ&¤U¯”ñpY×£>Y¨(¨ÜÚ?b òóe1¿ÇaFÝjgR¿Õôºç0߶|aŠBZ]™7T‹‡rÜ›2! U©óQßmó5ýs†sXé@8 $Ôð$Ùm±å[<¤Éev`fý]Ü$z†¸œ+.£7òÓ0(6Ëby2Ô\ ·¾»ÐTÙŸ1/GÆ«§>­€¢ +¿‡ù‚·Zý‡?»8|“‚>Ñ99þE…´Rg ™ +…ž;â<}ŸqÌú^néöendstream +endobj +1723 0 obj << +/Type /Page +/Contents 1724 0 R +/Resources 1722 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1712 0 R >> endobj -1218 0 obj << -/D [1214 0 R /XYZ 85.0394 636.8261 null] +1725 0 obj << +/D [1723 0 R /XYZ 56.6929 794.5015 null] >> endobj -310 0 obj << -/D [1214 0 R /XYZ 85.0394 425.0299 null] +486 0 obj << +/D [1723 0 R /XYZ 56.6929 291.4983 null] >> endobj -1222 0 obj << -/D [1214 0 R /XYZ 85.0394 396.4061 null] +1726 0 obj << +/D [1723 0 R /XYZ 56.6929 263.1273 null] >> endobj -314 0 obj << -/D [1214 0 R /XYZ 85.0394 136.3155 null] +1722 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F41 1208 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -1223 0 obj << -/D [1214 0 R /XYZ 85.0394 104.8822 null] +1729 0 obj << +/Length 2567 +/Filter /FlateDecode +>> +stream +xÚµY_sÛF÷§ÐÛÑ3§íþ'Ù<¥‰“s§ur®2s3m(‘²9•HE$íúnî»°%J¦lO›Ì„+,Àb°k5‘ðOM'¤Ií$N­pR¹Éb}&'70÷ñL1Ï´gš¹~˜}÷ÁÄ“T¤^ûÉl9•™$j2ËÞýãíçÙÅõùT;yq>u^F?\^½'JJŸwŸ®>\~ürýö<¶ÑìòÓ‘¯/>\\_\½»8ŸªÄ)X¯Y‰.º ÑÇë·?ÿüöúü÷Ùg³Ý^†ûUÒàF¾žýú»œä°íϤ0iâ&÷ðC +•¦z²>³Îgé)«³_Îþ¹8˜ KÇüçL"\¢ãj=æ@— +o´ ,«¶Ø.³Eû‚½– ~]”Ýeå*›¯Š¿ãAJp±· %Tٺșk¨Îë¤çº/W+RÑ5éhoYé¢ÞnÏUͦ®ò²º¡ùæ¡i‹5±äÅ2ëV-Ml³ê¦xã$Žj²½/0~˨dž}eÛ ™“©Ò©0Ò&0R"uN ëûŠÎ–u5ßÓ¦ìpër2ÕZèD§a ÈžÞÙi—o¦›z ò§^Êè?ô fÒPImiä3î ÿû&Ø#í2ýëdh0Vh“Wu[|>µÚGëìfd5þJèhpô54ž3­é–Èú›”zQU»z ú* "nXâ²Þ2±è¶eûp®”Š Álb£·4•My®@ D3—ÿ.ú¹MQ嬻®è{—m˺câ&›Ž9p  AÝ`DXÍ; “F÷ ¬Šm¶B³‘Lû^Ôë5¨#Ž’W,êªÍÊŠ~d-M®Š¬áyåMbiÈG… ¿IÈA&ÏK¢¦Q½¤YpXÐXo€Q ÜŠgÂjVMM£öTì0òFyN¿¡R¦8N~[TD„ÈÊi´Îhr΢ں&B³ÎBâ- ÒÚÛ @ÚtÛMM¹¦M”†ŒõîlÀÊ|TÜ‘%AíÈÁ-nqQiÁìrUŒ€÷ÂX£ž¥}Ê\d¾…£N¢®ªa=ôÎ\UÅ=³ôvï ˆY×Öë¬-5@šóÂl³Y•{›aƒMÖ±Îú/ڌṪ³¼Èá—•F@ò:ïNÀhÖá·¨u·Í‚?ñw[Ób3÷¦Ï÷Çæ*bu¬ÙG÷ØòD +ïcÇ 0,Fœ …ôÎ…úõ¼ øü¼( l` o‡BF v˜ãl¿KÀ@e„Ñq|˜Ncp†e`gø“‚=PâgM]„ñ²"èYDXR¯éÅœ“;;qÌ© £9K …5bŒ- þêª}â Ë#ºN¸¨B#ø ‡K²öÈD¼G%§â ñBYíž [-Ò8a&Ê°†„‡ÄÇÁ†p[ÎY‘BN’ªs°wIߦ^3%à£NMô±‰ÅŸÙzÃm 8A¥3Ҧ—«Ëa~kFȆ~p>èª[@>×÷c[× lÝšç3VKì½¢þ%èkoë®×DrD¯~³-ïåBˆž¶P +kRÓ‚,\W`¸*AÐW4Â& ”].yÏÝâ–û¯„(?p 4Úí#ÙhèüªÅªË - WªˆÊIÍئX”?ÄaC• &s¨·‹¶È± ÑlS´4…ÇŠ„¯]±} R°JÀø^þHx´,ká(7ÜÕD:ÚÐu@ߊ²{_ ÔD³%·ïŒ.êiU}Ï“sHô"ô×0=/¡+LÑ!w a¶ìB`k²5óô Ã’U0—ï7%ûŽ樶eÎ<£ýjÀkQÐjœ5n4Í ºÈ°I0ÚwᎣéÂb©ùÃïðŠƒ+9ª¢@¶–;=D–ptÈŠ8¿äu}6Ùzߢ°˜ÏfèŠ`Õ‰è2‰¸ Š”XÓÔ.Š‘°‚bå•ïû=òÅ‘¼©µÂ5ñ‡è? 5";vÂY˜çoC¬w fÀ³²Á[is™:„£Ø…[+£(;FU·žÃ5T…‘гÅxëÝ°LºÎæDÞíàQžÚ4Ìš SáuÙ…iìRŸN¦û?•¼:õš<îý[ÈŠ½ð1ÄÞËwÚ¯8…#)^C ðŸ†åbaµÖßF”‚~=öìîÏ¥Ì50ý9”© +endstream +endobj +1728 0 obj << +/Type /Page +/Contents 1729 0 R +/Resources 1727 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1712 0 R >> endobj -1213 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F41 939 0 R /F22 737 0 R /F53 1029 0 R >> +1730 0 obj << +/D [1728 0 R /XYZ 85.0394 794.5015 null] +>> endobj +1727 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F41 1208 0 R /F62 1352 0 R /F63 1355 0 R >> +/XObject << /Im2 1341 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1226 0 obj << -/Length 3704 -/Filter /FlateDecode ->> -stream -xÚ­]sã¶ñݿ“—Ê3'†ì=]R_â´¹¤Ww:$“¡$ÊbM‘ªHÎíô¿w»I:+í-ÀÅb¿wAqÃO\k™\æ×ižD:úz¹½Š¯`î›+ÁkænÑ|¼ê«û«/ߪô:r#Íõýz„+‹â,×÷«Ÿf&’Ñ `ˆg_ÿðîíÝ7}ÿæ&Mf÷w?¼»™KÏÞÞýé–Fß¼óý÷oÞßÌE¦Åìëoßüxûž¦ ãøêîÝ’Óã Ò÷·ooßß¾ûúöæ—ûï®nïýYÆç±Âƒüóê§_âëû»«8Ry¦¯ð'ŽDžËëíU¢U¤¥¤¾úËÕŸ=ÂѬ}5È?GR` ”!ê<2J*ËÀšú •$³¶)ñ8ð’½”È(O² vÂÕuûðP5¼nŒ\¥‘‰[×õE_n˦'ÔU‡O=;tåŠ }KUùsKØÙB ^·-&j¹)š¦¬^4üúÐ?´ûªt#Ø߈lVðX4}¹Ѫ8›Ý­ ØoÊa¥ Îr=Ï€…F™ë¹Q®µ´§hÚC„ŠR™%1Ääú”!¯Hƒ€ 8öϲm‡}ÑWmCÀcU×4Z”¿§’1A ÿ(ÎS°‘EIjò asdzÛCÊ<Ê2»ntFæä-\•ëâP÷î­1ì×¯§ÀU¹88Ø^Ûmb·lph¶E¿Ü Œ¶hu=E2K“'Œ†ýT%JÒ~wÀ6`<Û2Žrà9ñž7øçψ -‹ÏÖZŽJࢮ:K:Ž›’{¼ ÞÊ)×YÔ©yÁ¦à}% ›0¼+öUa§t2¡ÝÉ„™ex2%gUO3G‹&¦Ô€&ô¬k-#Rÿ\Ë%ª/:œÕœ1¸’gf[Ý“cüóý˜YÞÁ¸+÷À2Iö©Ž nl¢HV&*ÁMö=‰þvÈ .­D)5’.LoË®+J~•„ó@^båuOM_|¤q¹·“íž_©z’ýs¡Â¬*ŒZ~£¼™xã -ÈÙ¹9öíž½DKO8r³bª âɤ¿ÕúÄ­ü,eðÂHˆ™“×<$QG-±ˆˆ¨ÝÈ'Y‡‹”íÊe…§Gñ>W£¹H“Èh¢TI”«Lù¨ AK@,ŽÁæïÕÌúóãf_teØॎÒ$Î,²7Î=‚à™ÒC¿;ô4~hËnÊ̶)§\Þ¶l´v+•y¡1ŽÇ‚™á£QÀtkþ^â§öÀç*˜oÛâ‘7w äP‡ä 2ÜN×x<Ñ"²‘å‘ÐM¼þ-Ø¢3鈗Ƹ0[±az{èzš«še}X•.ÜúL¬–/ë‚7Mö›¢'hW²lJðõ%ïÜW[ÞÔdk£wòÒü‡[09ÍêË–éD…ÿXT8t,& OL”©ì$'nŸDÓöS7Ø4º‘æ y…9Œû`ôX ÄNt˜Ø$E”I¦#7ƒÃÈ‘'0ìnÃ4GN"Çðok…œ„‰Rµ|ìÈÚÐ*0üŸØ¸]%c² CÑ;:ôX´VmHŤ8ê$Å$ d¾®} F¨ÁÚÑ‘—EE Çú œ–¹ -“yý·iDÐL„Ô&Äl•jÏl•"GˆªeßÑ$©&®r´ã2k3©õ™ø>>ÒÑîÊ€›Bwe_-šL  Ö'Ì/,€»´ÎQ¶iÄlÈu"“)³kâ uaF0—aàÒ)[‡'(N{´ž -W¶ô\”ËvkÀI¸:(nj\a×±\០µç6d/i±Ó³+>¸Ëb¹áw­Fž%;èßÁ™¬‚úªJr -ö -Š$šäg2tc¢$VNsüùžë¨¹1&2yÂêSVŸÚ¡…¤Ö•5ýrÈ’/ùÎN¤œç Vân¤“}aÓikPh›8C2ÂÑ¢X>v4?È gÚõÀ ;= -ä‚zÉ8=ñ“ËT*yc —²ýTr~…#.á`„r¨õi:{k5€Ëàámš¬¶I6BIB0XnÚ–ÌN²=ÉÙcYîÜ>´7/hë FGCðÚS…5ñ“Ü=>µ- ŠPžÏÅ ó(M}:Š‚MR,xÈlö›üáhQ®[_²ÂÿŠá¶Ø‚')l¨’I›4ö}O dõÏé* ÏS§ƒ¹—­èÛÀN&‰tØG†ö˜¤„?ösd(Ô™‹ð.ð~j°¸QÒs CŸ#ØÅùÉâó‚’B^ȹ鉀MÊ:ºçh¡&2Hvü²z@˜iñ™©_¢S`ˆ)¿ÉAí´'@)ª¸”wªû#oqþÐØ@ôGP%%Iî Áå”/ÁÀeÕ¹Ëþqò°]ØJÆ6PÀÓmˆGKºcp0ÇÌ ¤Ç¾cÚUÿ -tˆûF{ëñ¥5à¬\¢Ôuí²¢¼é;V[G™‘á‚7ª!îœÅ‘ŽOÒ²}H!N¢Ôš³HÃÍ.­¸FÖì"Æ)¢L/JÆbœ§°àòã²,WÝÉ‹U³ª–| X„œÁæ¬LgïZZá"ŽÇí4ŒN¯G¨`¸?Ê•4çȯ}úË=“U×û^«ï çꮿϯ;8ÙêLÔ>›?g>ž×€ÌèS À*`MuBÆ”u\Üð“zè8íÊVb;´ÑS*ªWý»nBRz!RW¨dCü Ö#;:uÉJ§ê"+G6Õº.xï&RbH²é9}•·YEó+׿Nà|!§¢o‰'ò\WÈ$\ô¿ŠÙÕ\þSô yàHÆÛ×Ák¤}ÕôsªXqÝSÙïêhÝôÆίɽäJîlÔ™o}p“62 °äâLŸIŽúLrÚú@gJrÜC’œŽfaïÞöÜaŒ™ì Æ£ÙÃÂMŠßgç’s4ë'ù}NÅ7˜Á]ÚN, -¾aÖàÍÒLœvó_ õ­­ŽÏVü)$øIž¼È0Aþäj­mÁ8w`qXßÆföǦ=2”ûáö"ÿã«©¸¨”· Çrß„›‚ñi6m[DRGHnêv­šT^Še[TuØ+$žÜ³Hœþ­ -pÕ¡ÙÌDf—S öŸ#æâ#®Ì"P¢ôR<õ.È_}ò@ó?)À\gâ 9Lp iŠ$ ‘8½=–»™,É^ÂâÒ†å>(,Ðœ\êKIAYËû’zŽ¹Gr)¦u¿;ÇçX\Š¤n—Eª¢%¨ ‰åoÂ#þwn*{í³|“@^Ç7þ0e;Ì êøS …ùuè» “EYžNü§d$Sï ù^Í~Jáš$Ž,ÈãíøvŒÒ¦“O0ΰØàwŒ>îcC ÈÁ;Q¼¾ ¥êëüäJ*.yÆ\yã“ÅI«§Ý9ª‡†KJî÷` ÂÔù…})”ÿæÏ]ó¿šÒÂUâ©Ò³c»dõ¬«Ç`ˆTøªøÂDáw¡Ç¯y âµ{ëðß«¡cGm4íåk;,Oã/X÷E‚íýÑ“?ê„9ú -I;¥Ž©‡]n›$ÊÓL6|öEõ°ÁÝeNÚOTt5êÓœ}m‚Ë6–6ºáµiêšE"Kcre;7jöýà{dî-Qæã†+œÊϺ,:Ú -W¹*£O5ìJúT†Õ‡’Ïâzc¡¯‹•Žð“àÀ·À±ÿzëÿþòxø,;I#•e2üQ±D}Ì …œSÉ3ÊÝ'ÊÏIÿ/ ¶ð‹endstream +1733 0 obj << +/Length 3302 +/Filter /FlateDecode +>> +stream +xÚÝZQoã6~ϯð[e fIJ”ÈÇm7ÛKqÍövs(îÚ>(¶ kK^ËÞ4ýõ7ÃÒ’-{³×îpRä3œùf8$­&þÔÄä"wÚM +— #•™Ì×Wrò}ß_)¦™¢YŸêÛ»«oÞ¤ÅÄ —ë|r÷Ð›Ë +i­šÜ-~Ir¡ÅfÉwooßÜ|ÿ÷w¯¦E–Üݼ½Î´‘É››¿^Síûw¯~üñÕ»éLY£’ïþòꧻëwÔ•óßÞܾ¦GÅ™Iß]¿¹~w}ûÝõô·»®®ïâZúëU2Å…|¼úå79YÀ²¸’"uÖLžàC +圞¬¯2“ +“¥ihY]½¿ú[œ°×뇎é/Ò€l"•F½ˆ­ÒÂ9“³•` %ò\eçç¢qæâj1œê`Þܤëj=QJ8c4š7×"-T>)Œ“çdÞ[T°§tÂä™BB%a ‚{Š·ÓY®’;ø¯“sÀœ²ÐH¦„M5rž|œ(!3çR¢éÕýJð ßܬõäu ë™ô–æõ&öKÊu°€S BîP±yîå}_U€¡Â&åªkiuyÚ”)XàžV·Û–M÷0U2©¶S-“Y×î}e^ñØ>ÃÌŸ[6‹‘ù•© Ó7í®~x¾<)¬ÕI°Ç*Îr'´uvÒ³îŸÃ "Ó¸sÀüŸCó‚*Í{T#&‡ŠÓÀ#D•‹↔2ùgÛTî¦J©Ä¨Úv= †éÀ‰4ê„-OÁ¾’eÙQe]Í—eSwkþ®*7«lá«»Ë"y(çõT%«zWî*júË≢þ-ï+]µ£Êª^×;îm™ÉnÉ£Ëu»o˜°}àm¹ .»e¹ÃÅár¢»Fhzž¨ «ÈKÏ+Ýs·«ÖcSò]h}hW«ö©nyÔfW· ÏVn6«gž¥¥ò¨øÈùŒF ðÈ|b¬Óz|»a¢YŸê<"•÷)pÚyÍ1o%!neàî™Gªî}ì(ˆr'Ü_W¿J©› + ©!‚`Q$«ö¾\QÓªîvTó†„Þ›Ÿ˜x±ØN•Mª®£ñ“ؤ)×Õºjû‰P¤Ùð4–FòÆ-OÐU ܾ½»yóª¯CùXy‡€p£]6„ÎÓ²j*`„“~ÂX¼%µÎÛÍ3Õ’*àUFÜË¤î¨ ÑZ-¾†kÙ‰$®¸FHÑùQo–ÃZáõV-ˆ"ŒðûŠ9ݾúmS$ú¼õåp ;„¤{ùŒI–ÕjÃU/”UÓí£Z±´ 5Xy]1µ_»ïe2”…ûžêÕŠj÷õüú oPµ0ó#ñ*€–X®vKþ å‹1×~ë]±\Á”â@¯:3h'eɦÝ.Ÿ©r_QÙmªyEUbÃSì°V•ó%‡È¾“i 0/²4lYC÷:ò pÜÜš°ñ÷M,| @)ª†ÙS‚ +OIR|• W£En\1ÔGX2¸ L¹ÅªEƒ5ÔÈlÀòÕC¹_Òj„ä 4.]ró@0ìT*·Bk“¿T…–ŠiÉçqæº#–õ§Še«j*GxÂþ {ØÙ½WòÒ™&¨ÃÝg ~ÿ5M[3gÂ"¶´€ªm½¨HŸ©2È#º *lD…ÐJ†Ô$ni¦zê€-pL#’£N¤Ä´Þêäç%ª#Í䨬Y!]_ žéyõç yÂŒFá&ÍRÓî •];Æ6ƒm(‰ØPÔÞ1ºå)G˜ÔöLvÒzKÒ:¢ØÇ5f€ +o§¢IR¦_†ELÛõ‹89G'¨ÁPªÜ{¾:ìÐ÷ ¨ü¿Úm¶db´ 4s–rl‹‡uwX ×/8OBú;ÐCµÞì8·`×Ú¯`ц3°¡b×m^ÒVF½:›~œD–ÑÙé|úѧ:Ÿ~D*}]þ> ÙÚ|¶«×Õ¬nNrg${Y¦c€A8™p:㦹‡”÷K›Z? µ)ìŠ6Ù7Ïð°{Õ6~ÓGR=©æífq?ižiäºnö»Š›I–ö?¤Ú®ëÙ¸HAVU L.¹8Î7ÑÙP急Ғ*‘e@ƒ¦êÎFY{8Ø¢^ï×ôñ©\í«áÌÚ2Ûò¹7k&Ó#Ž—‘¤s8_Âò.#©GuIjIõb5Š¤¬’ÖË’DªQ†hÒ¢pÊe9 IE4©!š¢ã!Iá~NåÆËÞ>l¥@‘¥"²”A¥C€fp©˜D)—:—‚ã$¬`?^®ü¶Ô[ÿ5hŸAÆñ™#Rè<°ÑùÕîw§!*J9uQŽHt*ÈV9ØIüú’¼ÝïVòv>=â wn…Ï~ÂïÀƒã”§¦,Ï×jBhòµhXøàj÷UJ¶"È2þM(ýÇ©4u"WŸESêœÕù85Š§T@ÞóQ"Õˆ,Ã@eE +IûP˜¤R •J9ˆTR"•T© ‰T0ÐG*°Ec}¤’„­)bˆ{8RI‚—Å*a€å¢€ø5Lòÿ­´ƒ¤[js`}ªó‹T>}¯¶u¹š}ÜWÛçÙïÖŽ•¢>/ À4#ü Jsá A +ð~U~B¥úp%¡ÓN y"¶‹zîä¾ÏKKë²Ûù`•ªþxM'[(ý•Ñ‚Ðo|cý@ ‰w]2Ãf¿¾ç+MP®O€-{€«%Él]‚˜a°§'×xÌ÷íÝ>Ô‚°PÝû»'¬•T鹉¯!µ¥Û+l££5N·Ši•ÓY‘%_ñlMµ{j·èã¾lOõb·½Û¸›: j`«÷·¢Xå l‹R@ÝK©A˜‘haxפµ +F@ãzSvGszXÑìÌîi‰çÄ9OˆòW>ž$Ü +áGG‡XΈ(:y†¥ÏýÍ£]§¶‰Eó¤édäxG.ÏÈ~Ä4τβl bè/<™ZæÇ{æ`~èðæ‡60î|¿%È{Ûûi8ÑÞß$ã'qÈÏ—¦ö#Ø°“üu.ôø W(ý® %ÄÀnM[4R糖vÞ4^Ÿaf¯x‰T˜ð|ýŽŠEKü,ßp9ÏvÉüª±V=æ·}‰ÈëY'±Ár<â<6-§‡X3r¥fÁ´Î¤_`Z%u>0-‡Ÿ›¯)îiº÷„»pÛ +²‡» Ã]ÿ 3gªâÈsãSÑa¹ø +C!>">°¹ Y =‡,èsßÅ·¤sŒVPÉ—ÅÀ"+ì‘B΄K“²P—ÃIŸê|8‰Tý§6Ÿí=´ÛuyšþjÓô²‘jDŠa¦"E^dùP zúTÎô^üœã†€•{î'[aâ=µTYà5®MxA‘”Ö}=¶w¥…°. »È1ž`‚‘ É ŒlÔñ#ø‘_+]¸àÄœ›çu +[Mt +J*ü=‡ÊŽîµïÆaç ^FÎØòwJ˜ÜžÄXcy[+|B-¡‡}ÈRBSÄdÉ´T.*0m˜œœÓS³<ĈK|N¡g¢£u¥ +b{6aÕH‹P7C?k/HŠµŠ·é”!¦~YþùªH^ß¾§¾!¦VŸ `+‡Á–^Óü³yl /r4$¨žúckÒà öBd8‘©ø€²)çXvÿ¾ýiŽ®äñ'#x§>PÊ©ìZǯ‰ÔXr¹i»®¾_1)d`-÷SÁ:£8ÔÂZõRÔ[!U^Ejæ¾nÙi‘TÞýõxÍoB:Mîý!CqPÛøs ÔºýßÒªï¹5ô¢ûg:`§U¹ƒíØ?nJLôŸ¨“ϾJ§|ÑŸ;°ÝA†4[œ§‰[9ôYñ;Óý£ìõe CmóTÞv38dŒ»zêÄŠÌöUÌö§7æcêO!îÚ­è—˜twTÒ;¼–iO«¾õ‡%Ã(¦Ô?Ösº„èÚnúyj `hÑ>u4þ ¾ Ç”ÛÓ’kbdõ`Î"wÙ`õ…E| +³¦p_S3§T”Žß€îïVèárQ5Ã_±”üûžþPahÙ…SÆýó “ ñ.5ñ¹‘§Q*ǯދæ™_¦FàOGv}e÷§xø!UVˆÔÚ3Ç ‰Vfa +WPÈÓ´I +Іý_ãe˜$endstream endobj -1225 0 obj << +1732 0 obj << /Type /Page -/Contents 1226 0 R -/Resources 1224 0 R +/Contents 1733 0 R +/Resources 1731 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1203 0 R +/Parent 1712 0 R >> endobj -1227 0 obj << -/D [1225 0 R /XYZ 56.6929 794.5015 null] +1734 0 obj << +/D [1732 0 R /XYZ 56.6929 794.5015 null] >> endobj -318 0 obj << -/D [1225 0 R /XYZ 56.6929 607.7662 null] +490 0 obj << +/D [1732 0 R /XYZ 56.6929 672.8271 null] >> endobj -1228 0 obj << -/D [1225 0 R /XYZ 56.6929 584.6557 null] +1362 0 obj << +/D [1732 0 R /XYZ 56.6929 648.9121 null] >> endobj -1224 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F21 714 0 R /F41 939 0 R /F39 899 0 R >> +1731 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F62 1352 0 R /F63 1355 0 R /F21 930 0 R >> +/XObject << /Im2 1341 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1231 0 obj << -/Length 2890 -/Filter /FlateDecode ->> -stream -xÚ½ZÝoãÆ÷_aäådà´ÙOry÷tIíä‚äÒ:îS4EÉD)R!©SÔ"ÿ{gvv)RZÛ) -‡÷{çó73+‹kÿĵ5Œ«L_§™f† s]l¯øõæ¾¹~Í2,ZNW}õpõåJ¯3–%2¹~XOβŒ[+®V?/¾þöÃ_nïo–ÒðEÂn–&ዯ>~ú dôùúÇOw¿ùûý‡›T/>þø‰†ïoïnïo?}}{³ÖØ/ý Ïl¸ûøý-µ¾¹ÿðÃîo~yøîêöaäeʯà -ùíêç_øõ -ØþîŠ3•Ys}€g"ËäõöJÅŒV*ŒÔW?]ýmTu=¿;/Šrw3”+0jaIf¥£ô#®E¶8¶{jäÝ°‹’:û±è«fƒ;o1á;µLÉ Å…ÇôǾnò©x¤e©©_öŽM²ÝÐ(€Ë³µe6Qfv6+Úf¹À¦R.ýÚ]Wµ — -e‡ç“4_ußbË.VåPvÛªñ<žòZ ÅfØçu}¤þ.ï{8¥¶”B0¥µé –CÒžœ´Úýæ l<±bq‡ªU`ßåïùvW—È17pç?8— ŠfÕ"§E^íÔYçEU;b/oV´ô¤j7ÜG䥸ǰA«¼Ü¶MDVš3i’ W¼áò,É™ÉÀÉüQåã>¦V%Á%LâW=mê#Q [’äÀ9˜Nø™ä6q«’Ì%³3FØ!ïšÓò™óCRb?WyäH‘0#ÿ¬1iŠÖJÆ£¸Zù¾/±)'¾‰è›8:*)r¿ $Z5ë6æ'‚Y¥^VȘ• SeL5œ%vTàСžüìnð`©lÊ2emÐqAá:„ÂF_k Ø•ëÊ€Š' jƒúr¯ w¨†§“™0Ñ&ß–«PU;8 K;×›§ -0^†,/rÐ,5:êó–J’2 JrN §zÈËv\e„\—×$€rz$—l,ÆâKR­çÎph÷µ `yòy8¨ü4ɼ(«ÏcX!Ýnã±% -ÿQüC“fôÂ~X•]³ÙŒ -Ó*zP’7ؾ(jòl¯*Oî€\$#uÙ ±ƒÖê¾a¶/»Ïó@oüÎ~ï (µ¢EH2Þù=Ý•o“Áˆ€Éª§©ñÛ e³"Ë¥X¦¹<(ŠÑV.ˆ€öƒ‹Z8DäY9’‡mw6,ënìbßÔãxÞû/}ð\¤nã#Â_Á%3™'ŽRš8T*9‡…ŽË¼`:/£l‚ä ³Q -“…)RÑ\_­%@+Ò¬\u¤1ðŠÎc$ôâi•’I¥’×±P:8¿—÷éîÖñ|=K 9Ä0R±eìla˜< ?ªÊ=É붮ÛBÙ”­œ>»Â38ì¡÷‚´7'dV† &ÃΉ^Jb)!QÚª¹„»fUxêòhpÕš%`ž~‡/‰×,ì5‹ˆç5kì¨YD»Üƒ#%ç–”:…¾©éAªìÒ@\8µM¹Ì¾ž3l*?ÓÑꌌFòæH¡Ú–¾õä#Âanå×£A^\/œÓ!ܤ!ãÝø<ätS»Ž]w™U#B(«g‡Ã”ãì*8ÙÎ<“JKÎçi£Õ½*b ¥˜jô±œ„£©¬bF -Ï2.œ;­‚¾q8F‡Ö«¯’§ZO -·{¡ÝdžØúø¹ÇŠK1d€RJœêÿfX:-Gä`™MÁÖhé“KÌ´(vÑ]ó”ÂhÛ #j‚¿9+Ì­ g Î9ÃÂ!ÿã¦/_n«ÐXÆõX ýÔoóãô’ ¼@ÔÍlbÎjŽX© …`"ÌkO: -êÙ$à¼ÇW ÿÀ¹Ïð2°/ÿž‚] ì‘«`·¯š"š¦¤‚q‘þ9:DHTè}Ï…ÕþŸ5f^aH) ç@ʤL7+¡–*;WMçlÚî¡&I™Hm£>ƒ[j0-ùYD!ðøm“«—1¯÷fÐBT§f1Þæzî05§iï=´É[ ?úi²:j;SO±j¯b¤›wP«¡fBÈÁ -&&¥%³b|O 9œ=wÌ䷘ʈoÞŽ¥SãEÃSfðq†„CBNq -zk ép_ˆÓÊQØñ1Z~$xßRgÉ3õ®TS2Ñ3Ÿ)xù˜ýµ;¬qzOD~œ_ Ⱥ¢– &"!%ÚöÑWÊo=n&„)Hºç.êlr[¯\H5óú{uŠ†1Gné—ºTJ+YÊ«)ñ¢4Ù=vïè]ÝUeòhnÁ$”g&Œ{¾Ÿ~Ü…ž—ØÂ}§b š¬MÜ‹F4:Ò¢¨j»Tb^Õ È/“Ù¹f\ú5R€ DË£–Fác¶žGi—wåãÂ,§G˜wܼƒÊÁ&ŠF6eSvy ²„¨Çý›\èu³œ[>Ÿ·=L¤”¨ Á >ì;¦‚Ò¿$;}ÃhqÊ@2Ðù!ÊÛ"¶|P¸°( 3ž½Vr–ecùHï1˜¬ó}=èldkHC.EìÑ|´]|ÛhLôH»òiSLÚó—vÏ‚ÏÑ(î‹®z‡›óŸDŠÅšÔP™ÈÒÀ¡ÉnsMûÉ/>ãúåtÃå/>—ç"?•Exúâî7/Á™<' â2S\ØI?=«^!äò4ª¼". ”HýBÁàõø«·¯• -ÓeôNÿì^¡áù¥/AJ0lajçFÜ&´œÓ6º²³Z3œ3þ0≙-•‘¢Ÿ .¨¡ß&ætùŸ‹&ÛbÔÈ5yØìëL_ó`hPg ü1P$Bý¼Ô'uTTèâ¼>sNÊc¾@N…žpŠÏåå\ðãêÀéë|ºâŽk»:ŸvôVºOÎ> +stream +xÚÅ]sÛ6òÝ¿Bo'ÍD ¾>¦©ÓsçšäR÷á®í%Q6§©Š”]÷×w ЄDÉɤ77™˜ `,û ñ ƒ|âtÆd®&6W™f\O–Û+6¹ƒ±ï®xÀ™G¤ùë›Û«×ï¤äYn„™Ü®k¹Œ9Ç'·«Ÿ§oÿùæãíõ§Ù\h65Ùl® ›~sóþ[êÉéóöÃûw7ßýôéÍ̪éí͇÷ÔýéúÝõ§ë÷o¯gsî4‡ù"¬pf»›]ôݧ7?üðæÓì×Ûﯮoû³ Ï˙ăü~õó¯l²‚cÅ2™;=y„Ëxž‹ÉöJi™i%eìÙ\ýxõï~ÁÁ¨Ÿ:Æ?¥]¦…2“¹T™3°Æ(—YÆ4pmnuž)dÏeÁǸ±Ëݾ¨Ûu¹oçU}|d.mf·“áº'»÷X#Û‹Áö\‰L;™n{_ÎæR¨é¶ø£Ú¶Ô¨ÛE¹'¸YÓ·ªÍ¡^QãϦózúCó¾èZ5‹€¹Ÿ¹é¡®«ú. 4õò°ßϸ›–u·yšqΧ($Rx²€Àv´ÂÑ8Ïr­…§yU®‹Ã·azúPl%U‹s^¿SC¦[ž9©,° +§rF()cÂÚ„(Ì›zI¤-RL³† k9&M˜u|G[²F $ämñD·»²\xØáNìy(= we½ þ2pâ¦x]xí+€sq\©:bÏ5ˆ¾8b`±iÒ5O ÕóqKêñ„ °iŠAM}2´,6¶OmWn³­ ªa™Êcêý`]Пˆ•2¾9t' +¤dÆs—·ï±FöOÈe\@WB€× Åóg ÂFÔ %˜¿4ìƒ +a‹T¡ +!:©xB`0‡*„¨gTˆ4ˆµF¤7ÿ_¿©¿Ã°)µh‰ßeÛµQ è[þ±,ÛЇIï¿Ú‚¤yð±ÚIX”Ã5ׇ¶\e(žŒX…C½c#h°ßtLƒ%Øi–sñ%*|F +a™`O.Jáë¼öX©îHgçu{"ŒÚdÖåæ2=Öɉ ϬeyJq˜³gaÄFFÁrºCΞÍ96HÈ¢ozYÄy^±k0Od/™¿Fs2×`€…ÊS9\ûy Ò—³iAŸ»ê¡¬ ¤e·MWR».¶jË=šE°Ðh¨EŽœ…*ªüŒP ¥2kxô bÌfg¹µfà$û,¯ÜÊO¼B*G;YNÎÙ¡wðGõÞ!(3ßm{.R„æ}h<ù .F|ŒzŸƒÑg@Wï3„ >:«ŽðÈ;`ù)èJ½Ã`K¼"¡wH¨^"Ð%zR—xÊC–ÊÊç2\¬½ºX'(úprÚ< P®V(aØß„oAÃqé@M…KnøDh‡–Âèê(D9¢$=ÓÒÈc!¼ŽQyÄÜÝHÛšvßb.ˬÒ)—á§ÛH~Ña›¶+ÀMƒÂžµ‘ð?“î\>mäë¼ì±†¼ >7‡ý²<5‘"Ë…zˆë*¸¶YÎôç‘q,MÀ5ë\àÚªìÊý¶¥Í3ðx_-ï Œ!äÓbµ"‘o#ùDŒ&~ƒÍ쮡®›Š Û· 5®ËeW5$èxÑàÌA2Ò+GÏŠ~ÓÑZð]—§ @¯âa4ÚdO\˜òlÿuîÅÛc’ƒv©••ÂáŽbèèRž$s§¸Ó2´Ãa›ƒ^ùƒ±ÔžD™6;<|±ñ^Úam;ýéÛÔ³köÝ+ê‹l°Óu³OðMŒA®÷Ô aξ"²Íóž0ù±ðˆ«¸Þê LVµ¤ñÃnªÓ"?jM(uÓ¥'‰Úè©D ½SK-aÂ[üPðL0\~GÞq³ñ„@_ôfFÑCÄ  C{Ìdñü÷HåR}ìËŒO I‚<Àu®‹e˜ó‹j¹iÚùØé JD.À â!¶ÃÎÄìÃ@Ycü§·÷ÞžNB"mqÍb·+‹=õVuØç>¬•®-qí´#6Rr“in¢æ4ó^óOÕÝØL1m1‰í€2\°ÌrÈ¥R‘%&K ú̬CcQz7! “=R>” +i¦Õš)î´ª¥ðùËêÆÍÓüX´Ý4d, Œû É wúȽhöëCmÒ'Ø  ;&bà@ ±"»ã #„:äÿ܆ŽÄc;ŒÔŒø¡*žâH(:ÀHôÌ>„(›ÃŠ¼3t£B¡2-¾”#Óƒ¢wwؤ؉=›ò$\à vPf¢ Ò6çŸS“ΗÝx=ŒŒ5™±@õÙµhƒµg¤KÍ#usÜ’3£‡ITWÈ@ LVv¢ M›¤,êý€‹Ú@ ˜€KYýa67|z Åôú„5°¨Ï7Q Ì +W>ƒ›ü>IR¹øXûÓ>sÁw¼¾ÙŠÉ· œi2\ÚŸË$É!œ&w (à9D>Œ"Ÿ› Vî+eEæS‘éŒèý eÀÙT>†žUS|ôvh»ª§é =eבöAƒì5ö’ZÑ`óÉÞCc=ƒ8'˜Ö#ïBaÅ@b9lúþA[Dˆ¡Ê-äNo/úëd2±ÌäLNæυᯓlÈæ2}Šs~!´Æè^@À®øåȺÇ:cÉææD,”Vîp\G¬BÃh•<¢¤¯ð´”°TŒùgm2.rþE–|´s}%÷Õsyj +Iž·B݊º0ÞüÚ¶ 5ÍÑ!ª9›IÈ£Œ/¤EC¬ —±(6é染áñA>.Ò‘FèHï<·ë“òý±µHP¹¯ bY3(âà0¸Ç62ø%tòÑг© ¦]¬z,Uæ gƺ/uÇFÆ)ë¢Ú´èz5æg!ÊU4Ú(Ì‘ÛÁwç*s¹ÔãņÃ$i{¿[1xÖM +¸{kùßã&VÔX:?ìÎ9/) TäÂò—¼¤ÁÑàzþV/ Yßæá%‡K_ð’p4@ ÎÿÆ?±°éºæ@VÄajÙ$BáÁ†‘Þ $Lƒòà Œ€H¡¿óJ«ô^1ú.B³Y¬Ì1“RÐÞ7‡Í*ÀeG¼¿w¶l¥$É€íaA/ÕDÉNyÂE&´ŽV’±}³ Aœ +sL%HÝ@ñaRŸ D2öÌB`UîÊ:tvM‹a«„ì»G`àkÎþÛ"ÿÃ)|ߢÑoù„ÚÆ*¶î1§Äƾ\ï)ý‡¦ÿÈG¤˜y>¤jÅ×)Úÿ9¤àép§^xÐè±.x¥±°ÂI†ôb¸É©c +H#¤$Òç0$³2¥å—6tLؼ`A+©:YN¶Ée!Õ¶¬wL;&¡$ï³àól8¢Þ) ÉEêœ<áãÎ l¥evàœH/Xe'¬:~³=&“ÖõuåKÎ)†-\ŠÌ‚¼Ú .ÈP@:5@—ƒ¼wƒ÷~’é””D†r5åLBËOþUÛEûàòD˜œ +“ËÂÔÒpÀ¤ùg'M@Áä½ Köa&ô +94ÚQǹa)û›±?è‹e¤2P7cOŸ +„5JQçÛƒoŠï©]òÞDatGÎdfEË OåØ“DlòGœ_˜f¡ä:üa‹Å„í®èªEµ©º'@ågÅÏå™\^¿Òyñ‹HĬ®Z?8J‚űK{÷H—7çÌ·‚ ôâîÇɌ̤6|ä}k~¡È‹¿äï Ø›ÄÞ0””Óýï?(‰ÔaÛ¾nŽsBÝ‘©|Œ£‹ðc/ZæcÏ Ò“Åo[R±ÀN߸½y÷êÝů#c±Òb/bR±‡b±×8*öš˜Jà6áÁÒôïs«¦ãõ^“ãO3ž_ÿÀÄ>ºIü=—G3ª§¥MZÝ]nŠƒ”“Šª‘R™Xs@†2Ü$eg…±æRµ‰öò?’ã‘y°Ý è뛾è‹Ðxe‘+ˆ™ó¾^ùb¶Ò 뽸¶¯÷"Ð?k*»’~ÙuæÇyRgø‹ºmb}BñÕ?Ü{þU#Äí&‰qG!4øÑÜF¢ð„–S®Q"ÀÝŽþfŽ-òendstream endobj -1230 0 obj << +1736 0 obj << /Type /Page -/Contents 1231 0 R -/Resources 1229 0 R +/Contents 1737 0 R +/Resources 1735 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1203 0 R -/Annots [ 1233 0 R ] +/Parent 1712 0 R >> endobj -1233 0 obj << +1738 0 obj << +/D [1736 0 R /XYZ 85.0394 794.5015 null] +>> endobj +1735 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R /F62 1352 0 R /F63 1355 0 R >> +/XObject << /Im2 1341 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +1741 0 obj << +/Length 3298 +/Filter /FlateDecode +>> +stream +xÚ¥Z_sÛ6÷§ÐÛÉ3Šÿ.OiâäÜiœã>õú@I´Í‰Dª"eÕ½¹ï~»X€¤$ÊI&íL‚‹ÝÅb÷·»Å„Ãÿbb,³^úIæ53\˜Éb}Á'ðíý…ˆ4³D4Rýtwñã;•M<óVÚÉÝý€—cÜ91¹[þ>µL²KàÀ§o>ܼ»~ÿÛíëËLOï®?Ü\ΤáÓw׿\Ñèýíë_}}{9Έé›½þxwuKŸläñÓõÍ[šñô8ÃôöêÝÕíÕÍ›«Ë?î~¾¸ºëö2ܯà +7òçÅïðɶýógÊ;3Ùà gÂ{9Y_h£˜ÑJ¥™Õŧ‹w _ÃÒQû Τ²rÄ€R è3Þ›If<³Jª`Ày[ÊÜ´~*¶Ûr¹,ªøžÙ4§×M±½n:û»®Ò‚íá—§²ØÓ’yÞ” }œ?Ó³¬«Ý²¬è5G»vb ÌÀdFg°'Ô«ªÛòþyÖÔ»í¢ˆäÃÍXŸç&R7mÞë¢j‰ÿ¾l˸ö±‘6S*cR0ŸÌ#Ÿ°½SaR3žy…ÁÎOgŽ$Á£|¬Ì’ÒóU½øL”…'*‹ºúçòa·ÍÛ²Ž_qfU°c§ëÎU†qñN§\ˆ!7ît< 9¥Ïò¢uxÅaZqÈj–”›Yå™äN}³3=8'Gæ€ —Ìnƒ…n64V‹`hÎŒ’ÉÐ.gVLïà_9=‰Fg™‡˜Xã˜6ìfòçD0®½WD4‡½ö6?^¯åäm ;š 7φœÃ¦ìð¸…ThZMlÆ™v 4ªü©^å;ÂL1J”õSÉ 4Ì«% ŠH³*!¾Â̲."=Ä šÝfƒq¨ÁsâLѶ!Ìð%xS˜¥(" Ëå¶h"§ûKÅ£?ã©CáîÍG +¦¦^\J>ýŒÿms J¸ ¶p¸Î»Éð”¿Ïqx„õ€¡³ú¾Ï­gÒC|dh µTî š²L g+4SΊÞaÅH6ê¨N@ködÍ$g@bÈúDD4¢Às)ˆveÔ¡¿”ŸÇàN¦¾[Á¶R%ê|æ»–ùfNÙDÀªéI,i¼÷ÊEC¨< ½þ–!Và‹˜<`AÑ°1˜V0i‡Ò¸]Ûe}a™ƒáœO{û‘ø}¬·QÖ/e®ÝZ8«¸t×ÀÁèÙn¹™AèÍÑö³Œië|·ýSµ@ëd$ÈŸêrù%žàÌZ ýµ<ƒ–ö›´œIEð1rú¾œ>Ò÷eîγÌó”ñšM± ãU6TðX…qd¦õ=ÍÀ¹ê`r€üçúQ¶Ié’HO¦H0ló–Fûrµ"ºP¥À Ø%òå<"Iÿ)ŒÐ¿Ñ»Q dܧåÉi¡T\M?Å ÆiŲ ÂÂhÈõÞg—ôqû3Æí Ž;úÙpÁi Ÿò Y¢XÄÄÊE?Á“®òJx¡>|Y‘ipÒkmèÐæu +üÇzT¥äOy¹Êç«øš Œ_(®éeY´Åv]VÅ­+ (æ‡/Å_ùz³*"Ä`Ùv$á¾^­ê=Ž#eQp\=ôuwÀOÍ…¤™Àø/=¶yõPÐPÉÌ:Zc”yEãÿ½:Lâ\ ÙjÀ$þêD„Áé(b@A"ŽŽâhÁK•ì,¬¤Q‡SL8Óã.Îîâü}8‹z=VµBò…¼p©Ê×ÅrDÀ^ᬊT–(Ã%`ùŠï¡9*GêП#γ4ÿ„ÊZ±h{$Ãß•‡ÿ~ 0‘à¾:3Ù!˜ ‘Åa^Ñ´ˆü/`!SÑ…Ë6xÌpÚÊov \2Í8þS—©ìñwÀv‘#pA8Èe;NÙ Üžú©ª2Ó%‹³Ç =ïzªÎm‚œÅc]7‡ -@,Ì–!ÞatI†­g\úì0hÐXÓŠvƒ‰˜`úHx†V)lYǦ&Ÿ‘c!&Ðþ÷yH0 F;âî_ä­9`]ƒãFÞ¡ÜY¸i^Åu÷ÅýôÏ]±}+¡÷‚Rä. l„8œÊé14 žø¥Ûsxy¬²GþaXî#QÕìC×ã}½[-iµ 0÷P´C®¶_ylHâ¶ì©Fv‰ÞÈM±} +rìäÂôcþ BxÓ,èò‡¼¬vqzzS·`‚2jß—ES’F‘[DT†°ÀA¾jj"ŸÇO´$BaZ^W«(9Å8 Üö+êEÇ¡«ï‚ëL †!a³ï(ï”Òñ(ĹK -™“ÒàÌX˜Ãö´H¬ëMpmâÛ¥m|‰fßUË<ø1L ©FðmS¼ŠÇûX<ò!7 låÀkèhê§rY,SªEÁ<_|Þ‡eJûë Dà¼\•íóÀ'TßÔMSÎWñsSB]Ñu$]9±é„PÒ¢»ShŸI#M‡MLJMEHªL>=7m±Ž×ƒEj¸©Y—£G|Ô™Ü=Æ"7…Q¦§ÿhRÝ›?į¡Ú†jvWÏ‘>‰†qtøTâzJ 0H…ô +•¢z «ÝE¾JÕóS¾Ú¥e}‡/˜Á‰ÊO÷Eä{4Ä8ëƒò$IÇR[[KÅ ‚dÒƒ#R“0Ý­x?bN¥Lv2QÖ<Ê$ÇQY½òøæÇ%Sý…Ÿà½µpRˆEç–n‹Ñ&Xqͬæòд»*âˆR:ch•¢CÐmBº†–­_K¯M(ÁUl«`†"ëü¯r½[ÓË°ÞÇ×u½«Ú1•¥ÅëPJ‰eqŸïVíxeé3=.6Gò£Ñh.£}ÉÊ*–Z3cÕQɈ’*l/Èg‡xB-|ÎÓE›oÛ®WÁNðp¤¤Å¶Üô÷²£>˜QÝeoSþ}ÒQ*p9‘¤ñÒukÇ%Ñ`çn¸:Ž³!ËÓÛ+%3J½Ž,µùc·Ö:“<œL~° À(´:ØÆ qG?¢äoœð=lŒÃ7â¤MçoRô6'=qGõN¹¡,zľȌ9lÇ•:è]áµK´2yS´i¶O#ðÚa9ŒO±Wv& [´I&c$!º6ÌÆd é€î7ôôSèzFà›ÔÁâÀA)VWÿ@ür"^<·4ß^8 +HÏš.àœKåœ ÆÍôCìqDòŒ4Ôƒ9MB-PQçˆ/Ô|:ê…p¦lš]€vä4î»**žjŽ„.øLŒ~Ììô¢….……Ïðn6{ùæxHuþ渣 +éªÞcá“Â|Ap"<ôeï3ì‘ໄj=Їòéï¢Ã6ª·R%vp±³[o"LÞõèHXŸŒzzE#¥À[zûÅ䀷Uº»‡>(je£Ôe@õ¡$ª YÞæg%Ãdó¢àD4"øèP2üò@0Ó‹Á¡À ¥[‡cñ<¨I‹uMŽÛ´¾À+~ÇÒKÉ^Nhð2zh +*°Ìgæ› )«cØé%Ëœ•G7kHd cìªß—0 ¸Ï~_z°qCu2Ê„¾õúžæ¢1†‹ tig6—`ª&RÕñ`6´qÉwe-ÂïgAŸNFÙŒágP›7ž%=lAIÌÛtÍ £{(¯µƒb¥DPÄÙxp6jønG«"ôÖa2±ï·iðbµ†5=ï!o¬éåíͧ~U¹ úóä§ÀGú¿ˆ‹ÊsÚ5¦ó˜Ûhœæ¶±{ý¶ øý±Ûªp„s9=öy¤ ùÂÆ4ÇLÙÉc IÓEK0‡£}¦á™\ÍMVüí„~ࢲ¥ß3¨i‚2+h¯ŠT4'Poó²‰ýAN7ƒœnS¼Â(Bì°Äµ]‰k)aÑ[ב~MW[¨Ï3}‹ARºE9»çz‡7tб• ú¸]úN.Nç¹cxì4a® Þý³ó磥‡Òö$#²×,S>!@Ýl‘/‹Y‚Üã(y•ð_ºiõZ§p[,vÛ¦|*fsœbNuh¡Åª,ªÑ]Ahœ>¾(¡?Ø=äÙœd SR|áæŽæ…Ÿ—‰åÓ_4Ç3¨ø¹T/IL$'n±´Sv(1V²Ù° ̦Õn=§Â2‹?ýená¥MËú4‹ &݆śÐÁhQWpRU €!„˜·6½}Ž‚—ñ•)¦mwÑþRƒl0›u÷ëìÜßq)Ãôx~çݯ|÷ßxõm»rNŽÌžJJ¡â™<û“à©êÿüƒÛéendstream +endobj +1740 0 obj << +/Type /Page +/Contents 1741 0 R +/Resources 1739 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1747 0 R +/Annots [ 1744 0 R 1746 0 R ] +>> endobj +1744 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [173.6261 333.9221 242.2981 343.3317] +/Rect [442.7768 538.094 511.2325 550.1536] /Subtype /Link -/A << /S /GoTo /D (the_category_phrase) >> +/A << /S /GoTo /D (query_address) >> >> endobj -1232 0 obj << -/D [1230 0 R /XYZ 85.0394 794.5015 null] +1746 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [361.118 266.807 409.8647 278.8666] +/Subtype /Link +/A << /S /GoTo /D (configuration_file_elements) >> >> endobj -1229 0 obj << -/Font << /F37 802 0 R /F22 737 0 R /F21 714 0 R /F41 939 0 R >> +1742 0 obj << +/D [1740 0 R /XYZ 56.6929 794.5015 null] +>> endobj +494 0 obj << +/D [1740 0 R /XYZ 56.6929 595.1873 null] +>> endobj +1743 0 obj << +/D [1740 0 R /XYZ 56.6929 572.1218 null] +>> endobj +498 0 obj << +/D [1740 0 R /XYZ 56.6929 347.8106 null] +>> endobj +1745 0 obj << +/D [1740 0 R /XYZ 56.6929 322.2744 null] +>> endobj +1739 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F62 1352 0 R /F41 1208 0 R >> +/XObject << /Im2 1341 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1237 0 obj << -/Length 2569 +1750 0 obj << +/Length 3299 /Filter /FlateDecode >> stream -xÚµ]sÛ6òÝ¿BÓ—H3B€ žŸÜÄιsIz®ûpÓv24IœP¤Ê»êÍý÷ÛÅüiÙ½äÆ‹Åb¿4ŸyðÇg2da,âYLz\ÎÒÝ™7ÛÀÚû3nq–i9ÄúþöìÍ•Íb‡"œÝ®´ó”â³ÛÕ/ó ¶ -Þüí§W×ï¾¹XDÁüöúÓÇÅRHo~uýK½¿¹øðáâf±äJòùÛ¿_üx{yCK¡¥ñýõÇw‰éç ¢7—W—7—ß^.~»ýáìò¶»Ëð¾Üóñ"¿Ÿýò›7[Áµ8ó˜+9{€‰Çx‹Ùî,>“ï;H~öÓÙ?;‚ƒU³uR~ÜcÂÅ„>%@³Ð¾àÎñ@h)|s/0Ðt›…ÎËÐóæE›ÛÑ¿ .Xì 5[rÎb)Iˆt²à½yCøMY×4JŠC³ÍŠ Íj]4Â3y¡£) ÍŽÌ6³d_¸ŽQÈÁx]èÍ•ƒ«ãõb¦TœÛ­¶HCù0ò ÊJ¯“6oŽÌAÖ~ÌÂ÷‘BžÓ°`±RjZ¿KGp9¤ht7âsŸù„Þ¡“wíf⺾`Ò÷"{•N™~ηIƒ„ª Rïuš%vy_-¸š—{]5‚4Û¤¡YC²È#ìU›êÚ®µÍ¾µø[]8î,]Ýëj±ozU“(1>Ö<]ÌøZ®ï‘w¢àoQj:×çÞüºq+Õ.É‘=œ=TY£í04ó›Ðϯž'rMãvè‰qä0°È8•c‘ìôŠUm1!qð-¡Tl1³ÂºµGŒïMÌ•Õã8Yeæ::mÊê°àœÏIÇ÷BDŠÇx]dè_•@KÄÐM[¸äfD#©Ë¢~½À­V¸F¬ÀàW!‚‰»òÀg*æÜÞ`ÙN\ÒiˆP !C2-w»¤XÑ$Ï -s’+j²ÒoT¿m­W†7i8šàçP¾L摈Ãvœ–Z‰4zeYBÓ%ÁF‚ .Ž‚G²n@M¡A0Å•25åv«¥r"4ž&ddüoc8ÊÚaäLCÍ ý@Ÿ¯ß½¦ÉÖ j¤óÕy‚7ºÐ•½D‡Ëò©ÀÒfŠ£¿Ä~f¹¯›¤j¬¡ªy»·â‹¤ø‘ø ã`äu“aÎÀaµ€]EA`n¤Yc-K¼IäÓi]euš˜¥è E‰ùõšÖeKƒBk{Ž‘&ü¦É¾iIÙDR.‘¼P²ÊëIìÚºògÉ¥ ÿÖ_qü5[—#‡¯sî'< -RšP± ËÍK -(vžƒ‹ŒÁ³ÞÝG -Y@°#ˆ®H´Õ‰À碋ÏD ¹ .Ê°ñ©H­ã–8ìóÂȵ$¨)Ö›)9 <ÜÒŽï4°œ» Ö ! ·–ie´9œ'y£|^Ñ̆/ Ùfy³47k5!õ²É)ˆ¾žÒÛ]kEGÇš`e½+WÙúp»]%@Ù¨Ülº¨}gQ÷eV44‡Ü”Uæ2Ob·x¾M:=öaÏh‹óAÝ‹eT\ÔE·[=:Ü2öã¶JjýD=°8ેœóø1ÄŸ~¢æ;„Ü_ tør^—´`FoE JýÉÕ²è¯,qÔ”´Tk‹ýà82nøh—e]ü{¬e -E@‰4vAG Ç©1•²xÕ é“Œ)ÒÀªE‹z4[&ã@ YÂYm‰”둯Xƒ\Sžîð;íq‚ã„lÚN×u²Ñ–笘ºŸ-Ë„¨Ü1ˆ/ÂÑûBÅ6BŒ”ÒL–¿;Q|-PëšáÇk,¯ ÒwÃíþî|:Aø2ÂÆMY±.Ï]ë:"ÏZñ!±Õõê{†×‰ûOeÃc“ààÈ€§.pºõ*áÖhÕu=]±gSen;½AD?-F%Ìqh˜´Ž‰žKù}7‡¯Ù…ªÍ÷ÍS–÷˜‡ÄNDˆ?ÖºZbz†ûNÒc…Œi@9d®uŠÂé0r5ˆŠ^Ðçvœ!ô>Éòä.‡‚ËBFU b˜2w[Óp¥ë´ÊL­j±Êõˆ0Ôᇽ>Z£4ôh×m©K»öô²h’¬`Sæø¡ì®0Qmí’ƒ‹(ÖhV+½ÛѺ4 røìGÐzh]³Go?^ ˜Ï„½£ÁK o±È‹Žž÷þ·]Ž¬!W‡òÄóíó€–ºÇïOîRK†Ì—а<ñ…=d4ã±Ï” Õ35B°HÎ×LyøQŸ4P Ù%ª~kš6´%ìÓBKgl8Áêj²2*kÜò‘qàü¡¯sƒ‹À&xàé©ÝV8Û´•5Nb;?ÕMh]L•ïCà dÄý÷PÄ_§64¨•‹Äþ_ év©ê®]ên5‘‚çÁâÓâ0þ­ÄûˆM‘Ç"þô'0¯ -™=J;•®Ëü¾{²Z¼ï>þ´XJ(HÉaW‹b~ß}£yݦ[\¦×iD3qöE±áßkZËËòK»¯i}Oya2Ý`yëjO§RltóõØCÒ<£6|ø¨˜ôq©Sû£ gºå§t>æ×)(ð€’€šËN¡ääghoöl{éGïþ?‚ˆùJ rÕ¨U‹®ŠÜ}’w_Ç-Ö€õÿî@+(endstream +xÚ¥]sÛÆñ]¿‚o¥fB侦O¶k§Ê8Ž++ÍCš+’"SÙìn3XË&ÂZ9»[ÿ6÷÷7ŸïÞß^/T*æYr½H31{óéo„)èñîçOn~øåöÍunæw7?"ôíûïoßz÷þz!m*á}Å+œyáÃÍÇ÷ýpû槟ÞÜ^ÿ~÷ãÕû»x–áy¥Ðxÿ\ýö»˜­áØ?^‰D6=Á@$²(Ôl{eR¤F뀩¯¾\ý#.8˜õ¯NÉϤ6I•Éf Jëi)‹D¤ µEndbr«¢”•œ’r B)w}¹úÚU¸ÓóJ•&Ežf³á¢/¶ŽT{«ÁÞR‹¤H³b¼ù݃#™oËoÕö°¥A¹mMOp»¡§g“iݶÝ?܇:·tû°Ï:—®¥8n´v›òPóâU‡‡þþƒJI§Ä çCà žpt$8ˆ5Z2]ÂÃ¥FÂõeè¿Ö‰Má’‘uQf D ›Bˆù—ï·®kûsû±ÚV}7±·˜Á|¢²,=ÊQ«b¾iëº}ªš{Úy»ë«¶éh®s=5­J áú°B$Ç_øÅýµ´sàëZÎ^1í +Ö>lýa•’÷(é%ÚÄ5›–_\ÓtÕônß”uýLãå3%%èIJê1y»ûÐûpýes¢íÎ…—€ó¹ëÝ6yaÌl1™‰²Ö^6«!Õy³ŠTÈ:(ô¢ú¶ñ§^ÔíýbÒÄ2™äV—ÙˆT|ŒL,Ë’<Ôˆ‘»‡ +¯±Ð¬ «yÄ-»¶v½ûëõÂdf^õãérµr»Þ_Žš5Oß7tŸa¯×äž‘ÆbÕnwp˪®úçk)%Ê"×Ö«,^9øäÄÊLožy}iRZ&Z¨`t(僽€&EŸH%·`xlèPàuÛ±£a{¨KV©Í¡Y‘œ¼‡àç ìœÕ¥‚—RÆ\Ö¥!Õy]ŠTçNyªFF(s™ƒH5Á©i«í˜‡/Î{ ã…†è±qà¹òi®\=ĬÓà_B¨Ú8{qg‰Él6:MîïgÜé_9ØËué`|ÝÈ‘AÏ|Êøø$-dqY¼‘ê.^®†\€($æ'VÌ}pÌ ùä3ô¶£•L2“cã)w;o-\CUÏsöt;·ªp ´]€»û@«ç]»e*v‡¯µõÚu=#÷eÓ•+-ˆñf2$ã੪ZòtyèÛ-¸…•#ÏO¹y—mûèÖ>‚K‘'F‚TÈæxpÞ—Þ²*È9uŒá¼UÕde áÏCË’B†ÒŒœ xïóÿh¦\–]Õ÷”N˜W"Ðê‚×Tx˜‡¶ë6õU‚î`°/G‘H¥Õe&"Õ#Ç‘cb ¹êˆOfƒÍò¹EmËÕ@;"!íà˜ ysØ.}¼‡ ¯–ðijÑìñ€4ãš~_Ñ‚ Ž-!—¼îWfxÇ™žj{2¡ ˜NÑy -¨Úîj·…µ¼‘üÙ8 À‰ñZP]¸Ñ@å­û®zt‹U]sÝ‹ûL‹$We^d!RMð0&ÉEQŒ™˜JÙåñ’†);L×}Ù¸öÐY5‚ˆê¶ýzØu£$NŽò=ödZ¼‰„²ÔIHzô‰\º‡²F6¬$vÀ¯²ÌàþÐ| ;t'@;íNt‘ØJWr˜²Ox¥“ËÂèI ÖÎߺU E-N¡|ž¹£ix£#¨¤ÉMYí ±¬úá©d(†0±òNÜFÁÈ J!íDJ­18x&Ö(e-Éá#Z ­êvùÜ»VÕ: ïåóDz>„%6„êÜD¦&­/,2–Ȥòžæj9äj*ø혯JKŽ÷z(yw4nÄ,y¼v+’kÙù´Å¢€: j%Žc :‘.èXÿÀúÈ¡bXiRÖzÆÚ†J.ƒø¢µ©Î[{¤ò7µÚµs­`]•_Þ.ÍsØþdw²"˜9 ¢™ì5ž'f˜¨Ëß½ûÌȶi\ÌAµ"A~¯ühö€d³ˆŠ„¯2ÇÑø"ÿDj©$µf`ÊZ(ó¤Ð*ÖõS¯}HªË?¤:ñ‘Š,ÅËa½èÚÕW7qû”wTþ9ˆT,Œ½|š@JfÇÎ5íáíÙJ Ö¡¤Yˆòê@Ôf˜÷Ú 8ߘؔ+×Mº4•EZCM¹L*µNŒAU é‰óJË·Íwëš,ɲ;N ÿ´~(cD`¡äuŸœ·8HÀÐÁÍœKÇj툀Æí–+ ¡„[”¿2¥áÊý}KAJcà?ÇY |[ªj?s ¯6n±Wû+扣½âÛ“Í8‘…HÃÇM¥:k°vÄ‹ô¸ pÄ ½”Χ÷ƒŠ +âxfNÚRÙ©/ PVáÚH &¸33t渳IÏd²ÀD&¬ö¿ìX»® [ú>í܆c½øÂå%nÎÅ L…øJ¯=°dÞ!ªæx:Î/hN~’ym=õ]ë: ¶4£¨Mwl²<”]¾}_³/w\e!c\fýz‚›uût¾¦RøA毸æ!ÕyשB'f…Uõt{ô…Î/ï©&iu +³y*ÇP§×Øaÿ¥ˆsœðYp›ç}®8Ÿ‹"ÀmšÐ÷ÌißPþ¤˜ÿåÚ_?â|Nª”‰…NEqT +w­ +yÒýüLq§æë²/ òŠO®þmK 'tÜÆÈ$y‚)Ÿ¨aÊ›¥ÇWc0'~AÊÁã‚+N~y)*ÕÜ}ÛU¡mãATzºW±¤„S^’’š9u¥ÓùÇÛ_ˆ4ÂÞ¾ìÝý3MP[Á„l( ‡ÀŸfÉj $¶Lä¾­ :RsD™ù" >9ÙÐSŒð5wY£ÜR°zW6è¯'[モoäK‘!òØÞ7 §øaàÞgÞ€¢Æw»%jV2®Á¶ñ½€žX<]µ§îî>òVÇ[ñ 2=Rð_p–D/}uÏOÌ'{X;þf2<áŶPždE" +Š©£®6¤ól¨‰ +ªË¥Õbºé‡¦«îê•KŸaÜ»=/ˆþY|#_wù?ôá˜-©$Vùæªçã™jBC#ð>®u¨l²¡©@WnºZ£;Ƨ ‡¯Á,ü«‡ +®ºq]Xªä7ºÃn×îy°m£rØð‰!­è¹¤O–:þàªp©$_ø@¸éÉÏB»¶«úŠê@MÂǥለÔsÒ›!ÔOo xBþÑ-à€ +Gsò5Cê˜Âö¼TKhX%!ÌMC˜’†Áë Š*IÄbUTíêÀe垨–Ñ[ž+Ú»ÀnMù•ï4îJtuøæÙž|ò +sÐ{á^@¸ñ5èÇkmTÿgCª´&QJ¾Ò¦R©‘*d»”"/ «<¸©ž–ÌEq™ƒH5ÁÂiOK¦Axà Zp®N0q³Ð^V»þÁ={¤ôØ f›šÅŠHÍïÞlFA·‡µo\M0ÛPG¯Æˆšb/5Ó'Õ—Äh09Uc½×?)e0¶rä\?#‚¦(v"DÝl„ *ïÉU×<÷Ð>°-›g‚|ÚÏÔÇž–,™ Š¶y³²–ä·&\ÕL)|8½’’ÌžÀ§²âï·0 J èÛ@œ:H[m¢¯Á™¥‹ïíÊŽ".ÀÞ`à ¾×ðO4 +v8ÉÉ4’S2 f†(“ð23U åÙ™OeÕa`žø9€2I!²lú×’ ðJ«v]­È"ï|÷©ìø·7Xž‚ÇëÎÙižC5ŸÉW~&r$ºð+&BW5e +‹Š÷Ù“€2RX}qÿHô’±æ‰±E6â€?c[5,Ј±ÇÁg€ä¯Ûàó)¢dóϤ.U{èêØ6õ-Š‹Çá§öP¯ <D¼aLKÖ1î¦FgSß±ð'ñwi1‘Rr2¥ÁER&ðõ<Õ–ÈÓJýÐ7¼¬[™“ÅÏèUsà´ +cþ†ôh¼K\Byïº!cg~$¥ÓÄLÿX þØüß? :þºÌäPŸûéö,˜|` +OœëSÎSm“Ôª|‚õÿÿ²½)endstream endobj -1236 0 obj << +1749 0 obj << /Type /Page -/Contents 1237 0 R -/Resources 1235 0 R +/Contents 1750 0 R +/Resources 1748 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1203 0 R +/Parent 1747 0 R +/Annots [ 1753 0 R ] +>> endobj +1753 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [375.4723 594.4187 432.5882 606.4783] +/Subtype /Link +/A << /S /GoTo /D (journal) >> >> endobj -1238 0 obj << -/D [1236 0 R /XYZ 56.6929 794.5015 null] +1751 0 obj << +/D [1749 0 R /XYZ 85.0394 794.5015 null] >> endobj -322 0 obj << -/D [1236 0 R /XYZ 56.6929 556.3324 null] +502 0 obj << +/D [1749 0 R /XYZ 85.0394 722.9644 null] >> endobj -1234 0 obj << -/D [1236 0 R /XYZ 56.6929 531.5504 null] +1752 0 obj << +/D [1749 0 R /XYZ 85.0394 700.3281 null] >> endobj -1239 0 obj << -/D [1236 0 R /XYZ 56.6929 214.5791 null] +506 0 obj << +/D [1749 0 R /XYZ 85.0394 132.4925 null] >> endobj -1240 0 obj << -/D [1236 0 R /XYZ 56.6929 202.6239 null] +1754 0 obj << +/D [1749 0 R /XYZ 85.0394 107.2061 null] >> endobj -1235 0 obj << -/Font << /F37 802 0 R /F41 939 0 R /F22 737 0 R /F21 714 0 R >> +1748 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R /F48 1228 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1243 0 obj << -/Length 2985 +1757 0 obj << +/Length 2635 /Filter /FlateDecode >> stream -xÚÍZÝsÛ¸÷_¡™>=W±ø"@æͱåÔ7;µÝ™¶w÷@‹°Í EêDÊ>ß_ßv!Q -e6M2“x&Xâc,»¿]ˆOüñIšÄLfjb2'Œ'“ùâˆM íݧ>ÓÐiÚïõööèoçÒL²8ÓBOnï{¼Ò˜¥)ŸÜ¿D§?ùp;»>žŠ„E:>ž&šEo/.Ï°&ÃâôêòüâÝ?¯OŽŠn/®.±úzv>»ž]žÎŽ§yÿþäúø·ÛŸŽf·›½ô÷Ë™tùýè—ßؤ€mÿtÄb™¥Éä>X̳LLG*‘q¢¤ 5ÕÑÍÑ?6 {­~èüã1‰œLe«$IO‹S0˜–HÎã,Iögri€“qg’蘹9Á{g•ŒS)“‰I²XK!ý¡üqoWÇ<¦eícDo ˆÆ$ÊÀD®ïšÚ¢H»U^·0²¥ÏGªoíê øyº¤FÏÞÎmùTÖñþ)(8£µ˜ôÿe‘*%hˆ†:|M+³Œ%c2V&ÖÆð]7ëî ¹µuñºx{ëþžÅ+EÌe"ÇÄ+a[‚g^buÓ•÷/£‚½ ò»¼º½8ÿ7ÒK0M×Ì›êááªÔ÷.<=S&Æ„'¤ÛVê¥2¯J[kå”Óܶ-¨Ê®¹Ç’Xô.ûïkÛví+òì-ôkÉŒš1ŸeOȃòԚŊ)5&OX[ʹö‚Z׋¼›?ÚbT¤ïA–ùƒ… œp·;§ÐŸD;S kÁ!u¾d,ÁtfJP¯çœx®ëü®²Ä¿Á²°]-Ê:TÃ¥~°kg#aÅDíÈ[`&é´} –Gª,º÷T•P^PJÔw]UCâá± ÂyÌëÚ¾b‰ûWòË®ù7µÄ˜+•YbÀ  ZâÚvÏÍêã¨Ý¸¤~hƒ—v•weS¿bmû‹ùŽ½—+¦²1c«ƒˆ‚‘±]p3F%vö†³œ£ÄpÌkâÚ®ã{–X»D¦é˜¸œí`|¶âš¶v¾^•Ý8b:Y‡'Q‡¥ ÿÇ\ë1Ô¯¹Ž¹aYÁæW%¸÷1)ß,íÜáW/·ç­uŸÝÇf]‘üï¨ÃÆYySÙì°Ô•‚ÝÏWÝz F_¥À gõ`εúèÂ_3àï´Š…æÁXÞ Ä¶Ìð )Áì{ÞÞɒDZ”"Ù]ª%À"Læ¸óÝtæ÷‰À>ÖuØihÂÄB‰´·À9°B81£‚_j–΂"ïÇÜðŠÖÖ ‹³T¦»À ÐùW[ Šà `äW¤[‹'À}†:<îe³êhâ. D<ñU_|ÀæECZjpwr`~ÇP—6àvw68|™i¼Å®ÅOåZ£ÔÚcLêÐtØyYZ‡»4.ö Ê…€Oöv Ü!úÜ&×εxðyfÛGX2–ùqȉUkñɯ,a?BD¥³JÚa£ÎáES¬À†Ä…›0ŽS¯ÐŒëƒæp~:Lµ_ŸNüœ7:š]Þ ­ Ñ°‚•ÕX®['}¥<‡qðî±<»ÂÒµÓ›Ù)~_}tq솫“ȶwvÏuà¸N)ûæF>ÚùÇMxwV¶î68—xá_×å:ÄxÇTÿ6²ýXÃDÍXä.*øñ˜ÿE‹Dê7ÇS.š»—7ƒÂ{~ŽíùbYÙxÞ,ËÅ%–'ð©ofC›ìOýæ Nj>oÒÚv‡&⤃®ï8¾Ð}S8¡T ÎÇò. -Ö`2“mÍëb‰f5îå.j9Z}ò;— óäÖËÁ‡„=EfB4ÜßQkÛ,,ÖÜçeµÆŽ‡aFs_ fg¯f?aF>1>vO!æ4^ªEÙ.]L=©#Þn)´AYÖp¨–GË|þÑzs-)ø•‚,!›Ä#Ћ¦XWèü÷oÛ†ánòêfÉ,·&ò¨Ãg¹Ò—ÉýÛ^'–Å`sÇйââ~輨açóñ“$G°Çoo.Þ}šÐüD°¯fˆûkþZ·D&qª“ϱ~aÄAÑJ#c°£–Šh3 y˜fŠÚ;n©~Î>•‘¾·îHã]K ù6Ë•E‹²7µC‚kŠÅTbèç¡v^4©îßšÄÁr¡Ý…ž7Ov€dÆ}~Æ•øTæ¨ ¸h5R€&ýötƒ%â–·Ö=6íÎSyõ¢ÂàüÉö6ÕÚmè°ÒôOãËNøÛ* Pš«±û(usÎɶÚÊ>øóœ6u5-Ÿmú;\.#?“| ´YôsóÐbËÖßüPù“EÊÇžrYV8‰9&$¥;ܽü×ÙÕû“ ÿò XÝŸ§F¦çHñvã“„Ðo£¾íOz†2?Áüð ¤mBÐ7.=£b¥X&½kw& pT1zéj»õRn^È - ! -Þ¹WT´wö_KE!žŸåýiÄAåBÄàÜFUTdâjŠ—ÁgL Âéã†ÍGŸL÷ôé , úu¤@íèŸëÝ`_»¸Še•—Ô×Å=ž(ÖvÐîxŸE]¹°€ýœ]……474` ¾ê¾óóC•cåë6ƒQ©w¬ªïÐ3e™í”öÎR¢ÎóS$(GA¸ÛÒ/s¯xã(Œá#¯žó—iœ¹[¯j⦣ó«ëéЖßÏ®Ýï„D5 -"ÇE :‹•~SP9Cщ¾i€jtïn0…ÍPgÿÙ´Þɱ4œ{ #Æ;ˆ´hꨒ¶ 2Lç\‚¢½q©3²«RR:Ç |ÊÃy^#™GÝQ“×f)A‹A”H"ä Û6’î[KÑ){&{©TÁLõ„˜¡Ûðµ5Ø_Tu¨%U‡ê êóá‹Šò1½”£Î¨› ¦mñ ayÃú‹ne²XTçÝz³|Cc³y4ÚŸß-z»Bg&À‹3£`f*|')ŠH×>Ù]ß"Éb=D`›VP¢l'©}§h§Ë¦-»òi'¹í[¯éJª .fWÕP>5U.ÐÏÆwybÌN25 ¹NxFo»`»f‰T‡KÌ;zluî…ʼnd{ï»íÚ=ݺ¬U0Êøò\h~5Ù}(Q—€ ]r Cx´î+2ÙOLàuyhQÙî2=h-ábtHúÄt"ãÉpW ïÊÔH»3ª%û¤eyÿ2hQmÔöÖ9ÚqB*§·­P²®ÄmAÛvÊâ®0–C¯r18;Lêœ -™òm4uOyU@Â7=¬»ná9…2£Ä„ÜP÷à m£Ùý ‘~ìõp4¾õq¯ã}Ìòe8h ­¶?žû5žc˜Ùû5Þÿ7*,„ë _¦‰†nøŒ~Å÷ɯù„à±ÉÂQu¿=Ȇ~óÇ&£ †ÿõ†ÛŸ_*Ë4íÁ;ƒé8™q8V¹çw§ Òìc"Ó8IŶ[oñÿ„¿$”endstream +xÚ­YÝsÛ6÷_¡{:y&bðE˜<¹©“sçêܹ¾§¶´IœP¤"Òqtûßo P D)í$“q,‹ðÛ/ˆOüã“4K2#Ì$7*IO'óÍ›¬`ìý÷<³À4‹¹~x¼zýN擘Ld“Çe$K'Lk>y\ü:Í‘\ƒ6}ûáþÝÝûÿ<Ü\çjúx÷áþz&R6}w÷Ï[j½¸ùù盇ë×)Ÿ¾ýÇÍ¿oh(ó2~¸»ÿ‘(†>g„>ܾ»}¸½{{ýûãOW·ý^âýr&q#Ÿ®~ýM°íŸ®X"N'/Ða 7FL6W*•Iª¤ ”êê—«÷£Q7uôü8K„ÌÄÈ + æIjL:ÉS“dRHw€»ivûë™LÍ´¼æÓšš}`ìšë©Åžž¶Ív]¶]9/:»ð E]Û µ'.Û©n:"‘˜jOäƯҭ½ä­Ý•Í¢œy^Ù¢.ëU»*“à©ÃÖgœ'&M…ÛÇ/[;/—{7 ¯¨M©Õl»$ª%Ë~cH^ž·nèk—8º´óÎË8̧FkwŸqß‹¿û¹Ov]|.A.Ð’`ð$ç<›äuq,“é‰SZú,²rxp©È<^Hf3†’³àßY·¡â6BÇÏpq¾>n§l·QÀ0nƒl·]’ëÁÖù´˜½¦ÉñÁ‘ýäµ ƒ=Ác(ER ç£ÍŸ*”ÐÞ îÓã…Ä5ÉX–ž—EóÈòÍ0c(j´›)¨””ƒÀÛß +\nžˆ\ °®<Ñ©!F H3År 4J¡<>@¾Ç§ð¿˜ž:K Tq•Ë$n/“O8$eà”OÔv;=œ€#¼¾ÛˆÉ ìgoÉËE‚ÝŽ²Q •¡’¥Y’g>©¿o\ú¦§ûk¥‘ï”›me7¶v¥ #ÔôõE4´Ìɽ«Ì$Dô$>Ùo»,HbÁA­=;”Èߥáý3­äeG¨D + •ö:‡Ül°„ýˆƒÜ +•Å•›~㪜áJUh +¬;êUKä'ëb’í§ç¢ƒT)÷¹1[âì+0 Î×MÓZ/¢ Oí\%Ž8¹³t¤a´ÞiIqvÍ>!tŠ.‰âäd$½ÅäÂði‰µëËpA‚ôO0â¢Q +Ï\:Ær}OCó +7Ö…qÏßµ¶Zb]¥úLò8Ð3@Mæ-²;=J%Lù|‡y¿¤wÅGëµ+ê‘uœ +sxš_,(Yš)ˆ^"×QZ»³m;â*™æb"ó,Ñê’Åð-sÝNà,–xŠn ;Ï«ºðUtóõIXçJl©¿Ÿ‚½Ä¯hÈ9dí’™§‰¯Rðpî©Jæ”`y0v­§ua ¿™{ ƒn‹/L®æ‡Î!Ó‚<…Oo 87XšUBT4—ìlƒ¢ýREÛ–«ÚzeüBwXÓ;× 6'3®‡P¹oêYmWþ!Nð å‚“^¡—FrAý ’ˆOE¦¹D\¸¤¿ÜiÛ´%U8à¨dŸ‚2U4fé*’>Ï,°p2ÊÝ‘Àãše;æ(œõJíg€xPy× ’ü˜îµÈXÄ¿nv®²H‰¶.ýŒÄį{±¶&–Ò¯âQ-ã]£{G€‹N§7D?½4ý΀î3K‰eÒX‰Ý·è—‰r8¤Æwe"ï;˜1T Üælžãp'Æï—26ì;]ñàTÄb±ðïWžÛo†<èAXF@«_×%žCœ|.ŸwÇ|ñR‡RhÉÆ¡òO°èãâ)`ëœÀX˜á³ÚwáíÈ~)0wyE^Bña4Ga ž†Y¡ü·iH‘ >í¶ÎÙkýfìLþÆ!¯…z3ù?H0ð¼æÙêH”äZÿ£9³Ñið4™ˆÕE;Â-õ}P¦W8WlñðÎèë_ÄtÓ8‹Ã'€e*jäÀŠ¿k`¸(N‚%^,Ö 0º)Ú4E¤i‚À•È¨ñ8 (‰Ur*Q)•Âf»5 “Êа_æ6<þ':$E½CàP$Q9E%5‡jcPÓ©Š{\Ýcæ”^öáÌÃSÆÈž*[À7¾ê‚äæð Gt›}Å׿~Qi êíîÔü8izÚîS5Záñ¼‰ú°ÿv€È±¼¸‹ÿÜ/^ß!½V 9Áÿj!‡3Ž2‰Ã/‹PÎ0v®ŽË@÷œgPþ@ºoøw)ä@&Ëáæ 2in¾[!äÎ"Á§…þšo¸yÎ{ü¸-erðª˜HGáì(Ö’Æþ75ÿ³~ëæ»T†ÑU}Ûå#ÌR“™¿R~šŽ!ÿéŒM‚kÿæ_}ÀUyÅê™708I(¢AˆLEל«ÓÇ?ÿûp`‹”ÿ?V•ÎÕendstream endobj -1242 0 obj << +1756 0 obj << /Type /Page -/Contents 1243 0 R -/Resources 1241 0 R +/Contents 1757 0 R +/Resources 1755 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1245 0 R +/Parent 1747 0 R >> endobj -1244 0 obj << -/D [1242 0 R /XYZ 85.0394 794.5015 null] +1758 0 obj << +/D [1756 0 R /XYZ 56.6929 794.5015 null] >> endobj -1241 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R >> +510 0 obj << +/D [1756 0 R /XYZ 56.6929 439.8265 null] +>> endobj +1759 0 obj << +/D [1756 0 R /XYZ 56.6929 416.0359 null] +>> endobj +1755 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F62 1352 0 R /F41 1208 0 R /F63 1355 0 R >> +/XObject << /Im2 1341 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1248 0 obj << -/Length 3540 +1762 0 obj << +/Length 3018 /Filter /FlateDecode >> stream -xÚÍ[msÛ6þî_¡™ûpòŒ…øæ~r§çNãô·s3i¦CK°Í E*$Õ½¹ÿ~»X€%ÊRr¹»$âeñ²Ï>Ø`1áð_LˆEiNâT±‹p2_žðÉ=”ýp"l™«4ók}sò쥌')K£ šÜÜy²Æ“DLnï¦ Ø)HàÓ篯_^ýðË›‹ÓXMo®^_ŸÎ‚O_^ýtI©Þ\¼zuñæt&’PLŸÿíâç›Ë7TYß_]¿ œ”~ö}sùòòÍåõóËÓ÷7?ž\Þtsñç+¸Ä‰|ÉT7뢥¼䯪²¡ª!ô›Ï¨4/9Ο -2ÛFŸŠimš€_ÉÓé+Ý4Ù½“RÝQåö!·9ýBb~F=SQû éÍeGÓª,ŒÂQÅ4S²»¢º¿ÇeF`lòöaDßaÈB!«C£‚EKÁ‚’T«ÐŸtÑ0Zâ$bq"è8f© S㢥N[Tl’ÔšÒfòð+ìgM¿ù=N–ìŒ2tfVR¾¼‰ {3•æÕB{y L†Ó__¢ä‹«Ÿ(7·cñ+³ywUQT€ Y%†ÖD3Ž ýE˜2w%X¢¤°õÀ ãPNªî Ë*ˆ˜JD<´¢eo¯˜¬½:@;,6µÊê6Ÿ¯‹¬FÖ3 ÖÅÊ"®£¯jçÙº9 -±wÎN Ñàïº}¨ê¼ÍÚü“•Ðèú“¶¬ã ²m ‘´Gª3PÈë ²Í@ / Ó1d 4ŠQ½ÒXm^Ãÿa»ÈKï†V•C™¦ùºnhÔ]VSk¬nÇÐ>dí àG=)DßïcèHÆÂÛJ!—VÝÛ --ªêƒMåôçÓ­ûn‘ÉÐJÁ˜Á¦[GÎxkœ>¨ìv.~€ .(%Ðç"‘ŽsÚ| ŒpEµnŸ5ëù&KMß-ªe–—çžô³ZßdÅyɦHŸÇgëÇð{žœ¡psžÙRŸó³¦S׸ÍÐ`u.βÅ-eÝÁ‰´ÉOYA©÷O±SÜy)³€GÆüëÀcc]”}ëo…<²€†*óª0€ƒ¼üÆgVDFÛ ì²)Lšîõ[Rï +ß`ªžÐ_ñu5¦ª£E*z5Rv½”Ø~'+™™b®L™”ëû/XHÆT¡]ÃÊY»æ‚Õ uc1Rw½¦¶í;†¼1e€:b‡ŽÆ|*ÇoCåc<&àG§ŽÆ{S÷=ã8L:&7.DÂdFÛ;ö+¥µS³uR9ACˆtŒ(•·cav·Èø1p¡ªÑ‰×8|¸Æ–kKZÈqýöíåsʓȆ#“¨Ü˜J‚åÙ¶%0G±ÉMZL;“Ƃ̓.)UVTÜwc›‚ì媥'o™-4†Z]•ÔŽ6;,´€Ú—Ý&ˆ5¬sƒU†,m$[1hˆ³Ù`<ç‡Óù·Ù­‰ çVÛM?2¤f\«؇²h×kl¹ãüXT›’RÆ—ßuIåàZBfFðYèlA¾ TAK1’ì'ñ}äVœä®kc¤lLS¦aÉ|˜Æm"ÃÙbNYY7Úª 7­Á^îSd‚ 3ƒ”Ev¢¦ºœE-(ßD3ðÛ|\÷q|ßÖÙüƒn­š7èS4àÉ4N€¿™'¸Õ…3“DZžL¤sìXÈ"‘Ž^gc+Õq®ŠÝ¬A$}¸: Œ$f1”ºðÅlacñ ÒBà"U´e],¨7Yåö…ÞŒ^‘ùBîŸUi³íæaRzš¢¢Tzñ怇lQ|ç5î%o\\gi üPJ9\›ÎQôœò‚,G9ø8ÛötÐÍ'¸³Îõ41f'Ö©ºOÍz¹ÌêüO+åå–Ÿe1­‹í;ƒQg‘J¢ca¬ ,G Oa¾°™‰‡À½c v„Ù¤k1Õ’)ž@JªîŒg€ÚH2ÁÜEÀìå<­ì‚[Á‚”K ÞNåzyë4å´hŒ¨f,(î¡ÚåÌ5x> W™µ¾0D7.`ݳ—%-Üs,Ì®¶áÝV.(±›Çvå~í»ƒlܱ·jÚÞw0G×ÊFC‹a7bŠ~×ô„À£¸PD_Kÿ™â ÆÂ0ñBǯ&™FÀr‰Ü&äŠ8É@Jë„îú˜ßTFG¡iþ8/t£¬=¨¶Î’¨pYµƒx´qûY/j—Óƒ$aÕ1¤Fîè -Ét ‚ý©‘™ÉÁáCXãÈŽ˜9ìmˆC¾ªš&ï6h+šul—·gŽ}W~~UŽwo²èØÇWÛCÿPÏÅèÈø9^t¿ÃàcuÊ’´?àûœÅÜk7> ¿²Ý|MÆS¡8‘âi»‘7¥äKÙàvôäH1اÒc §?Q>¸ö(‹à -f,¢ã”(ŽT¢·:ß²ã€%AœPb1ÐPHŽ’õÓG(ÅúÝB>©D+Åy=y9×_´£ºó¥Ìm^¾å?¥oâßòæq–ÄàÆŒê'T0‘XO˜ÒÍžYX óåGé¦ØbÂææEó‡ÍME,áB~ñt±ËÒÎÇŽÃÑý­Þž—Î{?üöqxÜ›—&ˆÜw!Ò»ÝvP‘Ž!üµ¬ªëÕЗÇ+Öô¯®ýbaÛº9dàÓgî·Å‹ßãÖùoÚwÛö(kàÚÍMÀô”5x0û–ÙJ%,q´‡­RÆU“ rEašŽÀ+ -X5±–ÀXͶº?ǃÓå¼Z—­ÕßV„7pt{ÜÓö$!JO¾Øž^;o Üù¥ó¤æóqóßv>‡•·Ž¶Bˆã8¾ÚåÕóW??!|+l·÷ OaÞÓ·Œy¡ -ÕZq<Û5ªµ×£Íã">*JW ‹…Œ`ürɪöW¼…ÞºqÚUÛÐ7àW8î·àŽŠ|™ï?{®ðpœA æ"·nÈ Œ¾X¸“¸îEN¶Zé.¦ÛzÁ‹"DÈ’( ý»è=@öòÕ€Ü?:ýÿ\ `1^PÌ‚ˆ AN…{ÿºó6\«D˜R,LúPixLm*À^…õ¯–ÜE]ö¯–"ïÕ’}S y’~èÕR¸õj)潜†63¨ë=ö‚¯Ì -lªÆV ·H¡kùcTä„EþëMÌw/ #÷ gÜÓ‘«Ð.\07ì!9¯&µý^m]FÓkCø¶jK©RßÛGaøµå!cV³ÆƒfL™—z(æ/^¿º¸º¶¹Ý%:J«Z_Ð=ÒK^O‚7ò‘y¹ÃÑ»ìÏÕ°úk8ø¯iXuVã†ì_Jz{F•mÂÞ¯Iór¸±)óˆRuŤÄQêÍß´îô«úáKåže«„Ô„ØØŽ]o¢{µ1p÷„oýÅÜÅÕîtl‘ßaót»;Ær»ˆ÷Â8¿k1¼|ǘuï¡;­˜÷gR±$QýŸ.aßÝ›Úm™oÛ¬ÕË.Êû¡ÎðVü˜W÷»î·录1F _éCĪÂ.–¡q„¬1ëÅ6Ãû‹´»óÅàpÅN<ºú 6¯Ê»ñS*¹ÿ´¢Ðc!gA"˜Häði–]Q|€øO&Š²åRï¨F‘7­.gUéÐÛÇÕïÆ©¥WŒ«ªn»|üxO_ßÙò/hã„Íþ×wîsĦmŸr½éS¿ã -ѪÑY힇ÚÙ‘Ïñ;E[»ÙW|ä˜Ë[.ªÖꂼ}¿ÍØÛ p{ð^FþÚ…Oz×Çþm÷¦ÑœãþBçVØAá¼d²3r÷G8»Cÿ7?â[4endstream +xÚÅ]oÜ6òÝ¿bßN² +?% +yJS;qÑ:­ãÃ=´}we[ˆVr$m£è¿©¥´ZÛwñá`’Ãáp8œ/-_0øã £c&3µH3kÆõbµ9b‹˜{ÄÎÒ#-C¬.^ŸÊt‘ÅY"’Ååu@ËÄ̾¸\ÿ½ûðö×Ë“‹ã¥Ð,Jâã¥NXôÃÙù4’QóîãùéÙû^¼=NUtyöñœ†/NNO.NÎß/¹ÑÖ GáÀ‚Ó³ŸOzñö—_Þ^ÿyùÓÑÉåp–ð¼œI<È—£ßÿd‹5û§#ËÌèÅ=tX̳L,6GJËX+)ýHuôéè·`0k—ÎÉOKk#Ò +>'@ʼnÒ +ÏÌ“˜Kc,º¼-è„]ÓöUÙõÔûÔç}±)êO tE@—-–ÂÄ™I´¥H¤ŠÚcn¢¢»kêΎȨoh&§î矨ÿe[´nòš\Á2ÚF›kÜl«¾¼«Æ4[ ¬F£«Æ¶ëŽþÁ4»¸è á„uÝ´›²¾¡Ùü?¡À#sgZ {ä®@>3å·)zÜtI)éä“u¾qPW´_‹–àû²ªÜ<°”WÕõhÛ~ÛÖÔŽ€¾_Ùß–ãYÙÝ ôsyM ËcÕë¢/ðäp4êÎìŒFÏ ÏsµEz,® p3RƒP½àÀFkÐT»²meÓ:•Ñ,œ{ÜnP.Køž<+¡dÌx²HY§R[ý¦¹öfAÀEð <ú2ħ÷2±GyùT¬ú²©‰ÿ8Ô”!ÉU,”s´÷0¬'Ù§æd*$²Ä©0´ªÊAL^[+R%œmÖ¯»m¶Õ:ÄËÛ6¯o‚ ´ê^ûRˆ, ÌÏH¯sÔ´”GùÝ¥Òܵ%\Õ+M€JÞÓ|ÙÙ¡4Úvô¦pMýà€õÚ±ÚŽž•/´ÄU³Ê+ëÂuH´uq]P[¯ÜkLPig¶ÙI°Þšû%à«9¯ÜO™(·ï€P° ­ì`›ª 8/ÝTÓºå´Ìá7­3½}Ïv¨þƒ1qCÆ¥X#{,‹þu[8Ò9Q®†ü^¬Ë Ð{>Ç›ãM8.œ±Xt “FWµwE‹&±XS× +ß$Ž–I'»€N^åGn­™ÎðŽzÁ­ IèdÊÎ/µò1^M¿lK‡ë( R# „»X{:k‘U«’à¹è~ û ÷.ŽØ¦ÁâÄ$jðbû6ŽƒçL”òvË»È}'ÁCL±oà$øX´ªÖ˜b窨š{ç—2¸¼ü3žgòzŽpö&ËGe rÝ·O6¤&]$€.„QωDøpcæãå@q’Ü2$ØK¤z·3²¹ÉûÕí“JÅFrñ‚LzŠO1©ÒØÆÇL¸JžÆ2‘Ü ¼^Óí”58Rg›zwceO—§¦‘MãÍöº»bU¢>¯¬Ÿ'Ëkà,Jš±ƒmÅG•ðε@e©cªo¹y˜á}œ‰ì{Z ½nì;K„UÉ=¯+³˜)J$À¦R>åv=þ2\0ãw÷èŽoÂÇ+ö›Å†›K3~—žàcVàuA“¢“t–î ¹# ‚›­HbQ–^…“×Ï2\f³í<ý¾+ªkRÅ€Sz¬2hÉe*l¸'ÁßîªrUö3ì$*V€ú¸ áFÅ™±$žH ×÷>Ïâ2$¹ÿ<¹IãL€X´ƒ6D –½“Å'˜à xŠZ2yȆ@ÊŠÆ“Ž;ÝUStYEà@ßPTV¹Ðc‚5¥Ñz´¨’ŸÑìþ¶\9Ò6‘BàÊ­$½ÑÙ¯¤E\ ÂÕ$âÛùjðŸ"»Lg¸Ì¶Îä!ß&(oßýLe:ÙsA›cc ¸ëzˆö5R€ïÕù>îÖ‡–ƒÌ™£,²ðŽâ2$9ç1ØQ¦w;vk)ÈÕ(ù‚LzŠO1™j4d|Ìä!•­MAÍÙ`öÜ]S[X뇵~8ëgAL&­Bƒ9lW·Åê3]/0ÍTœ0TÆúu“—µ/*ô»ZCrc¨¶ÓB°ù¸ÂW ÜÖ}é"»œº –ŽÀu³­×“@ þG›P€qBv¤cvÁÊ(\áØAäÛÜ!]6ÈòS¬ñµ$– '_5xËB1BÂà綷A3.Eû1;»€ +ó‹òU¿Å¬Ar̪ÊMÙ—_ êî, g.±ÃaÇ9u:#ùp>‘礀¸í†µ µàÄÀÏûm®¯çNE—/²iaId” B»i¾NF†EWÅMY×”ERóÑ|HÔæf2:›â„>_Þc›Sãªe!ñ{Ç…·æ¯¨¤ÔSÒçHÏ$¥]7nEg«1N²&ê]Vß“€S/LHúÈö”{ÜùĘ8UL>aqY ÐÚ…–Ë;/`Ì<ÅeHr.‘£'àê´G +“½ ŽàS,Bp­ÒÔŒY<œFh%Œ7†‹öŽæ|!‹òY±½†,`Ûc ›ûðÕê†50°2Ï„C>§f †œÎvBè™w]ySÛd?! ÍN™S-ëõ.ü¥‘‘ Gj5µƒO_1LQ\4BÚ”u¹Ùnæö,a|ó~÷æ°ÝÐldæœÊØÌÎðÖŒq €ë¦‚ìÝR”&…;ßÜUXSBR ±Ð;”6«ê«¢´\["T[ÛPoXeL¸Ù¤†Äöpnë”r ƒ…©ÆŒÐMÑÏÙ›ðäÕ…we7WzÁJò¤”‡åã¡Èüன*Ò¶TU¹Y0k58{aXò.ÀD¶Ÿm]2®óâ[Ox{D ø Â!ìÊmØY/ç.~Ì,3‘¯ëºú§‰x†y¦‰ùk¡hÊq„†š'N¯1¿î©Êj|Ùp‹Ò•™Ù•T=IáHº +a0#‡·u¬öÏœ¢F×)çë 8ÞÝ6÷5W@¢)£Î¡PV!y(o­eôÛ ˜€?QLÀz95NÃ$Uq-u«|@a$͹R«?®Ô©×I€‚ƒÙ¾+è"8UyMwˆS.HÑ阬 4´÷‡zz–¨õ¬zz!”ŸxùÌ\ÄNZ:›JKžñ.áqÒ¸º¦ÇX6ì®Üî>YšAÑSiÚ‹Ðøˆp—ž9afN˜3§™¾e4ˆõ`Ë–Àu9ªccÑ4xÁX^ %öúTñɇÁÀzî¾(&ŒEY¦„Œ3üP:bíõkB9;¥ÖÊWõFÐ +vFÇüÚË'ç]—­ßóºtžtD90äØ­±¤7#´¿>ƒ7‡¢"¹UyßÍ›G¶ UùÍxHî†þÞo©jdkžéã¢ö‚YU9:nßwâSùn;'Ø¿rDZ7 &}9wc“Ãí„ð˜Xa«ÿ½àø)8qXpb*8þ¸à9Üs' î‘Kù?iœ<,8ù”àÄ3' Ž?[=C?)áw .V“³ê©œîZòdéò~°m<à ÿjŸ=âF¼þ³jH“3¿ J2ô¹;IB«Œ]^SÇýn [Å@È%Å]SçW視Ϳ–6³Ðû=ü—TÉY#äòê¤oÉÔ%ÂÈÎ%Î…o»K +ÙÚWâ +SiÔ•›²Ê[´E í™Ó#æ¡G K0=©“%ÖÅ]›nÁˆÿ-T©8‹¿9..‚X—QÎp0¤,Hkˆl%WLz9"èCÄ!B‘å_mxƒ”áHWj”ÙŽÆX´8DØ ã×4 ³t K±¡v—yA' g‰‹™gàM`äp÷F¸/ÜôC!h&*aT»À:NS+ Î,¹I C´“ðYŒPA' ŠÉß¡‘r_W2-}¨çx +¿_?ü*¨V:÷Ó6©c5ÿÝ þÝÎßý³·ÝoñÙ1âÀ<–€¡ÌRÏž8ÕS·ßÇí³þoòÒ!endstream endobj -1247 0 obj << +1761 0 obj << /Type /Page -/Contents 1248 0 R -/Resources 1246 0 R +/Contents 1762 0 R +/Resources 1760 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1245 0 R ->> endobj -1249 0 obj << -/D [1247 0 R /XYZ 56.6929 794.5015 null] ->> endobj -326 0 obj << -/D [1247 0 R /XYZ 56.6929 769.5949 null] +/Parent 1747 0 R +/Annots [ 1765 0 R 1766 0 R ] >> endobj -1250 0 obj << -/D [1247 0 R /XYZ 56.6929 749.9737 null] +1765 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [242.0197 702.9298 315.2448 714.9895] +/Subtype /Link +/A << /S /GoTo /D (rrset_ordering) >> >> endobj -1251 0 obj << -/D [1247 0 R /XYZ 56.6929 433.0023 null] +1766 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [238.0484 622.4676 311.8142 634.5272] +/Subtype /Link +/A << /S /GoTo /D (topology) >> >> endobj -1252 0 obj << -/D [1247 0 R /XYZ 56.6929 421.0471 null] +1763 0 obj << +/D [1761 0 R /XYZ 85.0394 794.5015 null] >> endobj -330 0 obj << -/D [1247 0 R /XYZ 56.6929 173.1316 null] +514 0 obj << +/D [1761 0 R /XYZ 85.0394 769.5949 null] >> endobj -1253 0 obj << -/D [1247 0 R /XYZ 56.6929 148.792 null] +1764 0 obj << +/D [1761 0 R /XYZ 85.0394 751.153 null] >> endobj -1246 0 obj << -/Font << /F37 802 0 R /F21 714 0 R /F22 737 0 R /F41 939 0 R >> +1760 0 obj << +/Font << /F37 1018 0 R /F21 930 0 R /F22 953 0 R /F41 1208 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1256 0 obj << -/Length 1976 +1769 0 obj << +/Length 2587 /Filter /FlateDecode >> stream -xÚ¥YKsã6¾ëWèHW­0Àçæ4™±'N%ή휗‹&! >’²ãd÷¿o7 D‰öj<5UÃf³Ñϯ€Ìç>üãó$d¾Lƒyœ,ôy8Ï«™?_Á·/3neNh±/õýíìÃ…Œç)K#Ío—{ºæ' ŸßwÞ§>þëöüúl!Bß‹ØÙ"Œ|ïûË«ÏÄIéñé—«‹Ë/¿^<‹ïöò—+b_Ÿ_œ_Ÿ_}:?[ð$ä°^X ¯,¸¸ü霨/×þùãõÙýí³óÛ!–ýx¹/1?fw÷þ¼€°œùL¦I8†Ÿñ4ój„’…”ŽSÎnfÿî}5K§òÊ„…‰ˆ'ð©†)‹¤&ÿýcøp!øœs–†¡@Q¾b–D24B˜. K¾ï{ås«:ÊÂMŸõªRuO¯ŸÕo¾/jÝë¦&NVDüÚe+e-‰=ŸÀ™Hyl Ý®ÕàÎNˆ§,‰ŒeÈþ±*°H¥°RÝÎ5)¸—75ú¶Ú¶g<ñÐäö`ÎuVÊ÷:Õ>©Ö~n處£r«/³2z”zµîŸþO k¦)­²A1à 1&¤÷›ú7JB(>K°LQ± Ž9“>¶«9×ûÕwò‹ý¦ú£ôëÅ4ݨ|@½eÈ’ùb|¤:ò4ð D‡~r±ÄÅ<Št‚§“ؤûbÇÞkC䈀RŽÈ œ’CUöBÄ£aH¯Ú–½Þ”“ðñ"üøDâ§#;;ézE&GEG™qÑ‘CEïHþY÷kbz‰¢K€Ô”€G1“2ŠÇUØ¡f£Ú^«ŽQhž0sñFÛ@Á}H¤Zw½ªPÐãÈÉb9Ñ72ôºÊ5nZFFðÀGuÄh–ÄÉŠÂÆß‘lhn&Êmš¶ï¨žø­_gVA¿ÖV^×`½ÎÕbgq¿Åà;Y³è „ 'nè>ν"S‚énÝlË‚è,ÏÕrß*üc«:,:~mjèÕJw¹$FÝЃ!J[Ñ]¢Š`ÃG{2©àdÁ o;Uh¶Y@M{ ®â&6êÛ¦Ò}oLát{Žœg]–Daƒ˜Ql"Uv»ÍEÌ&Œ[Mä´Ù:?Àš|{Did1ô¤ÕóTƒèt 4‘HïQ×EG$¥© ð ÏŒˆ3îí0¼q"ÇÞ(nF -Œ›ÖŽ³lM}¾º!7†ÎMÈ€!Æ…Ød¹ÂÜÉÄÃMB@#´…¹"ÂúµiêN‘¼/éåÑŠÁéúö,ñ¶9UÊ4…Ój…:³W!Ueumâľ숗ѣnÚ*³Ú)`@Ú·´Ï×f’ ׂ#”‰]!Sav,Ÿ[¬Vƒ1V¥çØ;tJéÛ]>j™Á˜&Ê>Rnv…é”Î æÛ`rÿû†¨ƒ}ÍrðÚšÏj’Q- Òv°:qßêÕÊš*¾bÖþyÆÛ*kóõD HÎDLÌZ$&(|B#맬ø¶Ajò8atFÑîÜó>Óv[Ãh·-|P}þ¡5Å¥Ë iÈ¢€»ý #ýÔ»ìÉw»‰=éBÙ(3zÐF‚T³¤6“(ŠÅÁ0/š*ƒq`§ÛZCŒ4Ö,ÌËf£êÂÍ8“·a:–Y¯Ÿ¬œéj"µ„Ø_·½BÉwi¯‹¦Ÿ‘õ€/Âp\pà“ãáOã ú&˯Ô; ½ïª8kMÅCœ[…ÎÁhgc2ã ø•†¹WÛ‘*ñ*ùçN]m+PD^½­ÍÄtž‰×p°vÈÉèu\gEÐÐW{ÄÜ|Fj8 «;š"ðͭˬõ'þe†'q˦ù}»!ö£Z6;66&~tÀÝd½¥T隯š½rIƒ3{ê'Áî’&í%­Êà¸×N_Ó¾´YU™c ÆÆD”ƒ’È÷mþº£C’zó€/÷ôö7=ðØG”Uð@MŽœÿ ëÌyñm}w¿«¢€¸”s¢¾³BŒ1ûíô»lpBšN¼Íò×o³NûÄ0†ƒ~†{gsWý²lž‰D0ySUΓNY'Í™(<Ä >wôSY§Ë¢q“µ_-g¸9‘æ~ûxmWfnpþÕÔvFfyáB²˜”»d‡6ÙÍSy&ßþ…@»Éí¢][çVVÇ(1¯ÌPïA¸8Ï& -…×ROMÑÝÞ1Ø5S,™w;¦¡}Š×i$˜ˆ"ç ®TÿœP 7aŸ…iäCb© qøÉRüj4‚îHo¤Ó{/pî„ã í©û©£‘]½nº~7 ÜÛéëéJ¼ÐÅþëƒ.ÞÔ0ò¿Ð­Êû¦µ³éúp‚q˜#‹oXnŠ¸øïí§¬yÝ£íU×e½È[UŠ4žÐˆ<×›¬<Á£Çml&†>1Z½Þ¬»jâ[ŸRƒ<Ë×j±Ô¥úú,ÛjóÎ¥•ª°a^êÜâýEuMûP7'x=ZþN6ºxçJ€Ýš­^¾~äý7»ŽÓ{qRþ¦~Ó†¹Ž?DOüÊçÁ7ÿÞ½ûcìÙ2IÄôÏ…ÒÇëà¾e ezôSªûaüØõÿ)ekendstream +xÚÅksÛ¸ñ»'Ÿ¨Î Á›Àå“/g§¾é9­£N§“ËF¢cN)R'Rq|7ýï]¼(ð!;©¯ÓÉ$„€Åbw±o„$þDH$5ÕI¦9˜ˆd½=ÃÉ'X{sF<Ì2-c¨Vg//Y–h¤%•Éê6Â¥VŠ$«ÍûT"Š€§¯ß^_^½ùûÍù"ãéêêíõbIN/¯þráFonÎþùüf±$JôõŸÏÿºº¸qKÒãøáêúG7£ÝçÒ›‹Ë‹›‹ë׋«ŸÎ.V=/1¿3Ãȯgï?àdlÿt†ÓJ$÷ð#¢5M¶g\0$8ca¦:{wö·a´j·ÎÊ`D™¤3ädN€B#É(³l›}W•m·XJŒÓß C‰(Œ'KB‚ZÀßDÕ¬óê®i»WÑïºèZÿû߯, +|zóx9:Ð]­[|yIc/gŒõ×O$"n››¶èܽÝoŠ}YòHè åHsÂ-’Ü5ì‘"ݪ®ÜU…ù%Óý‚¨´X7ö»iHîfcˆî°¯‹[.k·’{ŒyÝÞ{¿Ö¹µmþà&>z4‡¶¸=Tn®kÜwÝÔ¿`L?âóº»Â­zšf™6·~óÝ Òg®dWåkK5g@µ=–s¦†v×ÔmÖÁ°JW°6½Â¢B*ÀoÐî÷pËÆFò#‘ +:ض˻b[Ô;rWì·e×:BŽüç]ÙÔÂò ßžÊ^æ¢í¾ Èœ(À¤¨Î†g/T'wŸHà×Oŵ֠ë×Gà!׆<8ó›f›—õĪ1A’0ñÇ1Þc|‚q†9’R— ã/æ8/¡2=äü:g¸§ˆ+Ã|a\=²;›+ˆ=Lè´nÌWy[±S傤~hì¹4VZl¾ƒåúٰ)ns:~K;ëºXc.èüúŸó®AjØ@#Nyâ4h4´+ú³ìâIÚtL›:A[Ƨ}D{Œ6ù8mV9£ƒ@Þ-™"r˜Ã É ±Ö;BO®ù¼ã/”ò9±EtÝõ§²9pÆ‚ Y4!8o;P“ö_0&>ïÅ0ˆvh«ŠOy冟óêPôNz?CœR€A°§uâ_¦ûÜÊç©ßOœÖˆÀ?‰`%Š¯±]ÆÊ éZï·+b’pë™ñn\~vŒýf`j)pv r™¯D n”ÑBÊ\|5úóæT¢P–XUs½”G¥'ãR–m6ɃJHœ´»ù‡ ¢a‡M#,8ý­©‹a>Oz6ª qÉN,™çIÛÜ+D)u´Å¯Gvœ¼@®"`0Þ× Y„IWqä5„©o¼>K½Ïäûë¸/Úf`ÜA£(’ñô´Ð#nž' £Ìy• þ”aÇi™ÃQ̺‚TK(W3¯ÖU¹þŸ ÝW`þ”#ps¨7K7ú`§W1.u¯|MèÛ;¦àµ&LÇU¶/‡ïËînTE—eQç«bé}ÆÒV»>˜rtjUšæÝœ•®›í®´%%›6YÁ¶0¡‹ÙÒ»öóöT +a¹.»Ò† +†Çµ.,ÛZ7†í˜»/«ÊMnón}7'–>VâtýO‡÷уþÖÃ>åob¥zž¢uÿØûD,"5b$ŸP:#%é 7)ji¦Àló"PÀsÁæ‹ÚЕc¦e¨¸ói—ÍÞI¹ø’ow• ã£vž¹MHp%V“ÆKÔË ùéàæ}bj ®®Ý×8vtî>.3£¦Ý‡<%4ø…›Îr®ñÕœÆGPÎœ}Ïo–°¾ç7j×A1¦ˆpñÚk¶”é:?´Eè·=Ä/×’±-»ÌæU®}fy4£ó“>Ù·ð¼ÌÐÉ`êîrßûË?{TÇœrp;TSPò¶±gØ„P!MKrcÖ<¹û´‡[C­õ@ÆsdÄô }’¬6áf Ó¼ºÏ¼ûýø¤ç}$ÈÙþÖyå3×|Â~®5ömž>vñ'<¹UòìèÉãÖÜ4_æÕŽì“íHÉ´·Ö»]‘[ZŽÅÅà suãË ¸WˆJC¸Álä=A£º‘Ë…Cª²hÑ©—È¡2ÙW=%(²µà'nÅ@Řþ—vŒ\rÿd”A>lØõÊÙ€5 U¸p%\îpÝ„•w%Œå þ‚¤+ø—¦“7À‰3Prp–ˆ +08:ù5!àcµf([^2°/¯¶4ù±Ž’ˆ©€xc¶LÉ*ÓqÊŠ@ù‡ˆ+PgNLÞ¤f´/ª"7îÉü0‘Ú|]bFtŠs}lËAƒ‡c„©Ô½/`‹ÓäÅÇîÅ€0Á!)îK먹nÎÛ4…'̪«´‡ÝθFS]¸›åDz€ ¢Ø×flpĬk'æÙä$R§ yn %¸ÁcÊpã< ˜¹,=f0³íN´Ñ©I¸ Î*lrXG™üèÊm1%À¦3·¾\§?qJçNXF¼R» òÍÚ}-ÃÀ,ÓÇâ „mÁ‰ºøswÓ< ’ ª´Jb zžQó”æò¤Ç]ÆÐÎ…yu›- ŽÁôos¿ͭ²ÑCí¯càìh.¸‰,C4“äÄ+§ƒYF@§) @† +2™e×U“?Ø»†xìÔ3=uàLiMÈàÔwEç‹Œ¾ˆ¨Û®ú§þŠ‚Qƒ¹Žs¦,É×nµQV*›¹ ûÏIYoʵ}óOtØÍoÊÖ”)«Áf„NReºV«»PÍöò˜‚1¡!4^¿]ÍuA9 S£wÛ lÁùlŠ 2}1—;¬N5ç¦éaiECúÙã\/ºrÀÁ>?(ëCW´îhfëÍ(oó/åö°Úp‘cnV³@QóôHÄû‡C›’s2Ð3¨²}•'OöY¾ö¿ ÚTgJÑy}öµ D~29µZÿÿ¦¤ÿÂ{ ’endstream endobj -1255 0 obj << +1768 0 obj << /Type /Page -/Contents 1256 0 R -/Resources 1254 0 R +/Contents 1769 0 R +/Resources 1767 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1245 0 R -/Annots [ 1259 0 R 1260 0 R ] +/Parent 1747 0 R +/Annots [ 1771 0 R ] >> endobj -1259 0 obj << +1771 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [519.8432 682.6714 539.579 694.731] +/Rect [325.3322 626.0361 398.9856 638.0957] /Subtype /Link -/A << /S /GoTo /D (lwresd) >> +/A << /S /GoTo /D (the_sortlist_statement) >> >> endobj -1260 0 obj << -/Type /Annot -/Border[0 0 0]/H/I/C[1 0 0] -/Rect [84.0431 670.7162 117.8035 682.7759] -/Subtype /Link -/A << /S /GoTo /D (lwresd) >> +1770 0 obj << +/D [1768 0 R /XYZ 56.6929 794.5015 null] >> endobj -1257 0 obj << -/D [1255 0 R /XYZ 85.0394 794.5015 null] +518 0 obj << +/D [1768 0 R /XYZ 56.6929 696.6262 null] >> endobj -334 0 obj << -/D [1255 0 R /XYZ 85.0394 731.9325 null] +1294 0 obj << +/D [1768 0 R /XYZ 56.6929 669.0349 null] >> endobj -1258 0 obj << -/D [1255 0 R /XYZ 85.0394 701.4683 null] +1772 0 obj << +/D [1768 0 R /XYZ 56.6929 543.3462 null] >> endobj -338 0 obj << -/D [1255 0 R /XYZ 85.0394 475.6865 null] +1773 0 obj << +/D [1768 0 R /XYZ 56.6929 531.391 null] >> endobj -1261 0 obj << -/D [1255 0 R /XYZ 85.0394 450.9966 null] +522 0 obj << +/D [1768 0 R /XYZ 56.6929 132.8855 null] >> endobj -342 0 obj << -/D [1255 0 R /XYZ 85.0394 393.3855 null] +1774 0 obj << +/D [1768 0 R /XYZ 56.6929 106.4421 null] >> endobj -1262 0 obj << -/D [1255 0 R /XYZ 85.0394 362.9213 null] +1767 0 obj << +/Font << /F37 1018 0 R /F41 1208 0 R /F21 930 0 R /F22 953 0 R /F53 1303 0 R /F62 1352 0 R /F63 1355 0 R >> +/XObject << /Im2 1341 0 R >> +/ProcSet [ /PDF /Text ] >> endobj -346 0 obj << -/D [1255 0 R /XYZ 85.0394 329.3761 null] +1777 0 obj << +/Length 3335 +/Filter /FlateDecode +>> +stream +xÚ½]sä¶íÝ¿bß*Ïœt")Šâ£sçK&¾Öv:ÓIó Ý¥mÍi¥=IkŸóë ¾Vk§s3µ‚ ‚€ËV1ü³U&£Xèd¥tɘÉÕfw¯ ïÇ3F4¡' +ÇT?ܽÿ$ÔJG:åéêî~4WÅYÆVwÛß‚¿øçÝåÍyÈe¤Ñy(Ó8øáêú#b4~>|¾þtõã¯7ç* î®>_#úæòÓåÍåõ‡Ëóe’ÁxN3œðéêçK„~¼¹øå—‹›óßï~:»¼ë÷2Þ/‹…ÝÈ׳ß~W[ØöOgq$t&WÏЈ#¦5_íÎ)"™á1åÙíÙ¿ú G½nè’ü¤È"™qµ @ÎGd1ÀIºRRG©à ðç|g®+a[Iäe[#´©«®9gYP—­ÅÈ {4D´«U‡p}ß®ØQïÇëÛÛË?åe±Í»¢®pŠû¼(nVÓÒ\Ø¢5óÍ£Ùˆ8 î͸¯ðp¦]Q¡•>ˆ d,ÒRr·ŸÝa‡'ä8ƒ¯ˆñÛØÒ¶ÅF¾ß—…Ùb£«ñ»Î áø@Ѐ +C£ +š²ó½å <ÛÝú•ºéÄ¥i[?2¯ÙŠŽ4)Žb J®Xi.Õ²åQ8¦ÂƒgK–ã©œ òoaåvêv0[žI%\ë××縉hžL£„11åàî\óÀŠˆËz{ØXÉò$¨L÷\7_°³kò{Ûÿß8æìÏ«-öÕÇæ­AÌÞ4÷u³Ë«yg1šÎ ºZÓ›e&Í0ͤRÌôîHœ3¤Y”2‘€à,¹Ó.‚Cë´ §,ðEí G>aâ•pÈqZ‰6eÇ¡å»&Ô£i GûÀFQõý~-/ß™ Bž³€trzÆi»èwïÐT°5÷ù¡ìäž‹1î7üWä£%`zù8’d<#¸­,QDÁâ,ŽæŸ‡)ƒ 2Lypy$˜TÀ®¸Ü9O¹]|õuÅ¢8ÑZ Õv»¤àï¯v|õ±†=­ÆÛò3‡ã©Ý¾Òé[ÌbËŽx"Щ];ES Ç»}ivp¿;Õµˆ +¿”̤<Ñ +2¹T¬Æ"ý¾SL©!u ‡Œóût(wa;­¹(%^ @† 2êvÚ›õT.Ä+B—hÝKèÜ?´ŽÎ_ÉHe_8ölžjÉY»*… sÂÈíÞl +›£¸»Où€@©Á»Òy7Õ‚€žkÄÑ/Ý¡Ï~•2L…$}z XØy•w£„úóCWï ‘Áä8Tq”q!§.jWµ½¿!Ë~0•i(„„¦½Ý?43º­˜<3|·/U¾+6Ø8ì!Å74Ð^°sÙÛø$ ê*€—*v6d^7£SèéÃñ€ãS8žc¸ %GÀ\@Gܤ<’`´nŽ4¡§z‹‡£Ù,¾þd¾íén‚›ëtRàˆé"³¢'Öë½ÝFN£1¡kGš©œªS¼Ò01óQ©Û±VZÄcýŒ@YW­Í}íy±mÇë ÂxÕ"DÝs½s+ºâdøÅî^Ál„™Šàê{]Žäù —â=dz ¡ÊÇVÇJ/„ô‹Cf‹#™Ût²÷ 4Â(W<°$Þ¸: ÂÛÛ­Šòwð i; %‚^ÌDU,Æ}Þê%&eÊ—Õ@&\—wbØ¢Ó,͹§+Ð¥ð3L^ìÍsÑOØM§š0‹+â×¥Å6rPüÎ;£!rñ\.llijΖÓ÷DEœ©Œ®k±”¼³$Òœùˆöó=O…UV [ߤphÕ¡ïš2á¼|`ï9¶í´V¥ =nHó áÒZy(PBƒÅ8Õ‹É›–ª#8U”8e€ØÓEhlðŽÔs±94ˆ¯ºù¢~:XÉz_qZÐ*+”Å®è‹}ÑxTšÝ”õæ •&¾˜g[œÉˆ÷2:®Ò0£¤ðe—“QÀLô°y¿¡[I¹õQ½ÍAÓ8È)ã(MÞv„k ¤N± cÖP@¸ÖŽó_fÄíç Ä >ÛÈdø~&ŸQ LB1Þ])5)å)qà‹pâë’R 7mî¯=W1ê Û¯fÕꧼ)ꃯDùҔXKµÅnrû¨´p§ŸLM!…TE¼QSæz*ŒdÒaUoÍqŠšBR‰ôuzª&þ¢`‘&zÊ„ äî­ ˜ÉØØE°QD°; @~qP¨5œ5 7ß dªœ9s¸î$]õ0_yÕùé)Þ+ ŠåR%,Ó³[Òù¾¡–÷Z;@ÏE÷8éªÌ3Cþãò?猱 BÌYêøØ8d©šõåN¶X„e*Ò‚«S‰j¯F"¸D‰7ÔhDõŠyª¹yǺ KY[W¯óÑS-02Ù³fϦ| šdßè5ã‘b—Ǻ¤GŒ^›vÚdëðóàÞ u¾‰ûˆÇáLzåª]îõc(,¡j [ #UÊ@퇒>º˜Î¿œ‘ò¹Š³¿\ÿŸ +¦d“‚÷ +¶¤_Ä÷úÅÀÛ'IüÆãÙ˜ê´~õTsýê^öæøùLC*§¯sÐS-°0Ùmš@¢Ã§, ª¥ñU>û¦xBM€ÆÍG|½vVD9V²JK|[€6½CD§EÏ]%ÁC«b®d^µU"†BµLlMäTú”$°Qðát¾ë¹ ®°Ð×Ëè¹ +´GĉœFWv1FEq&íMi":ãÄ›•ƒ<Å>oòÁX›ù‚7N`Ìo{W?á$B3< +øL2xè¶UD¼Ÿ™­ÉoŒ_ÐŒ©põ~’¶ƒ»#PZÅžàiu d¡Þ(©^QwOÕŒÍ=¸ÐÇÐïðèì{ÍÚQwÍË1­G%噶ohÙë[è©ö0IÊ5¤"áÓMÜá«(åÖ-6F¿t@„»ñ-àßqÀ€þFá>Ï`jW!+ôÚ<æO… Ñ„Ü) ÿX{ï½=ZŒÀ‡]ø#øóõ`C…æ…¨Šø€£I6ï=zwp 5ã…º~°p?´pŠ p×äU{OoH± ~míRÀ J\Ú œ&.Åò¸ºÖ£¤HoÚWÍC›h”0içVlÁúÐ!οNÏæœ$Z˜ÃvýÒB`19œ  Í;¤†:hËü‰èú78;õv±À` ZNW7­ÏXºÎÕµpYË“˜™¢¨ WjOåv®®ŠAã Úô”ÅcYÃâ¶#v¨¯Æ¯†£Ávÿpâp®*a±><µ™êÍH{}A¼7ȹ|Lá¼SÈÁŸïÑM…öœßá/q<ê©ÀÔíþ2Ç©Fƒ‡²^»¤”¢úM;úd$Ûý +Hà†D=À¬¥uÙ +,Ðv‡5¢,S--OÝ`-e¾ÛŸú}–‘ýQÕ‚“‰ûØâ»»5ü°-Qdü„·²Ï>\+Ï”½RsÎûy³þ'oPÑÂendstream +endobj +1776 0 obj << +/Type /Page +/Contents 1777 0 R +/Resources 1775 0 R +/MediaBox [0 0 595.2756 841.8898] +/Parent 1747 0 R +/Annots [ 1779 0 R ] >> endobj -1263 0 obj << -/D [1255 0 R /XYZ 85.0394 301.8169 null] +1779 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [315.1789 427.0782 363.5077 439.1379] +/Subtype /Link +/A << /S /GoTo /D (dynamic_update) >> >> endobj -1254 0 obj << -/Font << /F37 802 0 R /F41 939 0 R /F21 714 0 R /F22 737 0 R >> +1778 0 obj << +/D [1776 0 R /XYZ 85.0394 794.5015 null] +>> endobj +1775 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F41 1208 0 R /F48 1228 0 R /F62 1352 0 R >> +/XObject << /Im2 1341 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1266 0 obj << -/Length 1168 +1782 0 obj << +/Length 3921 /Filter /FlateDecode >> stream -xÚ½XÛnã6}÷WèÑ.@V÷ ö)›:iÝlëzŸÒÀ %*&B‰Z’rìnößKYK‰ÝJŽ$J<3çpf8¦¡éêÏкh^`CG7-LFºö Þ]ŒêPÚ_}œ~¾²<-€kºÚŸÎÊWn…ññæö—r$(/G@gÓ«élz{9ÜÏ?¦ó†K›¯¡[‘o£»{]‹íO#ZïhOêA‡F˜Z2² :¶eÕ#tôçè°õv7õ ~†MË5h-}ºº‚òœº–ií¼›W×Ç(—+n"– ’–C[,Œ/Rö¡|¾/È*‹À0`à8f{z„¥,D–¼!ò ‚hžµï,“„¥‡çí¹1zÄ€|Ë1ß7c®ÀÍñ si.Vào–bQ0«\Fì©Ÿ‚+¤hBJp*ÅpOVLH $’DH¾$hS¾Hód‰y II‚(àXd,ø'’œJ’Q Â%§¤L’øe”Ïåo2JÂ:B«Á ‰¹ZBºíA”ã0çB…æpÿxš–î¹Í°1|z.TœG cŒ±"·¥úds°Dâ„€ßM9K@Dâsœ†õ2ý¥;úaÉKu;C‚¢5V3Œ>•!‡§hIñpÚÕô5¢$Bò¤U« (cH¨r¢]-%ÏUú 4\1Þ~Û<)–ˆ"¸X82 -CœIU3ÂqtBucü ñh¿¼å]‘%ÅŒ ²ùÊèŒy;ßËKdÙEQ¥ã]ƸlÆ‹‡ûò©2!¬íí.?úè“«2¥j]ø¨äæëÆ£¶¾ïÀL ŶÞa´×¥\­EQ¹þîyW£tàúq/d®U( À ¬’m#MWpG%M¸ÂJ•VõÝó;–Æ‘ºø·üì! -†´RˆÐÎyHÇG‚ì%#ã5£dó’Îmêÿ"ß¡QØdΔ+ç«:8‘Ûá©_³-wÐwä,øúým’%%éÃp•Švõ ´›…ª¹‡…X$H5… Jêºö£‡O%h« =/&¨w®Ó`c°!Rbþ/ïßèöpÉQ*âºM]ÝÙÜmpϯDž©ŽŸY‡T[t“^gpºB.s÷Q</RE• 3¥i¬¼Xšøkˆm*WXq6vKªú‰£çË¥¢Û_Û 2Pìý]W‹‘¡ë»fêÇÃ_{螯òÐ=çâk¼O½»=P§¯ê´gXºÆ¬"ó¾–ËÒ+XÎÃW[ñþŽdv«Ï¬úQ/€–é9 -z¶eïPê´ª­Mk ׃–gÚõßSlo1¯{a :žmT¶c¶½í¶nÏ•'¦38ÜÙV¢öRÂò íÛöpoŽZ,Nñßé â› ÷'©¶Zß7›s@Ólšž¯È)Ê©‚‚­¿ò¼>U|íú?ËØ̈endstream +xÚ¥ksÛ6ò»…?Ê3‹'s77“¦I››kÚKÜûÒö-B6/©ŠT÷×ß.v‘e·sO„Çb±Xì”×þÉk›&i¡Šë¬0‰Ò^ovWâúæ¾»’ ³@ë1Ô7·W_¿ÕÙu‘©J¯o·#\y"ò\^ßV¿¬ÒD%7€A¬^ÿøþí»ï~þðê&3«Ûw?¾¿Y++Voßýë µ¾ûðê‡^}¸YËÜÊÕëï_ýtûæM¥Œã›wï¿¥‘‚~. ýðæí›oÞ¿~sóÛí?¯ÞÜƳŒÏ+…ƃü~õËo⺂cÿóJ$ºÈíõ#tD"‹B]ﮌՉ5Z‡‘æêãÕ¿#ÂѬ_ºÈ?)¥SµÀ@¥F Ìeb‹Â^g¶HR­´gàðàèL|EÃÌWnK?ý –m5žOÔêë¹ÙñoÀØïݦþUåxíç²9º>A¦åp‰ÉÒ“q‹‹´ÈVÛ®iºÇº½ÇnºªÜ¶<6CO“å~ß<ÝH)W œOŽÎ'µML. À(wu»>À9à k$“WL8"«ŒäZÚ¦w›®­ú¯ö°y’ZkÂå—· ¬*l›j¶gÇZ[›dF`‹L +k•‡ÿUXaˆyÎ}ê¡/—È2i’ c&'‡;ºDTZ$Æä9ƒ[$È_X8w¼òó2ØÉœxìðÌN™H„H3—Jél7êàAÕì É™vÉ$“2òó$KÁ,k­ÇP¤ rÁšD(¤ÏUm¿>Vûu_ÿáæ»ñIžÉâùí#ÔÂþcÆHe“Üj5%à£CQWB±A£¬>»ÃP÷^‰ ÿæÛ÷©õó·?Qãî¸E­ÜºöõÊSïgê–!žwô ̼2wÍlÇÓònK÷åæS¤Œ,ÀÆÕŸ]Eº¼6&QŒõDvÿsSõMíéÎXù±®JÂAR(C-"-[D±8-ÌVÝqèëŠ5ÊöÞъǺihðŽÁúºqíÐ ‡Ù‡a“©†Öƒ|ŽÎ|XjÙá\4úØa£MÚƲ×Z°ˆ„AÚàð9öaØ÷> Ïø0•Aü“g£ñ9ùŠÆž|b/égâÃp GZ:Ž´q‰·€Ø ™B$ìÃ&`Þ[ù;…8<1>i+öćaä3öaJ˜s†@äÃ<8ù#lŽ}®ÅP:ú°É":=>¡ÅMfâµîó²N€‰¢à Fão[¹=h Ð<µf1¡›„¢1ô‘ o0D9ª_H´’êÏÆ9KÇ8'&×(Î`xÒlê€?²h2éõ,;-érÌQNʉ»1õGxî +¼c×–ÍɼÒCéŒR±¹£¡ œÃÂE‰+føæy0†ºì"i ˜ŠRظ5(ðŽ¢‰c€ÄYe™yžˆµ@ÅÄ1ÙX€ c1À«dÎþ™×p›éóm?üý£k'}èXÑ»3'§!¯d“³ÐäáþšF§Šð/œê/ Ûƒ(J†ÎèÉ!ÔZ?ÏÛõgØN:Rb‚ÏG~:Ñpæ¸}ýÖLŒ¶_.‚ÓÜ—aA ÁßXÓ" ¯8óSi"M:5=õsC¹þÒmH.°}dÇ*ž‚íÈã˜5í9ST"ñp¹Y½­éöoK¿ >P“d§§m¼õ;?¨†\FgÐ~þ¤Y¢CÅæäå‘Ô§}½»ÿD]÷eŠ7 y¹š±$ž¬?è}ì}R +ý{׺CÉÓÛ3؃[,liðU™‡>ëM·Û?¼vœ¡Ó8v¬]ãƒy½zß .Äþ”@¼ñàÝ[f)0¬r8”Gë)PUOBúvébžØÂSÇ[eúÒÝX“…È^¸`´Ö!òÆ06]Y¹j±0fÛƒFP\™É³<ÚnW3‡únçxlÁ\Ù<¸Í'¦ƒßó´;6hòõßñê½; '‚T`£¸-”êOµj–?¸B%ÀÇ ì#S²)™ð;Çò‚Èg® ƒðïPW•·³:[ùÓêÜËüìɆ®YÆà0ù\»Gš¹+{Ϙô^†êvÓ+ +z=Ò…û±dë©úk 0ÝŠp]ã+€MQöj>Æò%¬ÁP'Âd³Êá¥L"²(Adç·*A›âã‹gÉ"žTEÏ’+ŸßÌ"ósù³"Êß…0Ÿià†ŸÒG@—ƒôä5¡©¯ý:ÜöïGwxâgÌ çç$*]$&Oå³4F s"§L4‰I!âS ±eÏUöÞE( +. úIÄD=Tðw0¹;î0L¥yzM„Y¬ ùÂvÚãîÎE‡¨à®³™UöÎW‡rÝæxàœÆ²ÞÂݲuݱ§‘ ¸_âõI¡¡Q¶OÔ¸‡Õ-5‰£¾yJZåDƒ@˜m&ƒ`ý}é±+ÉL¬|üŽFð«ß!d„ÿ7 fHs°´i OþñNæ .‚ùÖßr€’L¯>•%sÙ˜ˆxYl6nïí?X‡œ ÕðbUQÉc¿ç,:Ÿå¿y×Å7X8Q*¢³ÆØ4Bâ ; `böøö›ÃÁš-µ†cëBa–ûü”Àçá‘®þ‹iñýB$/nâÎNÉþ %û{|ÑâòžQâ6Æ/R̞ɥÓwîŒUÈ“-ÓH64ûˆ+jR0B’zð¥ +‰ÊâZ(­Tà—ÌØŽy ¿$é’žà'È94ÛrLòƒ:NñÎCùÉ1¹þ."}}×|^,Œ‡¨Bú¤Ž¡.G©ŠßuëíÓºrMùtþ¸¨[€v<»{„ZØ~r¡2ƒ` réÉþä”3üP)ÀïÀP]rNótüSŽU—áѹ8ÕrŠ”e!„ÕsR>ñs$? “7…á’~ÐxûbZ1&(D Љ•›Ù¼6ŠùEx.ÁHÓrLwú j)¬‚ 3)DŠ¹4t®ãÇ2…¿›5Äbõͱn†uÈsb<èsJòbšãsÙ=Uø!šÈG‚ù ¾šRu¶û\WŽßz©<†­×ì·Ç†«º¼o;0üšœPAoÄãOFèë† ‡ü3@ŽoKápØ#ú=(ä¥0Gì{w¬ºõÐí×¾²®:ô K­’ÔÆÏ4îê¶Z®«,¾D{’tv©0N#– ^ÿêÇ !F/òåûdKÞ`£8çBüáȘáÇ¢4ž®< Ôò¬¢ªvGƒUpúÂËIü"3>ù³Iüf÷}®Å3Œ“% /¿Êž[ 6Bç#BìÃ<»ÿÓ(…’i>üŽr³é+%>äé WP¹ŒeÈP´ècZäHDVôYm·£9Ž½‹‘ý€×z‰°ê‰J€OyåÝß½_ò`#2 +?‹óg¾œú¡ÅT)§ÆpßtwesIDðC[­—nF\ ü¿?}>ɘÉçêB©"䀄‰ÂSfù¹oäo¤ÏIÿG7ÝIendstream endobj -1265 0 obj << +1781 0 obj << /Type /Page -/Contents 1266 0 R -/Resources 1264 0 R +/Contents 1782 0 R +/Resources 1780 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1245 0 R +/Parent 1787 0 R +/Annots [ 1784 0 R 1786 0 R ] >> endobj -1267 0 obj << -/D [1265 0 R /XYZ 56.6929 794.5015 null] +1784 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [324.9335 477.5927 381.8296 489.6523] +/Subtype /Link +/A << /S /GoTo /D (zonefile_format) >> >> endobj -1264 0 obj << -/Font << /F37 802 0 R /F41 939 0 R /F22 737 0 R >> +1786 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [55.6967 61.5153 116.59 73.5749] +/Subtype /Link +/A << /S /GoTo /D (view_statement_grammar) >> +>> endobj +1783 0 obj << +/D [1781 0 R /XYZ 56.6929 794.5015 null] +>> endobj +526 0 obj << +/D [1781 0 R /XYZ 56.6929 131.3071 null] +>> endobj +1785 0 obj << +/D [1781 0 R /XYZ 56.6929 107.529 null] +>> endobj +1780 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F41 1208 0 R /F11 1442 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1270 0 obj << -/Length 1164 +1792 0 obj << +/Length 2818 /Filter /FlateDecode >> stream -xÚµXMsÛ6½ëWðhu(>’˜œWviœVUOªFÆ"r¢4ýï?$‘e‘t<>˜¹oßb ` ™?ly "ÊmËå6d3+XuoÞÝŒpõ Ø}ê_½~¾¦®Å!wˆcÍV5,"ÏÃÖ,œ_\ýzùûl2ÂÐ…Ç€9èâííÝ/å/ÿ]}¸»¾½ùkz9ví‹Ù퇻rx:¹žL'wW“1ÀÃÆžT' ®o›”O7ÓË÷ï/§ãÅìÝh2ÛûR÷#š;òy4_ +4n¿!H¹Ç¬/悘sb­G6£Ù”îF¢ÑŸ£?ö€µ·…i›~ŒzyÄmÐÆ51%Ðs¶\Æ¡C -œƒÐEš(]>ý*Ÿdº< Ï}µ06|\ 0tmÊ -ˆŸªW3†­Ú …KëÅ»x³ÏM¶9´)wÌSBêÔ>o„Ú‚,Ù¨@€Gç)Ë:_g釡jæ.$Ž Å)ÂäˆpÉÈ„’"ó¶Ñ0±ìSsÛíb}¯˜átÇ×™äîŠ,ë¤u¡íÙ¬è·èG­òãWÏ& XA9&ITŽoE¶LÔ2NX¨Uå¦=ÈŸ*ÉãÍú£PíäˆMúZÈX õèG=±ÖþW •g+¡€–kd|?‘lôKhÈ0êFã D' Wt‚ ’"î“9F~šÚ|̃Êä£è>}ƒ¸™\úQ¹82Ë¡çü5{)ú’ÏU‹d¦EœlD_ÑwA[%jíå~ `>ø"ö¨ -w¼­Æ% wa[M—K “^žîm¬­½mj|{‹¼S©Ü¼*ÉÔ>®Ï.‡”¸mõ™AîºN{mœŠlUq­5²ÜÏpžM¶Ã¦jŸ j£J…„º¼}Ë4è%k íd%ˆC‚k•µ…ëYi Á»Èy%ºÄ…ØöÈÉò¤¼}¶Ë8Ñrµ¡ˆüí®TIf-”Ú§Bè”6Ž ©KìS‚±—¥K!µ9?Ïò|Ò2ð’s Iq8®þ“xvŽ‰e (‘Ê÷¬®žc;`!l´ÿul,äוQr2ùM èþ1qÍ{0ÏŸ–Y*‚ ‚Ä´Ç–å6ý¡ßÓ¾áÁJF»¦ ÿä™öƒO/aDÂe|º·¸ öÂWú£ð5Ø#f+?CŒÚôG2Ȇú “41˯™-Õmiš¦àa™w`Õ¢^¼yŽŒIŠÃ·/‚R*$*ÜõfZ1räù³oŸ¦æ!COËùæ´¡õCOøÁÃPã¶Í6]Þ|J½m] -•PåE÷“yeº/²$NÂf?%ÿïëê…OAém*ñY˨$é}˜Ê›¼`÷ØäS•<Ê°£ÓQ΂2=ÐZ«¼P -øÈRÿ¨eêìD!žX™>‡òa0k½;HÛí%e0¿rl¹kDû{šßl®}mÓÀyÙ_ZR»´¤ÈáîŽT2ß_SÿnÖŸendstream +xÚ½]oã¸ñ=¿"ou€3ËO‰jŸ²›äêC7»MÒâÐÛ{Ple#¬#û,ysé¯ï ‡”)E–²¸¢’£á|q¾ÈDœrø§Ö0®2}šfš.Ìéòé„Ÿ~o?ž3HóëÝÝÉŸ¯Tzš±,‘ÉéÝCDË2n­8½[ý2{ÿ·óOw—7gsiø,ags“ðÙ»ÅõA2Þ¼¾ZüøÏ›ó³TÏî¯ |syuysyýþòl.¬°_z +G6\-þ~I³oÎ?|8¿9ûõ˻V—X_Á*òÛÉ/¿òÓ¨ýÓ g*³æôœ‰,“§O'Ú(f´R²>¹=ùGK0úê¶ÙÏ(ËŒ•é€¥2 ÉX¢¤r¬‹Ý·bJev¶Ù6妪iQï—8Kgyj1\0+­L¾^ožç¿í‹Ý‹GŽ9Ë·™Ç]mˆCµih’o·ëâÕ<ƒIí§ÿÙTE ¶˜-ö²ÙÓä¡(Öí¢QÅʃ<§UYç÷ëeòt.0ºJÁrB°Ìéäsü~8›«ÄÎö(„Òš¨ã¤5’Òfv_€Úg™œ9ôt¶Ùü±\õ÷ÝïËu3/«[J©YªD°%øôÇÛ+jÁ¸IÖ·²xö”_ˆéªø̹¬Êê ÁóŠÆâ÷íº\– ­Â>3Û<d¹Îë¡#žËÄ°ÔfI×¼``¾VD‡d6í…ç™h@+ÌLLå`*ª…>ËùHÛ:ù7Ë¢®]F@˜sÉ=`‚®SÇ£01œÙ„ëñ(Œ±ŽGa‹…²>nê&øf' eÆ”PãŒÒãŽ)Íd¦{œ)“ä ‚[5ÜF!ÎCBjïD!|£(„‰BÂÔ™9¦y, +­`:MB]  C°7y'‘ÉpΕ…h²FuÃéMÑ{ÍÑÀSœe’«ï< yG!b“y5Á±L»Ñ…žÁ.Ÿ T”åcYE¸Tòb”°ûpž¥N<×2mu×2›}…G­SWP¥Y_Š&ˆô™¿‚0öÕÛTgÞ·`ÃvW>åÎp±ßm7®™Ñ>CзWÚ†$péG×¹ÀGè#ªrAŸË° è *¼›ÐAŽ/ûû--Oóêe™× -È.ÈŽ[b‹Ëf%ú%à×Ï ›Ë°„žkG³6m@C5•ÞÀ·¤•¦çãDóÛ_‡ +TOÌ,¼›×ÜÙ©L1®y¯LüO²Áª˜@ˆŽf»ëx¶k±¢&$œ—«×)ZèßÇÙ·Xü»I3©2Ó€Ó¦³ÅM´éç!ÝÙ^º³èzEYå7²4€r®é`avQ]8ÆÖ4@0†®o>ŽBÉSÙ{øÍ.Pv‡.A)ÌP3÷WdµÈüQ#àHÆÅjDpÆÅ»½¼ù×åÍЕŰ$Kº=>ÖóÀ5-k‹øÛ²,’;ÚÞ¤èäo˲É!Ë"É;²?$!„¶I¿¹„OB Iˆ¬@áÔý¾ßån.)[ÃxHM¸ò© §._ØÓ%£Î׌pÑ&#G؇dDøm2Â%%#œ’‘N&’Q/[vÃ2Kz<#iˆ~þ*#¹=ý܃0ê +ÓÐM¦‘”©‘ãRJÎÔÖÎ!C4¿•Yë¶ë5mYæûúH› ´¢{ÖH}¨Ž*:ø°ó„LûKr¦‚¶:.àÎk‚ú‹ wgÍÂõƒ%Öm:”ØTóмë¶y(9Z2m óáäÛ¿·j&T‚¨¼ k)˜ýt¤=—R‡¶mTуÀå:åªÌaâ󓀦-…äœÏÞ…W¼.Ÿ¶Í MÿŒÁ½¡JX®SGïÚ"°P³GwFÏê;µïnUuDqÏÅ“¸ýxNð¼òÄ®oiô…`ãÆ•g°©Ö/xxp\‰tÇU{†9áÓâÁ½”t¹Ñ““’ +Q§Á &ß=ù:û‚FÊ ŽüŠ ëÍ2 ’¡¡Ê’¨ëÊ¢>æþUê@¼†4G3zN2á¥)™-ª¦ØUEó'O‡A à“&&hØÐq:6H°«ã²Ä»¦T*jÍ”neørCEU©öy ¦2õ6_~Ù¡Ùï*ú~ýóÅÇç‹kZÑ×z»©jÚ H-¥cš‡l¥¸5 a›ïšr9:—ý:w7^,ßV¶¤RÓ +»Á„„@= Õ— yÂóÕÊ LÒèŒüD«›«÷´Ê™õ{Üi¾™™RÐÑmNáÅ£­ë m-«åz¿*†Ô"‰•ìI¬DGbøN|ñé[B 炌ԠoXE ¨_ªb…¡ƒ6TIKIÌÖeõuŒ¦{­Ä-Í™˜‰cA6ÛùïÝç˯þY®# œãæÙÓƒÙ¾úZmž«W;YËÃ2#¹‰“”ÊW#œåMƒ ‡Îý`\LOî^‡Ë»w©]o)ãt…+ÌžÔÚ¿Ó¬^Pü^Öx±Ä¹;¤å×ÐQ”ßüF<òÍ6$•¥ˆ)œê3¥­ÕÛ‹D8íÍcU@_·Ë±lù76©·Ì(×àk¨W¢).Å!é{•a*Âቩ¢gýø±1ö;bQù-ë²nº×¤/ïeý—cäPøÇS9þGË]W ìEí +L­Šh¡ÔŸ9ÔÀþ-‰Cë‘@eåÚb½fÛmÅ9ÌuÒeËÙâz~~qqÃÎo>á£þùQÍye;±šGX#š¬iÍǸFš÷Ùk³pÝx«îp+ƒ{屇ù {Œu\÷kR÷Q®Ý_±Ô½ÃVèÿ’ìíú.‡örBÿkDÿ€5­ÿ×Hÿ>Ûaýc¶’áåÛõ7ò‹ÑúGX#ú¬iýǸFú÷Ùë³…VZ{0}» Oü1;B1€GšÖ„e¤~ç°öOWMÎ$Wo×vh dÆ•°F´XÓêqôï³6@ÌV|W;ü¾Õ"sLŸb¬ãvh±&í0Êõ`‡WlíÐaËÙûY|J¦m–&Lk•NØ,±YÀš¶Ù×Èf}¶Ã6‹ÙŠÿ‡ÍLÊ2Ù ›EX#6 XÓ6ãÙ¬ÏvØf1[ËÞ± ,9Îòm6PÓ\N´[1Öˆ Ö´ ƸF6賶AÌö‚]¡¾oÓ]rf­œh·b¬ÝÖ´îc\#Ýûl‡uÙZvù=ÚsÉT"&š­kDû€5­ý×Hû>Ûaíc¶Ùwio³ZLtZÒqÝÒ¤êc,š÷y*ó<ÿ.½Ôœ¨¬œãZ{œI¥Gøtî1T9bøî»4V†á?ù H¿þ±áÿ/áÁx:e +"rX¼Z™¥A(Ô&Íú’·ÿtøZôÿÃóîendstream endobj -1269 0 obj << +1791 0 obj << /Type /Page -/Contents 1270 0 R -/Resources 1268 0 R +/Contents 1792 0 R +/Resources 1790 0 R /MediaBox [0 0 595.2756 841.8898] -/Parent 1245 0 R +/Parent 1787 0 R >> endobj -1271 0 obj << -/D [1269 0 R /XYZ 85.0394 794.5015 null] +1793 0 obj << +/D [1791 0 R /XYZ 85.0394 794.5015 null] >> endobj -1268 0 obj << -/Font << /F37 802 0 R /F41 939 0 R /F22 737 0 R >> +530 0 obj << +/D [1791 0 R /XYZ 85.0394 496.0455 null] +>> endobj +1794 0 obj << +/D [1791 0 R /XYZ 85.0394 467.7701 null] +>> endobj +1790 0 obj << +/Font << /F37 1018 0 R /F22 953 0 R /F21 930 0 R /F41 1208 0 R /F14 956 0 R >> /ProcSet [ /PDF /Text ] >> endobj -1274 0 obj << -/Length 2424 +1797 0 obj << +/Length 3233 /Filter /FlateDecode >> stream -xÚ¥]s›HòÝ¿Bo‡«af>*OÞÄÉyïÖ¹³½uI*‡ÐH¢‚@ÁŽr»ÿýº§ö*Žý@ÓÓÓÝÓ߃Ø̇6“¡&<™EIàIŸÉY¶9óg+X{wÆ,Û¹Cª_îÎ^¾Ñ,ñ’‡³»å€WìùqÌfw‹Nèqï8øÎë÷×o¯Þý~sqÎÝÕûës—Kßy{õÏK‚ÞÝ\üöÛÅ͹Ëbɜ׿ø×Ýå -…–Ç/W×o“Ðã¦7—o/o.¯__žºûõìò®?Ëð¼Ìx¯g>ù³û×3ßI,gðâ{,IølsHáÉ@ˆSœÝžý»g8X5['íÇ|‹O0`ƾúÀ*’‰ -.Œ?œ»¡ï;›¼tk¥ë«ó"\Ùnæª&ø=>áAªË˜—HÉG,Òo?Ëb[Õš |û_¦÷°ážt±Èu^•iá.ëj㦭^ÓÊN5Ÿ«úsY,ÿW–fkõ\fuZ.€ÇBÝç™e²Mõús™vÖ9áthT£…Ûäßí6„>7[•ý€kt¶v7év«.²VM£šƒƒâŸZ-U]“UÑZm>úÒ'è‚Ø7ø!®ß__ö[Ø gW‹²qÛÅvptŠ§ƒñ™[ëªÒàµB­RŒ·*‹­tz}ËŠvaÙþÏr§yc£÷ÏNÊ©nþÚªzWT«çÆÚ"oÒy¡Ü´XUu®×ë\À4/Gšö$¯F‡:D[Ýÿ<%k(@U‰*üÀ Ø“¬Pi™—+7/µªïÓâ~O>a²"W¥nÜ­ª]ã›SËÙqò>—ÓÁ±0Ç2/«ÒyŸ{Z}ÓÔé&ÕÉüÔf«wnî”ø¡ªDÛ³ªÔi¦OÛ?!þ{UªæÇÃf2ð÷ ÐUÚ类ܲr›*uµ.ž«Ð›S[ˆË…—0?ó„ìƒÅ—o9›õè% -–Ì‹ƒ Ÿ€XS̪-–¬†¦”[jµè£×7ê£ïóÒ48Â@ƒ"à÷&])+Š&Ä#χÉȺ[«^Ÿ=‹½$I" FšNƒcff#!¤¥kÊ á4J7µ[z®ŠjŽéðþXð¢+|Î\Ù Z4ßÑÇ8À»un·ܤ–›bZ[9¦Ô”)rŒ”¨6;kªC'ÅGä@& mWm’uq 1…=B™8WKBê5$‹EQ9DCLL6Œ½8IØ_[6Ð-ûx'¼L²z#¢ÀyQe_|Èq`B -±J8¢%\CËhxD亱1ë‡^,“dœO µLÛÂÝC^wÁÝåÍÍÌ‹ g‚^Gâ‘9—ˆÜ!•sGfëfðžÊ(•×*Ó”ßÉIä…A?-¹#š<ôó9ÄŠÏÇ¢1k\Á¥óPÕ_ µÑ (dâê'sP/ƒ­–ôÔÝ[¢áöWˆú‹Ò’–0š¤ó¦*ZmiqºÄ’‡.æÅè×q”’¢Ôú“A®ûá8ÔɃ" „$`úE•„JzÒY -à{ßU´¢M"´?1—1fŽ”0k ¤è"@€vjÂt=6U£ 2¦ãÙ…ªÕÛÖ.Ñ¡šîEúÊ[y”8£ÑA'@ã-¼º-'r îapñä6ǨÙrp‹)/QwN„&Ï)bnj¤St#fe¥ À¡%ÇÓ¨d3}ò&.õÑ4É  mcìÙÂÔM ýï„!D(ànèwEÜ›2€—DQh þö‚"&€¶%¢PŽC†".`‡j‰€;Kƒ©6Dð°ÎMÉÐnâ]ÈÓ:âVk,®Œe1ØÐd–ߺj‹-Îí>Sa­O ‰†Žéôh¡âBzRúQ¨†Tªž -¥~Q;÷ÑbÅXäÉ(xZzG4!}T¬8‡U)Æâÿ³6©Íà®ó&ŒšT°üÄYì =òŒÛí"5e`S³€ QYÛ÷6F#Xó‚j9—ùGÔà%›žtÛ΋NN*p>:(>ðTß“:‚;o®oo/_ Æ$`_Û,Ìí®eÕ–˜bB -'_n赤"ƒâð€+zmÈ@–œ}L³¯ö†ÕTí“a7RÆÞQ>‹q\óˆ;›¶Ñ´dZ+`P)|ß·ÄR»"ŠM)¼®hAà)4‘tÅKô±ëÔ"ËŠÊÚ#³r;B[“„e÷`Áž¶{Gà(`.yIU Þ±¥uîÃwpŸ¥lZ,ffµÝÍ¢£:Æ}˜Öâ°«cu¹È< ‚ãrD^ óË°àMå9Î`"Œƒ§ó|Hõxž÷T}¯q¿-U}”ä~ l!Ÿ”ÝS É0ÍTöf—‘t‹…ˆ÷“ž°Ó(â0~”VSm I<%µÛ•¦T§ ãˆ2ã<é›*®Å„0“õ4ca|˨(wŠÝž D³ ‚z¿ŸfÛ¶ƒ0~¤F.™i[ˆ¡Z‡ ùÚªrZì{0{‰q)5·]f&‡=ïnoݻ۫w„¶¥«¬*ð2œ$Îë}*ìf{ãä?T=§F\5´&é1ЕZ³±†k÷i^Ð÷DÓ…½NÉ¡É&Z]n :NÅAr¨†ÄÎy™å[ó-¬™»`p™MSI»¯Ù×6ï& ¤ÒkâÛ®÷®¬Í ¿¡3@ ’úÖ‹®OÕ›´(vOÝ(èp/•Î^~©ç»NçS:VÀ‚¾¹!œëN $aw‡h` |íÐf3„X7¥Äî»!ÔGΫg<úh{A+ºîË©vj?JÙ ÆÊžý¦||’(ò"?îª1 -6§‰»ó„;i ‚bZÄÒ‹DŽƒº‹áÅ5ˆ½PF]m5ÕâQ]Bü­‹wdz£EÑTãïÒÞc?ãÁdŒ¿½M¿ÿ ÷Ó?ñíÿÄæÇ|ºRñ<«ž+àÇEÚþx¬úÿ[@•¿endstream +xÚ¥]sÛ6òÝ¿BÓ—£f"” ’¸{J§u§uîßô¡íEQ6ç(R);]ì‚%Êé]&3¸X,‹ý†å"„r¡‘˜È,R J½(vWáâæ~¸’Œ³rH+ë»û«oß«ta„I¢dq¿õhe"Ì2¹¸ßü$"K ß¸}óÿïÞ.Ó8¸¿ùp»\E: Þßü|M£îÞþòËÛ»åJfZßÿøöŸ÷×w4•0ïnnßÄÐÏ¢w×ï¯ï®o¿¿^þqÿÓÕõýpÿ¼2TxOW¿ý.6p쟮B¡L¦Ïð +iL´Ø]ÅZ +å õÕÇ« ½Y»tV~2‘J¢FÑœµ‰Š”àõnß¿À©¤þl›²Ãa䇥̂’à]Ù÷ùºæ¯¼'”þ‘OUùL£º|*k&ÐlÖ65“Ï÷{ÂÚv\Ú1Þ–¦Š:ïts+hð®êpÿ a”3ëc¸ÊJJa´Žì™¥ƒªy,Uo)©$ØÚ5íŽ&Û}_µMGSÕ–€pÊAåsMKÀÍÈ@{0áØh·/‹ê÷0ŒÜÞVŒ´XŒŠÅGW¡î—& +xŸö©<ªÍì‰ ¨æx +ø¨«®gð–~=^áË2ø†Æ/í‘EÞLpécØ€dÖö#åý "ÙÀñ6Ûö@ƒòs¾Û×åßñ4ß¾¥§¨©©ÅV¡HCðx@ffeÅ»¢m“0 ¾ßüƒHLt}5¥‘Y7(“ðQðq\Ê «šú¢c ÎfCXV-pÈ›‡’ÇÞ‰ÝÀ©Ë¼¾tÜ©{l5ãä5áäÔ£ƒÇü‰7£  Ù1À©ÛkÂߌxÜâ:¥câÇ®­J"Ü4Ùò¢¯Š’¾úÇŠ—€©–ù?ÐXñ·Á;ÇÁÚâ³ê" È;=Wý#vyóB£OG`Û1³.í cSú;èó3‘¯ší!ïúÃ2 ŽEî,…û*(,ú Õ‚A“ïJ†U ýéέÙÃEçEÙ¡‰¥*øØœ8ömA:nyΣ./Ö‹*¯g˜x.}þš²ÜXÕ@íÜ…­ÙZ6å¾n_œaZ‰¶ø˜7õ©¾e¡D_Ø´Úœ—äÏ9Ã<·æ¯º$F˜âˆKá, ¡ô_Œg2Æèx>žÁé3ˆh)ØûEZ´.Z<¤§¤Æ¼AG‘HS€^Ød¼]$‘P©LÚ(!Iê·žËÐ 0hEµŠ€o‹ñ,E‚û{ ÎÂ

    Mismatch responses received. + The DNS ID, response's source address, + and/or the response's source port does not + match what was expected. + (The port must be 53 or as defined by + the port option.) + This may be an indication of a cache + poisoning attempt.

    + + + + + + +
    arpaname
    +Prev Manual pages Next +
    +
    +
    +
    +
    +
    +

    Name

    +

    arpaname — translate IP addresses to the corresponding ARPA names

    +
    +
    +

    Synopsis

    +

    arpaname {ipaddress ...}

    +
    +
    +

    DESCRIPTION

    +

    + arpaname translates IP addresses (IPv4 and + IPv6) to the corresponding IN-ADDR.ARPA or IP6.ARPA names. +

    +
    +
    +

    SEE ALSO

    +

    + BIND 9 Administrator Reference Manual. +

    +
    +
    +

    AUTHOR

    +

    Internet Systems Consortium +

    +
    +
    + + + diff --git a/doc/arm/man.ddns-confgen.html b/doc/arm/man.ddns-confgen.html new file mode 100644 index 0000000..0155dbf --- /dev/null +++ b/doc/arm/man.ddns-confgen.html @@ -0,0 +1,180 @@ + + + + + +ddns-confgen + + + + + + + + +
    +
    +
    +

    Name

    +

    ddns-confgen — ddns key generation tool

    +
    +
    +

    Synopsis

    +

    ddns-confgen [-a algorithm] [-h] [-k keyname] [-r randomfile] [ -s name | -z zone ] [-q] [name]

    +
    +
    +

    DESCRIPTION

    +

    ddns-confgen + generates a key for use by nsupdate + and named. It simplifies configuration + of dynamic zones by generating a key and providing the + nsupdate and named.conf + syntax that will be needed to use it, including an example + update-policy statement. +

    +

    + If a domain name is specified on the command line, it will + be used in the name of the generated key and in the sample + named.conf syntax. For example, + ddns-confgen example.com would + generate a key called "ddns-key.example.com", and sample + named.conf command that could be used + in the zone definition for "example.com". +

    +

    + Note that named itself can configure a + local DDNS key for use with nsupdate -l. + ddns-confgen is only needed when a + more elaborate configuration is required: for instance, if + nsupdate is to be used from a remote system. +

    +
    +
    +

    OPTIONS

    +
    +
    -a algorithm
    +

    + Specifies the algorithm to use for the TSIG key. Available + choices are: hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, + hmac-sha384 and hmac-sha512. The default is hmac-sha256. +

    +
    -h
    +

    + Prints a short summary of the options and arguments to + ddns-confgen. +

    +
    -k keyname
    +

    + Specifies the key name of the DDNS authentication key. + The default is ddns-key when neither + the -s nor -z option is + specified; otherwise, the default + is ddns-key as a separate label + followed by the argument of the option, e.g., + ddns-key.example.com. + The key name must have the format of a valid domain name, + consisting of letters, digits, hyphens and periods. +

    +
    -q
    +

    + Quiet mode: Print only the key, with no explanatory text or + usage examples. +

    +
    -r randomfile
    +

    + Specifies a source of random data for generating the + authorization. If the operating system does not provide a + /dev/random or equivalent device, the + default source of randomness is keyboard input. + randomdev specifies the name of a + character device or file containing random data to be used + instead of the default. The special value + keyboard indicates that keyboard input + should be used. +

    +
    -s name
    +

    + Single host mode: The example named.conf text + shows how to set an update policy for the specified + name + using the "name" nametype. + The default key name is + ddns-key.name. + Note that the "self" nametype cannot be used, since + the name to be updated may differ from the key name. + This option cannot be used with the -z option. +

    +
    -z zone
    +

    + zone mode: The example named.conf text + shows how to set an update policy for the specified + zone + using the "zonesub" nametype, allowing updates to all subdomain + names within + that zone. + This option cannot be used with the -s option. +

    +
    +
    +
    +

    SEE ALSO

    +

    nsupdate(1), + named.conf(5), + named(8), + BIND 9 Administrator Reference Manual. +

    +
    +
    +

    AUTHOR

    +

    Internet Systems Consortium +

    +
    +
    + + + diff --git a/doc/arm/man.dig.html b/doc/arm/man.dig.html index 6afc34b..73b2b88 100644 --- a/doc/arm/man.dig.html +++ b/doc/arm/man.dig.html @@ -1,5 +1,5 @@ - + @@ -52,7 +52,7 @@

    dig [global-queryopt...] [query...]

    -

    DESCRIPTION

    +

    DESCRIPTION

    dig (domain information groper) is a flexible tool for interrogating DNS name servers. It performs DNS lookups and @@ -98,7 +98,7 @@

    -

    SIMPLE USAGE

    +

    SIMPLE USAGE

    A typical invocation of dig looks like:

    @@ -144,7 +144,7 @@

    -

    OPTIONS

    +

    OPTIONS

    The -b option sets the source IP address of the query to address. This must be a valid @@ -248,7 +248,7 @@

    -

    QUERY OPTIONS

    +

    QUERY OPTIONS

    dig provides a number of query options which affect the way in which lookups are made and the results displayed. Some of @@ -517,6 +517,12 @@ each record on a single line, to facilitate machine parsing of the dig output.

    +
    +[no]onesoa
    +

    + Print only one (starting) SOA record when performing + an AXFR. The default is to print both the starting and + ending SOA records. +

    +[no]fail

    Do not try the next server if you receive a SERVFAIL. The @@ -573,7 +579,7 @@

    -

    MULTIPLE QUERIES

    +

    MULTIPLE QUERIES

    The BIND 9 implementation of dig supports @@ -619,7 +625,7 @@ dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr

    -

    IDN SUPPORT

    +

    IDN SUPPORT

    If dig has been built with IDN (internationalized domain name) support, it can accept and display non-ASCII domain names. @@ -633,14 +639,14 @@ dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr

    -

    FILES

    +

    FILES

    /etc/resolv.conf

    ${HOME}/.digrc

    -

    SEE ALSO

    +

    SEE ALSO

    host(1), named(8), dnssec-keygen(8), @@ -648,7 +654,7 @@ dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr

    -

    BUGS

    +

    BUGS

    There are probably too many query options.

    diff --git a/doc/arm/man.dnssec-dsfromkey.html b/doc/arm/man.dnssec-dsfromkey.html index 245d387..133bfbc 100644 --- a/doc/arm/man.dnssec-dsfromkey.html +++ b/doc/arm/man.dnssec-dsfromkey.html @@ -1,5 +1,5 @@ - + @@ -47,18 +47,18 @@

    Synopsis

    -

    dnssec-dsfromkey [-v level] [-1] [-2] [-a alg] {keyfile}

    -

    dnssec-dsfromkey {-s} [-v level] [-1] [-2] [-a alg] [-c class] [-d dir] {dnsname}

    +

    dnssec-dsfromkey [-v level] [-1] [-2] [-a alg] [-l domain] {keyfile}

    +

    dnssec-dsfromkey {-s} [-1] [-2] [-a alg] [-K directory] [-l domain] [-s] [-c class] [-f file] [-A] [-v level] {dnsname}

    -

    DESCRIPTION

    +

    DESCRIPTION

    dnssec-dsfromkey outputs the Delegation Signer (DS) resource record (RR), as defined in RFC 3658 and RFC 4509, for the given key(s).

    -

    OPTIONS

    +

    OPTIONS

    -1

    @@ -72,34 +72,54 @@

    -a algorithm

    Select the digest algorithm. The value of - algorithm must be one of SHA-1 (SHA1) or - SHA-256 (SHA256). These values are case insensitive. + algorithm must be one of SHA-1 (SHA1), + SHA-256 (SHA256) or GOST. These values are case insensitive.

    -
    -v level
    +
    -K directory

    - Sets the debugging level. + Look for key files (or, in keyset mode, + keyset- files) in + directory. +

    +
    -f file
    +

    + Zone file mode: in place of the keyfile name, the argument is + the DNS domain name of a zone master file, which can be read + from file. If the zone name is the same as + file, then it may be omitted. +

    +
    -A
    +

    + Include ZSK's when generating DS records. Without this option, + only keys which have the KSK flag set will be converted to DS + records and printed. Useful only in zone file mode. +

    +
    -l domain
    +

    + Generate a DLV set instead of a DS set. The specified + domain is appended to the name for each + record in the set. + The DNSSEC Lookaside Validation (DLV) RR is described + in RFC 4431.

    -s

    Keyset mode: in place of the keyfile name, the argument is - the DNS domain name of a keyset file. Following options make sense - only in this mode. + the DNS domain name of a keyset file.

    -c class

    - Specifies the DNS class (default is IN), useful only - in the keyset mode. + Specifies the DNS class (default is IN). Useful only + in keyset or zone file mode.

    -
    -d directory
    +
    -v level

    - Look for keyset files in - directory as the directory, ignored when - not in the keyset mode. + Sets the debugging level.

    -

    EXAMPLE

    +

    EXAMPLE

    To build the SHA-256 DS RR from the Kexample.com.+003+26160 @@ -114,7 +134,7 @@

    -

    FILES

    +

    FILES

    The keyfile can be designed by the key identification Knnnn.+aaa+iiiii or the full file name @@ -128,22 +148,23 @@

    -

    CAVEAT

    +

    CAVEAT

    A keyfile error can give a "file not found" even if the file exists.

    -

    SEE ALSO

    +

    SEE ALSO

    dnssec-keygen(8), dnssec-signzone(8), BIND 9 Administrator Reference Manual, RFC 3658, + RFC 4431. RFC 4509.

    -

    AUTHOR

    +

    AUTHOR

    Internet Systems Consortium

    diff --git a/doc/arm/man.dnssec-keyfromlabel.html b/doc/arm/man.dnssec-keyfromlabel.html index 4a28c5e..670c85a 100644 --- a/doc/arm/man.dnssec-keyfromlabel.html +++ b/doc/arm/man.dnssec-keyfromlabel.html @@ -1,5 +1,5 @@ - + @@ -47,26 +47,30 @@

    Synopsis

    -

    dnssec-keyfromlabel {-a algorithm} {-l label} [-c class] [-f flag] [-k] [-n nametype] [-p protocol] [-t type] [-v level] {name}

    +

    dnssec-keyfromlabel {-l label} [-3] [-a algorithm] [-A date/offset] [-c class] [-D date/offset] [-E engine] [-f flag] [-G] [-I date/offset] [-k] [-K directory] [-n nametype] [-P date/offset] [-p protocol] [-R date/offset] [-t type] [-v level] [-y] {name}

    -

    DESCRIPTION

    +

    DESCRIPTION

    dnssec-keyfromlabel gets keys with the given label from a crypto hardware and builds key files for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034.

    +

    + The name of the key is specified on the command + line. This must match the name of the zone for which the key is + being generated. +

    -

    OPTIONS

    +

    OPTIONS

    -a algorithm

    Selects the cryptographic algorithm. The value of - algorithm must be one of RSAMD5, - RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, - RSASHA512 or DH (Diffie Hellman). + algorithm must be one of RSAMD5, RSASHA1, + DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512 or ECCGOST. These values are case insensitive.

    @@ -84,10 +88,23 @@ Note 2: DH automatically sets the -k flag.

    +
    -3
    +

    + Use an NSEC3-capable algorithm to generate a DNSSEC key. + If this option is used and no algorithm is explicitly + set on the command line, NSEC3RSASHA1 will be used by + default. +

    +
    -E engine
    +

    + Specifies the name of the crypto hardware (OpenSSL engine). + When compiled with PKCS#11 support it defaults to "pkcs11". +

    -l label

    - Specifies the label of keys in the crypto hardware - (PKCS#11 device). + Specifies the label of the key pair in the crypto hardware. + The label may be preceded by an optional OpenSSL engine name, + separated by a colon, as in "pkcs11:keylabel".

    -n nametype

    @@ -96,8 +113,17 @@ zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with a host (KEY)), USER (for a key associated with a user(KEY)) or OTHER (DNSKEY). - These values are - case insensitive. + These values are case insensitive. +

    +
    -C
    +

    + Compatibility mode: generates an old-style key, without + any metadata. By default, dnssec-keyfromlabel + will include the key's creation date in the metadata stored + with the private key, and other dates may be set there as well + (publication date, activation date, etc). Keys that include + this data may be incompatible with older versions of BIND; the + -C option suppresses them.

    -c class

    @@ -107,12 +133,21 @@

    -f flag

    Set the specified flag in the flag field of the KEY/DNSKEY record. - The only recognized flag is KSK (Key Signing Key) DNSKEY. + The only recognized flags are KSK (Key Signing Key) and REVOKE. +

    +
    -G
    +

    + Generate a key, but do not publish it or sign with it. This + option is incompatible with -P and -A.

    -h

    Prints a short summary of the options and arguments to - dnssec-keygen. + dnssec-keyfromlabel. +

    +
    -K directory
    +

    + Sets the directory in which the key files are to be written.

    -k

    @@ -120,7 +155,7 @@

    -p protocol

    - Sets the protocol value for the generated key. The protocol + Sets the protocol value for the key. The protocol is a number between 0 and 255. The default is 3 (DNSSEC). Other possible values for this argument are listed in RFC 2535 and its successors. @@ -136,10 +171,65 @@

    Sets the debugging level.

    +
    -y
    +

    + Allows DNSSEC key files to be generated even if the key ID + would collide with that of an existing key, in the event of + either key being revoked. (This is only safe to use if you + are sure you won't be using RFC 5011 trust anchor maintenance + with either of the keys involved.) +

    +
    +
    +
    +

    TIMING OPTIONS

    +

    + Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. + If the argument begins with a '+' or '-', it is interpreted as + an offset from the present time. For convenience, if such an offset + is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', + then the offset is computed in years (defined as 365 24-hour days, + ignoring leap years), months (defined as 30 24-hour days), weeks, + days, hours, or minutes, respectively. Without a suffix, the offset + is computed in seconds. +

    +
    +
    -P date/offset
    +

    + Sets the date on which a key is to be published to the zone. + After that date, the key will be included in the zone but will + not be used to sign it. If not set, and if the -G option has + not been used, the default is "now". +

    +
    -A date/offset
    +

    + Sets the date on which the key is to be activated. After that + date, the key will be included in the zone and used to sign + it. If not set, and if the -G option has not been used, the + default is "now". +

    +
    -R date/offset
    +

    + Sets the date on which the key is to be revoked. After that + date, the key will be flagged as revoked. It will be included + in the zone and will be used to sign it. +

    +
    -I date/offset
    +

    + Sets the date on which the key is to be retired. After that + date, the key will still be included in the zone, but it + will not be used to sign it. +

    +
    -D date/offset
    +

    + Sets the date on which the key is to be deleted. After that + date, the key will no longer be included in the zone. (It + may remain in the key repository, however.) +

    -

    GENERATED KEY FILES

    +

    GENERATED KEY FILES

    When dnssec-keyfromlabel completes successfully, @@ -151,8 +241,7 @@

  • nnnn is the key name.

  • aaa is the numeric representation - of the - algorithm. + of the algorithm.

  • iiiii is the key identifier (or footprint). @@ -163,8 +252,7 @@ on the printed string. Knnnn.+aaa+iiiii.key contains the public key, and Knnnn.+aaa+iiiii.private contains the - private - key. + private key.

    The .key file contains a DNS KEY record @@ -173,14 +261,14 @@ statement).

    - The .private file contains algorithm - specific + The .private file contains + algorithm-specific fields. For obvious security reasons, this file does not have general read permission.

  • -

    SEE ALSO

    +

    SEE ALSO

    dnssec-keygen(8), dnssec-signzone(8), BIND 9 Administrator Reference Manual, @@ -188,7 +276,7 @@

    -

    AUTHOR

    +

    AUTHOR

    Internet Systems Consortium

    diff --git a/doc/arm/man.dnssec-keygen.html b/doc/arm/man.dnssec-keygen.html index d775f56..3d63f8e 100644 --- a/doc/arm/man.dnssec-keygen.html +++ b/doc/arm/man.dnssec-keygen.html @@ -1,5 +1,5 @@ - + @@ -23,7 +23,7 @@ - +

    Synopsis

    -

    dnssec-keygen {-a algorithm} {-b keysize} {-n nametype} [-c class] [-e] [-f flag] [-g generator] [-h] [-k] [-p protocol] [-r randomdev] [-s strength] [-t type] [-v level] {name}

    +

    dnssec-keygen [-a algorithm] [-b keysize] [-n nametype] [-3] [-A date/offset] [-C] [-c class] [-D date/offset] [-E engine] [-e] [-f flag] [-G] [-g generator] [-h] [-I date/offset] [-i interval] [-K directory] [-k] [-P date/offset] [-p protocol] [-q] [-R date/offset] [-r randomdev] [-S key] [-s strength] [-t type] [-v level] [-z] {name}

    -

    DESCRIPTION

    +

    DESCRIPTION

    dnssec-keygen generates keys for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034. It can also generate keys for use with - TSIG (Transaction Signatures), as defined in RFC 2845. + TSIG (Transaction Signatures) as defined in RFC 2845, or TKEY + (Transaction Key) as defined in RFC 2930.

    The name of the key is specified on the command @@ -63,37 +64,56 @@

    -

    OPTIONS

    +

    OPTIONS

    -a algorithm

    Selects the cryptographic algorithm. For DNSSEC keys, the value of algorithm must be one of RSAMD5, RSASHA1, - DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256 or RSASHA512. - For TSIG/TKEY, the value must + DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512 or ECCGOST. + For TSIG/TKEY, the value must be DH (Diffie Hellman), HMAC-MD5, HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, HMAC-SHA384, or HMAC-SHA512. These values are case insensitive.

    + If no algorithm is specified, then RSASHA1 will be used by + default, unless the -3 option is specified, + in which case NSEC3RSASHA1 will be used instead. (If + -3 is used and an algorithm is specified, + that algorithm will be checked for compatibility with NSEC3.) +

    +

    Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement algorithm, and DSA is recommended. For TSIG, HMAC-MD5 is mandatory.

    - Note 2: HMAC-MD5 and DH automatically set the -k flag. + Note 2: DH, HMAC-MD5, and HMAC-SHA1 through HMAC-SHA512 + automatically set the -T KEY option.

    -b keysize
    -

    +

    +

    Specifies the number of bits in the key. The choice of key size depends on the algorithm used. RSA keys must be between 512 and 2048 bits. Diffie Hellman keys must be between 128 and 4096 bits. DSA keys must be between 512 and 1024 bits and an exact multiple of 64. HMAC keys must be between 1 and 512 bits. -

    +

    +

    + The key size does not need to be specified if using a default + algorithm. The default key size is 1024 bits for zone signing + keys (ZSK's) and 2048 bits for key signing keys (KSK's, + generated with -f KSK). However, if an + algorithm is explicitly specified with the -a, + then there is no default key size, and the -b + must be used. +

    +
    -n nametype

    Specifies the owner type of the key. The value of @@ -104,11 +124,36 @@ These values are case insensitive. Defaults to ZONE for DNSKEY generation.

    +
    -3
    +

    + Use an NSEC3-capable algorithm to generate a DNSSEC key. + If this option is used and no algorithm is explicitly + set on the command line, NSEC3RSASHA1 will be used by + default. Note that RSASHA256, RSASHA512 and ECCGOST algorithms + are NSEC3-capable. +

    +
    -C
    +

    + Compatibility mode: generates an old-style key, without + any metadata. By default, dnssec-keygen + will include the key's creation date in the metadata stored + with the private key, and other dates may be set there as well + (publication date, activation date, etc). Keys that include + this data may be incompatible with older versions of BIND; the + -C option suppresses them. +

    -c class

    Indicates that the DNS record containing the key should have the specified class. If not specified, class IN is used.

    +
    -E engine
    +

    + Uses a crypto hardware (OpenSSL engine) for random number + and, when supported, key generation. When compiled with PKCS#11 + support it defaults to pkcs11; the empty name resets it to + no engine. +

    -e

    If generating an RSAMD5/RSASHA1 key, use a large exponent. @@ -116,7 +161,12 @@

    -f flag

    Set the specified flag in the flag field of the KEY/DNSKEY record. - The only recognized flag is KSK (Key Signing Key) DNSKEY. + The only recognized flags are KSK (Key Signing Key) and REVOKE. +

    +
    -G
    +

    + Generate a key, but do not publish it or sign with it. This + option is incompatible with -P and -A.

    -g generator

    @@ -130,9 +180,13 @@ Prints a short summary of the options and arguments to dnssec-keygen.

    +
    -K directory
    +

    + Sets the directory in which the key files are to be written. +

    -k

    - Generate KEY records rather than DNSKEY records. + Deprecated in favor of -T KEY.

    -p protocol

    @@ -141,6 +195,20 @@ Other possible values for this argument are listed in RFC 2535 and its successors.

    +
    -q
    +

    + Quiet mode: Suppresses unnecessary output, including + progress indication. Without this option, when + dnssec-keygen is run interactively + to generate an RSA or DSA key pair, it will print a string + of symbols to stderr indicating the + progress of the key generation. A '.' indicates that a + random number has been found which passed an initial + sieve test; '+' means a number has passed a single + round of the Miller-Rabin primality test; a space + means that the number has passed all the tests and is + a satisfactory key. +

    -r randomdev

    Specifies the source of randomness. If the operating @@ -153,12 +221,37 @@ keyboard indicates that keyboard input should be used.

    +
    -S key
    +

    + Create a new key which is an explicit successor to an + existing key. The name, algorithm, size, and type of the + key will be set to match the existing key. The activation + date of the new key will be set to the inactivation date of + the existing one. The publication date will be set to the + activation date minus the prepublication interval, which + defaults to 30 days. +

    -s strength

    Specifies the strength value of the key. The strength is a number between 0 and 15, and currently has no defined purpose in DNSSEC.

    +
    -T rrtype
    +
    +

    + Specifies the resource record type to use for the key. + rrtype must be either DNSKEY or KEY. The + default is DNSKEY when using a DNSSEC algorithm, but it can be + overridden to KEY for use with SIG(0). +

    +

    +

    +

    + Using any TSIG algorithm (HMAC-* or DH) forces this option + to KEY. +

    +
    -t type

    Indicates the use of the key. type must be @@ -173,7 +266,78 @@

    -

    GENERATED KEYS

    +

    TIMING OPTIONS

    +

    + Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. + If the argument begins with a '+' or '-', it is interpreted as + an offset from the present time. For convenience, if such an offset + is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', + then the offset is computed in years (defined as 365 24-hour days, + ignoring leap years), months (defined as 30 24-hour days), weeks, + days, hours, or minutes, respectively. Without a suffix, the offset + is computed in seconds. +

    +
    +
    -P date/offset
    +

    + Sets the date on which a key is to be published to the zone. + After that date, the key will be included in the zone but will + not be used to sign it. If not set, and if the -G option has + not been used, the default is "now". +

    +
    -A date/offset
    +

    + Sets the date on which the key is to be activated. After that + date, the key will be included in the zone and used to sign + it. If not set, and if the -G option has not been used, the + default is "now". +

    +
    -R date/offset
    +

    + Sets the date on which the key is to be revoked. After that + date, the key will be flagged as revoked. It will be included + in the zone and will be used to sign it. +

    +
    -I date/offset
    +

    + Sets the date on which the key is to be retired. After that + date, the key will still be included in the zone, but it + will not be used to sign it. +

    +
    -D date/offset
    +

    + Sets the date on which the key is to be deleted. After that + date, the key will no longer be included in the zone. (It + may remain in the key repository, however.) +

    +
    -i interval
    +
    +

    + Sets the prepublication interval for a key. If set, then + the publication and activation dates must be separated by at least + this much time. If the activation date is specified but the + publication date isn't, then the publication date will default + to this much time before the activation date; conversely, if + the publication date is specified but activation date isn't, + then activation will be set to this much time after publication. +

    +

    + If the key is being created as an explicit successor to another + key, then the default prepublication interval is 30 days; + otherwise it is zero. +

    +

    + As with date offsets, if the argument is followed by one of + the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the + interval is measured in years, months, weeks, days, hours, + or minutes, respectively. Without a suffix, the interval is + measured in seconds. +

    +
    +
    +
    +
    +

    GENERATED KEYS

    When dnssec-keygen completes successfully, @@ -219,7 +383,7 @@

    -

    EXAMPLE

    +

    EXAMPLE

    To generate a 768-bit DSA key for the domain example.com, the following command would be @@ -240,7 +404,7 @@

    -

    SEE ALSO

    +

    SEE ALSO

    dnssec-signzone(8), BIND 9 Administrator Reference Manual, RFC 2539, @@ -249,7 +413,7 @@

    -

    AUTHOR

    +

    AUTHOR

    Internet Systems Consortium

    @@ -261,14 +425,14 @@ Prev  UpNextNext dnssec-keyfromlabel  Homednssec-signzonednssec-revoke diff --git a/doc/arm/man.dnssec-revoke.html b/doc/arm/man.dnssec-revoke.html new file mode 100644 index 0000000..1c9ba5a --- /dev/null +++ b/doc/arm/man.dnssec-revoke.html @@ -0,0 +1,126 @@ + + + + + +dnssec-revoke + + + + + + + + +
    +
    +
    +

    Name

    +

    dnssec-revoke — Set the REVOKED bit on a DNSSEC key

    +
    +
    +

    Synopsis

    +

    dnssec-revoke [-hr] [-v level] [-K directory] [-E engine] [-f] {keyfile}

    +
    +
    +

    DESCRIPTION

    +

    dnssec-revoke + reads a DNSSEC key file, sets the REVOKED bit on the key as defined + in RFC 5011, and creates a new pair of key files containing the + now-revoked key. +

    +
    +
    +

    OPTIONS

    +
    +
    -h
    +

    + Emit usage message and exit. +

    +
    -K directory
    +

    + Sets the directory in which the key files are to reside. +

    +
    -r
    +

    + After writing the new keyset files remove the original keyset + files. +

    +
    -v level
    +

    + Sets the debugging level. +

    +
    -E engine
    +

    + Use the given OpenSSL engine. When compiled with PKCS#11 support + it defaults to pkcs11; the empty name resets it to no engine. +

    +
    -f
    +

    + Force overwrite: Causes dnssec-revoke to + write the new key pair even if a file already exists matching + the algorithm and key ID of the revoked key. +

    +
    +
    +
    +

    SEE ALSO

    +

    dnssec-keygen(8), + BIND 9 Administrator Reference Manual, + RFC 5011. +

    +
    +
    +

    AUTHOR

    +

    Internet Systems Consortium +

    +
    +
    + + + diff --git a/doc/arm/man.dnssec-settime.html b/doc/arm/man.dnssec-settime.html new file mode 100644 index 0000000..19e467e --- /dev/null +++ b/doc/arm/man.dnssec-settime.html @@ -0,0 +1,247 @@ + + + + + +dnssec-settime + + + + + + + + +
    +
    +
    +

    Name

    +

    dnssec-settime — Set the key timing metadata for a DNSSEC key

    +
    +
    +

    Synopsis

    +

    dnssec-settime [-f] [-K directory] [-P date/offset] [-A date/offset] [-R date/offset] [-I date/offset] [-D date/offset] [-h] [-v level] [-E engine] {keyfile}

    +
    +
    +

    DESCRIPTION

    +

    dnssec-settime + reads a DNSSEC private key file and sets the key timing metadata + as specified by the -P, -A, + -R, -I, and -D + options. The metadata can then be used by + dnssec-signzone or other signing software to + determine when a key is to be published, whether it should be + used for signing a zone, etc. +

    +

    + If none of these options is set on the command line, + then dnssec-settime simply prints the key timing + metadata already stored in the key. +

    +

    + When key metadata fields are changed, both files of a key + pair (Knnnn.+aaa+iiiii.key and + Knnnn.+aaa+iiiii.private) are regenerated. + Metadata fields are stored in the private file. A human-readable + description of the metadata is also placed in comments in the key + file. +

    +
    +
    +

    OPTIONS

    +
    +
    -f
    +

    + Force an update of an old-format key with no metadata fields. + Without this option, dnssec-settime will + fail when attempting to update a legacy key. With this option, + the key will be recreated in the new format, but with the + original key data retained. The key's creation date will be + set to the present time. +

    +
    -K directory
    +

    + Sets the directory in which the key files are to reside. +

    +
    -h
    +

    + Emit usage message and exit. +

    +
    -v level
    +

    + Sets the debugging level. +

    +
    -E engine
    +

    + Use the given OpenSSL engine. When compiled with PKCS#11 support + it defaults to pkcs11; the empty name resets it to no engine. +

    +
    +
    +
    +

    TIMING OPTIONS

    +

    + Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. + If the argument begins with a '+' or '-', it is interpreted as + an offset from the present time. For convenience, if such an offset + is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', + then the offset is computed in years (defined as 365 24-hour days, + ignoring leap years), months (defined as 30 24-hour days), weeks, + days, hours, or minutes, respectively. Without a suffix, the offset + is computed in seconds. To unset a date, use 'none'. +

    +
    +
    -P date/offset
    +

    + Sets the date on which a key is to be published to the zone. + After that date, the key will be included in the zone but will + not be used to sign it. +

    +
    -A date/offset
    +

    + Sets the date on which the key is to be activated. After that + date, the key will be included in the zone and used to sign + it. +

    +
    -R date/offset
    +

    + Sets the date on which the key is to be revoked. After that + date, the key will be flagged as revoked. It will be included + in the zone and will be used to sign it. +

    +
    -I date/offset
    +

    + Sets the date on which the key is to be retired. After that + date, the key will still be included in the zone, but it + will not be used to sign it. +

    +
    -D date/offset
    +

    + Sets the date on which the key is to be deleted. After that + date, the key will no longer be included in the zone. (It + may remain in the key repository, however.) +

    +
    -S predecessor key
    +

    + Select a key for which the key being modified will be an + explicit successor. The name, algorithm, size, and type of the + predecessor key must exactly match those of the key being + modified. The activation date of the successor key will be set + to the inactivation date of the predecessor. The publication + date will be set to the activation date minus the prepublication + interval, which defaults to 30 days. +

    +
    -i interval
    +
    +

    + Sets the prepublication interval for a key. If set, then + the publication and activation dates must be separated by at least + this much time. If the activation date is specified but the + publication date isn't, then the publication date will default + to this much time before the activation date; conversely, if + the publication date is specified but activation date isn't, + then activation will be set to this much time after publication. +

    +

    + If the key is being set to be an explicit successor to another + key, then the default prepublication interval is 30 days; + otherwise it is zero. +

    +

    + As with date offsets, if the argument is followed by one of + the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the + interval is measured in years, months, weeks, days, hours, + or minutes, respectively. Without a suffix, the interval is + measured in seconds. +

    +
    +
    +
    +
    +

    PRINTING OPTIONS

    +

    + dnssec-settime can also be used to print the + timing metadata associated with a key. +

    +
    +
    -u
    +

    + Print times in UNIX epoch format. +

    +
    -p C/P/A/R/I/D/all
    +

    + Print a specific metadata value or set of metadata values. + The -p option may be followed by one or more + of the following letters to indicate which value or values to print: + C for the creation date, + P for the publication date, + A for the activation date, + R for the revocation date, + I for the inactivation date, or + D for the deletion date. + To print all of the metadata, use -p all. +

    +
    +
    +
    +

    SEE ALSO

    +

    dnssec-keygen(8), + dnssec-signzone(8), + BIND 9 Administrator Reference Manual, + RFC 5011. +

    +
    +
    +

    AUTHOR

    +

    Internet Systems Consortium +

    +
    +
    + + + diff --git a/doc/arm/man.dnssec-signzone.html b/doc/arm/man.dnssec-signzone.html index 42bf068..05cea6e 100644 --- a/doc/arm/man.dnssec-signzone.html +++ b/doc/arm/man.dnssec-signzone.html @@ -1,5 +1,5 @@ - + @@ -22,7 +22,7 @@ - + @@ -31,7 +31,7 @@ dnssec-signzone -Prev  +Prev  Manual pages  Next @@ -47,21 +47,21 @@

    Synopsis

    -

    dnssec-signzone [-a] [-c class] [-d directory] [-e end-time] [-f output-file] [-g] [-h] [-k key] [-l domain] [-i interval] [-I input-format] [-j jitter] [-N soa-serial-format] [-o origin] [-O output-format] [-p] [-P] [-r randomdev] [-s start-time] [-t] [-v level] [-z] [-3 salt] [-H iterations] [-A] {zonefile} [key...]

    +

    dnssec-signzone [-a] [-c class] [-d directory] [-E engine] [-e end-time] [-f output-file] [-g] [-h] [-K directory] [-k key] [-l domain] [-i interval] [-I input-format] [-j jitter] [-N soa-serial-format] [-o origin] [-O output-format] [-p] [-P] [-r randomdev] [-S] [-s start-time] [-T ttl] [-t] [-u] [-v level] [-x] [-z] [-3 salt] [-H iterations] [-A] {zonefile} [key...]

    -

    DESCRIPTION

    +

    DESCRIPTION

    dnssec-signzone signs a zone. It generates NSEC and RRSIG records and produces a signed version of the - zone. It also generates a keyset- file containing - the key-signing keys for the zone, and if signing a zone which - contains delegations, it can optionally generate DS records for - the child zones from their keyset- files. + zone. The security status of delegations from the signed zone + (that is, whether the child zones are secure or not) is + determined by the presence or absence of a + keyset file for each child zone.

    -

    OPTIONS

    +

    OPTIONS

    -a

    @@ -71,6 +71,38 @@

    Specifies the DNS class of the zone.

    +
    -C
    +

    + Compatibility mode: Generate a + keyset-zonename + file in addition to + dsset-zonename + when signing a zone, for use by older versions of + dnssec-signzone. +

    +
    -d directory
    +

    + Look for dsset- or + keyset- files in directory. +

    +
    -E engine
    +

    + Uses a crypto hardware (OpenSSL engine) for the crypto operations + it supports, for instance signing with private keys from + a secure key store. When compiled with PKCS#11 support + it defaults to pkcs11; the empty name resets it to no engine. +

    +
    -g
    +

    + Generate DS records for child zones from + dsset- or keyset- + file. Existing DS records will be removed. +

    +
    -K directory
    +

    + Key repository: Specify a directory to search for DNSSEC keys. + If not specified, defaults to the current directory. +

    -k key

    Treat specified key as a key signing key ignoring any @@ -81,18 +113,6 @@ Generate a DLV set in addition to the key (DNSKEY) and DS sets. The domain is appended to the name of the records.

    -
    -d directory
    -

    - Look for keyset files in - directory as the directory -

    -
    -g
    -

    - If the zone contains any delegations, and there are - keyset- files for any of the child zones, - then DS records for the child zones will be generated from the - keys in those files. Existing DS records will be removed. -

    -s start-time

    Specify the date and time when the generated RRSIG records @@ -113,6 +133,8 @@ the start time. A time relative to the current time is indicated with now+N. If no end-time is specified, 30 days from the start time is used as a default. + end-time must be later than + start-time.

    -f output-file

    @@ -247,35 +269,119 @@ keyboard indicates that keyboard input should be used.

    +
    -S
    +
    +

    + Smart signing: Instructs dnssec-signzone to + search the key repository for keys that match the zone being + signed, and to include them in the zone if appropriate. +

    +

    + When a key is found, its timing metadata is examined to + determine how it should be used, according to the following + rules. Each successive rule takes priority over the prior + ones: +

    +
    +
    +

    + If no timing metadata has been set for the key, the key is + published in the zone and used to sign the zone. +

    +
    +

    + If the key's publication date is set and is in the past, the + key is published in the zone. +

    +
    +

    + If the key's activation date is set and in the past, the + key is published (regardless of publication date) and + used to sign the zone. +

    +
    +

    + If the key's revocation date is set and in the past, and the + key is published, then the key is revoked, and the revoked key + is used to sign the zone. +

    +
    +

    + If either of the key's unpublication or deletion dates are set + and in the past, the key is NOT published or used to sign the + zone, regardless of any other metadata. +

    +
    +
    +
    -T ttl
    +

    + Specifies the TTL to be used for new DNSKEY records imported + into the zone from the key repository. If not specified, + the default is the minimum TTL value from the zone's SOA + record. This option is ignored when signing without + -S, since DNSKEY records are not imported + from the key repository in that case. It is also ignored if + there are any pre-existing DNSKEY records at the zone apex, + in which case new records' TTL values will be set to match + them. +

    -t

    Print statistics at completion.

    +
    -u
    +

    + Update NSEC/NSEC3 chain when re-signing a previously signed + zone. With this option, a zone signed with NSEC can be + switched to NSEC3, or a zone signed with NSEC3 can + be switch to NSEC or to NSEC3 with different parameters. + Without this option, dnssec-signzone will + retain the existing chain when re-signing. +

    -v level

    Sets the debugging level.

    +
    -x
    +

    + Only sign the DNSKEY RRset with key-signing keys, and omit + signatures from zone-signing keys. (This is similar to the + dnssec-dnskey-kskonly yes; zone option in + named.) +

    -z

    - Ignore KSK flag on key when determining what to sign. + Ignore KSK flag on key when determining what to sign. This + causes KSK-flagged keys to sign all records, not just the + DNSKEY RRset. (This is similar to the + update-check-ksk no; zone option in + named.)

    -3 salt

    - Generate a NSEC3 chain with the given hex encoded salt. + Generate an NSEC3 chain with the given hex encoded salt. A dash (salt) can be used to indicate that no salt is to be used when generating the NSEC3 chain.

    -H iterations

    - When generating a NSEC3 chain use this many interations. The - default is 100. + When generating an NSEC3 chain, use this many interations. The + default is 10.

    -A
    -

    - When generating a NSEC3 chain set the OPTOUT flag on all +

    +

    + When generating an NSEC3 chain set the OPTOUT flag on all NSEC3 records and do not generate NSEC3 records for insecure delegations. -

    +

    +

    + Using this option twice (i.e., -AA) + turns the OPTOUT flag off for all records. This is useful + when using the -u option to modify an NSEC3 + chain which previously had OPTOUT set. +

    +
    zonefile

    The file containing the zone to be signed. @@ -291,14 +397,15 @@

    -

    EXAMPLE

    +

    EXAMPLE

    The following command signs the example.com zone with the DSA key generated by dnssec-keygen - (Kexample.com.+003+17247). The zone's keys must be in the master - file (db.example.com). This invocation looks - for keyset files, in the current directory, - so that DS records can be generated from them (-g). + (Kexample.com.+003+17247). Because the -S option + is not being used, the zone's keys must be in the master file + (db.example.com). This invocation looks + for dsset files, in the current directory, + so that DS records can be imported from them (-g).

    % dnssec-signzone -g -o example.com db.example.com \
     Kexample.com.+003+17247
    @@ -320,39 +427,14 @@ db.example.com.signed
     %
    -

    KNOWN BUGS

    -

    - dnssec-signzone was designed so that it could - sign a zone partially, using only a subset of the DNSSEC keys - needed to produce a fully-signed zone. This permits a zone - administrator, for example, to sign a zone with one key on one - machine, move the resulting partially-signed zone to a second - machine, and sign it again with a second key. -

    -

    - An unfortunate side-effect of this flexibility is that - dnssec-signzone does not check to make sure - it's signing a zone with any valid keys at all. An attempt to - sign a zone without any keys will appear to succeed, producing - a "signed" zone with no signatures. There is no warning issued - when a zone is not fully signed. -

    -

    - This will be corrected in a future release. In the meantime, ISC - recommends examining the output of dnssec-signzone - to confirm that the zone is properly signed by all keys before - using it. -

    -
    -
    -

    SEE ALSO

    +

    SEE ALSO

    dnssec-keygen(8), BIND 9 Administrator Reference Manual, RFC 4033.

    -

    AUTHOR

    +

    AUTHOR

    Internet Systems Consortium

    @@ -362,14 +444,14 @@ db.example.com.signed +Prev  +dnssec-settime  diff --git a/doc/arm/man.genrandom.html b/doc/arm/man.genrandom.html new file mode 100644 index 0000000..c9ecc8e --- /dev/null +++ b/doc/arm/man.genrandom.html @@ -0,0 +1,112 @@ + + + + + +genrandom + + + + + + + +
    -Prev  Up  Next
    -dnssec-keygen  Home  named-checkconf
    + + + + + + +
    genrandom
    +Prev Manual pages Next +
    +
    + +
    +
    +
    +

    Name

    +

    genrandom — generate a file containing random data

    +
    +
    +

    Synopsis

    +

    genrandom [-n number] {size} {filename}

    +
    +
    +

    DESCRIPTION

    +

    + genrandom + generates a file or a set of files containing a specified quantity + of pseudo-random data, which can be used as a source of entropy for + other commands on systems with no random device. +

    +
    +
    +

    ARGUMENTS

    +
    +
    -n number
    +

    + In place of generating one file, generates number + (from 2 to 9) files, appending number to the name. +

    +
    size
    +

    + The size of the file, in kilobytes, to generate. +

    +
    domain
    +

    + The file name into which random data should be written. +

    +
    +
    +
    +

    SEE ALSO

    +

    + rand(3), + arc4random(3) +

    +
    +
    +

    AUTHOR

    +

    Internet Systems Consortium +

    +
    +
    + + + diff --git a/doc/arm/man.host.html b/doc/arm/man.host.html index 990d67e..7322353 100644 --- a/doc/arm/man.host.html +++ b/doc/arm/man.host.html @@ -1,5 +1,5 @@ - + @@ -50,7 +50,7 @@

    host [-aCdlnrsTwv] [-c class] [-N ndots] [-R number] [-t type] [-W wait] [-m flag] [-4] [-6] {name} [server]

    -

    DESCRIPTION

    +

    DESCRIPTION

    host is a simple utility for performing DNS lookups. It is normally used to convert names to IP addresses and vice versa. @@ -202,7 +202,7 @@

    -

    IDN SUPPORT

    +

    IDN SUPPORT

    If host has been built with IDN (internationalized domain name) support, it can accept and display non-ASCII domain names. @@ -216,12 +216,12 @@

    -

    FILES

    +

    FILES

    /etc/resolv.conf

    -

    SEE ALSO

    +

    SEE ALSO

    dig(1), named(8).

    diff --git a/doc/arm/man.isc-hmac-fixup.html b/doc/arm/man.isc-hmac-fixup.html new file mode 100644 index 0000000..bff6e91 --- /dev/null +++ b/doc/arm/man.isc-hmac-fixup.html @@ -0,0 +1,122 @@ + + + + + +isc-hmac-fixup + + + + + + + + +
    +
    +
    +

    Name

    +

    isc-hmac-fixup — fixes HMAC keys generated by older versions of BIND

    +
    +
    +

    Synopsis

    +

    isc-hmac-fixup {algorithm} {secret}

    +
    +
    +

    DESCRIPTION

    +

    + Versions of BIND 9 up to and including BIND 9.6 had a bug causing + HMAC-SHA* TSIG keys which were longer than the digest length of the + hash algorithm (i.e., SHA1 keys longer than 160 bits, SHA256 keys + longer than 256 bits, etc) to be used incorrectly, generating a + message authentication code that was incompatible with other DNS + implementations. +

    +

    + This bug has been fixed in BIND 9.7. However, the fix may + cause incompatibility between older and newer versions of + BIND, when using long keys. isc-hmac-fixup + modifies those keys to restore compatibility. +

    +

    + To modify a key, run isc-hmac-fixup and + specify the key's algorithm and secret on the command line. If the + secret is longer than the digest length of the algorithm (64 bytes + for SHA1 through SHA256, or 128 bytes for SHA384 and SHA512), then a + new secret will be generated consisting of a hash digest of the old + secret. (If the secret did not require conversion, then it will be + printed without modification.) +

    +
    +
    +

    SECURITY CONSIDERATIONS

    +

    + Secrets that have been converted by isc-hmac-fixup + are shortened, but as this is how the HMAC protocol works in + operation anyway, it does not affect security. RFC 2104 notes, + "Keys longer than [the digest length] are acceptable but the + extra length would not significantly increase the function + strength." +

    +
    +
    +

    SEE ALSO

    +

    + BIND 9 Administrator Reference Manual, + RFC 2104. +

    +
    +
    +

    AUTHOR

    +

    Internet Systems Consortium +

    +
    +
    + + + diff --git a/doc/arm/man.named-checkconf.html b/doc/arm/man.named-checkconf.html index 8bf240b..d6eff94 100644 --- a/doc/arm/man.named-checkconf.html +++ b/doc/arm/man.named-checkconf.html @@ -1,5 +1,5 @@ - + @@ -47,17 +47,30 @@

    Synopsis

    -

    named-checkconf [-h] [-v] [-j] [-t directory] {filename} [-z]

    +

    named-checkconf [-h] [-v] [-j] [-t directory] {filename} [-p] [-z]

    -

    DESCRIPTION

    +

    DESCRIPTION

    named-checkconf - checks the syntax, but not the semantics, of a named - configuration file. + checks the syntax, but not the semantics, of a + named configuration file. The file is parsed + and checked for syntax errors, along with all files included by it. + If no file is specified, /etc/named.conf is read + by default. +

    +

    + Note: files that named reads in separate + parser contexts, such as rndc.key and + bind.keys, are not automatically read + by named-checkconf. Configuration + errors in these files may cause named to + fail to run, even if named-checkconf was + successful. named-checkconf can be run + on these files explicitly, however.

    -

    OPTIONS

    +

    OPTIONS

    -h

    @@ -65,8 +78,7 @@

    -t directory

    - Chroot to directory so that - include + Chroot to directory so that include directives in the configuration file are processed as if run by a similarly chrooted named.

    @@ -75,6 +87,11 @@ Print the version of the named-checkconf program and exit.

    +
    -p
    +

    + Print out the named.conf and included files + in canonical form if no errors were detected. +

    -z

    Perform a test load of all master zones found in @@ -92,21 +109,21 @@

    -

    RETURN VALUES

    +

    RETURN VALUES

    named-checkconf returns an exit status of 1 if errors were detected and 0 otherwise.

    -

    SEE ALSO

    +

    SEE ALSO

    named(8), named-checkzone(8), BIND 9 Administrator Reference Manual.

    -

    AUTHOR

    +

    AUTHOR

    Internet Systems Consortium

    diff --git a/doc/arm/man.named-checkzone.html b/doc/arm/man.named-checkzone.html index aeaf7d3..e7d9dc1 100644 --- a/doc/arm/man.named-checkzone.html +++ b/doc/arm/man.named-checkzone.html @@ -1,5 +1,5 @@ - + @@ -47,11 +47,11 @@

    Synopsis

    -

    named-checkzone [-d] [-h] [-j] [-q] [-v] [-c class] [-f format] [-F format] [-i mode] [-k mode] [-m mode] [-M mode] [-n mode] [-s style] [-S mode] [-t directory] [-w directory] [-D] [-W mode] {zonename} {filename}

    -

    named-compilezone [-d] [-j] [-q] [-v] [-c class] [-C mode] [-f format] [-F format] [-i mode] [-k mode] [-m mode] [-n mode] [-o filename] [-s style] [-t directory] [-w directory] [-D] [-W mode] {-o filename} {zonename} {filename}

    +

    named-checkzone [-d] [-h] [-j] [-q] [-v] [-c class] [-f format] [-F format] [-i mode] [-k mode] [-m mode] [-M mode] [-n mode] [-o filename] [-r mode] [-s style] [-S mode] [-t directory] [-w directory] [-D] [-W mode] {zonename} {filename}

    +

    named-compilezone [-d] [-j] [-q] [-v] [-c class] [-C mode] [-f format] [-F format] [-i mode] [-k mode] [-m mode] [-n mode] [-r mode] [-s style] [-t directory] [-w directory] [-D] [-W mode] {-o filename} {zonename} {filename}

    -

    DESCRIPTION

    +

    DESCRIPTION

    named-checkzone checks the syntax and integrity of a zone file. It performs the same checks as named does when loading a @@ -71,7 +71,7 @@

    -

    OPTIONS

    +

    OPTIONS

    -d

    @@ -195,6 +195,14 @@ write to standard out. This is mandatory for named-compilezone.

    +
    -r mode
    +

    + Check for records that are treated as different by DNSSEC but + are semantically equal in plain DNS. + Possible modes are "fail", + "warn" (default) and + "ignore". +

    -s style

    Specify the style of the dumped zone file. @@ -257,14 +265,14 @@

    -

    RETURN VALUES

    +

    RETURN VALUES

    named-checkzone returns an exit status of 1 if errors were detected and 0 otherwise.

    -

    SEE ALSO

    +

    SEE ALSO

    named(8), named-checkconf(8), RFC 1035, @@ -272,7 +280,7 @@

    -

    AUTHOR

    +

    AUTHOR

    Internet Systems Consortium

    diff --git a/doc/arm/man.named-journalprint.html b/doc/arm/man.named-journalprint.html new file mode 100644 index 0000000..11d98a1 --- /dev/null +++ b/doc/arm/man.named-journalprint.html @@ -0,0 +1,112 @@ + + + + + +named-journalprint + + + + + + + + +
    +
    +
    +

    Name

    +

    named-journalprint — print zone journal in human-readable form

    +
    +
    +

    Synopsis

    +

    named-journalprint {journal}

    +
    +
    +

    DESCRIPTION

    +

    + named-journalprint + prints the contents of a zone journal file in a human-readable + form. +

    +

    + Journal files are automatically created by named + when changes are made to dynamic zones (e.g., by + nsupdate). They record each addition + or deletion of a resource record, in binary format, allowing the + changes to be re-applied to the zone when the server is + restarted after a shutdown or crash. By default, the name of + the journal file is formed by appending the extension + .jnl to the name of the corresponding + zone file. +

    +

    + named-journalprint converts the contents of a given + journal file into a human-readable text format. Each line begins + with "add" or "del", to indicate whether the record was added or + deleted, and continues with the resource record in master-file + format. +

    +
    +
    +

    SEE ALSO

    +

    + named(8), + nsupdate(8), + BIND 9 Administrator Reference Manual. +

    +
    +
    +

    AUTHOR

    +

    Internet Systems Consortium +

    +
    +
    + + + diff --git a/doc/arm/man.named.html b/doc/arm/man.named.html index 9a5617f..ac45d41 100644 --- a/doc/arm/man.named.html +++ b/doc/arm/man.named.html @@ -1,5 +1,5 @@ - + @@ -23,7 +23,7 @@ - +

    Synopsis

    -

    named [-4] [-6] [-c config-file] [-d debug-level] [-f] [-g] [-m flag] [-n #cpus] [-p port] [-s] [-S #max-socks] [-t directory] [-u user] [-v] [-V] [-x cache-file]

    +

    named [-4] [-6] [-c config-file] [-d debug-level] [-E engine-name] [-f] [-g] [-m flag] [-n #cpus] [-p port] [-s] [-S #max-socks] [-t directory] [-u user] [-v] [-V] [-x cache-file]

    -

    DESCRIPTION

    +

    DESCRIPTION

    named is a Domain Name System (DNS) server, part of the BIND 9 distribution from ISC. For more @@ -65,7 +65,7 @@

    -

    OPTIONS

    +

    OPTIONS

    -4

    @@ -97,6 +97,14 @@ Debugging traces from named become more verbose as the debug level increases.

    +
    -E engine-name
    +

    + Use a crypto hardware (OpenSSL engine) for the crypto operations + it supports, for instance re-signing with private keys from + a secure key store. When compiled with PKCS#11 support + engine-name + defaults to pkcs11, the empty name resets it to no engine. +

    -f

    Run the server in the foreground (i.e. do not daemonize). @@ -238,7 +246,7 @@

    -

    SIGNALS

    +

    SIGNALS

    In routine operation, signals should not be used to control the nameserver; rndc should be used @@ -259,7 +267,7 @@

    -

    CONFIGURATION

    +

    CONFIGURATION

    The named configuration file is too complex to describe in detail here. A complete description is provided @@ -276,7 +284,7 @@

    -

    FILES

    +

    FILES

    /etc/named.conf

    @@ -289,7 +297,7 @@

    -

    SEE ALSO

    +

    SEE ALSO

    RFC 1033, RFC 1034, RFC 1035, @@ -302,7 +310,7 @@

    -

    AUTHOR

    +

    AUTHOR

    Internet Systems Consortium

    @@ -314,14 +322,14 @@ Prev  UpNextNext named-checkzone  Homensupdatenamed-journalprint diff --git a/doc/arm/man.nsec3hash.html b/doc/arm/man.nsec3hash.html new file mode 100644 index 0000000..9f1fa6c --- /dev/null +++ b/doc/arm/man.nsec3hash.html @@ -0,0 +1,113 @@ + + + + + +nsec3hash + + + + + + + +
    +
    +
    +

    Name

    +

    nsec3hash — generate NSEC3 hash

    +
    +
    +

    Synopsis

    +

    nsec3hash {salt} {algorithm} {iterations} {domain}

    +
    +
    +

    DESCRIPTION

    +

    + nsec3hash generates an NSEC3 hash based on + a set of NSEC3 parameters. This can be used to check the validity + of NSEC3 records in a signed zone. +

    +
    +
    +

    ARGUMENTS

    +
    +
    salt
    +

    + The salt provided to the hash algorithm. +

    +
    algorithm
    +

    + A number indicating the hash algorithm. Currently the + only supported hash algorithm for NSEC3 is SHA-1, which is + indicated by the number 1; consequently "1" is the only + useful value for this argument. +

    +
    iterations
    +

    + The number of additional times the hash should be performed. +

    +
    domain
    +

    + The domain name to be hashed. +

    +
    +
    +
    +

    SEE ALSO

    +

    + BIND 9 Administrator Reference Manual, + RFC 5155. +

    +
    +
    +

    AUTHOR

    +

    Internet Systems Consortium +

    +
    +
    + + + diff --git a/doc/arm/man.nsupdate.html b/doc/arm/man.nsupdate.html index 597b2f1..c5d983a 100644 --- a/doc/arm/man.nsupdate.html +++ b/doc/arm/man.nsupdate.html @@ -1,5 +1,5 @@ - + @@ -22,7 +22,7 @@ - + @@ -31,7 +31,7 @@ nsupdate -Prev  +Prev  Manual pages  Next @@ -47,12 +47,12 @@

    Synopsis

    -

    nsupdate [-d] [-D] [[-g] | [-o] | [-y [hmac:]keyname:secret] | [-k keyfile]] [-t timeout] [-u udptimeout] [-r udpretries] [-R randomdev] [-v] [filename]

    +

    nsupdate [-d] [-D] [[-g] | [-o] | [-l] | [-y [hmac:]keyname:secret] | [-k keyfile]] [-t timeout] [-u udptimeout] [-r udpretries] [-R randomdev] [-v] [filename]

    -

    DESCRIPTION

    +

    DESCRIPTION

    nsupdate - is used to submit Dynamic DNS Update requests as defined in RFC2136 + is used to submit Dynamic DNS Update requests as defined in RFC 2136 to a name server. This allows resource records to be added or removed from a zone without manually editing the zone file. @@ -88,10 +88,14 @@ report additional debugging information to -d.

    + The -L option with an integer argument of zero or + higher sets the logging debug level. If zero, logging is disabled. +

    +

    Transaction signatures can be used to authenticate the Dynamic DNS updates. These use the TSIG resource record type described - in RFC2845 or the SIG(0) record described in RFC3535 and - RFC2931 or GSS-TSIG as described in RFC3645. TSIG relies on + in RFC 2845 or the SIG(0) record described in RFC 2535 and + RFC 2931 or GSS-TSIG as described in RFC 3645. TSIG relies on a shared secret that should only be known to nsupdate and the name server. Currently, the only supported encryption algorithm for TSIG is HMAC-MD5, @@ -108,44 +112,59 @@ record in a zone served by the name server. nsupdate does not read /etc/named.conf. - GSS-TSIG uses Kerberos credentials. +

    +

    + GSS-TSIG uses Kerberos credentials. Standard GSS-TSIG mode + is switched on with the -g flag. A + non-standards-compliant variant of GSS-TSIG used by Windows + 2000 can be switched on with the -o flag.

    nsupdate uses the -y or -k option to provide the shared secret needed to generate a TSIG record for authenticating Dynamic DNS update requests, default type - HMAC-MD5. These options are mutually exclusive. With the - -k option, nsupdate reads - the shared secret from the file keyfile, - whose name is of the form - K{name}.+157.+{random}.private. For - historical reasons, the file - K{name}.+157.+{random}.key must also be - present. When the -y option is used, a - signature is generated from + HMAC-MD5. These options are mutually exclusive. +

    +

    + When the -y option is used, a signature is + generated from [hmac:]keyname:secret. keyname is the name of the key, and - secret is the base64 encoded shared - secret. Use of the -y option is discouraged - because the shared secret is supplied as a command line - argument in clear text. This may be visible in the output - from - ps(1) or in a history file maintained by the user's - shell. + secret is the base64 encoded shared secret. + Use of the -y option is discouraged because the + shared secret is supplied as a command line argument in clear text. + This may be visible in the output from + ps(1) + or in a history file maintained by the user's shell.

    + With the + -k option, nsupdate reads + the shared secret from the file keyfile. + Keyfiles may be in two formats: a single file containing + a named.conf-format key + statement, which may be generated automatically by + ddns-confgen, or a pair of files whose names are + of the format K{name}.+157.+{random}.key and + K{name}.+157.+{random}.private, which can be + generated by dnssec-keygen. The -k may also be used to specify a SIG(0) key used to authenticate Dynamic DNS update requests. In this case, the key specified is not an HMAC-MD5 key.

    - The -g and -o specify that - GSS-TSIG is to be used. The -o should only - be used with old Microsoft Windows 2000 servers. + nsupdate can be run in a local-host only mode + using the -l flag. This sets the server address to + localhost (disabling the server so that the server + address cannot be overridden). Connections to the local server will + use a TSIG key found in /var/run/named/session.key, + which is automatically generated by named if any + local master zone has set update-policy to + local. The location of this key file can be + overridden with the -k option.

    - By default, - nsupdate + By default, nsupdate uses UDP to send update requests to the name server unless they are too large to fit in a UDP request in which case TCP will be used. The @@ -156,6 +175,10 @@ This may be preferable when a batch of update requests is made.

    + The -p sets the default port number to use for + connections to a name server. The default is 53. +

    +

    The -t option sets the maximum time an update request can take before it is aborted. The default is 300 seconds. Zero can be @@ -187,7 +210,7 @@

    -

    INPUT FORMAT

    +

    INPUT FORMAT

    nsupdate reads input from filename @@ -475,7 +498,7 @@

    -

    EXAMPLES

    +

    EXAMPLES

    The examples below show how nsupdate @@ -522,19 +545,23 @@ If there are, the update request fails. If this name does not exist, a CNAME for it is added. This ensures that when the CNAME is added, it cannot conflict with the - long-standing rule in RFC1034 that a name must not exist as any other + long-standing rule in RFC 1034 that a name must not exist as any other record type if it exists as a CNAME. - (The rule has been updated for DNSSEC in RFC2535 to allow CNAMEs to have + (The rule has been updated for DNSSEC in RFC 2535 to allow CNAMEs to have RRSIG, DNSKEY and NSEC records.)

    -

    FILES

    +

    FILES

    /etc/resolv.conf

    used to identify default name server

    +
    /var/run/named/session.key
    +

    + sets the default TSIG key for use in local-only mode +

    K{name}.+157.+{random}.key

    base-64 encoding of HMAC-MD5 key created by @@ -548,20 +575,22 @@

    -

    SEE ALSO

    -

    RFC2136, - RFC3007, - RFC2104, - RFC2845, - RFC1034, - RFC2535, - RFC2931, +

    SEE ALSO

    +

    + RFC 2136, + RFC 3007, + RFC 2104, + RFC 2845, + RFC 1034, + RFC 2535, + RFC 2931, named(8), + ddns-confgen(8), dnssec-keygen(8).

    -

    BUGS

    +

    BUGS

    The TSIG key is redundantly stored in two separate files. This is a consequence of nsupdate using the DST library @@ -575,14 +604,14 @@ +Prev  +named-journalprint  diff --git a/doc/arm/man.rndc-confgen.html b/doc/arm/man.rndc-confgen.html index 523ad92..f441b93 100644 --- a/doc/arm/man.rndc-confgen.html +++ b/doc/arm/man.rndc-confgen.html @@ -1,5 +1,5 @@ - + @@ -23,6 +23,7 @@ + - +
    -Prev  Up  Next
    -named  Home  rndc Prev  Manual pages  Next +


    @@ -48,7 +50,7 @@

    rndc-confgen [-a] [-b keysize] [-c keyfile] [-h] [-k keyname] [-p port] [-r randomfile] [-s address] [-t chrootdir] [-u user]

    -

    DESCRIPTION

    +

    DESCRIPTION

    rndc-confgen generates configuration files for rndc. It can be used as a @@ -64,7 +66,7 @@

    -

    OPTIONS

    +

    OPTIONS

    -a
    @@ -171,7 +173,7 @@
    -

    EXAMPLES

    +

    EXAMPLES

    To allow rndc to be used with no manual configuration, run @@ -188,7 +190,7 @@

    -

    SEE ALSO

    +

    SEE ALSO

    rndc(8), rndc.conf(5), named(8), @@ -196,7 +198,7 @@

    -

    AUTHOR

    +

    AUTHOR

    Internet Systems Consortium

    @@ -208,13 +210,15 @@ Prev  Up -  + Next + rndc.conf  Home -  + ddns-confgen + diff --git a/doc/arm/man.rndc.conf.html b/doc/arm/man.rndc.conf.html index f454cf4..456ac38 100644 --- a/doc/arm/man.rndc.conf.html +++ b/doc/arm/man.rndc.conf.html @@ -1,5 +1,5 @@ - + @@ -50,7 +50,7 @@

    rndc.conf

    -

    DESCRIPTION

    +

    DESCRIPTION

    rndc.conf is the configuration file for rndc, the BIND 9 name server control utility. This file has a similar structure and syntax to @@ -135,7 +135,7 @@

    -

    EXAMPLE

    +

    EXAMPLE

           options {
             default-server  localhost;
    @@ -209,7 +209,7 @@
         

    -

    NAME SERVER CONFIGURATION

    +

    NAME SERVER CONFIGURATION

    The name server must be configured to accept rndc connections and to recognize the key specified in the rndc.conf @@ -219,7 +219,7 @@

    -

    SEE ALSO

    +

    SEE ALSO

    rndc(8), rndc-confgen(8), mmencode(1), @@ -227,7 +227,7 @@

    -

    AUTHOR

    +

    AUTHOR

    Internet Systems Consortium

    diff --git a/doc/arm/man.rndc.html b/doc/arm/man.rndc.html index 0a6c65c..58fa67e 100644 --- a/doc/arm/man.rndc.html +++ b/doc/arm/man.rndc.html @@ -1,5 +1,5 @@ - + @@ -50,7 +50,7 @@

    rndc [-b source-address] [-c config-file] [-k key-file] [-s server] [-p port] [-V] [-y key_id] {command}

    -

    DESCRIPTION

    +

    DESCRIPTION

    rndc controls the operation of a name server. It supersedes the ndc utility @@ -79,7 +79,7 @@

    -

    OPTIONS

    +

    OPTIONS

    -b source-address

    @@ -151,7 +151,7 @@

    -

    LIMITATIONS

    +

    LIMITATIONS

    rndc does not yet support all the commands of the BIND 8 ndc utility. @@ -165,7 +165,7 @@

    -

    SEE ALSO

    +

    SEE ALSO

    rndc.conf(5), rndc-confgen(8), named(8), @@ -175,7 +175,7 @@

    -

    AUTHOR

    +

    AUTHOR

    Internet Systems Consortium

    diff --git a/doc/arm/managed-keys.xml b/doc/arm/managed-keys.xml new file mode 100644 index 0000000..f1e06f3 --- /dev/null +++ b/doc/arm/managed-keys.xml @@ -0,0 +1,100 @@ + + + + + + + Dynamic Trust Anchor Management + BIND 9.7.0 introduces support for RFC 5011, dynamic trust + anchor management. Using this feature allows + named to keep track of changes to critical + DNSSEC keys without any need for the operator to make changes to + configuration files. + + Validating Resolver + + To configure a validating resolver to use RFC 5011 to + maintain a trust anchor, configure the trust anchor using a + managed-keys statement. Information about + this can be found in + . + + + + Authoritative Server + To set up an authoritative zone for RFC 5011 trust anchor + maintenance, generate two (or more) key signing keys (KSKs) for + the zone. Sign the zone with one of them; this is the "active" + KSK. All KSK's which do not sign the zone are "stand-by" + keys. + Any validating resolver which is configured to use the + active KSK as an RFC 5011-managed trust anchor will take note + of the stand-by KSKs in the zone's DNSKEY RRset, and store them + for future reference. The resolver will recheck the zone + periodically, and after 30 days, if the new key is still there, + then the key will be accepted by the resolver as a valid trust + anchor for the zone. Any time after this 30-day acceptance + timer has completed, the active KSK can be revoked, and the + zone can be "rolled over" to the newly accepted key. + The easiest way to place a stand-by key in a zone is to + use the "smart signing" features of + dnssec-keygen and + dnssec-signzone. If a key with a publication + date in the past, but an activation date which is unset or in + the future, " + dnssec-signzone -S" will include the DNSKEY + record in the zone, but will not sign with it: + +$ dnssec-keygen -K keys -f KSK -P now -A now+2y example.net +$ dnssec-signzone -S -K keys example.net + + To revoke a key, the new command + dnssec-revoke has been added. This adds the + REVOKED bit to the key flags and re-generates the + K*.key and + K*.private files. + After revoking the active key, the zone must be signed + with both the revoked KSK and the new active KSK. (Smart + signing takes care of this automatically.) + Once a key has been revoked and used to sign the DNSKEY + RRset in which it appears, that key will never again be + accepted as a valid trust anchor by the resolver. However, + validation can proceed using the new active key (which had been + accepted by the resolver when it was a stand-by key). + See RFC 5011 for more details on key rollover + scenarios. + When a key has been revoked, its key ID changes, + increasing by 128, and wrapping around at 65535. So, for + example, the key "Kexample.com.+005+10000" becomes + "Kexample.com.+005+10128". + If two keys have ID's exactly 128 apart, and one is + revoked, then the two key ID's will collide, causing several + problems. To prevent this, + dnssec-keygen will not generate a new key if + another key is present which may collide. This checking will + only occur if the new keys are written to the same directory + which holds all other keys in use for that zone. + Older versions of BIND 9 did not have this precaution. + Exercise caution if using key revocation on keys that were + generated by previous releases, or if using keys stored in + multiple directories or on multiple machines. + It is expected that a future release of BIND 9 will + address this problem in a different way, by storing revoked + keys with their original unrevoked key ID's. + + diff --git a/doc/arm/pkcs11.xml b/doc/arm/pkcs11.xml new file mode 100644 index 0000000..23bf5fd --- /dev/null +++ b/doc/arm/pkcs11.xml @@ -0,0 +1,390 @@ +]> + + + + + + PKCS #11 (Cryptoki) support + PKCS #11 (Public Key Cryptography Standard #11) defines a + platform- independent API for the control of hardware security + modules (HSMs) and other cryptographic support devices. + BIND 9 is known to work with two HSMs: The Sun SCA 6000 + cryptographic acceleration board, tested under Solaris x86, and + the AEP Keyper network-attached key storage device, tested with + Debian Linux, Solaris x86 and Windows Server 2003. + + Prerequisites + See the HSM vendor documentation for information about + installing, initializing, testing and troubleshooting the + HSM. + BIND 9 uses OpenSSL for cryptography, but stock OpenSSL + does not yet fully support PKCS #11. However, a PKCS #11 engine + for OpenSSL is available from the OpenSolaris project. It has + been modified by ISC to work with with BIND 9, and to provide + new features such as PIN management and key by + reference. + The patched OpenSSL depends on a "PKCS #11 provider". + This is a shared library object, providing a low-level PKCS #11 + interface to the HSM hardware. It is dynamically loaded by + OpenSSL at runtime. The PKCS #11 provider comes from the HSM + vendor, and and is specific to the HSM to be controlled. + There are two "flavors" of PKCS #11 support provided by + the patched OpenSSL, one of which must be chosen at + configuration time. The correct choice depends on the HSM + hardware: + + + Use 'crypto-accelerator' with HSMs that have hardware + cryptographic acceleration features, such as the SCA 6000 + board. This causes OpenSSL to run all supported + cryptographic operations in the HSM. + + + Use 'sign-only' with HSMs that are designed to + function primarily as secure key storage devices, but lack + hardware acceleration. These devices are highly secure, but + are not necessarily any faster at cryptography than the + system CPU — often, they are slower. It is therefore + most efficient to use them only for those cryptographic + functions that require access to the secured private key, + such as zone signing, and to use the system CPU for all + other computationally-intensive operations. The AEP Keyper + is an example of such a device. + + + The modified OpenSSL code is included in the BIND 9.7.0 + release, in the form of a context diff against the latest OpenSSL. + + + The latest OpenSSL version at the time of the BIND release + is 0.9.8l. + ISC will provide an updated patch as new versions of OpenSSL + are released. The version number in the following examples + is expected to change. + + Before building BIND 9 with PKCS #11 support, it will be + necessary to build OpenSSL with this patch in place and inform + it of the path to the HSM-specific PKCS #11 provider + library. + Obtain OpenSSL 0.9.8l: + +$ wget http://www.openssl.org/source/openssl-0.9.8l.tar.gz + + Extract the tarball: + +$ tar zxf openssl-0.9.8l.tar.gz + + Apply the patch from the BIND 9 release: + +$ patch -p1 -d openssl-0.9.8l \ + < bind-9.7.0/bin/pkcs11/openssl-0.9.8l-patch + + (Note that the patch file may not be compatible with the + "patch" utility on all operating systems. You may need to + install GNU patch.) + When building OpenSSL, place it in a non-standard + location so that it does not interfere with OpenSSL libraries + elsewhere on the system. In the following examples, we choose + to install into "/opt/pkcs11/usr". We will use this location + when we configure BIND 9. + + + Building OpenSSL for the AEP Keyper on Linux + The AEP Keyper is a highly secure key storage device, + but does not provide hardware cryptographic acceleration. It + can carry out cryptographic operations, but it is probably + slower than your system's CPU. Therefore, we choose the + 'sign-only' flavor when building OpenSSL. + The Keyper-specific PKCS #11 provider library is + delivered with the Keyper software. In this example, we place + it /opt/pkcs11/usr/lib: + +$ cp pkcs11.GCC4.0.2.so.4.05 /opt/pkcs11/usr/lib/libpkcs11.so + + This library is only available for Linux as a 32-bit + binary. If we are compiling on a 64-bit Linux system, it is + necessary to force a 32-bit build, by specifying -m32 in the + build options. + Finally, the Keyper library requires threads, so we + must specify -pthread. + +$ cd openssl-0.9.8l +$ ./Configure linux-generic32 -m32 -pthread \ + --pk11-libname=/opt/pkcs11/usr/lib/libpkcs11.so \ + --pk11-flavor=sign-only \ + --prefix=/opt/pkcs11/usr + + After configuring, run "make" + and "make test". If "make + test" fails with "pthread_atfork() not found", you forgot to + add the -pthread above. + + + + Building OpenSSL for the SCA 6000 on Solaris + The SCA-6000 PKCS #11 provider is installed as a system + library, libpkcs11. It is a true crypto accelerator, up to 4 + times faster than any CPU, so the flavor shall be + 'crypto-accelerator'. + In this example, we are building on Solaris x86 on an + AMD64 system. + +$ cd openssl-0.9.8l +$ ./Configure solaris64-x86_64-cc \ + --pk11-libname=/usr/lib/64/libpkcs11.so \ + --pk11-flavor=crypto-accelerator \ + --prefix=/opt/pkcs11/usr + + (For a 32-bit build, use "solaris-x86-cc" and + /usr/lib/libpkcs11.so.) + After configuring, run + make and + make test. + Once you have built OpenSSL, run + "apps/openssl engine pkcs11" to confirm + that PKCS #11 support was compiled in correctly. The output + should be one of the following lines, depending on the flavor + selected: + + (pkcs11) PKCS #11 engine support (sign only) + + Or: + + (pkcs11) PKCS #11 engine support (crypto accelerator) + + Next, run + "apps/openssl engine pkcs11 -t". This will + attempt to initialize the PKCS #11 engine. If it is able to + do so successfully, it will report + [ available ]. + If the output is correct, run + "make install" which will install the + modified OpenSSL suite to + /opt/pkcs11/usr. + + + + Building BIND 9 with PKCS#11 + When building BIND 9, the location of the custom-built + OpenSSL library must be specified via configure. + + + Configuring BIND 9 for Linux + To link with the PKCS #11 provider, threads must be + enabled in the BIND 9 build. + The PKCS #11 library for the AEP Keyper is currently + only available as a 32-bit binary. If we are building on a + 64-bit host, we must force a 32-bit build by adding "-m32" to + the CC options on the "configure" command line. + +$ cd ../bind-9.7.0 +$ ./configure CC="gcc -m32" --enable-threads \ + --with-openssl=/opt/pkcs11/usr \ + --with-pkcs11=/opt/pkcs11/usr/lib/libpkcs11.so + + + + + Configuring BIND 9 for Solaris + To link with the PKCS #11 provider, threads must be + enabled in the BIND 9 build. + +$ cd ../bind-9.7.0 +$ ./configure CC="cc -xarch=amd64" --enable-threads \ + --with-openssl=/opt/pkcs11/usr \ + --with-pkcs11=/usr/lib/64/libpkcs11.so + + (For a 32-bit build, omit CC="cc -xarch=amd64".) + If configure complains about OpenSSL not working, you + may have a 32/64-bit architecture mismatch. Or, you may have + incorrectly specified the path to OpenSSL (it should be the + same as the --prefix argument to the OpenSSL + Configure). + + After configuring, run + "make", + "make test" and + "make install". + + + PKCS #11 Tools + BIND 9 includes a minimal set of tools to operate the + HSM, including + pkcs11-keygen to generate a new key pair + within the HSM, + pkcs11-list to list objects currently + available, and + pkcs11-destroy to remove objects. + In UNIX/Linux builds, these tools are built only if BIND + 9 is configured with the --with-pkcs11 option. (NOTE: If + --with-pkcs11 is set to "yes", rather than to the path of the + PKCS #11 provider, then the tools will be built but the + provider will be left undefined. Use the -m option or the + PKCS11_PROVIDER environment variable to specify the path to the + provider.) + + + Using the HSM + First, we must set up the runtime environment so the + OpenSSL and PKCS #11 libraries can be loaded: + +$ export LD_LIBRARY_PATH=/opt/pkcs11/usr/lib:${LD_LIBRARY_PATH} + + When operating an AEP Keyper, it is also necessary to + specify the location of the "machine" file, which stores + information about the Keyper for use by PKCS #11 provider + library. If the machine file is in + /opt/Keyper/PKCS11Provider/machine, + use: + +$ export KEYPER_LIBRARY_PATH=/opt/Keyper/PKCS11Provider + + + These environment variables must be set whenever running + any tool that uses the HSM, including + pkcs11-keygen, + pkcs11-list, + pkcs11-destroy, + dnssec-keyfromlabel, + dnssec-signzone, + dnssec-keygen(which will use the HSM for + random number generation), and + named. + We can now create and use keys in the HSM. In this case, + we will create a 2048 bit key and give it the label + "sample-ksk": + +$ pkcs11-keygen -b 2048 -l sample-ksk + + To confirm that the key exists: + +$ pkcs11-list +Enter PIN: +object[0]: handle 2147483658 class 3 label[8] 'sample-ksk' id[0] +object[1]: handle 2147483657 class 2 label[8] 'sample-ksk' id[0] + + Before using this key to sign a zone, we must create a + pair of BIND 9 key files. The "dnssec-keyfromlabel" utility + does this. In this case, we will be using the HSM key + "sample-ksk" as the key-signing key for "example.net": + +$ dnssec-keyfromlabel -l sample-ksk -f KSK example.net + + The resulting K*.key and K*.private files can now be used + to sign the zone. Unlike normal K* files, which contain both + public and private key data, these files will contain only the + public key data, plus an identifier for the private key which + remains stored within the HSM. The HSM handles signing with the + private key. + If you wish to generate a second key in the HSM for use + as a zone-signing key, follow the same procedure above, using a + different keylabel, a smaller key size, and omitting "-f KSK" + from the dnssec-keyfromlabel arguments: + +$ pkcs11-keygen -b 1024 -l sample-zsk +$ dnssec-keyfromlabel -l sample-zsk example.net + + Alternatively, you may prefer to generate a conventional + on-disk key, using dnssec-keygen: + +$ dnssec-keygen example.net + + This provides less security than an HSM key, but since + HSMs can be slow or cumbersome to use for security reasons, it + may be more efficient to reserve HSM keys for use in the less + frequent key-signing operation. The zone-signing key can be + rolled more frequently, if you wish, to compensate for a + reduction in key security. + Now you can sign the zone. (Note: If not using the -S + option to + dnssec-signzone, it will be necessary to add + the contents of both + K*.key files to the zone master file before + signing it.) + +$ dnssec-signzone -S example.net +Enter PIN: +Verifying the zone using the following algorithms: +NSEC3RSASHA1. +Zone signing complete: +Algorithm: NSEC3RSASHA1: ZSKs: 1, KSKs: 1 active, 0 revoked, 0 stand-by +example.net.signed + + + + Specifying the engine on the command line + The OpenSSL engine can be specified in + named and all of the BIND + dnssec-* tools by using the "-E + <engine>" command line option. If BIND 9 is built with + the --with-pkcs11 option, this option defaults to "pkcs11". + Specifying the engine will generally not be necessary unless + for some reason you wish to use a different OpenSSL + engine. + If you wish to disable use of the "pkcs11" engine — + for troubleshooting purposes, or because the HSM is unavailable + — set the engine to the empty string. For example: + +$ dnssec-signzone -E '' -S example.net + + This causes + dnssec-signzone to run as if it were compiled + without the --with-pkcs11 option. + + + Running named with automatic zone re-signing + If you want + named to dynamically re-sign zones using HSM + keys, and/or to to sign new records inserted via nsupdate, then + named must have access to the HSM PIN. This can be accomplished + by placing the PIN into the openssl.cnf file (in the above + examples, + /opt/pkcs11/usr/ssl/openssl.cnf). + The location of the openssl.cnf file can be overridden by + setting the OPENSSL_CONF environment variable before running + named. + Sample openssl.cnf: + + openssl_conf = openssl_def + [ openssl_def ] + engines = engine_section + [ engine_section ] + pkcs11 = pkcs11_section + [ pkcs11_section ] + PIN = <PLACE PIN HERE> + + This will also allow the dnssec-* tools to access the HSM + without PIN entry. (The pkcs11-* tools access the HSM directly, + not via OpenSSL, so a PIN will still be required to use + them.) + + + Placing the HSM's PIN in a text file in + this manner may reduce the security advantage of using an + HSM. Be sure this is what you want to do before configuring + OpenSSL in this way. + + + + + diff --git a/doc/misc/Makefile.in b/doc/misc/Makefile.in index 5a671b8..6468176 100644 --- a/doc/misc/Makefile.in +++ b/doc/misc/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.7.252.2 2009-07-11 23:47:17 tbox Exp $ +# $Id: Makefile.in,v 1.9 2009-07-10 23:47:58 tbox Exp $ srcdir = @srcdir@ VPATH = @srcdir@ diff --git a/doc/misc/options b/doc/misc/options index a6b2dcd..673abf7 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -44,6 +44,9 @@ lwres { view ; }; +managed-keys { + ; ... }; + masters [ port ] { ( | [ port ] | [ port ] ) [ key ]; ... }; @@ -52,6 +55,7 @@ options { acache-enable ; additional-from-auth ; additional-from-cache ; + allow-new-zones ; allow-notify { ; ... }; allow-query { ; ... }; allow-query-cache { ; ... }; @@ -68,11 +72,14 @@ options { alt-transfer-source ( | * ) [ port ( | * ) ]; alt-transfer-source-v6 ( | * ) [ port ( | * ) ]; + attach-cache ; auth-nxdomain ; // default changed avoid-v4-udp-ports { ; ... }; avoid-v6-udp-ports { ; ... }; + bindkeys-file ; blackhole { ; ... }; cache-file ; + check-dup-records ( fail | warn | ignore ); check-integrity ; check-mx ( fail | warn | ignore ); check-mx-cname ( fail | warn | ignore ); @@ -85,15 +92,31 @@ options { coresize ; datasize ; deallocate-on-exit ; // obsolete + deny-answer-addresses { ; ... } [ + except-from { ; ... } ]; + deny-answer-aliases { ; ... } [ except-from { + ; ... } ]; dialup ; directory ; disable-algorithms { ; ... }; disable-empty-zone ; + dns64 { + break-dnssec ; + clients { ; ... }; + exclude { ; ... }; + mapped { ; ... }; + recursive-only ; + suffix ; + }; + dns64-contact ; + dns64-server ; dnssec-accept-expired ; + dnssec-dnskey-kskonly ; dnssec-enable ; dnssec-lookaside trust-anchor ; dnssec-must-be-secure ; - dnssec-validation ; + dnssec-secure-to-insecure ; + dnssec-validation ( yes | no | auto ); dual-stack-servers [ port ] { ( [ port ] | [ port ] | [ port ] ); ... }; @@ -105,6 +128,8 @@ options { fake-iquery ; // obsolete fetch-glue ; // obsolete files ; + filter-aaaa { ; ... }; // not configured + filter-aaaa-on-v4 ; // not configured flush-zones-on-shutdown ; forward ( first | only ); forwarders [ port ] { ( | ) @@ -121,6 +146,7 @@ options { listen-on [ port ] { ; ... }; listen-on-v6 [ port ] { ; ... }; maintain-ixfr-base ; // obsolete + managed-keys-directory ; masterfile-format ( text | raw ); match-mapped-addresses ; max-acache-size ; @@ -168,13 +194,22 @@ options { request-ixfr ; request-nsid ; reserved-sockets ; + resolver-query-timeout ; + response-policy { + zone [ policy ( given | no-op | nxdomain | nodata + | cname ) ]; + }; rfc2308-type1 ; // not yet implemented root-delegation-only [ exclude { ; ... } ]; rrset-order { [ class ] [ type ] [ name ] ; ... }; + secroots-file ; serial-queries ; // obsolete serial-query-rate ; server-id ( | none | hostname ); + session-keyalg ; + session-keyfile ( | none ); + session-keyname ; sig-signing-nodes ; sig-signing-signatures ; sig-signing-type ; @@ -189,6 +224,7 @@ options { tkey-dhkey ; tkey-domain ; tkey-gssapi-credential ; + tkey-gssapi-keytab ; topology { ; ... }; // not implemented transfer-format ( many-answers | one-answer ); transfer-source ( | * ) [ port ( | * ) ]; @@ -242,6 +278,7 @@ view { acache-enable ; additional-from-auth ; additional-from-cache ; + allow-new-zones ; allow-notify { ; ... }; allow-query { ; ... }; allow-query-cache { ; ... }; @@ -258,8 +295,10 @@ view { alt-transfer-source ( | * ) [ port ( | * ) ]; alt-transfer-source-v6 ( | * ) [ port ( | * ) ]; + attach-cache ; auth-nxdomain ; // default changed cache-file ; + check-dup-records ( fail | warn | ignore ); check-integrity ; check-mx ( fail | warn | ignore ); check-mx-cname ( fail | warn | ignore ); @@ -270,17 +309,33 @@ view { cleaning-interval ; clients-per-query ; database ; + deny-answer-addresses { ; ... } [ + except-from { ; ... } ]; + deny-answer-aliases { ; ... } [ except-from { + ; ... } ]; dialup ; disable-algorithms { ; ... }; disable-empty-zone ; dlz { database ; }; + dns64 { + break-dnssec ; + clients { ; ... }; + exclude { ; ... }; + mapped { ; ... }; + recursive-only ; + suffix ; + }; + dns64-contact ; + dns64-server ; dnssec-accept-expired ; + dnssec-dnskey-kskonly ; dnssec-enable ; dnssec-lookaside trust-anchor ; dnssec-must-be-secure ; - dnssec-validation ; + dnssec-secure-to-insecure ; + dnssec-validation ( yes | no | auto ); dual-stack-servers [ port ] { ( [ port ] | [ port ] | [ port ] ); ... }; @@ -289,6 +344,8 @@ view { empty-server ; empty-zones-enable ; fetch-glue ; // obsolete + filter-aaaa { ; ... }; // not configured + filter-aaaa-on-v4 ; // not configured forward ( first | only ); forwarders [ port ] { ( | ) [ port ]; ... }; @@ -300,6 +357,8 @@ view { key-directory ; lame-ttl ; maintain-ixfr-base ; // obsolete + managed-keys { + ; ... }; masterfile-format ( text | raw ); match-clients { ; ... }; match-destinations { ; ... }; @@ -338,6 +397,11 @@ view { recursion ; request-ixfr ; request-nsid ; + resolver-query-timeout ; + response-policy { + zone [ policy ( given | no-op | nxdomain | nodata + | cname ) ]; + }; rfc2308-type1 ; // not yet implemented root-delegation-only [ exclude { ; ... } ]; rrset-order { [ class ] [ type ] [ name @@ -395,6 +459,8 @@ view { | * ) ]; alt-transfer-source-v6 ( | * ) [ port ( | * ) ]; + auto-dnssec ( allow | maintain | create | off ); + check-dup-records ( fail | warn | ignore ); check-integrity ; check-mx ( fail | warn | ignore ); check-mx-cname ( fail | warn | ignore ); @@ -405,6 +471,8 @@ view { database ; delegation-only ; dialup ; + dnssec-dnskey-kskonly ; + dnssec-secure-to-insecure ; file ; forward ( first | only ); forwarders [ port ] { ( | @@ -440,6 +508,9 @@ view { nsec3-test-zone ; // test only pubkey ; // obsolete + server-addresses { ( | ) [ + port ]; ... }; + server-names { ; ... }; sig-signing-nodes ; sig-signing-signatures ; sig-signing-type ; @@ -449,13 +520,14 @@ view { transfer-source-v6 ( | * ) [ port ( | * ) ]; try-tcp-refresh ; - type ( master | slave | stub | hint | forward | - delegation-only ); + type ( master | slave | stub | static-stub | hint | forward + | delegation-only ); update-check-ksk ; - update-policy { ( grant | deny ) ( name | - subdomain | wildcard | self | selfsub | selfwild | + update-policy ( local | { ( grant | deny ) ( name + | subdomain | wildcard | self | selfsub | selfwild | krb5-self | ms-self | krb5-subdomain | ms-subdomain | - tcp-self | 6to4-self ) ; ... }; + tcp-self | 6to4-self | zonesub | external ) [ + ] ; ... }; use-alt-transfer-source ; zero-no-soa-ttl ; zone-statistics ; @@ -475,6 +547,8 @@ zone { alt-transfer-source ( | * ) [ port ( | * ) ]; alt-transfer-source-v6 ( | * ) [ port ( | * ) ]; + auto-dnssec ( allow | maintain | create | off ); + check-dup-records ( fail | warn | ignore ); check-integrity ; check-mx ( fail | warn | ignore ); check-mx-cname ( fail | warn | ignore ); @@ -485,6 +559,8 @@ zone { database ; delegation-only ; dialup ; + dnssec-dnskey-kskonly ; + dnssec-secure-to-insecure ; file ; forward ( first | only ); forwarders [ port ] { ( | ) @@ -517,6 +593,9 @@ zone { notify-to-soa ; nsec3-test-zone ; // test only pubkey ; // obsolete + server-addresses { ( | ) [ port + ]; ... }; + server-names { ; ... }; sig-signing-nodes ; sig-signing-signatures ; sig-signing-type ; @@ -524,12 +603,13 @@ zone { transfer-source ( | * ) [ port ( | * ) ]; transfer-source-v6 ( | * ) [ port ( | * ) ]; try-tcp-refresh ; - type ( master | slave | stub | hint | forward | delegation-only ); + type ( master | slave | stub | static-stub | hint | forward | + delegation-only ); update-check-ksk ; - update-policy { ( grant | deny ) ( name | subdomain | - wildcard | self | selfsub | selfwild | krb5-self | ms-self | - krb5-subdomain | ms-subdomain | tcp-self | 6to4-self ) - ; ... }; + update-policy ( local | { ( grant | deny ) ( name | + subdomain | wildcard | self | selfsub | selfwild | krb5-self | + ms-self | krb5-subdomain | ms-subdomain | tcp-self | 6to4-self + | zonesub | external ) [ ] ; ... }; use-alt-transfer-source ; zero-no-soa-ttl ; zone-statistics ; diff --git a/lib/bind9/Makefile.in b/lib/bind9/Makefile.in index e37d524..ffc2ad9 100644 --- a/lib/bind9/Makefile.in +++ b/lib/bind9/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 2001 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.11 2007-06-19 23:47:16 tbox Exp $ +# $Id: Makefile.in,v 1.14 2009-12-05 23:31:40 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ diff --git a/lib/bind9/api b/lib/bind9/api index f3b0f9f..78dd0b4 100644 --- a/lib/bind9/api +++ b/lib/bind9/api @@ -1,3 +1,3 @@ -LIBINTERFACE = 50 -LIBREVISION = 4 +LIBINTERFACE = 80 +LIBREVISION = 1 LIBAGE = 0 diff --git a/lib/bind9/check.c b/lib/bind9/check.c index 76ca510..6fa9aa9 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2001-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: check.c,v 1.95.12.6 2010-03-04 23:47:53 tbox Exp $ */ +/* $Id: check.c,v 1.125 2011-01-07 23:47:07 tbox Exp $ */ /*! \file */ @@ -103,7 +103,7 @@ check_orderent(const cfg_obj_t *ent, isc_log_t *logctx) { isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "rrset-order: invalid name '%s'", str); @@ -202,7 +202,7 @@ check_dual_stack(const cfg_obj_t *options, isc_log_t *logctx) { dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); tresult = dns_name_fromtext(name, &buffer, dns_rootname, - ISC_FALSE, NULL); + 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "bad name '%s'", str); @@ -265,7 +265,7 @@ disabled_algorithms(const cfg_obj_t *disabled, isc_log_t *logctx) { str = cfg_obj_asstring(obj); isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); - tresult = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL); + tresult = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "bad domain name '%s'", str); @@ -352,7 +352,7 @@ mustbesecure(const cfg_obj_t *secure, isc_symtab_t *symtab, isc_log_t *logctx, str = cfg_obj_asstring(obj); isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); - result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "bad domain name '%s'", str); @@ -407,7 +407,7 @@ check_viewacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions, static const char *acls[] = { "allow-query", "allow-query-on", "allow-query-cache", "allow-query-cache-on", "blackhole", "match-clients", "match-destinations", - "sortlist", NULL }; + "sortlist", "filter-aaaa", NULL }; while (acls[i] != NULL) { tresult = checkacl(acls[i++], actx, NULL, voptions, config, @@ -418,6 +418,106 @@ check_viewacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions, return (result); } +static const unsigned char zeros[16]; + +static isc_result_t +check_dns64(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions, + const cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx) +{ + isc_result_t result = ISC_R_SUCCESS; + const cfg_obj_t *dns64 = NULL; + const cfg_obj_t *options; + const cfg_listelt_t *element; + const cfg_obj_t *map, *obj; + isc_netaddr_t na, sa; + unsigned int prefixlen; + int nbytes; + int i; + + static const char *acls[] = { "client", "exclude", "mapped", NULL}; + + if (voptions != NULL) + cfg_map_get(voptions, "dns64", &dns64); + if (config != NULL && dns64 == NULL) { + options = NULL; + cfg_map_get(config, "options", &options); + if (options != NULL) + cfg_map_get(options, "dns64", &dns64); + } + if (dns64 == NULL) + return (ISC_R_SUCCESS); + + for (element = cfg_list_first(dns64); + element != NULL; + element = cfg_list_next(element)) + { + map = cfg_listelt_value(element); + obj = cfg_map_getname(map); + + cfg_obj_asnetprefix(obj, &na, &prefixlen); + if (na.family != AF_INET6) { + cfg_obj_log(map, logctx, ISC_LOG_ERROR, + "dns64 requires a IPv6 prefix"); + result = ISC_R_FAILURE; + continue; + } + + if (prefixlen != 32 && prefixlen != 40 && prefixlen != 48 && + prefixlen != 56 && prefixlen != 64 && prefixlen != 96) { + cfg_obj_log(map, logctx, ISC_LOG_ERROR, + "bad prefix length %u [32/40/48/56/64/96]", + prefixlen); + result = ISC_R_FAILURE; + continue; + } + + for (i = 0; acls[i] != NULL; i++) { + obj = NULL; + (void)cfg_map_get(map, acls[i], &obj); + if (obj != NULL) { + dns_acl_t *acl = NULL; + isc_result_t tresult; + + tresult = cfg_acl_fromconfig(obj, config, + logctx, actx, + mctx, 0, &acl); + if (acl != NULL) + dns_acl_detach(&acl); + if (tresult != ISC_R_SUCCESS) + result = tresult; + } + } + + obj = NULL; + (void)cfg_map_get(map, "suffix", &obj); + if (obj != NULL) { + isc_netaddr_fromsockaddr(&sa, cfg_obj_assockaddr(obj)); + if (sa.family != AF_INET6) { + cfg_obj_log(map, logctx, ISC_LOG_ERROR, + "dns64 requires a IPv6 suffix"); + result = ISC_R_FAILURE; + continue; + } + nbytes = prefixlen / 8 + 4; + if (prefixlen >= 32 && prefixlen <= 64) + nbytes++; + if (memcmp(sa.type.in6.s6_addr, zeros, nbytes) != 0) { + char netaddrbuf[ISC_NETADDR_FORMATSIZE]; + isc_netaddr_format(&sa, netaddrbuf, + sizeof(netaddrbuf)); + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "bad suffix '%s' leading " + "%u octets not zeros", + netaddrbuf, nbytes); + result = ISC_R_FAILURE; + } + } + } + + return (result); +} + + /* * Check allow-recursion and allow-recursion-on acls, and also log a * warning if they're inconsistent with the "recursion" option. @@ -493,6 +593,78 @@ check_recursionacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions, return (result); } +static isc_result_t +check_filteraaaa(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions, + const char *viewname, const cfg_obj_t *config, + isc_log_t *logctx, isc_mem_t *mctx) +{ + const cfg_obj_t *options, *aclobj, *obj = NULL; + dns_acl_t *acl = NULL; + isc_result_t result = ISC_R_SUCCESS, tresult; + dns_v4_aaaa_t filter; + const char *forview = " for view "; + + if (voptions != NULL) + cfg_map_get(voptions, "filter-aaaa-on-v4", &obj); + if (obj == NULL && config != NULL) { + options = NULL; + cfg_map_get(config, "options", &options); + if (options != NULL) + cfg_map_get(options, "filter-aaaa-on-v4", &obj); + } + + if (obj == NULL) + filter = dns_v4_aaaa_ok; /* default */ + else if (cfg_obj_isboolean(obj)) + filter = cfg_obj_asboolean(obj) ? dns_v4_aaaa_filter : + dns_v4_aaaa_ok; + else + filter = dns_v4_aaaa_break_dnssec; /* break-dnssec */ + + if (viewname == NULL) { + viewname = ""; + forview = ""; + } + + aclobj = options = NULL; + acl = NULL; + + if (voptions != NULL) + cfg_map_get(voptions, "filter-aaaa", &aclobj); + if (config != NULL && aclobj == NULL) { + options = NULL; + cfg_map_get(config, "options", &options); + if (options != NULL) + cfg_map_get(options, "filter-aaaa", &aclobj); + } + if (aclobj == NULL) + return (result); + + tresult = cfg_acl_fromconfig(aclobj, config, logctx, + actx, mctx, 0, &acl); + + if (tresult != ISC_R_SUCCESS) { + result = tresult; + } else if (filter != dns_v4_aaaa_ok && dns_acl_isnone(acl)) { + cfg_obj_log(aclobj, logctx, ISC_LOG_WARNING, + "both \"filter-aaaa-on-v4 %s;\" and " + "\"filter-aaaa\" is 'none;'%s%s", + filter == dns_v4_aaaa_break_dnssec ? + "break-dnssec" : "yes", forview, viewname); + result = ISC_R_FAILURE; + } else if (filter == dns_v4_aaaa_ok && !dns_acl_isnone(acl)) { + cfg_obj_log(aclobj, logctx, ISC_LOG_WARNING, + "both \"filter-aaaa-on-v4 no;\" and " + "\"filter-aaaa\" is set%s%s", forview, viewname); + result = ISC_R_FAILURE; + } + + if (acl != NULL) + dns_acl_detach(&acl); + + return (result); +} + typedef struct { const char *name; unsigned int scale; @@ -524,6 +696,12 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) { { "statistics-interval", 60, 28 * 24 * 60 }, /* 28 days */ }; + static const char *server_contact[] = { + "empty-server", "empty-contact", + "dns64-server", "dns64-contact", + NULL + }; + /* * Check that fields specified in units of time other than seconds * have reasonable values. @@ -620,7 +798,7 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) { isc_buffer_add(&b, strlen(str)); tresult = dns_name_fromtext(name, &b, dns_rootname, - ISC_FALSE, NULL); + 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "bad domain name '%s'", @@ -666,14 +844,24 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) { element = cfg_list_next(element)) { const char *dlv; + const cfg_obj_t *anchor; obj = cfg_listelt_value(element); dlv = cfg_obj_asstring(cfg_tuple_get(obj, "domain")); + anchor = cfg_tuple_get(obj, "trust-anchor"); + + /* + * If domain is "auto" and trust anchor is missing, + * skip remaining tests + */ + if (!strcmp(dlv, "auto") && cfg_obj_isvoid(anchor)) + continue; + isc_buffer_init(&b, dlv, strlen(dlv)); isc_buffer_add(&b, strlen(dlv)); tresult = dns_name_fromtext(name, &b, dns_rootname, - ISC_TRUE, NULL); + 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "bad domain name '%s'", dlv); @@ -701,19 +889,32 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) { if (result == ISC_R_SUCCESS) result = ISC_R_FAILURE; } - dlv = cfg_obj_asstring(cfg_tuple_get(obj, - "trust-anchor")); - isc_buffer_init(&b, dlv, strlen(dlv)); - isc_buffer_add(&b, strlen(dlv)); - tresult = dns_name_fromtext(name, &b, dns_rootname, - ISC_TRUE, NULL); - if (tresult != ISC_R_SUCCESS) { + + if (!cfg_obj_isvoid(anchor)) { + dlv = cfg_obj_asstring(anchor); + isc_buffer_init(&b, dlv, strlen(dlv)); + isc_buffer_add(&b, strlen(dlv)); + tresult = dns_name_fromtext(name, &b, + dns_rootname, + DNS_NAME_DOWNCASE, + NULL); + if (tresult != ISC_R_SUCCESS) { + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "bad domain name '%s'", + dlv); + if (result == ISC_R_SUCCESS) + result = tresult; + } + } else { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "bad domain name '%s'", dlv); + "dnssec-lookaside requires " + "either 'auto' or a domain and " + "trust anchor"); if (result == ISC_R_SUCCESS) - result = tresult; + result = ISC_R_FAILURE; } } + if (symtab != NULL) isc_symtab_destroy(&symtab); } @@ -743,38 +944,29 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) { } /* - * Check empty zone configuration. + * Check server/contacts for syntactic validity. */ - obj = NULL; - (void)cfg_map_get(options, "empty-server", &obj); - if (obj != NULL) { - str = cfg_obj_asstring(obj); - isc_buffer_init(&b, str, strlen(str)); - isc_buffer_add(&b, strlen(str)); - tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, ISC_FALSE, NULL); - if (tresult != ISC_R_SUCCESS) { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "empty-server: invalid name '%s'", str); - result = ISC_R_FAILURE; - } - } - - obj = NULL; - (void)cfg_map_get(options, "empty-contact", &obj); - if (obj != NULL) { - str = cfg_obj_asstring(obj); - isc_buffer_init(&b, str, strlen(str)); - isc_buffer_add(&b, strlen(str)); - tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, ISC_FALSE, NULL); - if (tresult != ISC_R_SUCCESS) { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "empty-contact: invalid name '%s'", str); - result = ISC_R_FAILURE; + for (i= 0; server_contact[i] != NULL; i++) { + obj = NULL; + (void)cfg_map_get(options, server_contact[i], &obj); + if (obj != NULL) { + str = cfg_obj_asstring(obj); + isc_buffer_init(&b, str, strlen(str)); + isc_buffer_add(&b, strlen(str)); + tresult = dns_name_fromtext(dns_fixedname_name(&fixed), + &b, dns_rootname, 0, NULL); + if (tresult != ISC_R_SUCCESS) { + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "%s: invalid name '%s'", + server_contact[i], str); + result = ISC_R_FAILURE; + } } } + /* + * Check empty zone configuration. + */ obj = NULL; (void)cfg_map_get(options, "disable-empty-zone", &obj); for (element = cfg_list_first(obj); @@ -786,7 +978,7 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) { isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "disable-empty-zone: invalid name '%s'", @@ -950,6 +1142,12 @@ check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) { const char *str; isc_buffer_t b; + /* Check for "update-policy local;" */ + if (cfg_obj_isstring(policy) && + strcmp("local", cfg_obj_asstring(policy)) == 0) + return (ISC_R_SUCCESS); + + /* Now check the grant policy */ for (element = cfg_list_first(policy); element != NULL; element = cfg_list_next(element)) @@ -965,24 +1163,28 @@ check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) { isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(identity, logctx, ISC_LOG_ERROR, "'%s' is not a valid name", str); result = tresult; } - dns_fixedname_init(&fixed); - str = cfg_obj_asstring(dname); - isc_buffer_init(&b, str, strlen(str)); - isc_buffer_add(&b, strlen(str)); - tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, ISC_FALSE, NULL); - if (tresult != ISC_R_SUCCESS) { - cfg_obj_log(dname, logctx, ISC_LOG_ERROR, - "'%s' is not a valid name", str); - result = tresult; + if (tresult == ISC_R_SUCCESS && + strcasecmp(cfg_obj_asstring(matchtype), "zonesub") != 0) { + dns_fixedname_init(&fixed); + str = cfg_obj_asstring(dname); + isc_buffer_init(&b, str, strlen(str)); + isc_buffer_add(&b, strlen(str)); + tresult = dns_name_fromtext(dns_fixedname_name(&fixed), + &b, dns_rootname, 0, NULL); + if (tresult != ISC_R_SUCCESS) { + cfg_obj_log(dname, logctx, ISC_LOG_ERROR, + "'%s' is not a valid name", str); + result = tresult; + } } + if (tresult == ISC_R_SUCCESS && strcasecmp(cfg_obj_asstring(matchtype), "wildcard") == 0 && !dns_name_iswildcard(dns_fixedname_name(&fixed))) { @@ -1020,7 +1222,8 @@ check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) { #define HINTZONE 8 #define FORWARDZONE 16 #define DELEGATIONZONE 32 -#define CHECKACL 64 +#define STATICSTUBZONE 64 +#define CHECKACL 128 typedef struct { const char *name; @@ -1033,7 +1236,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, dns_rdataclass_t defclass, cfg_aclconfctx_t *actx, isc_log_t *logctx, isc_mem_t *mctx) { - const char *zname; + const char *znamestr; const char *typestr; unsigned int ztype; const cfg_obj_t *zoptions; @@ -1043,11 +1246,14 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, unsigned int i; dns_rdataclass_t zclass; dns_fixedname_t fixedname; + dns_name_t *zname = NULL; isc_buffer_t b; isc_boolean_t root = ISC_FALSE; + const cfg_listelt_t *element; static optionstable options[] = { - { "allow-query", MASTERZONE | SLAVEZONE | STUBZONE | CHECKACL }, + { "allow-query", MASTERZONE | SLAVEZONE | STUBZONE | CHECKACL | + STATICSTUBZONE }, { "allow-notify", SLAVEZONE | CHECKACL }, { "allow-transfer", MASTERZONE | SLAVEZONE | CHECKACL }, { "notify", MASTERZONE | SLAVEZONE }, @@ -1070,12 +1276,14 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, { "min-retry-time", SLAVEZONE | STUBZONE }, { "max-refresh-time", SLAVEZONE | STUBZONE }, { "min-refresh-time", SLAVEZONE | STUBZONE }, + { "dnssec-secure-to-insecure", MASTERZONE }, { "sig-validity-interval", MASTERZONE }, { "sig-re-signing-interval", MASTERZONE }, { "sig-signing-nodes", MASTERZONE }, { "sig-signing-type", MASTERZONE }, { "sig-signing-signatures", MASTERZONE }, - { "zone-statistics", MASTERZONE | SLAVEZONE | STUBZONE }, + { "zone-statistics", MASTERZONE | SLAVEZONE | STUBZONE | + STATICSTUBZONE}, { "allow-update", MASTERZONE | CHECKACL }, { "allow-update-forwarding", SLAVEZONE | CHECKACL }, { "file", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE }, @@ -1089,12 +1297,17 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, { "key-directory", MASTERZONE }, { "check-wildcard", MASTERZONE }, { "check-mx", MASTERZONE }, + { "check-dup-records", MASTERZONE }, { "integrity-check", MASTERZONE }, { "check-mx-cname", MASTERZONE }, { "check-srv-cname", MASTERZONE }, { "masterfile-format", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE }, { "update-check-ksk", MASTERZONE }, + { "dnssec-dnskey-kskonly", MASTERZONE }, + { "auto-dnssec", MASTERZONE }, { "try-tcp-refresh", SLAVEZONE }, + { "server-addresses", STATICSTUBZONE }, + { "server-names", STATICSTUBZONE }, }; static optionstable dialups[] = { @@ -1104,7 +1317,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, { "passive", SLAVEZONE | STUBZONE }, }; - zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); + znamestr = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); zoptions = cfg_tuple_get(zconfig, "options"); @@ -1112,7 +1325,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, (void)cfg_map_get(zoptions, "type", &obj); if (obj == NULL) { cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR, - "zone '%s': type not present", zname); + "zone '%s': type not present", znamestr); return (ISC_R_FAILURE); } @@ -1123,6 +1336,8 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, ztype = SLAVEZONE; else if (strcasecmp(typestr, "stub") == 0) ztype = STUBZONE; + else if (strcasecmp(typestr, "static-stub") == 0) + ztype = STATICSTUBZONE; else if (strcasecmp(typestr, "forward") == 0) ztype = FORWARDZONE; else if (strcasecmp(typestr, "hint") == 0) @@ -1132,7 +1347,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, else { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "zone '%s': invalid type %s", - zname, typestr); + znamestr, typestr); return (ISC_R_FAILURE); } @@ -1146,14 +1361,14 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, if (result != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "zone '%s': invalid class %s", - zname, r.base); + znamestr, r.base); return (ISC_R_FAILURE); } if (zclass != defclass) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "zone '%s': class '%s' does not " "match view/default class", - zname, r.base); + znamestr, r.base); return (ISC_R_FAILURE); } } @@ -1164,26 +1379,25 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, * deals with strings. */ dns_fixedname_init(&fixedname); - isc_buffer_init(&b, zname, strlen(zname)); - isc_buffer_add(&b, strlen(zname)); + isc_buffer_init(&b, znamestr, strlen(znamestr)); + isc_buffer_add(&b, strlen(znamestr)); tresult = dns_name_fromtext(dns_fixedname_name(&fixedname), &b, - dns_rootname, ISC_TRUE, NULL); + dns_rootname, DNS_NAME_DOWNCASE, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR, - "zone '%s': is not a valid name", zname); + "zone '%s': is not a valid name", znamestr); result = ISC_R_FAILURE; } else { char namebuf[DNS_NAME_FORMATSIZE]; - dns_name_format(dns_fixedname_name(&fixedname), - namebuf, sizeof(namebuf)); + zname = dns_fixedname_name(&fixedname); + dns_name_format(zname, namebuf, sizeof(namebuf)); tresult = nameexist(zconfig, namebuf, ztype == HINTZONE ? 1 : 2, symtab, "zone '%s': already exists " "previous definition: %s:%u", logctx, mctx); if (tresult != ISC_R_SUCCESS) result = tresult; - if (dns_name_equal(dns_fixedname_name(&fixedname), - dns_rootname)) + if (dns_name_equal(zname, dns_rootname)) root = ISC_TRUE; } @@ -1202,13 +1416,15 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "option '%s' is not allowed " "in '%s' zone '%s'", - options[i].name, typestr, zname); + options[i].name, typestr, + znamestr); result = ISC_R_FAILURE; } else cfg_obj_log(obj, logctx, ISC_LOG_WARNING, "option '%s' is not allowed " "in '%s' zone '%s'", - options[i].name, typestr, zname); + options[i].name, typestr, + znamestr); } obj = NULL; if ((options[i].allowed & ztype) != 0 && @@ -1230,7 +1446,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, if (cfg_map_get(zoptions, "masters", &obj) != ISC_R_SUCCESS) { cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR, "zone '%s': missing 'masters' entry", - zname); + znamestr); result = ISC_R_FAILURE; } else { isc_uint32_t count; @@ -1241,7 +1457,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, if (tresult == ISC_R_SUCCESS && count == 0) { cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR, "zone '%s': empty 'masters' entry", - zname); + znamestr); result = ISC_R_FAILURE; } } @@ -1251,7 +1467,10 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, * Master zones can't have both "allow-update" and "update-policy". */ if (ztype == MASTERZONE) { - isc_result_t res1, res2; + isc_result_t res1, res2, res3; + const char *arg; + isc_boolean_t ddns; + obj = NULL; res1 = cfg_map_get(zoptions, "allow-update", &obj); obj = NULL; @@ -1260,11 +1479,32 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "zone '%s': 'allow-update' is ignored " "when 'update-policy' is present", - zname); + znamestr); result = ISC_R_FAILURE; } else if (res2 == ISC_R_SUCCESS && check_update_policy(obj, logctx) != ISC_R_SUCCESS) result = ISC_R_FAILURE; + ddns = ISC_TF(res1 == ISC_R_SUCCESS || res2 == ISC_R_SUCCESS); + + obj = NULL; + arg = "off"; + res3 = cfg_map_get(zoptions, "auto-dnssec", &obj); + if (res3 == ISC_R_SUCCESS) + arg = cfg_obj_asstring(obj); + if (strcasecmp(arg, "off") != 0 && !ddns) { + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "'auto-dnssec %s;' requires " + "dynamic DNS to be configured in the zone", + arg); + result = ISC_R_FAILURE; + } + if (strcasecmp(arg, "create") == 0) { + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "'auto-dnssec create;' is not " + "yet implemented"); + result = ISC_R_FAILURE; + } + obj = NULL; res1 = cfg_map_get(zoptions, "sig-signing-type", &obj); if (res1 == ISC_R_SUCCESS) { @@ -1298,7 +1538,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, "dialup type '%s' is not " "allowed in '%s' " "zone '%s'", - str, typestr, zname); + str, typestr, znamestr); result = ISC_R_FAILURE; } break; @@ -1306,7 +1546,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, if (i == sizeof(dialups) / sizeof(dialups[0])) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "invalid dialup type '%s' in zone " - "'%s'", str, zname); + "'%s'", str, znamestr); result = ISC_R_FAILURE; } } @@ -1330,6 +1570,78 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, result = ISC_R_FAILURE; /* + * Check validity of static stub server addresses. + */ + obj = NULL; + (void)cfg_map_get(zoptions, "server-addresses", &obj); + if (ztype == STATICSTUBZONE && obj != NULL) { + for (element = cfg_list_first(obj); + element != NULL; + element = cfg_list_next(element)) + { + isc_sockaddr_t sa; + isc_netaddr_t na; + obj = cfg_listelt_value(element); + sa = *cfg_obj_assockaddr(obj); + + if (isc_sockaddr_getport(&sa) != 0) { + result = ISC_R_FAILURE; + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "port is not configurable for " + "static stub server-addresses"); + } + + isc_netaddr_fromsockaddr(&na, &sa); + if (isc_netaddr_getzone(&na) != 0) { + result = ISC_R_FAILURE; + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "scoped address is not allowed " + "for static stub " + "server-addresses"); + } + } + } + + /* + * Check validity of static stub server names. + */ + obj = NULL; + (void)cfg_map_get(zoptions, "server-names", &obj); + if (zname != NULL && ztype == STATICSTUBZONE && obj != NULL) { + for (element = cfg_list_first(obj); + element != NULL; + element = cfg_list_next(element)) + { + const char *snamestr; + dns_fixedname_t fixed_sname; + isc_buffer_t b2; + dns_name_t *sname; + + obj = cfg_listelt_value(element); + snamestr = cfg_obj_asstring(obj); + + dns_fixedname_init(&fixed_sname); + isc_buffer_init(&b2, snamestr, strlen(snamestr)); + isc_buffer_add(&b2, strlen(snamestr)); + sname = dns_fixedname_name(&fixed_sname); + tresult = dns_name_fromtext(sname, &b2, dns_rootname, + 0, NULL); + if (tresult != ISC_R_SUCCESS) { + cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR, + "server-name '%s' is not a valid " + "name", snamestr); + result = ISC_R_FAILURE; + } else if (dns_name_issubdomain(sname, zname)) { + cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR, + "server-name '%s' must not be a " + "subdomain of zone name '%s'", + snamestr, znamestr); + result = ISC_R_FAILURE; + } + } + } + + /* * Check various options. */ tresult = check_options(zoptions, logctx, mctx); @@ -1352,7 +1664,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, (ztype == MASTERZONE || ztype == HINTZONE)) { cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR, "zone '%s': missing 'file' entry", - zname); + znamestr); result = tresult; } } @@ -1374,6 +1686,9 @@ bind9_check_key(const cfg_obj_t *key, isc_log_t *logctx) { const char *algorithm; int i; size_t len = 0; + isc_result_t result; + isc_buffer_t buf; + unsigned char secretbuf[1024]; static const algorithmtable algorithms[] = { { "hmac-md5", 128 }, { "hmac-md5.sig-alg.reg.int", 0 }, @@ -1396,6 +1711,14 @@ bind9_check_key(const cfg_obj_t *key, isc_log_t *logctx) { return (ISC_R_FAILURE); } + isc_buffer_init(&buf, secretbuf, sizeof(secretbuf)); + result = isc_base64_decodestring(cfg_obj_asstring(secretobj), &buf); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(secretobj, logctx, ISC_LOG_ERROR, + "bad secret '%s'", isc_result_totext(result)); + return (result); + } + algorithm = cfg_obj_asstring(algobj); for (i = 0; algorithms[i].name != NULL; i++) { len = strlen(algorithms[i].name); @@ -1480,7 +1803,7 @@ check_keylist(const cfg_obj_t *keys, isc_symtab_t *symtab, isc_buffer_init(&b, keyid, strlen(keyid)); isc_buffer_add(&b, strlen(keyid)); tresult = dns_name_fromtext(name, &b, dns_rootname, - ISC_FALSE, NULL); + 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(key, logctx, ISC_LOG_ERROR, "key '%s': bad key name", keyid); @@ -1650,7 +1973,7 @@ check_servers(const cfg_obj_t *config, const cfg_obj_t *voptions, isc_buffer_add(&b, strlen(keyval)); keyname = dns_fixedname_name(&fname); tresult = dns_name_fromtext(keyname, &b, dns_rootname, - ISC_FALSE, NULL); + 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(keys, logctx, ISC_LOG_ERROR, "bad key name '%s'", keyval); @@ -1670,7 +1993,8 @@ check_servers(const cfg_obj_t *config, const cfg_obj_t *voptions, } static isc_result_t -check_trusted_key(const cfg_obj_t *key, isc_log_t *logctx) +check_trusted_key(const cfg_obj_t *key, isc_boolean_t managed, + isc_log_t *logctx) { const char *keystr, *keynamestr; dns_fixedname_t fkeyname; @@ -1704,6 +2028,19 @@ check_trusted_key(const cfg_obj_t *key, isc_log_t *logctx) result = ISC_R_FAILURE; } + if (managed) { + const char *initmethod; + initmethod = cfg_obj_asstring(cfg_tuple_get(key, "init")); + + if (strcasecmp(initmethod, "initial-key") != 0) { + cfg_obj_log(key, logctx, ISC_LOG_ERROR, + "managed key '%s': " + "invalid initialization method '%s'", + keynamestr, initmethod); + result = ISC_R_FAILURE; + } + } + isc_buffer_init(&keydatabuf, keydata, sizeof(keydata)); keystr = cfg_obj_asstring(cfg_tuple_get(key, "key")); @@ -1719,7 +2056,8 @@ check_trusted_key(const cfg_obj_t *key, isc_log_t *logctx) if ((alg == DST_ALG_RSASHA1 || alg == DST_ALG_RSAMD5) && r.length > 1 && r.base[0] == 1 && r.base[1] == 3) cfg_obj_log(key, logctx, ISC_LOG_WARNING, - "trusted key '%s' has a weak exponent", + "%s key '%s' has a weak exponent", + managed ? "managed" : "trusted", keynamestr); } @@ -1892,12 +2230,32 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions, element2 != NULL; element2 = cfg_list_next(element2)) { obj = cfg_listelt_value(element2); - tresult = check_trusted_key(obj, logctx); + tresult = check_trusted_key(obj, ISC_FALSE, logctx); if (tresult != ISC_R_SUCCESS) result = tresult; } } + keys = NULL; + if (voptions != NULL) + (void)cfg_map_get(voptions, "managed-keys", &keys); + if (keys == NULL) + (void)cfg_map_get(config, "managed-keys", &keys); + + for (element = cfg_list_first(keys); + element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *keylist = cfg_listelt_value(element); + for (element2 = cfg_list_first(keylist); + element2 != NULL; + element2 = cfg_list_next(element2)) { + obj = cfg_listelt_value(element2); + tresult = check_trusted_key(obj, ISC_TRUE, logctx); + if (tresult != ISC_R_SUCCESS) + result = tresult; + } + } /* * Check options. */ @@ -1917,7 +2275,16 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions, if (tresult != ISC_R_SUCCESS) result = tresult; - cfg_aclconfctx_destroy(&actx); + tresult = check_filteraaaa(&actx, voptions, viewname, config, + logctx, mctx); + if (tresult != ISC_R_SUCCESS) + result = tresult; + + tresult = check_dns64(&actx, voptions, config, logctx, mctx); + if (tresult != ISC_R_SUCCESS) + result = tresult; + + cfg_aclconfctx_clear(&actx); return (result); } @@ -2162,7 +2529,7 @@ bind9_check_controls(const cfg_obj_t *config, isc_log_t *logctx, result = tresult; } } - cfg_aclconfctx_destroy(&actx); + cfg_aclconfctx_clear(&actx); return (result); } diff --git a/lib/bind9/include/bind9/getaddresses.h b/lib/bind9/include/bind9/getaddresses.h index 677ced2..9ad8045 100644 --- a/lib/bind9/include/bind9/getaddresses.h +++ b/lib/bind9/include/bind9/getaddresses.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: getaddresses.h,v 1.9.332.2 2009-01-18 23:47:35 tbox Exp $ */ +/* $Id: getaddresses.h,v 1.11 2009-01-17 23:47:42 tbox Exp $ */ #ifndef BIND9_GETADDRESSES_H #define BIND9_GETADDRESSES_H 1 diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in index dfb8d7f..45c5c2a 100644 --- a/lib/dns/Makefile.in +++ b/lib/dns/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 1998-2003 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.163.50.2 2010-06-09 23:48:16 tbox Exp $ +# $Id: Makefile.in,v 1.176 2011-01-13 01:59:27 marka Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -34,8 +34,7 @@ USE_ISC_SPNEGO = @USE_ISC_SPNEGO@ CINCLUDES = -I. -Iinclude ${DNS_INCLUDES} \ ${ISC_INCLUDES} @DST_OPENSSL_INC@ @DST_GSSAPI_INC@ -CDEFINES = -DUSE_MD5 @USE_OPENSSL@ @USE_PKCS11@ @USE_GSSAPI@ \ - ${USE_ISC_SPNEGO} +CDEFINES = -DUSE_MD5 @USE_OPENSSL@ @USE_GSSAPI@ ${USE_ISC_SPNEGO} CWARNINGS = @@ -48,7 +47,7 @@ LIBS = @LIBS@ # Alphabetically OPENSSLLINKOBJS = openssl_link.@O@ openssldh_link.@O@ openssldsa_link.@O@ \ - opensslrsa_link.@O@ + opensslgost_link.@O@ opensslrsa_link.@O@ DSTOBJS = @DST_EXTRA_OBJS@ @OPENSSLLINKOBJS@ \ dst_api.@O@ dst_lib.@O@ dst_parse.@O@ dst_result.@O@ \ @@ -58,24 +57,26 @@ DSTOBJS = @DST_EXTRA_OBJS@ @OPENSSLLINKOBJS@ \ DNSOBJS = acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \ cache.@O@ callbacks.@O@ compress.@O@ \ db.@O@ dbiterator.@O@ dbtable.@O@ diff.@O@ dispatch.@O@ \ - dlz.@O@ dnssec.@O@ ds.@O@ forward.@O@ iptable.@O@ journal.@O@ \ - keytable.@O@ lib.@O@ log.@O@ lookup.@O@ \ + dlz.@O@ dns64.@O@ dnssec.@O@ ds.@O@ forward.@O@ iptable.@O@ \ + journal.@O@ keydata.@O@ keytable.@O@ \ + lib.@O@ log.@O@ lookup.@O@ \ master.@O@ masterdump.@O@ message.@O@ \ - name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ order.@O@ peer.@O@ portlist.@O@ \ + name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ order.@O@ peer.@O@ \ + portlist.@O@ private.@O@ \ rbt.@O@ rbtdb.@O@ rbtdb64.@O@ rcode.@O@ rdata.@O@ \ - rdatalist.@O@ \ - rdataset.@O@ rdatasetiter.@O@ rdataslab.@O@ request.@O@ \ - resolver.@O@ result.@O@ rootns.@O@ sdb.@O@ sdlz.@O@ \ - soa.@O@ ssu.@O@ \ + rdatalist.@O@ rdataset.@O@ rdatasetiter.@O@ rdataslab.@O@ \ + request.@O@ resolver.@O@ result.@O@ rootns.@O@ rpz.@O@ \ + rriterator.@O@ sdb.@O@ \ + sdlz.@O@ soa.@O@ ssu.@O@ ssu_external.@O@ \ stats.@O@ tcpmsg.@O@ time.@O@ timer.@O@ tkey.@O@ \ - tsig.@O@ ttl.@O@ validator.@O@ \ + tsec.@O@ tsig.@O@ ttl.@O@ validator.@O@ \ version.@O@ view.@O@ xfrin.@O@ zone.@O@ zonekey.@O@ zt.@O@ OBJS= ${DNSOBJS} ${OTHEROBJS} ${DSTOBJS} # Alphabetically -OPENSSLLINKSRCS = openssl_link.c openssldh_link.c \ - openssldsa_link.c opensslrsa_link.c +OPENSSLLINKSRCS = openssl_link.c openssldh_link.c openssldsa_link.c \ + opensslgost_link.c opensslrsa_link.c DSTSRCS = @DST_EXTRA_SRCS@ @OPENSSLLINKSRCS@ \ dst_api.c dst_lib.c dst_parse.c \ @@ -85,17 +86,16 @@ DSTSRCS = @DST_EXTRA_SRCS@ @OPENSSLLINKSRCS@ \ DNSSRCS = acache.c acl.c adb.c byaddr.c \ cache.c callbacks.c compress.c \ db.c dbiterator.c dbtable.c diff.c dispatch.c \ - dlz.c dnssec.c ds.c forward.c iptable.c journal.c \ - keytable.c lib.c log.c lookup.c \ + dlz.c dns64.c dnssec.c ds.c forward.c iptable.c journal.c \ + keydata.c keytable.c lib.c log.c lookup.c \ master.c masterdump.c message.c \ name.c ncache.c nsec.c nsec3.c order.c peer.c portlist.c \ - rbt.c rbtdb.c rbtdb64.c rcode.c rdata.c \ - rdatalist.c \ + rbt.c rbtdb.c rbtdb64.c rcode.c rdata.c rdatalist.c \ rdataset.c rdatasetiter.c rdataslab.c request.c \ - resolver.c result.c rootns.c sdb.c sdlz.c \ - soa.c ssu.c \ + resolver.c result.c rootns.c rpz.c rriterator.c \ + sdb.c sdlz.c soa.c ssu.c ssu_external.c \ stats.c tcpmsg.c time.c timer.c tkey.c \ - tsig.c ttl.c validator.c \ + tsec.c tsig.c ttl.c validator.c \ version.c view.c xfrin.c zone.c zonekey.c zt.c ${OTHERSRCS} SRCS = ${DSTSRCS} ${DNSSRCS} diff --git a/lib/dns/acl.c b/lib/dns/acl.c index cfb7fd8..118e394 100644 --- a/lib/dns/acl.c +++ b/lib/dns/acl.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: acl.c,v 1.50.44.3 2009-01-18 23:47:35 tbox Exp $ */ +/* $Id: acl.c,v 1.53 2009-01-17 23:47:42 tbox Exp $ */ /*! \file */ diff --git a/lib/dns/adb.c b/lib/dns/adb.c index cd9cadf..fcc2dd8 100644 --- a/lib/dns/adb.c +++ b/lib/dns/adb.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: adb.c,v 1.243.42.6 2010-08-11 23:45:49 tbox Exp $ */ +/* $Id: adb.c,v 1.254 2010-12-21 23:47:08 tbox Exp $ */ /*! \file * @@ -66,13 +66,6 @@ #define DNS_ADBFETCH6_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC) /*! - * The number of buckets needs to be a prime (for good hashing). - * - * XXXRTH How many buckets do we need? - */ -#define NBUCKETS 1009 /*%< how many buckets for names/addrs */ - -/*! * For type 3 negative cache entries, we will remember that the address is * broken for this long. XXXMLG This is also used for actual addresses, too. * The intent is to keep us from constantly asking about A/AAAA records @@ -139,30 +132,37 @@ struct dns_adb { * * XXXRTH Have a per-bucket structure that contains all of these? */ - dns_adbnamelist_t names[NBUCKETS]; - dns_adbnamelist_t deadnames[NBUCKETS]; - /*% See dns_adbnamelist_t */ - isc_mutex_t namelocks[NBUCKETS]; - /*% See dns_adbnamelist_t */ - isc_boolean_t name_sd[NBUCKETS]; - /*% See dns_adbnamelist_t */ - unsigned int name_refcnt[NBUCKETS]; + unsigned int nnames; + isc_mutex_t namescntlock; + unsigned int namescnt; + dns_adbnamelist_t *names; + dns_adbnamelist_t *deadnames; + isc_mutex_t *namelocks; + isc_boolean_t *name_sd; + unsigned int *name_refcnt; /*! - * Bucketized locks for entries. + * Bucketized locks and lists for entries. * * XXXRTH Have a per-bucket structure that contains all of these? */ - dns_adbentrylist_t entries[NBUCKETS]; - dns_adbentrylist_t deadentries[NBUCKETS]; - isc_mutex_t entrylocks[NBUCKETS]; - isc_boolean_t entry_sd[NBUCKETS]; /*%< shutting down */ - unsigned int entry_refcnt[NBUCKETS]; + unsigned int nentries; + isc_mutex_t entriescntlock; + unsigned int entriescnt; + dns_adbentrylist_t *entries; + dns_adbentrylist_t *deadentries; + isc_mutex_t *entrylocks; + isc_boolean_t *entry_sd; /*%< shutting down */ + unsigned int *entry_refcnt; isc_event_t cevent; isc_boolean_t cevent_sent; isc_boolean_t shutting_down; isc_eventlist_t whenshutdown; + isc_event_t growentries; + isc_boolean_t growentries_sent; + isc_event_t grownames; + isc_boolean_t grownames_sent; }; /* @@ -484,6 +484,322 @@ ttlclamp(dns_ttl_t ttl) { } /* + * Hashing is most efficient if the number of buckets is prime. + * The sequence below is the closest previous primes to 2^n and + * 1.5 * 2^n, for values of n from 10 to 28. (The tables will + * no longer grow beyond 2^28 entries.) + */ +static const unsigned nbuckets[] = { 1021, 1531, 2039, 3067, 4093, 6143, + 8191, 12281, 16381, 24571, 32749, + 49193, 65521, 98299, 131071, 199603, + 262139, 393209, 524287, 768431, 1048573, + 1572853, 2097143, 3145721, 4194301, + 6291449, 8388593, 12582893, 16777213, + 25165813, 33554393, 50331599, 67108859, + 100663291, 134217689, 201326557, + 268535431, 0 }; + +static void +grow_entries(isc_task_t *task, isc_event_t *ev) { + dns_adb_t *adb; + dns_adbentry_t *e; + dns_adbentrylist_t *newdeadentries = NULL; + dns_adbentrylist_t *newentries = NULL; + isc_boolean_t *newentry_sd = NULL; + isc_mutex_t *newentrylocks = NULL; + isc_result_t result; + unsigned int *newentry_refcnt = NULL; + unsigned int i, n, bucket; + + adb = ev->ev_arg; + INSIST(DNS_ADB_VALID(adb)); + + isc_event_free(&ev); + + isc_task_beginexclusive(task); + + i = 0; + while (nbuckets[i] != 0 && adb->nentries >= nbuckets[i]) + i++; + if (nbuckets[i] != 0) + n = nbuckets[i]; + else + goto done; + + DP(ISC_LOG_INFO, "adb: grow_entries to %u starting", n); + + /* + * Are we shutting down? + */ + for (i = 0; i < adb->nentries; i++) + if (adb->entry_sd[i]) + goto cleanup; + + /* + * Grab all the resources we need. + */ + newentries = isc_mem_get(adb->mctx, sizeof(*newentries) * n); + newdeadentries = isc_mem_get(adb->mctx, sizeof(*newdeadentries) * n); + newentrylocks = isc_mem_get(adb->mctx, sizeof(*newentrylocks) * n); + newentry_sd = isc_mem_get(adb->mctx, sizeof(*newentry_sd) * n); + newentry_refcnt = isc_mem_get(adb->mctx, sizeof(*newentry_refcnt) * n); + if (newentries == NULL || newdeadentries == NULL || + newentrylocks == NULL || newentry_sd == NULL || + newentry_refcnt == NULL) + goto cleanup; + + /* + * Initialise the new resources. + */ + result = isc_mutexblock_init(newentrylocks, n); + if (result != ISC_R_SUCCESS) + goto cleanup; + + for (i = 0; i < n; i++) { + ISC_LIST_INIT(newentries[i]); + ISC_LIST_INIT(newdeadentries[i]); + newentry_sd[i] = ISC_FALSE; + newentry_refcnt[i] = 0; + adb->irefcnt++; + } + + /* + * Move entries to new arrays. + */ + for (i = 0; i < adb->nentries; i++) { + e = ISC_LIST_HEAD(adb->entries[i]); + while (e != NULL) { + ISC_LIST_UNLINK(adb->entries[i], e, plink); + bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n; + e->lock_bucket = bucket; + ISC_LIST_APPEND(newentries[bucket], e, plink); + INSIST(adb->entry_refcnt[i] > 0); + adb->entry_refcnt[i]--; + newentry_refcnt[bucket]++; + e = ISC_LIST_HEAD(adb->entries[i]); + } + e = ISC_LIST_HEAD(adb->deadentries[i]); + while (e != NULL) { + ISC_LIST_UNLINK(adb->deadentries[i], e, plink); + bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n; + e->lock_bucket = bucket; + ISC_LIST_APPEND(newdeadentries[bucket], e, plink); + INSIST(adb->entry_refcnt[i] > 0); + adb->entry_refcnt[i]--; + newentry_refcnt[bucket]++; + e = ISC_LIST_HEAD(adb->deadentries[i]); + } + INSIST(adb->entry_refcnt[i] == 0); + adb->irefcnt--; + } + + /* + * Cleanup old resources. + */ + DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries); + isc_mem_put(adb->mctx, adb->entries, + sizeof(*adb->entries) * adb->nentries); + isc_mem_put(adb->mctx, adb->deadentries, + sizeof(*adb->deadentries) * adb->nentries); + isc_mem_put(adb->mctx, adb->entrylocks, + sizeof(*adb->entrylocks) * adb->nentries); + isc_mem_put(adb->mctx, adb->entry_sd, + sizeof(*adb->entry_sd) * adb->nentries); + isc_mem_put(adb->mctx, adb->entry_refcnt, + sizeof(*adb->entry_refcnt) * adb->nentries); + + /* + * Install new resources. + */ + adb->entries = newentries; + adb->deadentries = newdeadentries; + adb->entrylocks = newentrylocks; + adb->entry_sd = newentry_sd; + adb->entry_refcnt = newentry_refcnt; + adb->nentries = n; + + /* + * Only on success do we set adb->growentries_sent to ISC_FALSE. + * This will prevent us being continuously being called on error. + */ + adb->growentries_sent = ISC_FALSE; + goto done; + + cleanup: + if (newentries != NULL) + isc_mem_put(adb->mctx, newentries, + sizeof(*newentries) * n); + if (newdeadentries != NULL) + isc_mem_put(adb->mctx, newdeadentries, + sizeof(*newdeadentries) * n); + if (newentrylocks != NULL) + isc_mem_put(adb->mctx, newentrylocks, + sizeof(*newentrylocks) * n); + if (newentry_sd != NULL) + isc_mem_put(adb->mctx, newentry_sd, + sizeof(*newentry_sd) * n); + if (newentry_refcnt != NULL) + isc_mem_put(adb->mctx, newentry_refcnt, + sizeof(*newentry_refcnt) * n); + done: + isc_task_endexclusive(task); + + LOCK(&adb->lock); + if (dec_adb_irefcnt(adb)) + check_exit(adb); + UNLOCK(&adb->lock); + DP(ISC_LOG_INFO, "adb: grow_entries finished"); +} + +static void +grow_names(isc_task_t *task, isc_event_t *ev) { + dns_adb_t *adb; + dns_adbname_t *name; + dns_adbnamelist_t *newdeadnames = NULL; + dns_adbnamelist_t *newnames = NULL; + isc_boolean_t *newname_sd = NULL; + isc_mutex_t *newnamelocks = NULL; + isc_result_t result; + unsigned int *newname_refcnt = NULL; + unsigned int i, n, bucket; + + adb = ev->ev_arg; + INSIST(DNS_ADB_VALID(adb)); + + isc_event_free(&ev); + + isc_task_beginexclusive(task); + + i = 0; + while (nbuckets[i] != 0 && adb->nnames >= nbuckets[i]) + i++; + if (nbuckets[i] != 0) + n = nbuckets[i]; + else + goto done; + + DP(ISC_LOG_INFO, "adb: grow_names to %u starting", n); + + /* + * Are we shutting down? + */ + for (i = 0; i < adb->nnames; i++) + if (adb->name_sd[i]) + goto cleanup; + + /* + * Grab all the resources we need. + */ + newnames = isc_mem_get(adb->mctx, sizeof(*newnames) * n); + newdeadnames = isc_mem_get(adb->mctx, sizeof(*newdeadnames) * n); + newnamelocks = isc_mem_get(adb->mctx, sizeof(*newnamelocks) * n); + newname_sd = isc_mem_get(adb->mctx, sizeof(*newname_sd) * n); + newname_refcnt = isc_mem_get(adb->mctx, sizeof(*newname_refcnt) * n); + if (newnames == NULL || newdeadnames == NULL || + newnamelocks == NULL || newname_sd == NULL || + newname_refcnt == NULL) + goto cleanup; + + /* + * Initialise the new resources. + */ + result = isc_mutexblock_init(newnamelocks, n); + if (result != ISC_R_SUCCESS) + goto cleanup; + + for (i = 0; i < n; i++) { + ISC_LIST_INIT(newnames[i]); + ISC_LIST_INIT(newdeadnames[i]); + newname_sd[i] = ISC_FALSE; + newname_refcnt[i] = 0; + adb->irefcnt++; + } + + /* + * Move names to new arrays. + */ + for (i = 0; i < adb->nnames; i++) { + name = ISC_LIST_HEAD(adb->names[i]); + while (name != NULL) { + ISC_LIST_UNLINK(adb->names[i], name, plink); + bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n; + name->lock_bucket = bucket; + ISC_LIST_APPEND(newnames[bucket], name, plink); + INSIST(adb->name_refcnt[i] > 0); + adb->name_refcnt[i]--; + newname_refcnt[bucket]++; + name = ISC_LIST_HEAD(adb->names[i]); + } + name = ISC_LIST_HEAD(adb->deadnames[i]); + while (name != NULL) { + ISC_LIST_UNLINK(adb->deadnames[i], name, plink); + bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n; + name->lock_bucket = bucket; + ISC_LIST_APPEND(newdeadnames[bucket], name, plink); + INSIST(adb->name_refcnt[i] > 0); + adb->name_refcnt[i]--; + newname_refcnt[bucket]++; + name = ISC_LIST_HEAD(adb->deadnames[i]); + } + INSIST(adb->name_refcnt[i] == 0); + adb->irefcnt--; + } + + /* + * Cleanup old resources. + */ + DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames); + isc_mem_put(adb->mctx, adb->names, + sizeof(*adb->names) * adb->nnames); + isc_mem_put(adb->mctx, adb->deadnames, + sizeof(*adb->deadnames) * adb->nnames); + isc_mem_put(adb->mctx, adb->namelocks, + sizeof(*adb->namelocks) * adb->nnames); + isc_mem_put(adb->mctx, adb->name_sd, + sizeof(*adb->name_sd) * adb->nnames); + isc_mem_put(adb->mctx, adb->name_refcnt, + sizeof(*adb->name_refcnt) * adb->nnames); + + /* + * Install new resources. + */ + adb->names = newnames; + adb->deadnames = newdeadnames; + adb->namelocks = newnamelocks; + adb->name_sd = newname_sd; + adb->name_refcnt = newname_refcnt; + adb->nnames = n; + + /* + * Only on success do we set adb->grownames_sent to ISC_FALSE. + * This will prevent us being continuously being called on error. + */ + adb->grownames_sent = ISC_FALSE; + goto done; + + cleanup: + if (newnames != NULL) + isc_mem_put(adb->mctx, newnames, sizeof(*newnames) * n); + if (newdeadnames != NULL) + isc_mem_put(adb->mctx, newdeadnames, sizeof(*newdeadnames) * n); + if (newnamelocks != NULL) + isc_mem_put(adb->mctx, newnamelocks, sizeof(*newnamelocks) * n); + if (newname_sd != NULL) + isc_mem_put(adb->mctx, newname_sd, sizeof(*newname_sd) * n); + if (newname_refcnt != NULL) + isc_mem_put(adb->mctx, newname_refcnt, + sizeof(*newname_refcnt) * n); + done: + isc_task_endexclusive(task); + + LOCK(&adb->lock); + if (dec_adb_irefcnt(adb)) + check_exit(adb); + UNLOCK(&adb->lock); + DP(ISC_LOG_INFO, "adb: grow_names finished"); +} + +/* * Requires the adbname bucket be locked and that no entry buckets be locked. * * This code handles A and AAAA rdatasets only. @@ -836,12 +1152,12 @@ violate_locking_hierarchy(isc_mutex_t *have, isc_mutex_t *want) { */ static isc_boolean_t shutdown_names(dns_adb_t *adb) { - int bucket; + unsigned int bucket; isc_boolean_t result = ISC_FALSE; dns_adbname_t *name; dns_adbname_t *next_name; - for (bucket = 0; bucket < NBUCKETS; bucket++) { + for (bucket = 0; bucket < adb->nnames; bucket++) { LOCK(&adb->namelocks[bucket]); adb->name_sd[bucket] = ISC_TRUE; @@ -881,12 +1197,12 @@ shutdown_names(dns_adb_t *adb) { */ static isc_boolean_t shutdown_entries(dns_adb_t *adb) { - int bucket; + unsigned int bucket; isc_boolean_t result = ISC_FALSE; dns_adbentry_t *entry; dns_adbentry_t *next_entry; - for (bucket = 0; bucket < NBUCKETS; bucket++) { + for (bucket = 0; bucket < adb->nentries; bucket++) { LOCK(&adb->entrylocks[bucket]); adb->entry_sd[bucket] = ISC_TRUE; @@ -1306,6 +1622,16 @@ new_adbname(dns_adb_t *adb, dns_name_t *dnsname) { ISC_LIST_INIT(name->finds); ISC_LINK_INIT(name, plink); + LOCK(&adb->namescntlock); + adb->namescnt++; + if (!adb->grownames_sent && adb->namescnt > (adb->nnames * 8)) { + isc_event_t *event = &adb->grownames; + inc_adb_irefcnt(adb); + isc_task_send(adb->task, &event); + adb->grownames_sent = ISC_TRUE; + } + UNLOCK(&adb->namescntlock); + return (name); } @@ -1329,6 +1655,9 @@ free_adbname(dns_adb_t *adb, dns_adbname_t **name) { dns_name_free(&n->name, adb->mctx); isc_mempool_put(adb->nmp, n); + LOCK(&adb->namescntlock); + adb->namescnt--; + UNLOCK(&adb->namescntlock); } static inline dns_adbnamehook_t * @@ -1417,6 +1746,16 @@ new_adbentry(dns_adb_t *adb) { e->expires = 0; ISC_LIST_INIT(e->lameinfo); ISC_LINK_INIT(e, plink); + LOCK(&adb->entriescntlock); + adb->entriescnt++; + if (!adb->growentries_sent && + adb->entriescnt > (adb->nentries * 8)) { + isc_event_t *event = &adb->growentries; + inc_adb_irefcnt(adb); + isc_task_send(adb->task, &event); + adb->growentries_sent = ISC_TRUE; + } + UNLOCK(&adb->entriescntlock); return (e); } @@ -1444,6 +1783,9 @@ free_adbentry(dns_adb_t *adb, dns_adbentry_t **entry) { } isc_mempool_put(adb->emp, e); + LOCK(&adb->entriescntlock); + adb->entriescnt--; + UNLOCK(&adb->entriescntlock); } static inline dns_adbfind_t * @@ -1597,7 +1939,7 @@ find_name_and_lock(dns_adb_t *adb, dns_name_t *name, dns_adbname_t *adbname; int bucket; - bucket = dns_name_fullhash(name, ISC_FALSE) % NBUCKETS; + bucket = dns_name_fullhash(name, ISC_FALSE) % adb->nnames; if (*bucketp == DNS_ADB_INVALIDBUCKET) { LOCK(&adb->namelocks[bucket]); @@ -1639,7 +1981,7 @@ find_entry_and_lock(dns_adb_t *adb, isc_sockaddr_t *addr, int *bucketp, dns_adbentry_t *entry, *entry_next; int bucket; - bucket = isc_sockaddr_hash(addr, ISC_TRUE) % NBUCKETS; + bucket = isc_sockaddr_hash(addr, ISC_TRUE) % adb->nentries; if (*bucketp == DNS_ADB_INVALIDBUCKET) { LOCK(&adb->entrylocks[bucket]); @@ -1992,13 +2334,36 @@ destroy(dns_adb_t *adb) { isc_mempool_destroy(&adb->aimp); isc_mempool_destroy(&adb->afmp); - DESTROYMUTEXBLOCK(adb->entrylocks, NBUCKETS); - DESTROYMUTEXBLOCK(adb->namelocks, NBUCKETS); + DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries); + isc_mem_put(adb->mctx, adb->entries, + sizeof(*adb->entries) * adb->nentries); + isc_mem_put(adb->mctx, adb->deadentries, + sizeof(*adb->deadentries) * adb->nentries); + isc_mem_put(adb->mctx, adb->entrylocks, + sizeof(*adb->entrylocks) * adb->nentries); + isc_mem_put(adb->mctx, adb->entry_sd, + sizeof(*adb->entry_sd) * adb->nentries); + isc_mem_put(adb->mctx, adb->entry_refcnt, + sizeof(*adb->entry_refcnt) * adb->nentries); + + DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames); + isc_mem_put(adb->mctx, adb->names, + sizeof(*adb->names) * adb->nnames); + isc_mem_put(adb->mctx, adb->deadnames, + sizeof(*adb->deadnames) * adb->nnames); + isc_mem_put(adb->mctx, adb->namelocks, + sizeof(*adb->namelocks) * adb->nnames); + isc_mem_put(adb->mctx, adb->name_sd, + sizeof(*adb->name_sd) * adb->nnames); + isc_mem_put(adb->mctx, adb->name_refcnt, + sizeof(*adb->name_refcnt) * adb->nnames); DESTROYLOCK(&adb->reflock); DESTROYLOCK(&adb->lock); DESTROYLOCK(&adb->mplock); DESTROYLOCK(&adb->overmemlock); + DESTROYLOCK(&adb->entriescntlock); + DESTROYLOCK(&adb->namescntlock); isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t)); } @@ -2014,7 +2379,7 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr, { dns_adb_t *adb; isc_result_t result; - int i; + unsigned int i; REQUIRE(mem != NULL); REQUIRE(view != NULL); @@ -2054,6 +2419,30 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr, adb->shutting_down = ISC_FALSE; ISC_LIST_INIT(adb->whenshutdown); + adb->nentries = nbuckets[0]; + adb->entriescnt = 0; + adb->entries = NULL; + adb->deadentries = NULL; + adb->entry_sd = NULL; + adb->entry_refcnt = NULL; + adb->entrylocks = NULL; + ISC_EVENT_INIT(&adb->growentries, sizeof(adb->growentries), 0, NULL, + DNS_EVENT_ADBGROWENTRIES, grow_entries, adb, + adb, NULL, NULL); + adb->growentries_sent = ISC_FALSE; + + adb->nnames = nbuckets[0]; + adb->namescnt = 0; + adb->names = NULL; + adb->deadnames = NULL; + adb->name_sd = NULL; + adb->name_refcnt = NULL; + adb->namelocks = NULL; + ISC_EVENT_INIT(&adb->grownames, sizeof(adb->grownames), 0, NULL, + DNS_EVENT_ADBGROWNAMES, grow_names, adb, + adb, NULL, NULL); + adb->grownames_sent = ISC_FALSE; + isc_mem_attach(mem, &adb->mctx); result = isc_mutex_init(&adb->lock); @@ -2072,28 +2461,68 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr, if (result != ISC_R_SUCCESS) goto fail0e; + result = isc_mutex_init(&adb->entriescntlock); + if (result != ISC_R_SUCCESS) + goto fail0f; + + result = isc_mutex_init(&adb->namescntlock); + if (result != ISC_R_SUCCESS) + goto fail0g; + +#define ALLOCENTRY(adb, el) \ + do { \ + (adb)->el = isc_mem_get((adb)->mctx, \ + sizeof(*(adb)->el) * (adb)->nentries); \ + if ((adb)->el == NULL) { \ + result = ISC_R_NOMEMORY; \ + goto fail1; \ + }\ + } while (0) + ALLOCENTRY(adb, entries); + ALLOCENTRY(adb, deadentries); + ALLOCENTRY(adb, entrylocks); + ALLOCENTRY(adb, entry_sd); + ALLOCENTRY(adb, entry_refcnt); +#undef ALLOCENTRY + +#define ALLOCNAME(adb, el) \ + do { \ + (adb)->el = isc_mem_get((adb)->mctx, \ + sizeof(*(adb)->el) * (adb)->nnames); \ + if ((adb)->el == NULL) { \ + result = ISC_R_NOMEMORY; \ + goto fail1; \ + }\ + } while (0) + ALLOCNAME(adb, names); + ALLOCNAME(adb, deadnames); + ALLOCNAME(adb, namelocks); + ALLOCNAME(adb, name_sd); + ALLOCNAME(adb, name_refcnt); +#undef ALLOCNAME + /* * Initialize the bucket locks for names and elements. * May as well initialize the list heads, too. */ - result = isc_mutexblock_init(adb->namelocks, NBUCKETS); + result = isc_mutexblock_init(adb->namelocks, adb->nnames); if (result != ISC_R_SUCCESS) goto fail1; - for (i = 0; i < NBUCKETS; i++) { + for (i = 0; i < adb->nnames; i++) { ISC_LIST_INIT(adb->names[i]); ISC_LIST_INIT(adb->deadnames[i]); adb->name_sd[i] = ISC_FALSE; adb->name_refcnt[i] = 0; adb->irefcnt++; } - for (i = 0; i < NBUCKETS; i++) { + for (i = 0; i < adb->nentries; i++) { ISC_LIST_INIT(adb->entries[i]); ISC_LIST_INIT(adb->deadentries[i]); adb->entry_sd[i] = ISC_FALSE; adb->entry_refcnt[i] = 0; adb->irefcnt++; } - result = isc_mutexblock_init(adb->entrylocks, NBUCKETS); + result = isc_mutexblock_init(adb->entrylocks, adb->nentries); if (result != ISC_R_SUCCESS) goto fail2; @@ -2140,12 +2569,42 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr, isc_task_detach(&adb->task); /* clean up entrylocks */ - DESTROYMUTEXBLOCK(adb->entrylocks, NBUCKETS); + DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries); fail2: /* clean up namelocks */ - DESTROYMUTEXBLOCK(adb->namelocks, NBUCKETS); + DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames); fail1: /* clean up only allocated memory */ + if (adb->entries != NULL) + isc_mem_put(adb->mctx, adb->entries, + sizeof(*adb->entries) * adb->nentries); + if (adb->deadentries != NULL) + isc_mem_put(adb->mctx, adb->deadentries, + sizeof(*adb->deadentries) * adb->nentries); + if (adb->entrylocks != NULL) + isc_mem_put(adb->mctx, adb->entrylocks, + sizeof(*adb->entrylocks) * adb->nentries); + if (adb->entry_sd != NULL) + isc_mem_put(adb->mctx, adb->entry_sd, + sizeof(*adb->entry_sd) * adb->nentries); + if (adb->entry_refcnt != NULL) + isc_mem_put(adb->mctx, adb->entry_refcnt, + sizeof(*adb->entry_refcnt) * adb->nentries); + if (adb->names != NULL) + isc_mem_put(adb->mctx, adb->names, + sizeof(*adb->names) * adb->nnames); + if (adb->deadnames != NULL) + isc_mem_put(adb->mctx, adb->deadnames, + sizeof(*adb->deadnames) * adb->nnames); + if (adb->namelocks != NULL) + isc_mem_put(adb->mctx, adb->namelocks, + sizeof(*adb->namelocks) * adb->nnames); + if (adb->name_sd != NULL) + isc_mem_put(adb->mctx, adb->name_sd, + sizeof(*adb->name_sd) * adb->nnames); + if (adb->name_refcnt != NULL) + isc_mem_put(adb->mctx, adb->name_refcnt, + sizeof(*adb->name_refcnt) * adb->nnames); if (adb->nmp != NULL) isc_mempool_destroy(&adb->nmp); if (adb->nhmp != NULL) @@ -2161,6 +2620,10 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr, if (adb->afmp != NULL) isc_mempool_destroy(&adb->afmp); + DESTROYLOCK(&adb->namescntlock); + fail0g: + DESTROYLOCK(&adb->entriescntlock); + fail0f: DESTROYLOCK(&adb->overmemlock); fail0e: DESTROYLOCK(&adb->reflock); @@ -2728,7 +3191,7 @@ dns_adb_cancelfind(dns_adbfind_t *find) { void dns_adb_dump(dns_adb_t *adb, FILE *f) { - int i; + unsigned int i; isc_stdtime_t now; REQUIRE(DNS_ADB_VALID(adb)); @@ -2744,9 +3207,9 @@ dns_adb_dump(dns_adb_t *adb, FILE *f) { LOCK(&adb->lock); isc_stdtime_get(&now); - for (i = 0; i < NBUCKETS; i++) + for (i = 0; i < adb->nnames; i++) RUNTIME_CHECK(cleanup_names(adb, i, now) == ISC_FALSE); - for (i = 0; i < NBUCKETS; i++) + for (i = 0; i < adb->nentries; i++) RUNTIME_CHECK(cleanup_entries(adb, i, now) == ISC_FALSE); dump_adb(adb, f, ISC_FALSE, now); @@ -2762,7 +3225,7 @@ dump_ttl(FILE *f, const char *legend, isc_stdtime_t value, isc_stdtime_t now) { static void dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) { - int i; + unsigned int i; dns_adbname_t *name; dns_adbentry_t *entry; @@ -2772,15 +3235,15 @@ dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) { adb, adb->erefcnt, adb->irefcnt, isc_mempool_getallocated(adb->nhmp)); - for (i = 0; i < NBUCKETS; i++) + for (i = 0; i < adb->nnames; i++) LOCK(&adb->namelocks[i]); - for (i = 0; i < NBUCKETS; i++) + for (i = 0; i < adb->nentries; i++) LOCK(&adb->entrylocks[i]); /* * Dump the names */ - for (i = 0; i < NBUCKETS; i++) { + for (i = 0; i < adb->nnames; i++) { name = ISC_LIST_HEAD(adb->names[i]); if (name == NULL) continue; @@ -2824,7 +3287,7 @@ dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) { fprintf(f, ";\n; Unassociated entries\n;\n"); - for (i = 0; i < NBUCKETS; i++) { + for (i = 0; i < adb->nentries; i++) { entry = ISC_LIST_HEAD(adb->entries[i]); while (entry != NULL) { if (entry->refcnt == 0) @@ -2836,9 +3299,9 @@ dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) { /* * Unlock everything */ - for (i = 0; i < NBUCKETS; i++) + for (i = 0; i < adb->nentries; i++) UNLOCK(&adb->entrylocks[i]); - for (i = 0; i < NBUCKETS; i++) + for (i = 0; i < adb->nnames; i++) UNLOCK(&adb->namelocks[i]); } @@ -2999,10 +3462,20 @@ dbfind_name(dns_adbname_t *adbname, isc_stdtime_t now, dns_rdatatype_t rdtype) else adbname->fetch6_err = FIND_ERR_UNEXPECTED; - result = dns_view_find(adb->view, &adbname->name, rdtype, now, - NAME_GLUEOK(adbname) ? DNS_DBFIND_GLUEOK : 0, - ISC_TF(NAME_HINTOK(adbname)), - NULL, NULL, fname, &rdataset, NULL); + /* + * We need to specify whether to search static-stub zones (if + * configured) depending on whether this is a "start at zone" lookup, + * i.e., whether it's a "bailiwick" glue. If it's bailiwick (in which + * case NAME_STARTATZONE is set) we need to stop the search at any + * matching static-stub zone without looking into the cache to honor + * the configuration on which server we should send queries to. + */ + result = dns_view_find2(adb->view, &adbname->name, rdtype, now, + NAME_GLUEOK(adbname) ? DNS_DBFIND_GLUEOK : 0, + ISC_TF(NAME_HINTOK(adbname)), + (adbname->flags & NAME_STARTATZONE) != 0 ? + ISC_TRUE : ISC_FALSE, + NULL, NULL, fname, &rdataset, NULL); /* XXXVIX this switch statement is too sparse to gen a jump table. */ switch (result) { @@ -3557,9 +4030,9 @@ dns_adb_flush(dns_adb_t *adb) { /* * Call our cleanup routines. */ - for (i = 0; i < NBUCKETS; i++) + for (i = 0; i < adb->nnames; i++) RUNTIME_CHECK(cleanup_names(adb, i, INT_MAX) == ISC_FALSE); - for (i = 0; i < NBUCKETS; i++) + for (i = 0; i < adb->nentries; i++) RUNTIME_CHECK(cleanup_entries(adb, i, INT_MAX) == ISC_FALSE); #ifdef DUMP_ADB_AFTER_CLEANING @@ -3578,7 +4051,7 @@ dns_adb_flushname(dns_adb_t *adb, dns_name_t *name) { INSIST(DNS_ADB_VALID(adb)); LOCK(&adb->lock); - bucket = dns_name_hash(name, ISC_FALSE) % NBUCKETS; + bucket = dns_name_hash(name, ISC_FALSE) % adb->nnames; LOCK(&adb->namelocks[bucket]); adbname = ISC_LIST_HEAD(adb->names[bucket]); while (adbname != NULL) { diff --git a/lib/dns/api b/lib/dns/api index 87c3c90..9bac060 100644 --- a/lib/dns/api +++ b/lib/dns/api @@ -1,3 +1,3 @@ -LIBINTERFACE = 59 -LIBREVISION = 5 +LIBINTERFACE = 82 +LIBREVISION = 3 LIBAGE = 1 diff --git a/lib/dns/byaddr.c b/lib/dns/byaddr.c index 96b9f38..2fd61a2 100644 --- a/lib/dns/byaddr.c +++ b/lib/dns/byaddr.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: byaddr.c,v 1.39 2007-06-19 23:47:16 tbox Exp $ */ +/* $Id: byaddr.c,v 1.41 2009-09-02 23:48:02 tbox Exp $ */ /*! \file */ @@ -43,25 +43,6 @@ * XXXRTH We could use a static event... */ -struct dns_byaddr { - /* Unlocked. */ - unsigned int magic; - isc_mem_t * mctx; - isc_mutex_t lock; - dns_fixedname_t name; - /* Locked by lock. */ - unsigned int options; - dns_lookup_t * lookup; - isc_task_t * task; - dns_byaddrevent_t * event; - isc_boolean_t canceled; -}; - -#define BYADDR_MAGIC ISC_MAGIC('B', 'y', 'A', 'd') -#define VALID_BYADDR(b) ISC_MAGIC_VALID(b, BYADDR_MAGIC) - -#define MAX_RESTARTS 16 - static char hex_digits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' @@ -125,10 +106,29 @@ dns_byaddr_createptrname2(isc_netaddr_t *address, unsigned int options, len = (unsigned int)strlen(textname); isc_buffer_init(&buffer, textname, len); isc_buffer_add(&buffer, len); - return (dns_name_fromtext(name, &buffer, dns_rootname, - ISC_FALSE, NULL)); + return (dns_name_fromtext(name, &buffer, dns_rootname, 0, NULL)); } +#ifdef BIND9 +struct dns_byaddr { + /* Unlocked. */ + unsigned int magic; + isc_mem_t * mctx; + isc_mutex_t lock; + dns_fixedname_t name; + /* Locked by lock. */ + unsigned int options; + dns_lookup_t * lookup; + isc_task_t * task; + dns_byaddrevent_t * event; + isc_boolean_t canceled; +}; + +#define BYADDR_MAGIC ISC_MAGIC('B', 'y', 'A', 'd') +#define VALID_BYADDR(b) ISC_MAGIC_VALID(b, BYADDR_MAGIC) + +#define MAX_RESTARTS 16 + static inline isc_result_t copy_ptr_targets(dns_byaddr_t *byaddr, dns_rdataset_t *rdataset) { isc_result_t result; @@ -314,3 +314,4 @@ dns_byaddr_destroy(dns_byaddr_t **byaddrp) { *byaddrp = NULL; } +#endif /* BIND9 */ diff --git a/lib/dns/cache.c b/lib/dns/cache.c index 28ead66..bf93da2 100644 --- a/lib/dns/cache.c +++ b/lib/dns/cache.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: cache.c,v 1.80.50.3 2009-05-06 23:34:30 jinmei Exp $ */ +/* $Id: cache.c,v 1.87 2009-11-12 23:43:02 each Exp $ */ /*! \file */ @@ -122,6 +122,7 @@ struct dns_cache { isc_mutex_t lock; isc_mutex_t filelock; isc_mem_t *mctx; + char *name; /* Locked by 'lock'. */ int references; @@ -132,6 +133,7 @@ struct dns_cache { char *db_type; int db_argc; char **db_argv; + isc_uint32_t size; /* Locked by 'filelock'. */ char *filename; @@ -171,6 +173,16 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, const char *db_type, unsigned int db_argc, char **db_argv, dns_cache_t **cachep) { + return (dns_cache_create2(mctx, taskmgr, timermgr, rdclass, "", + db_type, db_argc, db_argv, cachep)); +} + +isc_result_t +dns_cache_create2(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, + isc_timermgr_t *timermgr, dns_rdataclass_t rdclass, + const char *cachename, const char *db_type, + unsigned int db_argc, char **db_argv, dns_cache_t **cachep) +{ isc_result_t result; dns_cache_t *cache; int i; @@ -179,6 +191,7 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, REQUIRE(cachep != NULL); REQUIRE(*cachep == NULL); REQUIRE(mctx != NULL); + REQUIRE(cachename != NULL); cache = isc_mem_get(mctx, sizeof(*cache)); if (cache == NULL) @@ -187,6 +200,15 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, cache->mctx = NULL; isc_mem_attach(mctx, &cache->mctx); + cache->name = NULL; + if (cachename != NULL) { + cache->name = isc_mem_strdup(mctx, cachename); + if (cache->name == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup_mem; + } + } + result = isc_mutex_init(&cache->lock); if (result != ISC_R_SUCCESS) goto cleanup_mem; @@ -275,6 +297,8 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, cleanup_lock: DESTROYLOCK(&cache->lock); cleanup_mem: + if (cache->name != NULL) + isc_mem_free(mctx, cache->name); isc_mem_put(mctx, cache, sizeof(*cache)); isc_mem_detach(&mctx); return (result); @@ -323,6 +347,9 @@ cache_free(dns_cache_t *cache) { if (cache->db_type != NULL) isc_mem_free(cache->mctx, cache->db_type); + if (cache->name != NULL) + isc_mem_free(cache->mctx, cache->name); + DESTROYLOCK(&cache->lock); DESTROYLOCK(&cache->filelock); cache->magic = 0; @@ -423,6 +450,7 @@ dns_cache_setfilename(dns_cache_t *cache, const char *filename) { return (ISC_R_SUCCESS); } +#ifdef BIND9 isc_result_t dns_cache_load(dns_cache_t *cache) { isc_result_t result; @@ -438,22 +466,29 @@ dns_cache_load(dns_cache_t *cache) { return (result); } +#endif /* BIND9 */ isc_result_t dns_cache_dump(dns_cache_t *cache) { +#ifdef BIND9 isc_result_t result; +#endif REQUIRE(VALID_CACHE(cache)); if (cache->filename == NULL) return (ISC_R_SUCCESS); +#ifdef BIND9 LOCK(&cache->filelock); result = dns_master_dump(cache->mctx, cache->db, NULL, &dns_master_style_cache, cache->filename); UNLOCK(&cache->filelock); - return (result); +#else + return (ISC_R_NOTIMPLEMENTED); +#endif + } void @@ -493,6 +528,26 @@ dns_cache_setcleaninginterval(dns_cache_t *cache, unsigned int t) { UNLOCK(&cache->lock); } +unsigned int +dns_cache_getcleaninginterval(dns_cache_t *cache) { + unsigned int t; + + REQUIRE(VALID_CACHE(cache)); + + LOCK(&cache->lock); + t = cache->cleaner.cleaning_interval; + UNLOCK(&cache->lock); + + return (t); +} + +const char * +dns_cache_getname(dns_cache_t *cache) { + REQUIRE(VALID_CACHE(cache)); + + return (cache->name); +} + /* * Initialize the cache cleaner object at *cleaner. * Space for the object must be allocated by the caller. @@ -519,6 +574,7 @@ cache_cleaner_init(dns_cache_t *cache, isc_taskmgr_t *taskmgr, cleaner->cleaning_timer = NULL; cleaner->resched_event = NULL; cleaner->overmem_event = NULL; + cleaner->cleaning_interval = 0; /* Initially turned off. */ result = dns_db_createiterator(cleaner->cache->db, ISC_FALSE, &cleaner->iterator); @@ -547,7 +603,6 @@ cache_cleaner_init(dns_cache_t *cache, isc_taskmgr_t *taskmgr, goto cleanup; } - cleaner->cleaning_interval = 0; /* Initially turned off. */ result = isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL, cleaner->task, cleaning_timer_action, cleaner, @@ -949,6 +1004,10 @@ dns_cache_setcachesize(dns_cache_t *cache, isc_uint32_t size) { if (size != 0 && size < DNS_CACHE_MINSIZE) size = DNS_CACHE_MINSIZE; + LOCK(&cache->lock); + cache->size = size; + UNLOCK(&cache->lock); + hiwater = size - (size >> 3); /* Approximately 7/8ths. */ lowater = size - (size >> 2); /* Approximately 3/4ths. */ @@ -972,6 +1031,19 @@ dns_cache_setcachesize(dns_cache_t *cache, isc_uint32_t size) { isc_mem_setwater(cache->mctx, water, cache, hiwater, lowater); } +isc_uint32_t +dns_cache_getcachesize(dns_cache_t *cache) { + isc_uint32_t size; + + REQUIRE(VALID_CACHE(cache)); + + LOCK(&cache->lock); + size = cache->size; + UNLOCK(&cache->lock); + + return (size); +} + /* * The cleaner task is shutting down; do the necessary cleanup. */ diff --git a/lib/dns/client.c b/lib/dns/client.c new file mode 100644 index 0000000..e55ea1f --- /dev/null +++ b/lib/dns/client.c @@ -0,0 +1,3019 @@ +/* + * Copyright (C) 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: client.c,v 1.12 2010-12-03 12:03:22 marka Exp $ */ + +#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 + +#include + +#define DNS_CLIENT_MAGIC ISC_MAGIC('D', 'N', 'S', 'c') +#define DNS_CLIENT_VALID(c) ISC_MAGIC_VALID(c, DNS_CLIENT_MAGIC) + +#define RCTX_MAGIC ISC_MAGIC('R', 'c', 't', 'x') +#define RCTX_VALID(c) ISC_MAGIC_VALID(c, RCTX_MAGIC) + +#define REQCTX_MAGIC ISC_MAGIC('R', 'q', 'c', 'x') +#define REQCTX_VALID(c) ISC_MAGIC_VALID(c, REQCTX_MAGIC) + +#define UCTX_MAGIC ISC_MAGIC('U', 'c', 't', 'x') +#define UCTX_VALID(c) ISC_MAGIC_VALID(c, UCTX_MAGIC) + +#define MAX_RESTARTS 16 + +/*% + * DNS client object + */ +struct dns_client { + /* Unlocked */ + unsigned int magic; + unsigned int attributes; + isc_mutex_t lock; + isc_mem_t *mctx; + isc_appctx_t *actx; + isc_taskmgr_t *taskmgr; + isc_task_t *task; + isc_socketmgr_t *socketmgr; + isc_timermgr_t *timermgr; + dns_dispatchmgr_t *dispatchmgr; + dns_dispatch_t *dispatchv4; + dns_dispatch_t *dispatchv6; + + unsigned int update_timeout; + unsigned int update_udptimeout; + unsigned int update_udpretries; + unsigned int find_timeout; + unsigned int find_udpretries; + + /* Locked */ + unsigned int references; + dns_viewlist_t viewlist; + ISC_LIST(struct resctx) resctxs; + ISC_LIST(struct reqctx) reqctxs; + ISC_LIST(struct updatectx) updatectxs; +}; + +/*% + * Timeout/retry constants for dynamic update borrowed from nsupdate + */ +#define DEF_UPDATE_TIMEOUT 300 +#define MIN_UPDATE_TIMEOUT 30 +#define DEF_UPDATE_UDPTIMEOUT 3 +#define DEF_UPDATE_UDPRETRIES 3 + +#define DEF_FIND_TIMEOUT 5 +#define DEF_FIND_UDPRETRIES 3 + +#define DNS_CLIENTATTR_OWNCTX 0x01 + +#define DNS_CLIENTVIEW_NAME "dnsclient" + +/*% + * Internal state for a single name resolution procedure + */ +typedef struct resctx { + /* Unlocked */ + unsigned int magic; + isc_mutex_t lock; + dns_client_t *client; + isc_boolean_t want_dnssec; + + /* Locked */ + ISC_LINK(struct resctx) link; + isc_task_t *task; + dns_view_t *view; + unsigned int restarts; + dns_fixedname_t name; + dns_rdatatype_t type; + dns_fetch_t *fetch; + dns_namelist_t namelist; + isc_result_t result; + dns_clientresevent_t *event; + isc_boolean_t canceled; + dns_rdataset_t *rdataset; + dns_rdataset_t *sigrdataset; +} resctx_t; + +/*% + * Argument of an internal event for synchronous name resolution. + */ +typedef struct resarg { + /* Unlocked */ + isc_appctx_t *actx; + dns_client_t *client; + isc_mutex_t lock; + + /* Locked */ + isc_result_t result; + isc_result_t vresult; + dns_namelist_t *namelist; + dns_clientrestrans_t *trans; + isc_boolean_t canceled; +} resarg_t; + +/*% + * Internal state for a single DNS request + */ +typedef struct reqctx { + /* Unlocked */ + unsigned int magic; + isc_mutex_t lock; + dns_client_t *client; + unsigned int parseoptions; + + /* Locked */ + ISC_LINK(struct reqctx) link; + isc_boolean_t canceled; + dns_tsigkey_t *tsigkey; + dns_request_t *request; + dns_clientreqevent_t *event; +} reqctx_t; + +/*% + * Argument of an internal event for synchronous DNS request. + */ +typedef struct reqarg { + /* Unlocked */ + isc_appctx_t *actx; + dns_client_t *client; + isc_mutex_t lock; + + /* Locked */ + isc_result_t result; + dns_clientreqtrans_t *trans; + isc_boolean_t canceled; +} reqarg_t; + +/*% + * Argument of an internal event for synchronous name resolution. + */ +typedef struct updatearg { + /* Unlocked */ + isc_appctx_t *actx; + dns_client_t *client; + isc_mutex_t lock; + + /* Locked */ + isc_result_t result; + dns_clientupdatetrans_t *trans; + isc_boolean_t canceled; +} updatearg_t; + +/*% + * Internal state for a single dynamic update procedure + */ +typedef struct updatectx { + /* Unlocked */ + unsigned int magic; + isc_mutex_t lock; + dns_client_t *client; + + /* Locked */ + dns_request_t *updatereq; + dns_request_t *soareq; + dns_clientrestrans_t *restrans; + dns_clientrestrans_t *restrans2; + isc_boolean_t canceled; + + /* Task Locked */ + ISC_LINK(struct updatectx) link; + dns_clientupdatestate_t state; + dns_rdataclass_t rdclass; + dns_view_t *view; + dns_message_t *updatemsg; + dns_message_t *soaquery; + dns_clientupdateevent_t *event; + dns_tsigkey_t *tsigkey; + dst_key_t *sig0key; + dns_name_t *firstname; + dns_name_t soaqname; + dns_fixedname_t zonefname; + dns_name_t *zonename; + isc_sockaddrlist_t servers; + unsigned int nservers; + isc_sockaddr_t *currentserver; + struct updatectx *bp4; + struct updatectx *bp6; +} updatectx_t; + +static isc_result_t request_soa(updatectx_t *uctx); +static void client_resfind(resctx_t *rctx, dns_fetchevent_t *event); +static isc_result_t send_update(updatectx_t *uctx); + +static isc_result_t +getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr, + isc_socketmgr_t *socketmgr, isc_taskmgr_t *taskmgr, + isc_boolean_t is_shared, dns_dispatch_t **dispp) +{ + unsigned int attrs, attrmask; + isc_sockaddr_t sa; + dns_dispatch_t *disp; + unsigned buffersize, maxbuffers, maxrequests, buckets, increment; + isc_result_t result; + + attrs = 0; + attrs |= DNS_DISPATCHATTR_UDP; + switch (family) { + case AF_INET: + attrs |= DNS_DISPATCHATTR_IPV4; + break; + case AF_INET6: + attrs |= DNS_DISPATCHATTR_IPV6; + break; + default: + INSIST(0); + } + attrmask = 0; + attrmask |= DNS_DISPATCHATTR_UDP; + attrmask |= DNS_DISPATCHATTR_TCP; + attrmask |= DNS_DISPATCHATTR_IPV4; + attrmask |= DNS_DISPATCHATTR_IPV6; + + isc_sockaddr_anyofpf(&sa, family); + + buffersize = 4096; + maxbuffers = is_shared ? 1000 : 8; + maxrequests = 32768; + buckets = is_shared ? 16411 : 3; + increment = is_shared ? 16433 : 5; + + disp = NULL; + result = dns_dispatch_getudp(dispatchmgr, socketmgr, + taskmgr, &sa, + buffersize, maxbuffers, maxrequests, + buckets, increment, + attrs, attrmask, &disp); + if (result == ISC_R_SUCCESS) + *dispp = disp; + + return (result); +} + +static isc_result_t +dns_client_createview(isc_mem_t *mctx, dns_rdataclass_t rdclass, + unsigned int options, isc_taskmgr_t *taskmgr, + unsigned int ntasks, isc_socketmgr_t *socketmgr, + isc_timermgr_t *timermgr, dns_dispatchmgr_t *dispatchmgr, + dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6, + dns_view_t **viewp) +{ + isc_result_t result; + dns_view_t *view = NULL; + const char *dbtype; + + result = dns_view_create(mctx, rdclass, DNS_CLIENTVIEW_NAME, &view); + if (result != ISC_R_SUCCESS) + return (result); + + /* Initialize view security roots */ + result = dns_view_initsecroots(view, mctx); + if (result != ISC_R_SUCCESS) { + dns_view_detach(&view); + return (result); + } + + result = dns_view_createresolver(view, taskmgr, ntasks, socketmgr, + timermgr, 0, dispatchmgr, + dispatchv4, dispatchv6); + if (result != ISC_R_SUCCESS) { + dns_view_detach(&view); + return (result); + } + + /* + * Set cache DB. + * XXX: it may be better if specific DB implementations can be + * specified via some configuration knob. + */ + if ((options & DNS_CLIENTCREATEOPT_USECACHE) != 0) + dbtype = "rbt"; + else + dbtype = "ecdb"; + result = dns_db_create(mctx, dbtype, dns_rootname, dns_dbtype_cache, + rdclass, 0, NULL, &view->cachedb); + if (result != ISC_R_SUCCESS) { + dns_view_detach(&view); + return (result); + } + + *viewp = view; + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_client_create(dns_client_t **clientp, unsigned int options) { + isc_result_t result; + isc_mem_t *mctx = NULL; + isc_appctx_t *actx = NULL; + isc_taskmgr_t *taskmgr = NULL; + isc_socketmgr_t *socketmgr = NULL; + isc_timermgr_t *timermgr = NULL; + + result = isc_mem_create(0, 0, &mctx); + if (result != ISC_R_SUCCESS) + return (result); + result = isc_appctx_create(mctx, &actx); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = isc_app_ctxstart(actx); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = isc_taskmgr_createinctx(mctx, actx, 1, 0, &taskmgr); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = isc_socketmgr_createinctx(mctx, actx, &socketmgr); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = isc_timermgr_createinctx(mctx, actx, &timermgr); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = dns_client_createx(mctx, actx, taskmgr, socketmgr, timermgr, + options, clientp); + if (result != ISC_R_SUCCESS) + goto cleanup; + + (*clientp)->attributes |= DNS_CLIENTATTR_OWNCTX; + + /* client has its own reference to mctx, so we can detach it here */ + isc_mem_detach(&mctx); + + return (ISC_R_SUCCESS); + + cleanup: + if (taskmgr != NULL) + isc_taskmgr_destroy(&taskmgr); + if (timermgr != NULL) + isc_timermgr_destroy(&timermgr); + if (socketmgr != NULL) + isc_socketmgr_destroy(&socketmgr); + if (actx != NULL) + isc_appctx_destroy(&actx); + isc_mem_detach(&mctx); + + return (result); +} + +isc_result_t +dns_client_createx(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr, + isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr, + unsigned int options, dns_client_t **clientp) +{ + dns_client_t *client; + isc_result_t result; + dns_dispatchmgr_t *dispatchmgr = NULL; + dns_dispatch_t *dispatchv4 = NULL; + dns_dispatch_t *dispatchv6 = NULL; + dns_view_t *view = NULL; + + REQUIRE(mctx != NULL); + REQUIRE(taskmgr != NULL); + REQUIRE(timermgr != NULL); + REQUIRE(socketmgr != NULL); + REQUIRE(clientp != NULL && *clientp == NULL); + + client = isc_mem_get(mctx, sizeof(*client)); + if (client == NULL) + return (ISC_R_NOMEMORY); + + result = isc_mutex_init(&client->lock); + if (result != ISC_R_SUCCESS) { + isc_mem_put(mctx, client, sizeof(*client)); + return (result); + } + + client->actx = actx; + client->taskmgr = taskmgr; + client->socketmgr = socketmgr; + client->timermgr = timermgr; + + client->task = NULL; + result = isc_task_create(client->taskmgr, 0, &client->task); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = dns_dispatchmgr_create(mctx, NULL, &dispatchmgr); + if (result != ISC_R_SUCCESS) + goto cleanup; + client->dispatchmgr = dispatchmgr; + + /* TODO: whether to use dispatch v4 or v6 should be configurable */ + client->dispatchv4 = NULL; + client->dispatchv6 = NULL; + result = getudpdispatch(AF_INET, dispatchmgr, socketmgr, + taskmgr, ISC_TRUE, &dispatchv4); + if (result == ISC_R_SUCCESS) + client->dispatchv4 = dispatchv4; + result = getudpdispatch(AF_INET6, dispatchmgr, socketmgr, + taskmgr, ISC_TRUE, &dispatchv6); + if (result == ISC_R_SUCCESS) + client->dispatchv6 = dispatchv6; + + /* We need at least one of the dispatchers */ + if (dispatchv4 == NULL && dispatchv6 == NULL) { + INSIST(result != ISC_R_SUCCESS); + goto cleanup; + } + + /* Create the default view for class IN */ + result = dns_client_createview(mctx, dns_rdataclass_in, options, + taskmgr, 31, socketmgr, timermgr, + dispatchmgr, dispatchv4, dispatchv6, + &view); + if (result != ISC_R_SUCCESS) + goto cleanup; + ISC_LIST_INIT(client->viewlist); + ISC_LIST_APPEND(client->viewlist, view, link); + + dns_view_freeze(view); /* too early? */ + + ISC_LIST_INIT(client->resctxs); + ISC_LIST_INIT(client->reqctxs); + ISC_LIST_INIT(client->updatectxs); + + client->mctx = NULL; + isc_mem_attach(mctx, &client->mctx); + + client->update_timeout = DEF_UPDATE_TIMEOUT; + client->update_udptimeout = DEF_UPDATE_UDPTIMEOUT; + client->update_udpretries = DEF_UPDATE_UDPRETRIES; + client->find_timeout = DEF_FIND_TIMEOUT; + client->find_udpretries = DEF_FIND_UDPRETRIES; + + client->references = 1; + client->magic = DNS_CLIENT_MAGIC; + + *clientp = client; + + return (ISC_R_SUCCESS); + + cleanup: + if (dispatchv4 != NULL) + dns_dispatch_detach(&dispatchv4); + if (dispatchv6 != NULL) + dns_dispatch_detach(&dispatchv6); + if (dispatchmgr != NULL) + dns_dispatchmgr_destroy(&dispatchmgr); + if (client->task != NULL) + isc_task_detach(&client->task); + isc_mem_put(mctx, client, sizeof(*client)); + + return (result); +} + +static void +destroyclient(dns_client_t **clientp) { + dns_client_t *client = *clientp; + dns_view_t *view; + + while ((view = ISC_LIST_HEAD(client->viewlist)) != NULL) { + ISC_LIST_UNLINK(client->viewlist, view, link); + dns_view_detach(&view); + } + + if (client->dispatchv4 != NULL) + dns_dispatch_detach(&client->dispatchv4); + if (client->dispatchv6 != NULL) + dns_dispatch_detach(&client->dispatchv6); + + dns_dispatchmgr_destroy(&client->dispatchmgr); + + isc_task_detach(&client->task); + + /* + * If the client has created its own running environments, + * destroy them. + */ + if ((client->attributes & DNS_CLIENTATTR_OWNCTX) != 0) { + isc_taskmgr_destroy(&client->taskmgr); + isc_timermgr_destroy(&client->timermgr); + isc_socketmgr_destroy(&client->socketmgr); + + isc_app_ctxfinish(client->actx); + isc_appctx_destroy(&client->actx); + } + + DESTROYLOCK(&client->lock); + client->magic = 0; + + isc_mem_putanddetach(&client->mctx, client, sizeof(*client)); + + *clientp = NULL; +} + +void +dns_client_destroy(dns_client_t **clientp) { + dns_client_t *client; + isc_boolean_t destroyok = ISC_FALSE; + + REQUIRE(clientp != NULL); + client = *clientp; + REQUIRE(DNS_CLIENT_VALID(client)); + + LOCK(&client->lock); + client->references--; + if (client->references == 0 && ISC_LIST_EMPTY(client->resctxs) && + ISC_LIST_EMPTY(client->reqctxs) && + ISC_LIST_EMPTY(client->updatectxs)) { + destroyok = ISC_TRUE; + } + UNLOCK(&client->lock); + + if (destroyok) + destroyclient(&client); + + *clientp = NULL; +} + +isc_result_t +dns_client_setservers(dns_client_t *client, dns_rdataclass_t rdclass, + dns_name_t *namespace, isc_sockaddrlist_t *addrs) +{ + isc_result_t result; + dns_view_t *view = NULL; + + REQUIRE(DNS_CLIENT_VALID(client)); + REQUIRE(addrs != NULL); + + if (namespace == NULL) + namespace = dns_rootname; + + LOCK(&client->lock); + result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME, + rdclass, &view); + if (result != ISC_R_SUCCESS) { + UNLOCK(&client->lock); + return (result); + } + UNLOCK(&client->lock); + + result = dns_fwdtable_add(view->fwdtable, namespace, addrs, + dns_fwdpolicy_only); + + dns_view_detach(&view); + + return (result); +} + +isc_result_t +dns_client_clearservers(dns_client_t *client, dns_rdataclass_t rdclass, + dns_name_t *namespace) +{ + isc_result_t result; + dns_view_t *view = NULL; + + REQUIRE(DNS_CLIENT_VALID(client)); + + if (namespace == NULL) + namespace = dns_rootname; + + LOCK(&client->lock); + result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME, + rdclass, &view); + if (result != ISC_R_SUCCESS) { + UNLOCK(&client->lock); + return (result); + } + UNLOCK(&client->lock); + + result = dns_fwdtable_delete(view->fwdtable, namespace); + + dns_view_detach(&view); + + return (result); +} + +static isc_result_t +getrdataset(isc_mem_t *mctx, dns_rdataset_t **rdatasetp) { + dns_rdataset_t *rdataset; + + REQUIRE(mctx != NULL); + REQUIRE(rdatasetp != NULL && *rdatasetp == NULL); + + rdataset = isc_mem_get(mctx, sizeof(*rdataset)); + if (rdataset == NULL) + return (ISC_R_NOMEMORY); + + dns_rdataset_init(rdataset); + + *rdatasetp = rdataset; + + return (ISC_R_SUCCESS); +} + +static void +putrdataset(isc_mem_t *mctx, dns_rdataset_t **rdatasetp) { + dns_rdataset_t *rdataset; + + REQUIRE(rdatasetp != NULL); + rdataset = *rdatasetp; + REQUIRE(rdataset != NULL); + + if (dns_rdataset_isassociated(rdataset)) + dns_rdataset_disassociate(rdataset); + + isc_mem_put(mctx, rdataset, sizeof(*rdataset)); + + *rdatasetp = NULL; +} + +static void +fetch_done(isc_task_t *task, isc_event_t *event) { + resctx_t *rctx = event->ev_arg; + dns_fetchevent_t *fevent; + + REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE); + REQUIRE(RCTX_VALID(rctx)); + REQUIRE(rctx->task == task); + fevent = (dns_fetchevent_t *)event; + + client_resfind(rctx, fevent); +} + +static inline isc_result_t +start_fetch(resctx_t *rctx) { + isc_result_t result; + + /* + * The caller must be holding the rctx's lock. + */ + + REQUIRE(rctx->fetch == NULL); + + result = dns_resolver_createfetch(rctx->view->resolver, + dns_fixedname_name(&rctx->name), + rctx->type, + NULL, NULL, NULL, 0, + rctx->task, fetch_done, rctx, + rctx->rdataset, + rctx->sigrdataset, + &rctx->fetch); + + return (result); +} + +static isc_result_t +view_find(resctx_t *rctx, dns_db_t **dbp, dns_dbnode_t **nodep, + dns_name_t *foundname) +{ + isc_result_t result; + dns_name_t *name = dns_fixedname_name(&rctx->name); + dns_rdatatype_t type; + + if (rctx->type == dns_rdatatype_rrsig) + type = dns_rdatatype_any; + else + type = rctx->type; + + result = dns_view_find(rctx->view, name, type, 0, 0, ISC_FALSE, + dbp, nodep, foundname, rctx->rdataset, + rctx->sigrdataset); + + return (result); +} + +static void +client_resfind(resctx_t *rctx, dns_fetchevent_t *event) { + isc_mem_t *mctx; + isc_result_t result, tresult; + isc_result_t vresult = ISC_R_SUCCESS; + isc_boolean_t want_restart; + isc_boolean_t send_event = ISC_FALSE; + dns_name_t *name, *prefix; + dns_fixedname_t foundname, fixed; + dns_rdataset_t *trdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + unsigned int nlabels; + int order; + dns_namereln_t namereln; + dns_rdata_cname_t cname; + dns_rdata_dname_t dname; + + REQUIRE(RCTX_VALID(rctx)); + + LOCK(&rctx->lock); + + mctx = rctx->view->mctx; + + result = ISC_R_SUCCESS; + name = dns_fixedname_name(&rctx->name); + + do { + dns_name_t *fname = NULL; + dns_name_t *ansname = NULL; + dns_db_t *db = NULL; + dns_dbnode_t *node = NULL; + + rctx->restarts++; + want_restart = ISC_FALSE; + + if (event == NULL && !rctx->canceled) { + dns_fixedname_init(&foundname); + fname = dns_fixedname_name(&foundname); + INSIST(!dns_rdataset_isassociated(rctx->rdataset)); + INSIST(rctx->sigrdataset == NULL || + !dns_rdataset_isassociated(rctx->sigrdataset)); + result = view_find(rctx, &db, &node, fname); + if (result == ISC_R_NOTFOUND) { + /* + * We don't know anything about the name. + * Launch a fetch. + */ + if (node != NULL) { + INSIST(db != NULL); + dns_db_detachnode(db, &node); + } + if (db != NULL) + dns_db_detach(&db); + result = start_fetch(rctx); + if (result != ISC_R_SUCCESS) { + putrdataset(mctx, &rctx->rdataset); + if (rctx->sigrdataset != NULL) + putrdataset(mctx, + &rctx->sigrdataset); + send_event = ISC_TRUE; + } + goto done; + } + } else { + INSIST(event->fetch == rctx->fetch); + dns_resolver_destroyfetch(&rctx->fetch); + db = event->db; + node = event->node; + result = event->result; + vresult = event->vresult; + fname = dns_fixedname_name(&event->foundname); + INSIST(event->rdataset == rctx->rdataset); + INSIST(event->sigrdataset == rctx->sigrdataset); + } + + /* + * If we've been canceled, forget about the result. + */ + if (rctx->canceled) + result = ISC_R_CANCELED; + else { + /* + * Otherwise, get some resource for copying the + * result. + */ + ansname = isc_mem_get(mctx, sizeof(*ansname)); + if (ansname == NULL) + tresult = ISC_R_NOMEMORY; + else { + dns_name_t *aname; + + aname = dns_fixedname_name(&rctx->name); + dns_name_init(ansname, NULL); + tresult = dns_name_dup(aname, mctx, ansname); + if (tresult != ISC_R_SUCCESS) + isc_mem_put(mctx, ansname, + sizeof(*ansname)); + } + if (tresult != ISC_R_SUCCESS) + result = tresult; + } + + switch (result) { + case ISC_R_SUCCESS: + send_event = ISC_TRUE; + /* + * This case is handled in the main line below. + */ + break; + case DNS_R_CNAME: + /* + * Add the CNAME to the answer list. + */ + trdataset = rctx->rdataset; + ISC_LIST_APPEND(ansname->list, rctx->rdataset, link); + rctx->rdataset = NULL; + if (rctx->sigrdataset != NULL) { + ISC_LIST_APPEND(ansname->list, + rctx->sigrdataset, link); + rctx->sigrdataset = NULL; + } + ISC_LIST_APPEND(rctx->namelist, ansname, link); + ansname = NULL; + + /* + * Copy the CNAME's target into the lookup's + * query name and start over. + */ + tresult = dns_rdataset_first(trdataset); + if (tresult != ISC_R_SUCCESS) + goto done; + dns_rdataset_current(trdataset, &rdata); + tresult = dns_rdata_tostruct(&rdata, &cname, NULL); + dns_rdata_reset(&rdata); + if (tresult != ISC_R_SUCCESS) + goto done; + tresult = dns_name_copy(&cname.cname, name, NULL); + dns_rdata_freestruct(&cname); + if (tresult == ISC_R_SUCCESS) + want_restart = ISC_TRUE; + else + result = tresult; + goto done; + case DNS_R_DNAME: + /* + * Add the DNAME to the answer list. + */ + trdataset = rctx->rdataset; + ISC_LIST_APPEND(ansname->list, rctx->rdataset, link); + rctx->rdataset = NULL; + if (rctx->sigrdataset != NULL) { + ISC_LIST_APPEND(ansname->list, + rctx->sigrdataset, link); + rctx->sigrdataset = NULL; + } + ISC_LIST_APPEND(rctx->namelist, ansname, link); + ansname = NULL; + + namereln = dns_name_fullcompare(name, fname, &order, + &nlabels); + INSIST(namereln == dns_namereln_subdomain); + /* + * Get the target name of the DNAME. + */ + tresult = dns_rdataset_first(trdataset); + if (tresult != ISC_R_SUCCESS) { + result = tresult; + goto done; + } + dns_rdataset_current(trdataset, &rdata); + tresult = dns_rdata_tostruct(&rdata, &dname, NULL); + dns_rdata_reset(&rdata); + if (tresult != ISC_R_SUCCESS) { + result = tresult; + goto done; + } + /* + * Construct the new query name and start over. + */ + dns_fixedname_init(&fixed); + prefix = dns_fixedname_name(&fixed); + dns_name_split(name, nlabels, prefix, NULL); + tresult = dns_name_concatenate(prefix, &dname.dname, + name, NULL); + dns_rdata_freestruct(&dname); + if (tresult == ISC_R_SUCCESS) + want_restart = ISC_TRUE; + else + result = tresult; + goto done; + case DNS_R_NCACHENXDOMAIN: + case DNS_R_NCACHENXRRSET: + ISC_LIST_APPEND(ansname->list, rctx->rdataset, link); + ISC_LIST_APPEND(rctx->namelist, ansname, link); + ansname = NULL; + rctx->rdataset = NULL; + /* What about sigrdataset? */ + if (rctx->sigrdataset != NULL) + putrdataset(mctx, &rctx->sigrdataset); + send_event = ISC_TRUE; + goto done; + default: + if (rctx->rdataset != NULL) + putrdataset(mctx, &rctx->rdataset); + if (rctx->sigrdataset != NULL) + putrdataset(mctx, &rctx->sigrdataset); + send_event = ISC_TRUE; + goto done; + } + + if (rctx->type == dns_rdatatype_any) { + int n = 0; + dns_rdatasetiter_t *rdsiter = NULL; + + tresult = dns_db_allrdatasets(db, node, NULL, 0, + &rdsiter); + if (tresult != ISC_R_SUCCESS) { + result = tresult; + goto done; + } + + tresult = dns_rdatasetiter_first(rdsiter); + while (tresult == ISC_R_SUCCESS) { + dns_rdatasetiter_current(rdsiter, + rctx->rdataset); + if (rctx->rdataset->type != 0) { + ISC_LIST_APPEND(ansname->list, + rctx->rdataset, + link); + n++; + rctx->rdataset = NULL; + } else { + /* + * We're not interested in this + * rdataset. + */ + dns_rdataset_disassociate( + rctx->rdataset); + } + tresult = dns_rdatasetiter_next(rdsiter); + + if (tresult == ISC_R_SUCCESS && + rctx->rdataset == NULL) { + tresult = getrdataset(mctx, + &rctx->rdataset); + if (tresult != ISC_R_SUCCESS) { + result = tresult; + break; + } + } + } + if (n == 0) { + /* + * We didn't match any rdatasets (which means + * something went wrong in this + * implementation). + */ + result = DNS_R_SERVFAIL; /* better code? */ + } else { + ISC_LIST_APPEND(rctx->namelist, ansname, link); + ansname = NULL; + } + dns_rdatasetiter_destroy(&rdsiter); + if (tresult != ISC_R_NOMORE) + result = DNS_R_SERVFAIL; /* ditto */ + else + result = ISC_R_SUCCESS; + goto done; + } else { + /* + * This is the "normal" case -- an ordinary question + * to which we've got the answer. + */ + ISC_LIST_APPEND(ansname->list, rctx->rdataset, link); + rctx->rdataset = NULL; + if (rctx->sigrdataset != NULL) { + ISC_LIST_APPEND(ansname->list, + rctx->sigrdataset, link); + rctx->sigrdataset = NULL; + } + ISC_LIST_APPEND(rctx->namelist, ansname, link); + ansname = NULL; + } + + done: + /* + * Free temporary resources + */ + if (ansname != NULL) { + dns_rdataset_t *rdataset; + + while ((rdataset = ISC_LIST_HEAD(ansname->list)) + != NULL) { + ISC_LIST_UNLINK(ansname->list, rdataset, link); + putrdataset(mctx, &rdataset); + } + dns_name_free(ansname, mctx); + isc_mem_put(mctx, ansname, sizeof(*ansname)); + } + + if (node != NULL) + dns_db_detachnode(db, &node); + if (db != NULL) + dns_db_detach(&db); + if (event != NULL) + isc_event_free(ISC_EVENT_PTR(&event)); + + /* + * Limit the number of restarts. + */ + if (want_restart && rctx->restarts == MAX_RESTARTS) { + want_restart = ISC_FALSE; + result = ISC_R_QUOTA; + send_event = ISC_TRUE; + } + + /* + * Prepare further find with new resources + */ + if (want_restart) { + INSIST(rctx->rdataset == NULL && + rctx->sigrdataset == NULL); + + result = getrdataset(mctx, &rctx->rdataset); + if (result == ISC_R_SUCCESS && rctx->want_dnssec) { + result = getrdataset(mctx, &rctx->sigrdataset); + if (result != ISC_R_SUCCESS) { + putrdataset(mctx, &rctx->rdataset); + } + } + + if (result != ISC_R_SUCCESS) { + want_restart = ISC_FALSE; + send_event = ISC_TRUE; + } + } + } while (want_restart); + + if (send_event) { + isc_task_t *task; + + while ((name = ISC_LIST_HEAD(rctx->namelist)) != NULL) { + ISC_LIST_UNLINK(rctx->namelist, name, link); + ISC_LIST_APPEND(rctx->event->answerlist, name, link); + } + + rctx->event->result = result; + rctx->event->vresult = vresult; + task = rctx->event->ev_sender; + rctx->event->ev_sender = rctx; + isc_task_sendanddetach(&task, ISC_EVENT_PTR(&rctx->event)); + } + + UNLOCK(&rctx->lock); +} + +static void +resolve_done(isc_task_t *task, isc_event_t *event) { + resarg_t *resarg = event->ev_arg; + dns_clientresevent_t *rev = (dns_clientresevent_t *)event; + dns_name_t *name; + + UNUSED(task); + + LOCK(&resarg->lock); + + resarg->result = rev->result; + resarg->vresult = rev->vresult; + while ((name = ISC_LIST_HEAD(rev->answerlist)) != NULL) { + ISC_LIST_UNLINK(rev->answerlist, name, link); + ISC_LIST_APPEND(*resarg->namelist, name, link); + } + + dns_client_destroyrestrans(&resarg->trans); + isc_event_free(&event); + + if (!resarg->canceled) { + UNLOCK(&resarg->lock); + + /* Exit from the internal event loop */ + isc_app_ctxsuspend(resarg->actx); + } else { + /* + * We have already exited from the loop (due to some + * unexpected event). Just clean the arg up. + */ + UNLOCK(&resarg->lock); + DESTROYLOCK(&resarg->lock); + isc_mem_put(resarg->client->mctx, resarg, sizeof(*resarg)); + } +} + +isc_result_t +dns_client_resolve(dns_client_t *client, dns_name_t *name, + dns_rdataclass_t rdclass, dns_rdatatype_t type, + unsigned int options, dns_namelist_t *namelist) +{ + isc_result_t result; + isc_appctx_t *actx; + resarg_t *resarg; + + REQUIRE(DNS_CLIENT_VALID(client)); + REQUIRE(namelist != NULL && ISC_LIST_EMPTY(*namelist)); + + if ((client->attributes & DNS_CLIENTATTR_OWNCTX) == 0 && + (options & DNS_CLIENTRESOPT_ALLOWRUN) == 0) { + /* + * If the client is run under application's control, we need + * to create a new running (sub)environment for this + * particular resolution. + */ + return (ISC_R_NOTIMPLEMENTED); /* XXXTBD */ + } else + actx = client->actx; + + resarg = isc_mem_get(client->mctx, sizeof(*resarg)); + if (resarg == NULL) + return (ISC_R_NOMEMORY); + + result = isc_mutex_init(&resarg->lock); + if (result != ISC_R_SUCCESS) { + isc_mem_put(client->mctx, resarg, sizeof(*resarg)); + return (result); + } + + resarg->actx = actx; + resarg->client = client; + resarg->result = DNS_R_SERVFAIL; + resarg->namelist = namelist; + resarg->trans = NULL; + resarg->canceled = ISC_FALSE; + result = dns_client_startresolve(client, name, rdclass, type, options, + client->task, resolve_done, resarg, + &resarg->trans); + if (result != ISC_R_SUCCESS) { + DESTROYLOCK(&resarg->lock); + isc_mem_put(client->mctx, resarg, sizeof(*resarg)); + return (result); + } + + /* + * Start internal event loop. It blocks until the entire process + * is completed. + */ + result = isc_app_ctxrun(actx); + + LOCK(&resarg->lock); + if (result == ISC_R_SUCCESS || result == ISC_R_SUSPEND) + result = resarg->result; + if (result != ISC_R_SUCCESS && resarg->vresult != ISC_R_SUCCESS) { + /* + * If this lookup failed due to some error in DNSSEC + * validation, return the validation error code. + * XXX: or should we pass the validation result separately? + */ + result = resarg->vresult; + } + if (resarg->trans != NULL) { + /* + * Unusual termination (perhaps due to signal). We need some + * tricky cleanup process. + */ + resarg->canceled = ISC_TRUE; + dns_client_cancelresolve(resarg->trans); + + UNLOCK(&resarg->lock); + + /* resarg will be freed in the event handler. */ + } else { + UNLOCK(&resarg->lock); + + DESTROYLOCK(&resarg->lock); + isc_mem_put(client->mctx, resarg, sizeof(*resarg)); + } + + return (result); +} + +isc_result_t +dns_client_startresolve(dns_client_t *client, dns_name_t *name, + dns_rdataclass_t rdclass, dns_rdatatype_t type, + unsigned int options, isc_task_t *task, + isc_taskaction_t action, void *arg, + dns_clientrestrans_t **transp) +{ + dns_view_t *view = NULL; + dns_clientresevent_t *event = NULL; + resctx_t *rctx = NULL; + isc_task_t *clone = NULL; + isc_mem_t *mctx; + isc_result_t result; + dns_rdataset_t *rdataset, *sigrdataset; + isc_boolean_t want_dnssec; + + REQUIRE(DNS_CLIENT_VALID(client)); + REQUIRE(transp != NULL && *transp == NULL); + + LOCK(&client->lock); + result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME, + rdclass, &view); + UNLOCK(&client->lock); + if (result != ISC_R_SUCCESS) + return (result); + + mctx = client->mctx; + rdataset = NULL; + sigrdataset = NULL; + want_dnssec = ISC_TF((options & DNS_CLIENTRESOPT_NODNSSEC) == 0); + + /* + * Prepare some intermediate resources + */ + clone = NULL; + isc_task_attach(task, &clone); + event = (dns_clientresevent_t *) + isc_event_allocate(mctx, clone, DNS_EVENT_CLIENTRESDONE, + action, arg, sizeof(*event)); + if (event == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + event->result = DNS_R_SERVFAIL; + ISC_LIST_INIT(event->answerlist); + + rctx = isc_mem_get(mctx, sizeof(*rctx)); + if (rctx == NULL) + result = ISC_R_NOMEMORY; + else { + result = isc_mutex_init(&rctx->lock); + if (result != ISC_R_SUCCESS) { + isc_mem_put(mctx, rctx, sizeof(*rctx)); + rctx = NULL; + } + } + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = getrdataset(mctx, &rdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + rctx->rdataset = rdataset; + + if (want_dnssec) { + result = getrdataset(mctx, &sigrdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + rctx->sigrdataset = sigrdataset; + + dns_fixedname_init(&rctx->name); + result = dns_name_copy(name, dns_fixedname_name(&rctx->name), NULL); + if (result != ISC_R_SUCCESS) + goto cleanup; + + rctx->client = client; + ISC_LINK_INIT(rctx, link); + rctx->canceled = ISC_FALSE; + rctx->task = client->task; + rctx->type = type; + rctx->view = view; + rctx->restarts = 0; + rctx->fetch = NULL; + rctx->want_dnssec = want_dnssec; + ISC_LIST_INIT(rctx->namelist); + rctx->event = event; + + rctx->magic = RCTX_MAGIC; + + LOCK(&client->lock); + ISC_LIST_APPEND(client->resctxs, rctx, link); + UNLOCK(&client->lock); + + client_resfind(rctx, NULL); + + *transp = (dns_clientrestrans_t *)rctx; + + return (ISC_R_SUCCESS); + + cleanup: + if (rdataset != NULL) + putrdataset(client->mctx, &rdataset); + if (sigrdataset != NULL) + putrdataset(client->mctx, &sigrdataset); + if (rctx != NULL) { + DESTROYLOCK(&rctx->lock); + isc_mem_put(mctx, rctx, sizeof(*rctx)); + } + if (event != NULL) + isc_event_free(ISC_EVENT_PTR(&event)); + isc_task_detach(&clone); + dns_view_detach(&view); + + return (result); +} + +void +dns_client_cancelresolve(dns_clientrestrans_t *trans) { + resctx_t *rctx; + + REQUIRE(trans != NULL); + rctx = (resctx_t *)trans; + REQUIRE(RCTX_VALID(rctx)); + + LOCK(&rctx->lock); + + if (!rctx->canceled) { + rctx->canceled = ISC_TRUE; + if (rctx->fetch != NULL) + dns_resolver_cancelfetch(rctx->fetch); + } + + UNLOCK(&rctx->lock); +} + +void +dns_client_freeresanswer(dns_client_t *client, dns_namelist_t *namelist) { + dns_name_t *name; + dns_rdataset_t *rdataset; + + REQUIRE(DNS_CLIENT_VALID(client)); + REQUIRE(namelist != NULL); + + while ((name = ISC_LIST_HEAD(*namelist)) != NULL) { + ISC_LIST_UNLINK(*namelist, name, link); + while ((rdataset = ISC_LIST_HEAD(name->list)) != NULL) { + ISC_LIST_UNLINK(name->list, rdataset, link); + putrdataset(client->mctx, &rdataset); + } + dns_name_free(name, client->mctx); + isc_mem_put(client->mctx, name, sizeof(*name)); + } +} + +void +dns_client_destroyrestrans(dns_clientrestrans_t **transp) { + resctx_t *rctx; + isc_mem_t *mctx; + dns_client_t *client; + isc_boolean_t need_destroyclient = ISC_FALSE; + + REQUIRE(transp != NULL); + rctx = (resctx_t *)*transp; + REQUIRE(RCTX_VALID(rctx)); + REQUIRE(rctx->fetch == NULL); + REQUIRE(rctx->event == NULL); + client = rctx->client; + REQUIRE(DNS_CLIENT_VALID(client)); + + mctx = client->mctx; + dns_view_detach(&rctx->view); + + LOCK(&client->lock); + + INSIST(ISC_LINK_LINKED(rctx, link)); + ISC_LIST_UNLINK(client->resctxs, rctx, link); + + if (client->references == 0 && ISC_LIST_EMPTY(client->resctxs) && + ISC_LIST_EMPTY(client->reqctxs) && + ISC_LIST_EMPTY(client->updatectxs)) + need_destroyclient = ISC_TRUE; + + UNLOCK(&client->lock); + + INSIST(ISC_LIST_EMPTY(rctx->namelist)); + + DESTROYLOCK(&rctx->lock); + rctx->magic = 0; + + isc_mem_put(mctx, rctx, sizeof(*rctx)); + + if (need_destroyclient) + destroyclient(&client); + + *transp = NULL; +} + +isc_result_t +dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass, + dns_name_t *keyname, isc_buffer_t *keydatabuf) +{ + isc_result_t result; + dns_view_t *view = NULL; + dst_key_t *dstkey = NULL; + dns_keytable_t *secroots = NULL; + + REQUIRE(DNS_CLIENT_VALID(client)); + + LOCK(&client->lock); + result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME, + rdclass, &view); + UNLOCK(&client->lock); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = dns_view_getsecroots(view, &secroots); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = dst_key_fromdns(keyname, rdclass, keydatabuf, client->mctx, + &dstkey); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = dns_keytable_add(secroots, ISC_FALSE, &dstkey); + + cleanup: + if (dstkey != NULL) + dst_key_free(&dstkey); + if (view != NULL) + dns_view_detach(&view); + if (secroots != NULL) + dns_keytable_detach(&secroots); + return (result); +} + +/*% + * Simple request routines + */ +static void +request_done(isc_task_t *task, isc_event_t *event) { + dns_requestevent_t *reqev = NULL; + dns_request_t *request; + isc_result_t result, eresult; + reqctx_t *ctx; + + UNUSED(task); + + REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); + reqev = (dns_requestevent_t *)event; + request = reqev->request; + result = eresult = reqev->result; + ctx = reqev->ev_arg; + REQUIRE(REQCTX_VALID(ctx)); + + isc_event_free(&event); + + LOCK(&ctx->lock); + + if (eresult == ISC_R_SUCCESS) { + result = dns_request_getresponse(request, ctx->event->rmessage, + ctx->parseoptions); + } + + if (ctx->tsigkey != NULL) + dns_tsigkey_detach(&ctx->tsigkey); + + if (ctx->canceled) + ctx->event->result = ISC_R_CANCELED; + else + ctx->event->result = result; + task = ctx->event->ev_sender; + ctx->event->ev_sender = ctx; + isc_task_sendanddetach(&task, ISC_EVENT_PTR(&ctx->event)); + + UNLOCK(&ctx->lock); +} + +static void +localrequest_done(isc_task_t *task, isc_event_t *event) { + reqarg_t *reqarg = event->ev_arg; + dns_clientreqevent_t *rev =(dns_clientreqevent_t *)event; + + UNUSED(task); + + REQUIRE(event->ev_type == DNS_EVENT_CLIENTREQDONE); + + LOCK(&reqarg->lock); + + reqarg->result = rev->result; + dns_client_destroyreqtrans(&reqarg->trans); + isc_event_free(&event); + + if (!reqarg->canceled) { + UNLOCK(&reqarg->lock); + + /* Exit from the internal event loop */ + isc_app_ctxsuspend(reqarg->actx); + } else { + /* + * We have already exited from the loop (due to some + * unexpected event). Just clean the arg up. + */ + UNLOCK(&reqarg->lock); + DESTROYLOCK(&reqarg->lock); + isc_mem_put(reqarg->client->mctx, reqarg, sizeof(*reqarg)); + } +} + +isc_result_t +dns_client_request(dns_client_t *client, dns_message_t *qmessage, + dns_message_t *rmessage, isc_sockaddr_t *server, + unsigned int options, unsigned int parseoptions, + dns_tsec_t *tsec, unsigned int timeout, + unsigned int udptimeout, unsigned int udpretries) +{ + isc_appctx_t *actx; + reqarg_t *reqarg; + isc_result_t result; + + REQUIRE(DNS_CLIENT_VALID(client)); + REQUIRE(qmessage != NULL); + REQUIRE(rmessage != NULL); + + if ((client->attributes & DNS_CLIENTATTR_OWNCTX) == 0 && + (options & DNS_CLIENTREQOPT_ALLOWRUN) == 0) { + /* + * If the client is run under application's control, we need + * to create a new running (sub)environment for this + * particular resolution. + */ + return (ISC_R_NOTIMPLEMENTED); /* XXXTBD */ + } else + actx = client->actx; + + reqarg = isc_mem_get(client->mctx, sizeof(*reqarg)); + if (reqarg == NULL) + return (ISC_R_NOMEMORY); + + result = isc_mutex_init(&reqarg->lock); + if (result != ISC_R_SUCCESS) { + isc_mem_put(client->mctx, reqarg, sizeof(*reqarg)); + return (result); + } + + reqarg->actx = actx; + reqarg->client = client; + reqarg->trans = NULL; + reqarg->canceled = ISC_FALSE; + + result = dns_client_startrequest(client, qmessage, rmessage, server, + options, parseoptions, tsec, timeout, + udptimeout, udpretries, + client->task, localrequest_done, + reqarg, &reqarg->trans); + if (result != ISC_R_SUCCESS) { + DESTROYLOCK(&reqarg->lock); + isc_mem_put(client->mctx, reqarg, sizeof(*reqarg)); + return (result); + } + + /* + * Start internal event loop. It blocks until the entire process + * is completed. + */ + result = isc_app_ctxrun(actx); + + LOCK(&reqarg->lock); + if (result == ISC_R_SUCCESS || result == ISC_R_SUSPEND) + result = reqarg->result; + if (reqarg->trans != NULL) { + /* + * Unusual termination (perhaps due to signal). We need some + * tricky cleanup process. + */ + reqarg->canceled = ISC_TRUE; + dns_client_cancelresolve(reqarg->trans); + + UNLOCK(&reqarg->lock); + + /* reqarg will be freed in the event handler. */ + } else { + UNLOCK(&reqarg->lock); + + DESTROYLOCK(&reqarg->lock); + isc_mem_put(client->mctx, reqarg, sizeof(*reqarg)); + } + + return (result); +} + +isc_result_t +dns_client_startrequest(dns_client_t *client, dns_message_t *qmessage, + dns_message_t *rmessage, isc_sockaddr_t *server, + unsigned int options, unsigned int parseoptions, + dns_tsec_t *tsec, unsigned int timeout, + unsigned int udptimeout, unsigned int udpretries, + isc_task_t *task, isc_taskaction_t action, void *arg, + dns_clientreqtrans_t **transp) +{ + isc_result_t result; + dns_view_t *view = NULL; + isc_task_t *clone = NULL; + dns_clientreqevent_t *event = NULL; + reqctx_t *ctx = NULL; + dns_tsectype_t tsectype = dns_tsectype_none; + + UNUSED(options); + + REQUIRE(DNS_CLIENT_VALID(client)); + REQUIRE(qmessage != NULL); + REQUIRE(rmessage != NULL); + REQUIRE(transp != NULL && *transp == NULL); + + if (tsec != NULL) { + tsectype = dns_tsec_gettype(tsec); + if (tsectype != dns_tsectype_tsig) + return (ISC_R_NOTIMPLEMENTED); /* XXX */ + } + + LOCK(&client->lock); + result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME, + qmessage->rdclass, &view); + UNLOCK(&client->lock); + if (result != ISC_R_SUCCESS) + return (result); + + clone = NULL; + isc_task_attach(task, &clone); + event = (dns_clientreqevent_t *) + isc_event_allocate(client->mctx, clone, + DNS_EVENT_CLIENTREQDONE, + action, arg, sizeof(*event)); + if (event == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + + ctx = isc_mem_get(client->mctx, sizeof(*ctx)); + if (ctx == NULL) + result = ISC_R_NOMEMORY; + else { + result = isc_mutex_init(&ctx->lock); + if (result != ISC_R_SUCCESS) { + isc_mem_put(client->mctx, ctx, sizeof(*ctx)); + ctx = NULL; + } + } + if (result != ISC_R_SUCCESS) + goto cleanup; + + ctx->client = client; + ISC_LINK_INIT(ctx, link); + ctx->parseoptions = parseoptions; + ctx->canceled = ISC_FALSE; + ctx->event = event; + ctx->event->rmessage = rmessage; + ctx->tsigkey = NULL; + if (tsec != NULL) + dns_tsec_getkey(tsec, &ctx->tsigkey); + + ctx->magic = REQCTX_MAGIC; + + LOCK(&client->lock); + ISC_LIST_APPEND(client->reqctxs, ctx, link); + UNLOCK(&client->lock); + + ctx->request = NULL; + result = dns_request_createvia3(view->requestmgr, qmessage, NULL, + server, options, ctx->tsigkey, + timeout, udptimeout, udpretries, + client->task, request_done, ctx, + &ctx->request); + if (result == ISC_R_SUCCESS) { + dns_view_detach(&view); + *transp = (dns_clientreqtrans_t *)ctx; + return (ISC_R_SUCCESS); + } + + cleanup: + if (ctx != NULL) { + LOCK(&client->lock); + ISC_LIST_UNLINK(client->reqctxs, ctx, link); + UNLOCK(&client->lock); + DESTROYLOCK(&ctx->lock); + isc_mem_put(client->mctx, ctx, sizeof(*ctx)); + } + if (event != NULL) + isc_event_free(ISC_EVENT_PTR(&event)); + isc_task_detach(&clone); + dns_view_detach(&view); + + return (result); +} + +void +dns_client_cancelrequest(dns_clientreqtrans_t *trans) { + reqctx_t *ctx; + + REQUIRE(trans != NULL); + ctx = (reqctx_t *)trans; + REQUIRE(REQCTX_VALID(ctx)); + + LOCK(&ctx->lock); + + if (!ctx->canceled) { + ctx->canceled = ISC_TRUE; + if (ctx->request != NULL) + dns_request_cancel(ctx->request); + } + + UNLOCK(&ctx->lock); +} + +void +dns_client_destroyreqtrans(dns_clientreqtrans_t **transp) { + reqctx_t *ctx; + isc_mem_t *mctx; + dns_client_t *client; + isc_boolean_t need_destroyclient = ISC_FALSE; + + REQUIRE(transp != NULL); + ctx = (reqctx_t *)*transp; + REQUIRE(REQCTX_VALID(ctx)); + client = ctx->client; + REQUIRE(DNS_CLIENT_VALID(client)); + REQUIRE(ctx->event == NULL); + REQUIRE(ctx->request != NULL); + + dns_request_destroy(&ctx->request); + mctx = client->mctx; + + LOCK(&client->lock); + + INSIST(ISC_LINK_LINKED(ctx, link)); + ISC_LIST_UNLINK(client->reqctxs, ctx, link); + + if (client->references == 0 && ISC_LIST_EMPTY(client->resctxs) && + ISC_LIST_EMPTY(client->reqctxs) && + ISC_LIST_EMPTY(client->updatectxs)) { + need_destroyclient = ISC_TRUE; + } + + UNLOCK(&client->lock); + + DESTROYLOCK(&ctx->lock); + ctx->magic = 0; + + isc_mem_put(mctx, ctx, sizeof(*ctx)); + + if (need_destroyclient) + destroyclient(&client); + + *transp = NULL; +} + +/*% + * Dynamic update routines + */ +static isc_result_t +rcode2result(dns_rcode_t rcode) { + /* XXX: isn't there a similar function? */ + switch (rcode) { + case dns_rcode_formerr: + return (DNS_R_FORMERR); + case dns_rcode_servfail: + return (DNS_R_SERVFAIL); + case dns_rcode_nxdomain: + return (DNS_R_NXDOMAIN); + case dns_rcode_notimp: + return (DNS_R_NOTIMP); + case dns_rcode_refused: + return (DNS_R_REFUSED); + case dns_rcode_yxdomain: + return (DNS_R_YXDOMAIN); + case dns_rcode_yxrrset: + return (DNS_R_YXRRSET); + case dns_rcode_nxrrset: + return (DNS_R_NXRRSET); + case dns_rcode_notauth: + return (DNS_R_NOTAUTH); + case dns_rcode_notzone: + return (DNS_R_NOTZONE); + case dns_rcode_badvers: + return (DNS_R_BADVERS); + } + + return (ISC_R_FAILURE); +} + +static void +update_sendevent(updatectx_t *uctx, isc_result_t result) { + isc_task_t *task; + + dns_message_destroy(&uctx->updatemsg); + if (uctx->tsigkey != NULL) + dns_tsigkey_detach(&uctx->tsigkey); + if (uctx->sig0key != NULL) + dst_key_free(&uctx->sig0key); + + if (uctx->canceled) + uctx->event->result = ISC_R_CANCELED; + else + uctx->event->result = result; + uctx->event->state = uctx->state; + task = uctx->event->ev_sender; + uctx->event->ev_sender = uctx; + isc_task_sendanddetach(&task, ISC_EVENT_PTR(&uctx->event)); +} + +static void +update_done(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + dns_requestevent_t *reqev = NULL; + dns_request_t *request; + dns_message_t *answer = NULL; + updatectx_t *uctx = event->ev_arg; + dns_client_t *client; + unsigned int timeout; + + UNUSED(task); + + REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); + reqev = (dns_requestevent_t *)event; + request = reqev->request; + REQUIRE(UCTX_VALID(uctx)); + client = uctx->client; + REQUIRE(DNS_CLIENT_VALID(client)); + + result = reqev->result; + if (result != ISC_R_SUCCESS) + goto out; + + result = dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE, + &answer); + if (result != ISC_R_SUCCESS) + goto out; + uctx->state = dns_clientupdatestate_done; + result = dns_request_getresponse(request, answer, + DNS_MESSAGEPARSE_PRESERVEORDER); + if (result == ISC_R_SUCCESS && answer->rcode != dns_rcode_noerror) + result = rcode2result(answer->rcode); + + out: + if (answer != NULL) + dns_message_destroy(&answer); + isc_event_free(&event); + + LOCK(&uctx->lock); + uctx->currentserver = ISC_LIST_NEXT(uctx->currentserver, link); + dns_request_destroy(&uctx->updatereq); + if (result != ISC_R_SUCCESS && !uctx->canceled && + uctx->currentserver != NULL) { + dns_message_renderreset(uctx->updatemsg); + dns_message_settsigkey(uctx->updatemsg, NULL); + + timeout = client->update_timeout / uctx->nservers; + if (timeout < MIN_UPDATE_TIMEOUT) + timeout = MIN_UPDATE_TIMEOUT; + result = dns_request_createvia3(uctx->view->requestmgr, + uctx->updatemsg, + NULL, + uctx->currentserver, 0, + uctx->tsigkey, + timeout, + client->update_udptimeout, + client->update_udpretries, + client->task, + update_done, uctx, + &uctx->updatereq); + UNLOCK(&uctx->lock); + + if (result == ISC_R_SUCCESS) { + /* XXX: should we keep the 'done' state here? */ + uctx->state = dns_clientupdatestate_sent; + return; + } + } else + UNLOCK(&uctx->lock); + + update_sendevent(uctx, result); +} + +static isc_result_t +send_update(updatectx_t *uctx) { + isc_result_t result; + dns_name_t *name = NULL; + dns_rdataset_t *rdataset = NULL; + dns_client_t *client = uctx->client; + unsigned int timeout; + + REQUIRE(uctx->zonename != NULL && uctx->currentserver != NULL); + + result = dns_message_gettempname(uctx->updatemsg, &name); + if (result != ISC_R_SUCCESS) + return (result); + dns_name_init(name, NULL); + dns_name_clone(uctx->zonename, name); + result = dns_message_gettemprdataset(uctx->updatemsg, &rdataset); + if (result != ISC_R_SUCCESS) { + dns_message_puttempname(uctx->updatemsg, &name); + return (result); + } + dns_rdataset_makequestion(rdataset, uctx->rdclass, dns_rdatatype_soa); + ISC_LIST_INIT(name->list); + ISC_LIST_APPEND(name->list, rdataset, link); + dns_message_addname(uctx->updatemsg, name, DNS_SECTION_ZONE); + if (uctx->tsigkey == NULL && uctx->sig0key != NULL) { + result = dns_message_setsig0key(uctx->updatemsg, + uctx->sig0key); + if (result != ISC_R_SUCCESS) + return (result); + } + timeout = client->update_timeout / uctx->nservers; + if (timeout < MIN_UPDATE_TIMEOUT) + timeout = MIN_UPDATE_TIMEOUT; + result = dns_request_createvia3(uctx->view->requestmgr, + uctx->updatemsg, + NULL, uctx->currentserver, 0, + uctx->tsigkey, timeout, + client->update_udptimeout, + client->update_udpretries, + client->task, update_done, uctx, + &uctx->updatereq); + if (result == ISC_R_SUCCESS && + uctx->state == dns_clientupdatestate_prepare) { + uctx->state = dns_clientupdatestate_sent; + } + + return (result); +} + +static void +resolveaddr_done(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + int family; + dns_rdatatype_t qtype; + dns_clientresevent_t *rev = (dns_clientresevent_t *)event; + dns_name_t *name; + dns_rdataset_t *rdataset; + updatectx_t *uctx; + isc_boolean_t completed = ISC_FALSE; + + UNUSED(task); + + REQUIRE(event->ev_arg != NULL); + uctx = *(updatectx_t **)event->ev_arg; + REQUIRE(UCTX_VALID(uctx)); + + if (event->ev_arg == &uctx->bp4) { + family = AF_INET; + qtype = dns_rdatatype_a; + LOCK(&uctx->lock); + dns_client_destroyrestrans(&uctx->restrans); + UNLOCK(&uctx->lock); + } else { + INSIST(event->ev_arg == &uctx->bp6); + family = AF_INET6; + qtype = dns_rdatatype_aaaa; + LOCK(&uctx->lock); + dns_client_destroyrestrans(&uctx->restrans2); + UNLOCK(&uctx->lock); + } + + result = rev->result; + if (result != ISC_R_SUCCESS) + goto done; + + for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL; + name = ISC_LIST_NEXT(name, link)) { + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + if (!dns_rdataset_isassociated(rdataset)) + continue; + if (rdataset->type != qtype) + continue; + + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + dns_rdata_t rdata; + dns_rdata_in_a_t rdata_a; + dns_rdata_in_aaaa_t rdata_aaaa; + isc_sockaddr_t *sa; + + sa = isc_mem_get(uctx->client->mctx, + sizeof(*sa)); + if (sa == NULL) { + /* + * If we fail to get a sockaddr, + we simply move forward with the + * addresses we've got so far. + */ + goto done; + } + + dns_rdata_init(&rdata); + switch (family) { + case AF_INET: + dns_rdataset_current(rdataset, &rdata); + dns_rdata_tostruct(&rdata, &rdata_a, + NULL); + isc_sockaddr_fromin(sa, + &rdata_a.in_addr, + 53); + dns_rdata_freestruct(&rdata_a); + break; + case AF_INET6: + dns_rdataset_current(rdataset, &rdata); + dns_rdata_tostruct(&rdata, &rdata_aaaa, + NULL); + isc_sockaddr_fromin6(sa, + &rdata_aaaa.in6_addr, + 53); + dns_rdata_freestruct(&rdata_aaaa); + break; + } + + ISC_LINK_INIT(sa, link); + ISC_LIST_APPEND(uctx->servers, sa, link); + uctx->nservers++; + } + } + } + + done: + dns_client_freeresanswer(uctx->client, &rev->answerlist); + isc_event_free(&event); + + LOCK(&uctx->lock); + if (uctx->restrans == NULL && uctx->restrans2 == NULL) + completed = ISC_TRUE; + UNLOCK(&uctx->lock); + + if (completed) { + INSIST(uctx->currentserver == NULL); + uctx->currentserver = ISC_LIST_HEAD(uctx->servers); + if (uctx->currentserver != NULL && !uctx->canceled) + send_update(uctx); + else { + if (result == ISC_R_SUCCESS) + result = ISC_R_NOTFOUND; + update_sendevent(uctx, result); + } + } +} + +static isc_result_t +process_soa(updatectx_t *uctx, dns_rdataset_t *soaset, dns_name_t *soaname) { + isc_result_t result; + dns_rdata_t soarr = DNS_RDATA_INIT; + dns_rdata_soa_t soa; + dns_name_t primary; + + result = dns_rdataset_first(soaset); + if (result != ISC_R_SUCCESS) + return (result); + dns_rdata_init(&soarr); + dns_rdataset_current(soaset, &soarr); + result = dns_rdata_tostruct(&soarr, &soa, NULL); + if (result != ISC_R_SUCCESS) + return (result); + + dns_name_init(&primary, NULL); + dns_name_clone(&soa.origin, &primary); + + if (uctx->zonename == NULL) { + uctx->zonename = dns_fixedname_name(&uctx->zonefname); + result = dns_name_copy(soaname, uctx->zonename, NULL); + if (result != ISC_R_SUCCESS) + goto out; + } + + if (uctx->currentserver != NULL) + result = send_update(uctx); + else { + /* + * Get addresses of the primary server. We don't use the ADB + * feature so that we could avoid caching data. + */ + LOCK(&uctx->lock); + uctx->bp4 = uctx; + result = dns_client_startresolve(uctx->client, &primary, + uctx->rdclass, + dns_rdatatype_a, + 0, uctx->client->task, + resolveaddr_done, &uctx->bp4, + &uctx->restrans); + if (result == ISC_R_SUCCESS) { + uctx->bp6 = uctx; + result = dns_client_startresolve(uctx->client, + &primary, + uctx->rdclass, + dns_rdatatype_aaaa, + 0, uctx->client->task, + resolveaddr_done, + &uctx->bp6, + &uctx->restrans2); + } + UNLOCK(&uctx->lock); + } + + out: + dns_rdata_freestruct(&soa); + + return (result); +} + +static void +receive_soa(isc_task_t *task, isc_event_t *event) { + dns_requestevent_t *reqev = NULL; + updatectx_t *uctx; + dns_client_t *client; + isc_result_t result, eresult; + dns_request_t *request; + dns_message_t *rcvmsg = NULL; + dns_section_t section; + dns_rdataset_t *soaset = NULL; + int pass = 0; + dns_name_t *name; + dns_message_t *soaquery = NULL; + isc_sockaddr_t *addr; + isc_boolean_t seencname = ISC_FALSE; + isc_boolean_t droplabel = ISC_FALSE; + dns_name_t tname; + unsigned int nlabels; + + UNUSED(task); + + REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); + reqev = (dns_requestevent_t *)event; + request = reqev->request; + result = eresult = reqev->result; + uctx = reqev->ev_arg; + client = uctx->client; + soaquery = uctx->soaquery; + addr = uctx->currentserver; + INSIST(addr != NULL); + + isc_event_free(&event); + + if (eresult != ISC_R_SUCCESS) { + result = eresult; + goto out; + } + + result = dns_message_create(uctx->client->mctx, + DNS_MESSAGE_INTENTPARSE, &rcvmsg); + if (result != ISC_R_SUCCESS) + goto out; + result = dns_request_getresponse(request, rcvmsg, + DNS_MESSAGEPARSE_PRESERVEORDER); + + if (result == DNS_R_TSIGERRORSET) { + dns_request_t *newrequest = NULL; + + /* Retry SOA request without TSIG */ + dns_message_destroy(&rcvmsg); + dns_message_renderreset(uctx->soaquery); + result = dns_request_createvia3(uctx->view->requestmgr, + uctx->soaquery, NULL, addr, 0, + NULL, + client->find_timeout * 20, + client->find_timeout, 3, + uctx->client->task, + receive_soa, uctx, + &newrequest); + if (result == ISC_R_SUCCESS) { + LOCK(&uctx->lock); + dns_request_destroy(&uctx->soareq); + uctx->soareq = newrequest; + UNLOCK(&uctx->lock); + + return; + } + goto out; + } + + section = DNS_SECTION_ANSWER; + + if (rcvmsg->rcode != dns_rcode_noerror && + rcvmsg->rcode != dns_rcode_nxdomain) { + result = rcode2result(rcvmsg->rcode); + goto out; + } + + lookforsoa: + if (pass == 0) + section = DNS_SECTION_ANSWER; + else if (pass == 1) + section = DNS_SECTION_AUTHORITY; + else { + droplabel = ISC_TRUE; + goto out; + } + + result = dns_message_firstname(rcvmsg, section); + if (result != ISC_R_SUCCESS) { + pass++; + goto lookforsoa; + } + while (result == ISC_R_SUCCESS) { + name = NULL; + dns_message_currentname(rcvmsg, section, &name); + soaset = NULL; + result = dns_message_findtype(name, dns_rdatatype_soa, 0, + &soaset); + if (result == ISC_R_SUCCESS) + break; + if (section == DNS_SECTION_ANSWER) { + dns_rdataset_t *tset = NULL; + if (dns_message_findtype(name, dns_rdatatype_cname, 0, + &tset) == ISC_R_SUCCESS + || + dns_message_findtype(name, dns_rdatatype_dname, 0, + &tset) == ISC_R_SUCCESS + ) + { + seencname = ISC_TRUE; + break; + } + } + + result = dns_message_nextname(rcvmsg, section); + } + + if (soaset == NULL && !seencname) { + pass++; + goto lookforsoa; + } + + if (seencname) { + droplabel = ISC_TRUE; + goto out; + } + + result = process_soa(uctx, soaset, name); + + out: + if (droplabel) { + result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION); + INSIST(result == ISC_R_SUCCESS); + name = NULL; + dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name); + nlabels = dns_name_countlabels(name); + if (nlabels == 1) + result = DNS_R_SERVFAIL; /* is there a better error? */ + else { + dns_name_init(&tname, NULL); + dns_name_getlabelsequence(name, 1, nlabels - 1, + &tname); + dns_name_clone(&tname, name); + dns_request_destroy(&request); + LOCK(&uctx->lock); + uctx->soareq = NULL; + UNLOCK(&uctx->lock); + dns_message_renderreset(soaquery); + dns_message_settsigkey(soaquery, NULL); + result = dns_request_createvia3(uctx->view->requestmgr, + soaquery, NULL, + uctx->currentserver, 0, + uctx->tsigkey, + client->find_timeout * + 20, + client->find_timeout, + 3, client->task, + receive_soa, uctx, + &uctx->soareq); + } + } + + if (!droplabel || result != ISC_R_SUCCESS) { + dns_message_destroy(&uctx->soaquery); + LOCK(&uctx->lock); + dns_request_destroy(&uctx->soareq); + UNLOCK(&uctx->lock); + } + + if (rcvmsg != NULL) + dns_message_destroy(&rcvmsg); + + if (result != ISC_R_SUCCESS) + update_sendevent(uctx, result); +} + +static isc_result_t +request_soa(updatectx_t *uctx) { + isc_result_t result; + dns_message_t *soaquery = uctx->soaquery; + dns_name_t *name = NULL; + dns_rdataset_t *rdataset = NULL; + + if (soaquery == NULL) { + result = dns_message_create(uctx->client->mctx, + DNS_MESSAGE_INTENTRENDER, + &soaquery); + if (result != ISC_R_SUCCESS) + return (result); + } + soaquery->flags |= DNS_MESSAGEFLAG_RD; + result = dns_message_gettempname(soaquery, &name); + if (result != ISC_R_SUCCESS) + goto fail; + result = dns_message_gettemprdataset(soaquery, &rdataset); + if (result != ISC_R_SUCCESS) + goto fail; + dns_rdataset_makequestion(rdataset, uctx->rdclass, dns_rdatatype_soa); + dns_name_clone(uctx->firstname, name); + ISC_LIST_APPEND(name->list, rdataset, link); + dns_message_addname(soaquery, name, DNS_SECTION_QUESTION); + rdataset = NULL; + name = NULL; + + result = dns_request_createvia3(uctx->view->requestmgr, + soaquery, NULL, uctx->currentserver, 0, + uctx->tsigkey, + uctx->client->find_timeout * 20, + uctx->client->find_timeout, 3, + uctx->client->task, receive_soa, uctx, + &uctx->soareq); + if (result == ISC_R_SUCCESS) { + uctx->soaquery = soaquery; + return (ISC_R_SUCCESS); + } + + fail: + if (rdataset != NULL) { + ISC_LIST_UNLINK(name->list, rdataset, link); /* for safety */ + dns_message_puttemprdataset(soaquery, &rdataset); + } + if (name != NULL) + dns_message_puttempname(soaquery, &name); + dns_message_destroy(&soaquery); + + return (result); +} + +static void +resolvesoa_done(isc_task_t *task, isc_event_t *event) { + dns_clientresevent_t *rev = (dns_clientresevent_t *)event; + updatectx_t *uctx; + dns_name_t *name, tname; + dns_rdataset_t *rdataset = NULL; + isc_result_t result = rev->result; + unsigned int nlabels; + + UNUSED(task); + + uctx = event->ev_arg; + REQUIRE(UCTX_VALID(uctx)); + + LOCK(&uctx->lock); + dns_client_destroyrestrans(&uctx->restrans); + UNLOCK(&uctx->lock); + + uctx = event->ev_arg; + if (result != ISC_R_SUCCESS && + result != DNS_R_NCACHENXDOMAIN && + result != DNS_R_NCACHENXRRSET) { + /* XXX: what about DNSSEC failure? */ + goto out; + } + + for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL; + name = ISC_LIST_NEXT(name, link)) { + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + if (dns_rdataset_isassociated(rdataset) && + rdataset->type == dns_rdatatype_soa) + break; + } + } + + if (rdataset == NULL) { + /* Drop one label and retry resolution. */ + nlabels = dns_name_countlabels(&uctx->soaqname); + if (nlabels == 1) { + result = DNS_R_SERVFAIL; /* is there a better error? */ + goto out; + } + dns_name_init(&tname, NULL); + dns_name_getlabelsequence(&uctx->soaqname, 1, nlabels - 1, + &tname); + dns_name_clone(&tname, &uctx->soaqname); + + result = dns_client_startresolve(uctx->client, &uctx->soaqname, + uctx->rdclass, + dns_rdatatype_soa, 0, + uctx->client->task, + resolvesoa_done, uctx, + &uctx->restrans); + } else + result = process_soa(uctx, rdataset, &uctx->soaqname); + + out: + dns_client_freeresanswer(uctx->client, &rev->answerlist); + isc_event_free(&event); + + if (result != ISC_R_SUCCESS) + update_sendevent(uctx, result); +} + +static isc_result_t +copy_name(isc_mem_t *mctx, dns_message_t *msg, dns_name_t *name, + dns_name_t **newnamep) +{ + isc_result_t result; + dns_name_t *newname = NULL; + isc_region_t r; + isc_buffer_t *namebuf = NULL, *rdatabuf = NULL; + dns_rdatalist_t *rdatalist; + dns_rdataset_t *rdataset, *newrdataset; + dns_rdata_t rdata = DNS_RDATA_INIT, *newrdata; + + result = dns_message_gettempname(msg, &newname); + if (result != ISC_R_SUCCESS) + return (result); + result = isc_buffer_allocate(mctx, &namebuf, DNS_NAME_MAXWIRE); + if (result != ISC_R_SUCCESS) + goto fail; + dns_name_init(newname, NULL); + dns_name_setbuffer(newname, namebuf); + dns_message_takebuffer(msg, &namebuf); + result = dns_name_copy(name, newname, NULL); + if (result != ISC_R_SUCCESS) + goto fail; + + for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + rdatalist = NULL; + result = dns_message_gettemprdatalist(msg, &rdatalist); + if (result != ISC_R_SUCCESS) + goto fail; + dns_rdatalist_init(rdatalist); + rdatalist->type = rdataset->type; + rdatalist->rdclass = rdataset->rdclass; + rdatalist->covers = rdataset->covers; + rdatalist->ttl = rdataset->ttl; + + result = dns_rdataset_first(rdataset); + while (result == ISC_R_SUCCESS) { + dns_rdata_reset(&rdata); + dns_rdataset_current(rdataset, &rdata); + + newrdata = NULL; + result = dns_message_gettemprdata(msg, &newrdata); + if (result != ISC_R_SUCCESS) + goto fail; + dns_rdata_toregion(&rdata, &r); + rdatabuf = NULL; + result = isc_buffer_allocate(mctx, &rdatabuf, + r.length); + if (result != ISC_R_SUCCESS) + goto fail; + isc_buffer_putmem(rdatabuf, r.base, r.length); + isc_buffer_usedregion(rdatabuf, &r); + dns_rdata_init(newrdata); + dns_rdata_fromregion(newrdata, rdata.rdclass, + rdata.type, &r); + newrdata->flags = rdata.flags; + + ISC_LIST_APPEND(rdatalist->rdata, newrdata, link); + dns_message_takebuffer(msg, &rdatabuf); + + result = dns_rdataset_next(rdataset); + } + + newrdataset = NULL; + result = dns_message_gettemprdataset(msg, &newrdataset); + if (result != ISC_R_SUCCESS) + goto fail; + dns_rdataset_init(newrdataset); + dns_rdatalist_tordataset(rdatalist, newrdataset); + + ISC_LIST_APPEND(newname->list, newrdataset, link); + } + + *newnamep = newname; + + return (ISC_R_SUCCESS); + + fail: + dns_message_puttempname(msg, &newname); + + return (result); + +} + +static void +internal_update_callback(isc_task_t *task, isc_event_t *event) { + updatearg_t *uarg = event->ev_arg; + dns_clientupdateevent_t *uev = (dns_clientupdateevent_t *)event; + + UNUSED(task); + + LOCK(&uarg->lock); + + uarg->result = uev->result; + + dns_client_destroyupdatetrans(&uarg->trans); + isc_event_free(&event); + + if (!uarg->canceled) { + UNLOCK(&uarg->lock); + + /* Exit from the internal event loop */ + isc_app_ctxsuspend(uarg->actx); + } else { + /* + * We have already exited from the loop (due to some + * unexpected event). Just clean the arg up. + */ + UNLOCK(&uarg->lock); + DESTROYLOCK(&uarg->lock); + isc_mem_put(uarg->client->mctx, uarg, sizeof(*uarg)); + } +} + +isc_result_t +dns_client_update(dns_client_t *client, dns_rdataclass_t rdclass, + dns_name_t *zonename, dns_namelist_t *prerequisites, + dns_namelist_t *updates, isc_sockaddrlist_t *servers, + dns_tsec_t *tsec, unsigned int options) +{ + isc_result_t result; + isc_appctx_t *actx; + updatearg_t *uarg; + + REQUIRE(DNS_CLIENT_VALID(client)); + + if ((client->attributes & DNS_CLIENTATTR_OWNCTX) == 0 && + (options & DNS_CLIENTRESOPT_ALLOWRUN) == 0) { + /* + * If the client is run under application's control, we need + * to create a new running (sub)environment for this + * particular resolution. + */ + return (ISC_R_NOTIMPLEMENTED); /* XXXTBD */ + } else + actx = client->actx; + + uarg = isc_mem_get(client->mctx, sizeof(*uarg)); + if (uarg == NULL) + return (ISC_R_NOMEMORY); + + result = isc_mutex_init(&uarg->lock); + if (result != ISC_R_SUCCESS) { + isc_mem_put(client->mctx, uarg, sizeof(*uarg)); + return (result); + } + + uarg->actx = actx; + uarg->client = client; + uarg->result = ISC_R_FAILURE; + uarg->trans = NULL; + uarg->canceled = ISC_FALSE; + + result = dns_client_startupdate(client, rdclass, zonename, + prerequisites, updates, servers, + tsec, options, client->task, + internal_update_callback, uarg, + &uarg->trans); + if (result != ISC_R_SUCCESS) { + DESTROYLOCK(&uarg->lock); + isc_mem_put(client->mctx, uarg, sizeof(*uarg)); + return (result); + } + + /* + * Start internal event loop. It blocks until the entire process + * is completed. + */ + result = isc_app_ctxrun(actx); + + LOCK(&uarg->lock); + if (result == ISC_R_SUCCESS || result == ISC_R_SUSPEND) + result = uarg->result; + + if (uarg->trans != NULL) { + /* + * Unusual termination (perhaps due to signal). We need some + * tricky cleanup process. + */ + uarg->canceled = ISC_TRUE; + dns_client_cancelupdate(uarg->trans); + + UNLOCK(&uarg->lock); + + /* uarg will be freed in the event handler. */ + } else { + UNLOCK(&uarg->lock); + + DESTROYLOCK(&uarg->lock); + isc_mem_put(client->mctx, uarg, sizeof(*uarg)); + } + + return (result); +} + +isc_result_t +dns_client_startupdate(dns_client_t *client, dns_rdataclass_t rdclass, + dns_name_t *zonename, dns_namelist_t *prerequisites, + dns_namelist_t *updates, isc_sockaddrlist_t *servers, + dns_tsec_t *tsec, unsigned int options, + isc_task_t *task, isc_taskaction_t action, void *arg, + dns_clientupdatetrans_t **transp) +{ + dns_view_t *view = NULL; + isc_result_t result; + dns_name_t *name, *newname; + updatectx_t *uctx; + isc_task_t *clone = NULL; + dns_section_t section = DNS_SECTION_UPDATE; + isc_sockaddr_t *server, *sa = NULL; + dns_tsectype_t tsectype = dns_tsectype_none; + + UNUSED(options); + + REQUIRE(DNS_CLIENT_VALID(client)); + REQUIRE(transp != NULL && *transp == NULL); + REQUIRE(updates != NULL); + REQUIRE(task != NULL); + + if (tsec != NULL) { + tsectype = dns_tsec_gettype(tsec); + if (tsectype != dns_tsectype_tsig) + return (ISC_R_NOTIMPLEMENTED); /* XXX */ + } + + LOCK(&client->lock); + result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME, + rdclass, &view); + UNLOCK(&client->lock); + if (result != ISC_R_SUCCESS) + return (result); + + /* Create a context and prepare some resources */ + uctx = isc_mem_get(client->mctx, sizeof(*uctx)); + if (uctx == NULL) { + dns_view_detach(&view); + return (ISC_R_NOMEMORY); + } + result = isc_mutex_init(&uctx->lock); + if (result != ISC_R_SUCCESS) { + dns_view_detach(&view); + isc_mem_put(client->mctx, uctx, sizeof(*uctx)); + return (ISC_R_NOMEMORY); + } + clone = NULL; + isc_task_attach(task, &clone); + uctx->client = client; + ISC_LINK_INIT(uctx, link); + uctx->state = dns_clientupdatestate_prepare; + uctx->view = view; + uctx->rdclass = rdclass; + uctx->canceled = ISC_FALSE; + uctx->updatemsg = NULL; + uctx->soaquery = NULL; + uctx->updatereq = NULL; + uctx->restrans = NULL; + uctx->restrans2 = NULL; + uctx->bp4 = NULL; + uctx->bp6 = NULL; + uctx->soareq = NULL; + uctx->event = NULL; + uctx->tsigkey = NULL; + uctx->sig0key = NULL; + uctx->zonename = NULL; + dns_name_init(&uctx->soaqname, NULL); + ISC_LIST_INIT(uctx->servers); + uctx->nservers = 0; + uctx->currentserver = NULL; + dns_fixedname_init(&uctx->zonefname); + if (tsec != NULL) + dns_tsec_getkey(tsec, &uctx->tsigkey); + uctx->event = (dns_clientupdateevent_t *) + isc_event_allocate(client->mctx, clone, DNS_EVENT_UPDATEDONE, + action, arg, sizeof(*uctx->event)); + if (uctx->event == NULL) + goto fail; + if (zonename != NULL) { + uctx->zonename = dns_fixedname_name(&uctx->zonefname); + result = dns_name_copy(zonename, uctx->zonename, NULL); + } + if (servers != NULL) { + for (server = ISC_LIST_HEAD(*servers); + server != NULL; + server = ISC_LIST_NEXT(server, link)) { + sa = isc_mem_get(client->mctx, sizeof(*sa)); + if (sa == NULL) + goto fail; + sa->type = server->type; + sa->length = server->length; + ISC_LINK_INIT(sa, link); + ISC_LIST_APPEND(uctx->servers, sa, link); + if (uctx->currentserver == NULL) + uctx->currentserver = sa; + uctx->nservers++; + } + } + + /* Make update message */ + result = dns_message_create(client->mctx, DNS_MESSAGE_INTENTRENDER, + &uctx->updatemsg); + if (result != ISC_R_SUCCESS) + goto fail; + uctx->updatemsg->opcode = dns_opcode_update; + + if (prerequisites != NULL) { + for (name = ISC_LIST_HEAD(*prerequisites); name != NULL; + name = ISC_LIST_NEXT(name, link)) { + newname = NULL; + result = copy_name(client->mctx, uctx->updatemsg, + name, &newname); + if (result != ISC_R_SUCCESS) + goto fail; + dns_message_addname(uctx->updatemsg, newname, + DNS_SECTION_PREREQUISITE); + } + } + + for (name = ISC_LIST_HEAD(*updates); name != NULL; + name = ISC_LIST_NEXT(name, link)) { + newname = NULL; + result = copy_name(client->mctx, uctx->updatemsg, name, + &newname); + if (result != ISC_R_SUCCESS) + goto fail; + dns_message_addname(uctx->updatemsg, newname, + DNS_SECTION_UPDATE); + } + + uctx->firstname = NULL; + result = dns_message_firstname(uctx->updatemsg, section); + if (result == ISC_R_NOMORE) { + section = DNS_SECTION_PREREQUISITE; + result = dns_message_firstname(uctx->updatemsg, section); + } + if (result != ISC_R_SUCCESS) + goto fail; + dns_message_currentname(uctx->updatemsg, section, &uctx->firstname); + + uctx->magic = UCTX_MAGIC; + + LOCK(&client->lock); + ISC_LIST_APPEND(client->updatectxs, uctx, link); + UNLOCK(&client->lock); + + if (uctx->zonename != NULL && uctx->currentserver != NULL) { + result = send_update(uctx); + if (result != ISC_R_SUCCESS) + goto fail; + } else if (uctx->currentserver != NULL) { + result = request_soa(uctx); + if (result != ISC_R_SUCCESS) + goto fail; + } else { + dns_name_clone(uctx->firstname, &uctx->soaqname); + result = dns_client_startresolve(uctx->client, &uctx->soaqname, + uctx->rdclass, + dns_rdatatype_soa, 0, + client->task, resolvesoa_done, + uctx, &uctx->restrans); + if (result != ISC_R_SUCCESS) + goto fail; + } + + *transp = (dns_clientupdatetrans_t *)uctx; + + return (ISC_R_SUCCESS); + + fail: + if (ISC_LINK_LINKED(uctx, link)) { + LOCK(&client->lock); + ISC_LIST_UNLINK(client->updatectxs, uctx, link); + UNLOCK(&client->lock); + } + if (uctx->updatemsg != NULL) + dns_message_destroy(&uctx->updatemsg); + while ((sa = ISC_LIST_HEAD(uctx->servers)) != NULL) { + ISC_LIST_UNLINK(uctx->servers, sa, link); + isc_mem_put(client->mctx, sa, sizeof(*sa)); + } + if (uctx->event != NULL) + isc_event_free(ISC_EVENT_PTR(&uctx->event)); + if (uctx->tsigkey != NULL) + dns_tsigkey_detach(&uctx->tsigkey); + isc_task_detach(&clone); + DESTROYLOCK(&uctx->lock); + uctx->magic = 0; + isc_mem_put(client->mctx, uctx, sizeof(*uctx)); + dns_view_detach(&view); + + return (result); +} + +void +dns_client_cancelupdate(dns_clientupdatetrans_t *trans) { + updatectx_t *uctx; + + REQUIRE(trans != NULL); + uctx = (updatectx_t *)trans; + REQUIRE(UCTX_VALID(uctx)); + + LOCK(&uctx->lock); + + if (!uctx->canceled) { + uctx->canceled = ISC_TRUE; + if (uctx->updatereq != NULL) + dns_request_cancel(uctx->updatereq); + if (uctx->soareq != NULL) + dns_request_cancel(uctx->soareq); + if (uctx->restrans != NULL) + dns_client_cancelresolve(uctx->restrans); + if (uctx->restrans2 != NULL) + dns_client_cancelresolve(uctx->restrans2); + } + + UNLOCK(&uctx->lock); +} + +void +dns_client_destroyupdatetrans(dns_clientupdatetrans_t **transp) { + updatectx_t *uctx; + isc_mem_t *mctx; + dns_client_t *client; + isc_boolean_t need_destroyclient = ISC_FALSE; + isc_sockaddr_t *sa; + + REQUIRE(transp != NULL); + uctx = (updatectx_t *)*transp; + REQUIRE(UCTX_VALID(uctx)); + client = uctx->client; + REQUIRE(DNS_CLIENT_VALID(client)); + REQUIRE(uctx->updatereq == NULL && uctx->updatemsg == NULL && + uctx->soareq == NULL && uctx->soaquery == NULL && + uctx->event == NULL && uctx->tsigkey == NULL && + uctx->sig0key == NULL); + + mctx = client->mctx; + dns_view_detach(&uctx->view); + while ((sa = ISC_LIST_HEAD(uctx->servers)) != NULL) { + ISC_LIST_UNLINK(uctx->servers, sa, link); + isc_mem_put(mctx, sa, sizeof(*sa)); + } + + LOCK(&client->lock); + + INSIST(ISC_LINK_LINKED(uctx, link)); + ISC_LIST_UNLINK(client->updatectxs, uctx, link); + + if (client->references == 0 && ISC_LIST_EMPTY(client->resctxs) && + ISC_LIST_EMPTY(client->reqctxs) && + ISC_LIST_EMPTY(client->updatectxs)) + need_destroyclient = ISC_TRUE; + + UNLOCK(&client->lock); + + DESTROYLOCK(&uctx->lock); + uctx->magic = 0; + + isc_mem_put(mctx, uctx, sizeof(*uctx)); + + if (need_destroyclient) + destroyclient(&client); + + *transp = NULL; +} + +isc_mem_t * +dns_client_mctx(dns_client_t *client) { + + REQUIRE(DNS_CLIENT_VALID(client)); + return (client->mctx); +} + +typedef struct { + isc_buffer_t buffer; + dns_rdataset_t rdataset; + dns_rdatalist_t rdatalist; + dns_rdata_t rdata; + size_t size; + isc_mem_t * mctx; + unsigned char data[FLEXIBLE_ARRAY_MEMBER]; +} dns_client_updaterec_t; + +isc_result_t +dns_client_updaterec(dns_client_updateop_t op, dns_name_t *owner, + dns_rdatatype_t type, dns_rdata_t *source, + dns_ttl_t ttl, dns_name_t *target, + dns_rdataset_t *rdataset, dns_rdatalist_t *rdatalist, + dns_rdata_t *rdata, isc_mem_t *mctx) +{ + dns_client_updaterec_t *updaterec = NULL; + size_t size = offsetof(dns_client_updaterec_t, data); + + REQUIRE(op < updateop_max); + REQUIRE(owner != NULL); + REQUIRE((rdataset != NULL && rdatalist != NULL && rdata != NULL) || + (rdataset == NULL && rdatalist == NULL && rdata == NULL && + mctx != NULL)); + if (op == updateop_add) + REQUIRE(source != NULL); + if (source != NULL) { + REQUIRE(source->type == type); + REQUIRE(op == updateop_add || op == updateop_delete || + op == updateop_exist); + } + + size += owner->length; + if (source != NULL) + size += source->length; + + if (rdataset == NULL) { + updaterec = isc_mem_get(mctx, size); + if (updaterec == NULL) + return (ISC_R_NOMEMORY); + rdataset = &updaterec->rdataset; + rdatalist = &updaterec->rdatalist; + rdata = &updaterec->rdata; + dns_rdataset_init(rdataset); + dns_rdatalist_init(&updaterec->rdatalist); + dns_rdata_init(&updaterec->rdata); + isc_buffer_init(&updaterec->buffer, updaterec->data, + size - offsetof(dns_client_updaterec_t, data)); + dns_name_copy(owner, target, &updaterec->buffer); + if (source != NULL) { + isc_region_t r; + dns_rdata_clone(source, rdata); + dns_rdata_toregion(rdata, &r); + rdata->data = isc_buffer_used(&updaterec->buffer); + isc_buffer_copyregion(&updaterec->buffer, &r); + } + updaterec->mctx = NULL; + isc_mem_attach(mctx, &updaterec->mctx); + } else if (source != NULL) + dns_rdata_clone(source, rdata); + + switch (op) { + case updateop_add: + break; + case updateop_delete: + if (source != NULL) { + ttl = 0; + dns_rdata_makedelete(rdata); + } else + dns_rdata_deleterrset(rdata, type); + break; + case updateop_notexist: + dns_rdata_notexist(rdata, type); + break; + case updateop_exist: + if (source == NULL) { + ttl = 0; + dns_rdata_exists(rdata, type); + } + case updateop_none: + break; + default: + INSIST(0); + } + + rdatalist->type = rdata->type; + rdatalist->rdclass = rdata->rdclass; + if (source != NULL) { + rdatalist->covers = dns_rdata_covers(rdata); + rdatalist->ttl = ttl; + } + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + dns_rdatalist_tordataset(rdatalist, rdataset); + ISC_LIST_APPEND(target->list, rdataset, link); + if (updaterec != NULL) { + target->attributes |= DNS_NAMEATTR_HASUPDATEREC; + dns_name_setbuffer(target, &updaterec->buffer); + } + if (op == updateop_add || op == updateop_delete) + target->attributes |= DNS_NAMEATTR_UPDATE; + else + target->attributes |= DNS_NAMEATTR_PREREQUISITE; + return (ISC_R_SUCCESS); +} + +void +dns_client_freeupdate(dns_name_t **namep) { + dns_client_updaterec_t *updaterec; + dns_rdatalist_t *rdatalist; + dns_rdataset_t *rdataset; + dns_rdata_t *rdata; + dns_name_t *name; + + REQUIRE(namep != NULL && *namep != NULL); + + name = *namep; + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_HEAD(name->list)) { + ISC_LIST_UNLINK(name->list, rdataset, link); + rdatalist = NULL; + dns_rdatalist_fromrdataset(rdataset, &rdatalist); + if (rdatalist == NULL) { + dns_rdataset_disassociate(rdataset); + continue; + } + for (rdata = ISC_LIST_HEAD(rdatalist->rdata); + rdata != NULL; + rdata = ISC_LIST_HEAD(rdatalist->rdata)) + ISC_LIST_UNLINK(rdatalist->rdata, rdata, link); + dns_rdataset_disassociate(rdataset); + } + + if ((name->attributes & DNS_NAMEATTR_HASUPDATEREC) != 0) { + updaterec = (dns_client_updaterec_t *)name->buffer; + INSIST(updaterec != NULL); + isc_mem_putanddetach(&updaterec->mctx, updaterec, + updaterec->size); + *namep = NULL; + } +} diff --git a/lib/dns/db.c b/lib/dns/db.c index f52f674..c74d24d 100644 --- a/lib/dns/db.c +++ b/lib/dns/db.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007-2009, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: db.c,v 1.88.50.2 2009-06-23 00:19:34 tbox Exp $ */ +/* $Id: db.c,v 1.97 2011-01-13 04:59:25 tbox Exp $ */ /*! \file */ @@ -34,10 +34,12 @@ #include #include +#include #include #include #include #include +#include #include /*** @@ -61,14 +63,18 @@ struct dns_dbimplementation { */ #include "rbtdb.h" +#ifdef BIND9 #include "rbtdb64.h" +#endif static ISC_LIST(dns_dbimplementation_t) implementations; static isc_rwlock_t implock; static isc_once_t once = ISC_ONCE_INIT; static dns_dbimplementation_t rbtimp; +#ifdef BIND9 static dns_dbimplementation_t rbt64imp; +#endif static void initialize(void) { @@ -80,15 +86,19 @@ initialize(void) { rbtimp.driverarg = NULL; ISC_LINK_INIT(&rbtimp, link); +#ifdef BIND9 rbt64imp.name = "rbt64"; rbt64imp.create = dns_rbtdb64_create; rbt64imp.mctx = NULL; rbt64imp.driverarg = NULL; ISC_LINK_INIT(&rbt64imp, link); +#endif ISC_LIST_INIT(implementations); ISC_LIST_APPEND(implementations, &rbtimp, link); +#ifdef BIND9 ISC_LIST_APPEND(implementations, &rbt64imp, link); +#endif } static inline dns_dbimplementation_t * @@ -290,6 +300,7 @@ dns_db_class(dns_db_t *db) { return (db->rdclass); } +#ifdef BIND9 isc_result_t dns_db_beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, dns_dbload_t **dbloadp) { @@ -318,14 +329,19 @@ dns_db_endload(dns_db_t *db, dns_dbload_t **dbloadp) { isc_result_t dns_db_load(dns_db_t *db, const char *filename) { - return (dns_db_load2(db, filename, dns_masterformat_text)); + return (dns_db_load3(db, filename, dns_masterformat_text, 0)); } isc_result_t dns_db_load2(dns_db_t *db, const char *filename, dns_masterformat_t format) { + return (dns_db_load3(db, filename, format, 0)); +} + +isc_result_t +dns_db_load3(dns_db_t *db, const char *filename, dns_masterformat_t format, + unsigned int options) { isc_result_t result, eresult; dns_rdatacallbacks_t callbacks; - unsigned int options = 0; /* * Load master file 'filename' into 'db'. @@ -376,6 +392,7 @@ dns_db_dump2(dns_db_t *db, dns_dbversion_t *version, const char *filename, return ((db->methods->dump)(db, version, filename, masterformat)); } +#endif /* BIND9 */ /*** *** Version Methods @@ -921,8 +938,27 @@ dns_db_getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, dns_name_t *name) } void -dns_db_resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version) +dns_db_resigned(dns_db_t *db, dns_rdataset_t *rdataset, + dns_dbversion_t *version) { if (db->methods->resigned != NULL) (db->methods->resigned)(db, rdataset, version); } + +void +dns_db_rpz_enabled(dns_db_t *db, dns_rpz_st_t *st) +{ + if (db->methods->rpz_enabled != NULL) + (db->methods->rpz_enabled)(db, st); +} + +isc_result_t +dns_db_rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, + dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version, + dns_rdataset_t *ardataset, dns_rpz_st_t *st) +{ + if (db->methods->rpz_findips == NULL) + return (ISC_R_NOTIMPLEMENTED); + return ((db->methods->rpz_findips)(rpz, rpz_type, zone, db, version, + ardataset, st)); +} diff --git a/lib/dns/diff.c b/lib/dns/diff.c index a92a496..3dbb5cf 100644 --- a/lib/dns/diff.c +++ b/lib/dns/diff.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: diff.c,v 1.18.50.2 2009-01-05 23:47:22 tbox Exp $ */ +/* $Id: diff.c,v 1.23 2009-12-01 00:47:09 each Exp $ */ /*! \file */ @@ -387,10 +387,22 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver, * from a server that is not as careful. * Issue a warning and continue. */ - if (warn) + if (warn) { + char classbuf[DNS_RDATATYPE_FORMATSIZE]; + char namebuf[DNS_NAME_FORMATSIZE]; + + dns_name_format(dns_db_origin(db), + namebuf, + sizeof(namebuf)); + dns_rdataclass_format(dns_db_class(db), + classbuf, + sizeof(classbuf)); isc_log_write(DIFF_COMMON_LOGARGS, ISC_LOG_WARNING, - "update with no effect"); + "%s/%s: dns_diff_apply: " + "update with no effect", + namebuf, classbuf); + } } else if (result == DNS_R_NXRRSET) { /* * OK. @@ -478,6 +490,7 @@ dns_diff_load(dns_diff_t *diff, dns_addrdatasetfunc_t addfunc, if (result == DNS_R_UNCHANGED) { isc_log_write(DIFF_COMMON_LOGARGS, ISC_LOG_WARNING, + "dns_diff_load: " "update with no effect"); } else if (result == ISC_R_SUCCESS || result == DNS_R_NXRRSET) { diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index 632d349..c074911 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dispatch.c,v 1.155.12.11 2009-12-02 23:26:28 marka Exp $ */ +/* $Id: dispatch.c,v 1.168.248.1.2.1 2011-06-02 23:47:34 tbox Exp $ */ /*! \file */ @@ -417,7 +417,7 @@ request_log(dns_dispatch_t *disp, dns_dispentry_t *resp, /*% * ARC4 random number generator derived from OpenBSD. - * Only dispatch_arc4random() and dispatch_arc4uniformrandom() are expected + * Only dispatch_random() and dispatch_uniformrandom() are expected * to be called from general dispatch routines; the rest of them are subroutines * for these two. * @@ -437,8 +437,11 @@ request_log(dns_dispatch_t *disp, dns_dispentry_t *resp, * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef BIND9 static void -dispatch_arc4init(arc4ctx_t *actx, isc_entropy_t *entropy, isc_mutex_t *lock) { +dispatch_initrandom(arc4ctx_t *actx, isc_entropy_t *entropy, + isc_mutex_t *lock) +{ int n; for (n = 0; n < 256; n++) actx->s[n] = n; @@ -527,7 +530,7 @@ dispatch_arc4stir(arc4ctx_t *actx) { } static isc_uint16_t -dispatch_arc4random(arc4ctx_t *actx) { +dispatch_random(arc4ctx_t *actx) { isc_uint16_t result; if (actx->lock != NULL) @@ -543,9 +546,38 @@ dispatch_arc4random(arc4ctx_t *actx) { return (result); } +#else +/* + * For general purpose library, we don't have to be too strict about the + * quality of random values. Performance doesn't matter much, either. + * So we simply use the isc_random module to keep the library as small as + * possible. + */ + +static void +dispatch_initrandom(arc4ctx_t *actx, isc_entropy_t *entropy, + isc_mutex_t *lock) +{ + UNUSED(actx); + UNUSED(entropy); + UNUSED(lock); + + return; +} static isc_uint16_t -dispatch_arc4uniformrandom(arc4ctx_t *actx, isc_uint16_t upper_bound) { +dispatch_random(arc4ctx_t *actx) { + isc_uint32_t r; + + UNUSED(actx); + + isc_random_get(&r); + return (r & 0xffff); +} +#endif /* BIND9 */ + +static isc_uint16_t +dispatch_uniformrandom(arc4ctx_t *actx, isc_uint16_t upper_bound) { isc_uint16_t min, r; if (upper_bound < 2) @@ -568,7 +600,7 @@ dispatch_arc4uniformrandom(arc4ctx_t *actx, isc_uint16_t upper_bound) { * to re-roll. */ for (;;) { - r = dispatch_arc4random(actx); + r = dispatch_random(actx); if (r >= min) break; } @@ -859,7 +891,7 @@ get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest, */ localaddr = disp->local; for (i = 0; i < 64; i++) { - port = ports[dispatch_arc4uniformrandom(DISP_ARC4CTX(disp), + port = ports[dispatch_uniformrandom(DISP_ARC4CTX(disp), nports)]; isc_sockaddr_setport(&localaddr, port); @@ -964,6 +996,7 @@ deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) { INSIST(dispsock->portentry != NULL); deref_portentry(disp, &dispsock->portentry); +#ifdef BIND9 if (disp->nsockets > DNS_DISPATCH_POOLSOCKS) destroy_dispsocket(disp, &dispsock); else { @@ -987,6 +1020,13 @@ deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) { destroy_dispsocket(disp, &dispsock); } } +#else + /* This kind of optimization isn't necessary for normal use */ + UNUSED(qid); + UNUSED(result); + + destroy_dispsocket(disp, &dispsock); +#endif } /* @@ -1707,13 +1747,17 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) { isc_mempool_destroy(&mgr->epool); isc_mempool_destroy(&mgr->rpool); isc_mempool_destroy(&mgr->dpool); - isc_mempool_destroy(&mgr->bpool); - isc_mempool_destroy(&mgr->spool); + if (mgr->bpool != NULL) + isc_mempool_destroy(&mgr->bpool); + if (mgr->spool != NULL) + isc_mempool_destroy(&mgr->spool); DESTROYLOCK(&mgr->pool_lock); +#ifdef BIND9 if (mgr->entropy != NULL) isc_entropy_detach(&mgr->entropy); +#endif /* BIND9 */ if (mgr->qid != NULL) qid_destroy(mctx, &mgr->qid); @@ -1752,9 +1796,13 @@ open_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local, return (result); isc_socket_setname(sock, "dispatcher", NULL); } else { +#ifdef BIND9 result = isc_socket_open(sock); if (result != ISC_R_SUCCESS) return (result); +#else + INSIST(0); +#endif } #ifndef ISC_ALLOW_MAPPED @@ -1764,8 +1812,13 @@ open_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local, if (result != ISC_R_SUCCESS) { if (*sockp == NULL) isc_socket_detach(&sock); - else + else { +#ifdef BIND9 isc_socket_close(sock); +#else + INSIST(0); +#endif + } return (result); } @@ -1897,10 +1950,14 @@ dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy, if (result != ISC_R_SUCCESS) goto kill_dpool; +#ifdef BIND9 if (entropy != NULL) isc_entropy_attach(entropy, &mgr->entropy); +#else + UNUSED(entropy); +#endif - dispatch_arc4init(&mgr->arc4ctx, mgr->entropy, &mgr->arc4_lock); + dispatch_initrandom(&mgr->arc4ctx, mgr->entropy, &mgr->arc4_lock); *mgrp = mgr; return (ISC_R_SUCCESS); @@ -2411,7 +2468,7 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests, ISC_LIST_INIT(disp->activesockets); ISC_LIST_INIT(disp->inactivesockets); disp->nsockets = 0; - dispatch_arc4init(&disp->arc4ctx, mgr->entropy, NULL); + dispatch_initrandom(&disp->arc4ctx, mgr->entropy, NULL); disp->port_table = NULL; disp->portpool = NULL; @@ -2708,7 +2765,7 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp, for (i = 0; i < 1024; i++) { in_port_t prt; - prt = ports[dispatch_arc4uniformrandom( + prt = ports[dispatch_uniformrandom( DISP_ARC4CTX(disp), nports)]; isc_sockaddr_setport(&localaddr_bound, prt); @@ -2844,8 +2901,10 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, disp->task[i] = NULL; result = isc_task_create(taskmgr, 0, &disp->task[i]); if (result != ISC_R_SUCCESS) { - while (--i >= 0) - isc_task_destroy(&disp->task[i]); + while (--i >= 0) { + isc_task_shutdown(disp->task[i]); + isc_task_detach(&disp->task[i]); + } goto kill_socket; } isc_task_setname(disp->task[i], "udpdispatch", disp); @@ -3045,7 +3104,7 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest, /* * Try somewhat hard to find an unique ID. */ - id = (dns_messageid_t)dispatch_arc4random(DISP_ARC4CTX(disp)); + id = (dns_messageid_t)dispatch_random(DISP_ARC4CTX(disp)); bucket = dns_hash(qid, dest, id, localport); ok = ISC_FALSE; for (i = 0; i < 64; i++) { diff --git a/lib/dns/dlz.c b/lib/dns/dlz.c index f848230..5a508e9 100644 --- a/lib/dns/dlz.c +++ b/lib/dns/dlz.c @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2005, 2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -50,7 +50,7 @@ * USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dlz.c,v 1.5.332.2 2009-01-18 23:47:35 tbox Exp $ */ +/* $Id: dlz.c,v 1.10 2010-12-20 23:47:20 tbox Exp $ */ /*! \file */ @@ -64,6 +64,8 @@ #include #include #include +#include +#include #include @@ -230,6 +232,12 @@ dns_dlzdestroy(dns_dlzdb_t **dbp) { */ REQUIRE(dbp != NULL && DNS_DLZ_VALID(*dbp)); +#ifdef BIND9 + if ((*dbp)->ssutable != NULL) { + dns_ssutable_detach(&(*dbp)->ssutable); + } +#endif + /* call the drivers destroy method */ if ((*dbp) != NULL) { mctx = (*dbp)->mctx; @@ -499,7 +507,7 @@ dns_dlzunregister(dns_dlzimplementation_t **dlzimp) { mctx = dlz_imp->mctx; /* - * return the memory back to the available memory pool and + * Return the memory back to the available memory pool and * remove it from the memory context. */ isc_mem_put(mctx, dlz_imp, sizeof(dns_dlzimplementation_t)); @@ -508,3 +516,143 @@ dns_dlzunregister(dns_dlzimplementation_t **dlzimp) { /* Unlock the dlz_implementations list. */ RWUNLOCK(&dlz_implock, isc_rwlocktype_write); } + +#ifdef BIND9 +/* + * Create a writeable DLZ zone. This can be called by DLZ drivers + * during configure() to create a zone that can be updated. The zone + * type is set to dns_zone_dlz, which is equivalent to a master zone + * + * This function uses a callback setup in dns_dlzconfigure() to call + * into the server zone code to setup the remaining pieces of server + * specific functionality on the zone + */ +isc_result_t +dns_dlz_writeablezone(dns_view_t *view, const char *zone_name) { + dns_zone_t *zone = NULL; + dns_zone_t *dupzone = NULL; + isc_result_t result; + isc_buffer_t buffer; + dns_fixedname_t fixorigin; + dns_name_t *origin; + dns_rdataclass_t zclass; + dns_dlzdb_t *dlzdatabase; + + REQUIRE(DNS_DLZ_VALID(view->dlzdatabase)); + + dlzdatabase = view->dlzdatabase; + + REQUIRE(dlzdatabase->configure_callback != NULL); + + isc_buffer_init(&buffer, zone_name, strlen(zone_name)); + isc_buffer_add(&buffer, strlen(zone_name)); + dns_fixedname_init(&fixorigin); + result = dns_name_fromtext(dns_fixedname_name(&fixorigin), + &buffer, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) + goto cleanup; + origin = dns_fixedname_name(&fixorigin); + + zclass = view->rdclass; + + /* See if the zone already exists */ + result = dns_view_findzone(view, origin, &dupzone); + if (result == ISC_R_SUCCESS) { + dns_zone_detach(&dupzone); + result = ISC_R_EXISTS; + goto cleanup; + } + INSIST(dupzone == NULL); + + /* Create it */ + result = dns_zone_create(&zone, view->mctx); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = dns_zone_setorigin(zone, origin); + if (result != ISC_R_SUCCESS) + goto cleanup; + dns_zone_setview(zone, view); + + dns_zone_setadded(zone, ISC_TRUE); + + if (dlzdatabase->ssutable == NULL) { + result = dns_ssutable_createdlz(dlzdatabase->mctx, + &dlzdatabase->ssutable, + view->dlzdatabase); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + dns_zone_setssutable(zone, dlzdatabase->ssutable); + + result = dlzdatabase->configure_callback(view, zone); + if (result != ISC_R_SUCCESS) + goto cleanup; + + /* + * Add the zone to its view in the new view list. + */ + result = dns_view_addzone(view, zone); + + result = ISC_R_SUCCESS; + + cleanup: + if (zone != NULL) + dns_zone_detach(&zone); + + return (result); +} +#endif + +/*% + * Configure a DLZ driver. This is optional, and if supplied gives + * the backend an opportunity to configure parameters related to DLZ. + */ +isc_result_t +dns_dlzconfigure(dns_view_t *view, isc_result_t (*callback)(dns_view_t *, + dns_zone_t *)) +{ + dns_dlzimplementation_t *impl; + dns_dlzdb_t *dlzdatabase; + isc_result_t result; + + REQUIRE(view != NULL); + REQUIRE(DNS_DLZ_VALID(view->dlzdatabase)); + REQUIRE(view->dlzdatabase->implementation != NULL); + + dlzdatabase = view->dlzdatabase; + impl = dlzdatabase->implementation; + + if (impl->methods->configure == NULL) + return (ISC_R_SUCCESS); + + dlzdatabase->configure_callback = callback; + + result = impl->methods->configure(impl->driverarg, + dlzdatabase->dbdata, view); + return (result); +} + +isc_boolean_t +dns_dlz_ssumatch(dns_dlzdb_t *dlzdatabase, + dns_name_t *signer, dns_name_t *name, isc_netaddr_t *tcpaddr, + dns_rdatatype_t type, const dst_key_t *key) +{ + dns_dlzimplementation_t *impl; + isc_boolean_t r; + + REQUIRE(dlzdatabase != NULL); + REQUIRE(dlzdatabase->implementation != NULL); + REQUIRE(dlzdatabase->implementation->methods != NULL); + impl = dlzdatabase->implementation; + + if (impl->methods->ssumatch == NULL) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_DLZ, ISC_LOG_INFO, + "No ssumatch method for DLZ database"); + return (ISC_FALSE); + } + + r = impl->methods->ssumatch(signer, name, tcpaddr, type, key, + impl->driverarg, dlzdatabase->dbdata); + return (r); +} diff --git a/lib/dns/dns64.c b/lib/dns/dns64.c new file mode 100644 index 0000000..180c0a9 --- /dev/null +++ b/lib/dns/dns64.c @@ -0,0 +1,299 @@ +/* + * Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: dns64.c,v 1.6 2010-12-09 04:59:09 marka Exp $ */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +struct dns_dns64 { + unsigned char bits[16]; /* + * Prefix + suffix bits. + */ + dns_acl_t * clients; /* + * Which clients get mapped + * addresses. + */ + dns_acl_t * mapped; /* + * IPv4 addresses to be mapped. + */ + dns_acl_t * excluded; /* + * IPv6 addresses that are + * treated as not existing. + */ + unsigned int prefixlen; /* + * Start of mapped address. + */ + unsigned int flags; + isc_mem_t * mctx; + ISC_LINK(dns_dns64_t) link; +}; + +isc_result_t +dns_dns64_create(isc_mem_t *mctx, isc_netaddr_t *prefix, + unsigned int prefixlen, isc_netaddr_t *suffix, + dns_acl_t *clients, dns_acl_t *mapped, dns_acl_t *excluded, + unsigned int flags, dns_dns64_t **dns64) +{ + dns_dns64_t *new; + unsigned int nbytes = 16; + + REQUIRE(prefix != NULL && prefix->family == AF_INET6); + /* Legal prefix lengths from draft-ietf-behave-address-format-04. */ + REQUIRE(prefixlen == 32 || prefixlen == 40 || prefixlen == 48 || + prefixlen == 56 || prefixlen == 64 || prefixlen == 96); + REQUIRE(isc_netaddr_prefixok(prefix, prefixlen) == ISC_R_SUCCESS); + REQUIRE(dns64 != NULL && *dns64 == NULL); + + if (suffix != NULL) { + static const unsigned char zeros[16]; + REQUIRE(prefix->family == AF_INET6); + nbytes = prefixlen / 8 + 4; + /* Bits 64-71 are zeros. draft-ietf-behave-address-format-04 */ + if (prefixlen >= 32 && prefixlen <= 64) + nbytes++; + REQUIRE(memcmp(suffix->type.in6.s6_addr, zeros, nbytes) == 0); + } + + new = isc_mem_get(mctx, sizeof(dns_dns64_t)); + if (new == NULL) + return (ISC_R_NOMEMORY); + memset(new->bits, 0, sizeof(new->bits)); + memcpy(new->bits, prefix->type.in6.s6_addr, prefixlen / 8); + if (suffix != NULL) + memcpy(new->bits + nbytes, suffix->type.in6.s6_addr + nbytes, + 16 - nbytes); + new->clients = NULL; + if (clients != NULL) + dns_acl_attach(clients, &new->clients); + new->mapped = NULL; + if (mapped != NULL) + dns_acl_attach(mapped, &new->mapped); + new->excluded = NULL; + if (excluded != NULL) + dns_acl_attach(excluded, &new->excluded); + new->prefixlen = prefixlen; + new->flags = flags; + ISC_LINK_INIT(new, link); + new->mctx = NULL; + isc_mem_attach(mctx, &new->mctx); + *dns64 = new; + return (ISC_R_SUCCESS); +} + +void +dns_dns64_destroy(dns_dns64_t **dns64p) { + dns_dns64_t *dns64; + + REQUIRE(dns64p != NULL && *dns64p != NULL); + + dns64 = *dns64p; + *dns64p = NULL; + + REQUIRE(!ISC_LINK_LINKED(dns64, link)); + + if (dns64->clients != NULL) + dns_acl_detach(&dns64->clients); + if (dns64->mapped != NULL) + dns_acl_detach(&dns64->mapped); + if (dns64->excluded != NULL) + dns_acl_detach(&dns64->excluded); + isc_mem_putanddetach(&dns64->mctx, dns64, sizeof(*dns64)); +} + +isc_result_t +dns_dns64_aaaafroma(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr, + const dns_name_t *reqsigner, const dns_aclenv_t *env, + unsigned int flags, unsigned char *a, unsigned char *aaaa) +{ + unsigned int nbytes, i; + isc_result_t result; + int match; + + if ((dns64->flags & DNS_DNS64_RECURSIVE_ONLY) != 0 && + (flags & DNS_DNS64_RECURSIVE) == 0) + return (DNS_R_DISALLOWED); + + if ((dns64->flags & DNS_DNS64_BREAK_DNSSEC) == 0 && + (flags & DNS_DNS64_DNSSEC) != 0) + return (DNS_R_DISALLOWED); + + if (dns64->clients != NULL) { + result = dns_acl_match(reqaddr, reqsigner, dns64->clients, env, + &match, NULL); + if (result != ISC_R_SUCCESS) + return (result); + if (match <= 0) + return (DNS_R_DISALLOWED); + } + + if (dns64->mapped != NULL) { + struct in_addr ina; + isc_netaddr_t netaddr; + + memcpy(&ina.s_addr, a, 4); + isc_netaddr_fromin(&netaddr, &ina); + result = dns_acl_match(&netaddr, NULL, dns64->mapped, env, + &match, NULL); + if (result != ISC_R_SUCCESS) + return (result); + if (match <= 0) + return (DNS_R_DISALLOWED); + } + + nbytes = dns64->prefixlen / 8; + INSIST(nbytes <= 12); + /* Copy prefix. */ + memcpy(aaaa, dns64->bits, nbytes); + /* Bits 64-71 are zeros. draft-ietf-behave-address-format-04 */ + if (nbytes == 8) + aaaa[nbytes++] = 0; + /* Copy mapped address. */ + for (i = 0; i < 4U; i++) { + aaaa[nbytes++] = a[i]; + /* Bits 64-71 are zeros. draft-ietf-behave-address-format-04 */ + if (nbytes == 8) + aaaa[nbytes++] = 0; + } + /* Copy suffix. */ + memcpy(aaaa + nbytes, dns64->bits + nbytes, 16 - nbytes); + return (ISC_R_SUCCESS); +} + +dns_dns64_t * +dns_dns64_next(dns_dns64_t *dns64) { + dns64 = ISC_LIST_NEXT(dns64, link); + return (dns64); +} + +void +dns_dns64_append(dns_dns64list_t *list, dns_dns64_t *dns64) { + ISC_LIST_APPEND(*list, dns64, link); +} + +void +dns_dns64_unlink(dns_dns64list_t *list, dns_dns64_t *dns64) { + ISC_LIST_UNLINK(*list, dns64, link); +} + +isc_boolean_t +dns_dns64_aaaaok(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr, + const dns_name_t *reqsigner, const dns_aclenv_t *env, + unsigned int flags, dns_rdataset_t *rdataset, + isc_boolean_t *aaaaok, size_t aaaaoklen) +{ + struct in6_addr in6; + isc_netaddr_t netaddr; + isc_result_t result; + int match; + isc_boolean_t answer = ISC_FALSE; + isc_boolean_t found = ISC_FALSE; + unsigned int i, ok; + + REQUIRE(rdataset != NULL); + REQUIRE(rdataset->type == dns_rdatatype_aaaa); + REQUIRE(rdataset->rdclass == dns_rdataclass_in); + if (aaaaok != NULL) + REQUIRE(aaaaoklen == dns_rdataset_count(rdataset)); + + for (;dns64 != NULL; dns64 = ISC_LIST_NEXT(dns64, link)) { + if ((dns64->flags & DNS_DNS64_RECURSIVE_ONLY) != 0 && + (flags & DNS_DNS64_RECURSIVE) == 0) + continue; + + if ((dns64->flags & DNS_DNS64_BREAK_DNSSEC) == 0 && + (flags & DNS_DNS64_DNSSEC) != 0) + continue; + /* + * Work out if this dns64 structure applies to this client. + */ + if (dns64->clients != NULL) { + result = dns_acl_match(reqaddr, reqsigner, + dns64->clients, env, + &match, NULL); + if (result != ISC_R_SUCCESS) + continue; + if (match <= 0) + continue; + } + + if (!found && aaaaok != NULL) { + for (i = 0; i < aaaaoklen; i++) + aaaaok[i] = ISC_FALSE; + } + found = ISC_TRUE; + + /* + * If we are not excluding any addresses then any AAAA + * will do. + */ + if (dns64->excluded == NULL) { + answer = ISC_TRUE; + for (i = 0; i < aaaaoklen; i++) + aaaaok[i] = ISC_TRUE; + goto done; + } + + i = 0; ok = 0; + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + dns_rdata_t rdata = DNS_RDATA_INIT; + if (aaaaok == NULL || !aaaaok[i]) { + + dns_rdataset_current(rdataset, &rdata); + memcpy(&in6.s6_addr, rdata.data, 16); + isc_netaddr_fromin6(&netaddr, &in6); + + result = dns_acl_match(&netaddr, NULL, + dns64->excluded, + env, &match, NULL); + if (result == ISC_R_SUCCESS && match <= 0) { + answer = ISC_TRUE; + if (aaaaok == NULL) + goto done; + aaaaok[i] = ISC_TRUE; + ok++; + } + } else + ok++; + i++; + } + /* + * Are all addresses ok? + */ + if (aaaaok != NULL && ok == aaaaoklen) + goto done; + } + + done: + if (!found && aaaaok != NULL) { + for (i = 0; i < aaaaoklen; i++) + aaaaok[i] = ISC_TRUE; + } + return (found ? answer : ISC_TRUE); +} diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c index 67a2c67..dc249b7 100644 --- a/lib/dns/dnssec.c +++ b/lib/dns/dnssec.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -16,7 +16,7 @@ */ /* - * $Id: dnssec.c,v 1.93.12.6 2009-06-22 23:47:18 tbox Exp $ + * $Id: dnssec.c,v 1.119 2010-01-13 23:48:59 tbox Exp $ */ /*! \file */ @@ -26,15 +26,18 @@ #include #include +#include #include #include #include #include #include +#include #include #include #include +#include #include #include #include @@ -539,6 +542,59 @@ dns_dnssec_verify(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, return (result); } +static isc_boolean_t +key_active(dst_key_t *key) { + isc_result_t result; + isc_stdtime_t now, publish, active, revoke, inactive, delete; + isc_boolean_t pubset = ISC_FALSE, actset = ISC_FALSE; + isc_boolean_t revset = ISC_FALSE, inactset = ISC_FALSE; + isc_boolean_t delset = ISC_FALSE; + int major, minor; + + /* Is this an old-style key? */ + result = dst_key_getprivateformat(key, &major, &minor); + + /* + * Smart signing started with key format 1.3; prior to that, all + * keys are assumed active + */ + if (major == 1 && minor <= 2) + return (ISC_TRUE); + + isc_stdtime_get(&now); + + result = dst_key_gettime(key, DST_TIME_PUBLISH, &publish); + if (result == ISC_R_SUCCESS) + pubset = ISC_TRUE; + + result = dst_key_gettime(key, DST_TIME_ACTIVATE, &active); + if (result == ISC_R_SUCCESS) + actset = ISC_TRUE; + + result = dst_key_gettime(key, DST_TIME_REVOKE, &revoke); + if (result == ISC_R_SUCCESS) + revset = ISC_TRUE; + + result = dst_key_gettime(key, DST_TIME_INACTIVE, &inactive); + if (result == ISC_R_SUCCESS) + inactset = ISC_TRUE; + + result = dst_key_gettime(key, DST_TIME_DELETE, &delete); + if (result == ISC_R_SUCCESS) + delset = ISC_TRUE; + + if ((inactset && inactive <= now) || (delset && delete <= now)) + return (ISC_FALSE); + + if (revset && revoke <= now && pubset && publish <= now) + return (ISC_TRUE); + + if (actset && active <= now) + return (ISC_TRUE); + + return (ISC_FALSE); +} + #define is_zone_key(key) ((dst_key_flags(key) & DNS_KEYFLAG_OWNERMASK) \ == DNS_KEYOWNER_ZONE) @@ -580,14 +636,70 @@ dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, directory, mctx, &keys[count]); + + /* + * If the key was revoked and the private file + * doesn't exist, maybe it was revoked internally + * by named. Try loading the unrevoked version. + */ if (result == ISC_R_FILENOTFOUND) { + isc_uint32_t flags; + flags = dst_key_flags(pubkey); + if ((flags & DNS_KEYFLAG_REVOKE) != 0) { + dst_key_setflags(pubkey, + flags & ~DNS_KEYFLAG_REVOKE); + result = dst_key_fromfile(dst_key_name(pubkey), + dst_key_id(pubkey), + dst_key_alg(pubkey), + DST_TYPE_PUBLIC| + DST_TYPE_PRIVATE, + directory, + mctx, &keys[count]); + if (result == ISC_R_SUCCESS && + dst_key_pubcompare(pubkey, keys[count], + ISC_FALSE)) { + dst_key_setflags(keys[count], flags); + } + dst_key_setflags(pubkey, flags); + } + } + + if (result != ISC_R_SUCCESS) { + char keybuf[DNS_NAME_FORMATSIZE]; + char algbuf[DNS_SECALG_FORMATSIZE]; + dns_name_format(dst_key_name(pubkey), keybuf, + sizeof(keybuf)); + dns_secalg_format(dst_key_alg(pubkey), algbuf, + sizeof(algbuf)); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING, + "dns_dnssec_findzonekeys2: error " + "reading private key file %s/%s/%d: %s", + keybuf, algbuf, dst_key_id(pubkey), + isc_result_totext(result)); + } + + if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) { keys[count] = pubkey; pubkey = NULL; count++; goto next; } + if (result != ISC_R_SUCCESS) goto failure; + + /* + * If a key is marked inactive, skip it + */ + if (!key_active(keys[count])) { + dst_key_free(&keys[count]); + keys[count] = pubkey; + pubkey = NULL; + count++; + goto next; + } + if ((dst_key_flags(keys[count]) & DNS_KEYTYPE_NOAUTH) != 0) { /* We should never get here. */ dst_key_free(&keys[count]); @@ -951,3 +1063,691 @@ dns_dnssec_selfsigns(dns_rdata_t *rdata, dns_name_t *name, dst_key_free(&dstkey); return (ISC_FALSE); } + +isc_result_t +dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey, + dns_dnsseckey_t **dkp) +{ + isc_result_t result; + dns_dnsseckey_t *dk; + int major, minor; + + REQUIRE(dkp != NULL && *dkp == NULL); + dk = isc_mem_get(mctx, sizeof(dns_dnsseckey_t)); + if (dk == NULL) + return (ISC_R_NOMEMORY); + + dk->key = *dstkey; + *dstkey = NULL; + dk->force_publish = ISC_FALSE; + dk->force_sign = ISC_FALSE; + dk->hint_publish = ISC_FALSE; + dk->hint_sign = ISC_FALSE; + dk->hint_remove = ISC_FALSE; + dk->first_sign = ISC_FALSE; + dk->is_active = ISC_FALSE; + dk->prepublish = 0; + dk->source = dns_keysource_unknown; + dk->index = 0; + + /* KSK or ZSK? */ + dk->ksk = ISC_TF((dst_key_flags(dk->key) & DNS_KEYFLAG_KSK) != 0); + + /* Is this an old-style key? */ + result = dst_key_getprivateformat(dk->key, &major, &minor); + + /* Smart signing started with key format 1.3 */ + dk->legacy = ISC_TF(major == 1 && minor <= 2); + + ISC_LINK_INIT(dk, link); + *dkp = dk; + return (ISC_R_SUCCESS); +} + +void +dns_dnsseckey_destroy(isc_mem_t *mctx, dns_dnsseckey_t **dkp) { + dns_dnsseckey_t *dk; + + REQUIRE(dkp != NULL && *dkp != NULL); + dk = *dkp; + if (dk->key != NULL) + dst_key_free(&dk->key); + isc_mem_put(mctx, dk, sizeof(dns_dnsseckey_t)); + *dkp = NULL; +} + +static void +get_hints(dns_dnsseckey_t *key) { + isc_result_t result; + isc_stdtime_t now, publish, active, revoke, inactive, delete; + isc_boolean_t pubset = ISC_FALSE, actset = ISC_FALSE; + isc_boolean_t revset = ISC_FALSE, inactset = ISC_FALSE; + isc_boolean_t delset = ISC_FALSE; + + REQUIRE(key != NULL && key->key != NULL); + + isc_stdtime_get(&now); + + result = dst_key_gettime(key->key, DST_TIME_PUBLISH, &publish); + if (result == ISC_R_SUCCESS) + pubset = ISC_TRUE; + + result = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active); + if (result == ISC_R_SUCCESS) + actset = ISC_TRUE; + + result = dst_key_gettime(key->key, DST_TIME_REVOKE, &revoke); + if (result == ISC_R_SUCCESS) + revset = ISC_TRUE; + + result = dst_key_gettime(key->key, DST_TIME_INACTIVE, &inactive); + if (result == ISC_R_SUCCESS) + inactset = ISC_TRUE; + + result = dst_key_gettime(key->key, DST_TIME_DELETE, &delete); + if (result == ISC_R_SUCCESS) + delset = ISC_TRUE; + + /* Metadata says publish (but possibly not activate) */ + if (pubset && publish <= now) + key->hint_publish = ISC_TRUE; + + /* Metadata says activate (so we must also publish) */ + if (actset && active <= now) { + key->hint_sign = ISC_TRUE; + key->hint_publish = ISC_TRUE; + } + + /* + * Activation date is set (maybe in the future), but + * publication date isn't. Most likely the user wants to + * publish now and activate later. + */ + if (actset && !pubset) + key->hint_publish = ISC_TRUE; + + /* + * If activation date is in the future, make note of how far off + */ + if (key->hint_publish && actset && active > now) { + key->prepublish = active - now; + } + + /* + * Key has been marked inactive: we can continue publishing, + * but don't sign. + */ + if (key->hint_publish && inactset && inactive <= now) { + key->hint_sign = ISC_FALSE; + } + + /* + * Metadata says revoke. If the key is published, + * we *have to* sign with it per RFC5011--even if it was + * not active before. + * + * If it hasn't already been done, we should also revoke it now. + */ + if (key->hint_publish && (revset && revoke <= now)) { + isc_uint32_t flags; + key->hint_sign = ISC_TRUE; + flags = dst_key_flags(key->key); + if ((flags & DNS_KEYFLAG_REVOKE) == 0) { + flags |= DNS_KEYFLAG_REVOKE; + dst_key_setflags(key->key, flags); + } + } + + /* + * Metadata says delete, so don't publish this key or sign with it. + */ + if (delset && delete <= now) { + key->hint_publish = ISC_FALSE; + key->hint_sign = ISC_FALSE; + key->hint_remove = ISC_TRUE; + } +} + +/*% + * Get a list of DNSSEC keys from the key repository + */ +isc_result_t +dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory, + isc_mem_t *mctx, dns_dnsseckeylist_t *keylist) +{ + isc_result_t result = ISC_R_SUCCESS; + isc_boolean_t dir_open = ISC_FALSE; + dns_dnsseckeylist_t list; + isc_dir_t dir; + dns_dnsseckey_t *key = NULL; + dst_key_t *dstkey = NULL; + char namebuf[DNS_NAME_FORMATSIZE], *p; + isc_buffer_t b; + unsigned int len; + + REQUIRE(keylist != NULL); + ISC_LIST_INIT(list); + isc_dir_init(&dir); + + isc_buffer_init(&b, namebuf, sizeof(namebuf) - 1); + RETERR(dns_name_totext(origin, ISC_FALSE, &b)); + len = isc_buffer_usedlength(&b); + namebuf[len] = '\0'; + + if (directory == NULL) + directory = "."; + RETERR(isc_dir_open(&dir, directory)); + dir_open = ISC_TRUE; + + while (isc_dir_read(&dir) == ISC_R_SUCCESS) { + if (dir.entry.name[0] == 'K' && + dir.entry.length > len + 1 && + dir.entry.name[len + 1] == '+' && + strncasecmp(dir.entry.name + 1, namebuf, len) == 0) { + p = strrchr(dir.entry.name, '.'); + if (p != NULL && strcmp(p, ".private") != 0) + continue; + + dstkey = NULL; + result = dst_key_fromnamedfile(dir.entry.name, + directory, + DST_TYPE_PUBLIC | + DST_TYPE_PRIVATE, + mctx, &dstkey); + + if (result != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, + DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_DNSSEC, + ISC_LOG_WARNING, + "dns_dnssec_findmatchingkeys: " + "error reading key file %s: %s", + dir.entry.name, + isc_result_totext(result)); + continue; + } + + RETERR(dns_dnsseckey_create(mctx, &dstkey, &key)); + key->source = dns_keysource_repository; + get_hints(key); + + if (key->legacy) { + dns_dnsseckey_destroy(mctx, &key); + } else { + ISC_LIST_APPEND(list, key, link); + key = NULL; + } + } + } + + if (!ISC_LIST_EMPTY(list)) + ISC_LIST_APPENDLIST(*keylist, list, link); + else + result = ISC_R_NOTFOUND; + + failure: + if (dir_open) + isc_dir_close(&dir); + INSIST(key == NULL); + while ((key = ISC_LIST_HEAD(list)) != NULL) { + ISC_LIST_UNLINK(list, key, link); + INSIST(key->key != NULL); + dst_key_free(&key->key); + dns_dnsseckey_destroy(mctx, &key); + } + if (dstkey != NULL) + dst_key_free(&dstkey); + return (result); +} + +/*% + * Add 'newkey' to 'keylist' if it's not already there. + * + * If 'savekeys' is ISC_TRUE, then we need to preserve all + * the keys in the keyset, regardless of whether they have + * metadata indicating they should be deactivated or removed. + */ +static void +addkey(dns_dnsseckeylist_t *keylist, dst_key_t **newkey, + isc_boolean_t savekeys, isc_mem_t *mctx) +{ + dns_dnsseckey_t *key; + + /* Skip duplicates */ + for (key = ISC_LIST_HEAD(*keylist); + key != NULL; + key = ISC_LIST_NEXT(key, link)) { + if (dst_key_id(key->key) == dst_key_id(*newkey) && + dst_key_alg(key->key) == dst_key_alg(*newkey) && + dns_name_equal(dst_key_name(key->key), + dst_key_name(*newkey))) + break; + } + + if (key != NULL) { + /* + * Found a match. If the old key was only public and the + * new key is private, replace the old one; otherwise + * leave it. But either way, mark the key as having + * been found in the zone. + */ + if (dst_key_isprivate(key->key)) { + dst_key_free(newkey); + } else if (dst_key_isprivate(*newkey)) { + dst_key_free(&key->key); + key->key = *newkey; + } + + key->source = dns_keysource_zoneapex; + return; + } + + dns_dnsseckey_create(mctx, newkey, &key); + if (key->legacy || savekeys) { + key->force_publish = ISC_TRUE; + key->force_sign = dst_key_isprivate(key->key); + } + key->source = dns_keysource_zoneapex; + ISC_LIST_APPEND(*keylist, key, link); + *newkey = NULL; +} + + +/*% + * Mark all keys which signed the DNSKEY/SOA RRsets as "active", + * for future reference. + */ +static isc_result_t +mark_active_keys(dns_dnsseckeylist_t *keylist, dns_rdataset_t *rrsigs) { + isc_result_t result = ISC_R_SUCCESS; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_t sigs; + dns_dnsseckey_t *key; + + REQUIRE(rrsigs != NULL && dns_rdataset_isassociated(rrsigs)); + + dns_rdataset_init(&sigs); + dns_rdataset_clone(rrsigs, &sigs); + for (key = ISC_LIST_HEAD(*keylist); + key != NULL; + key = ISC_LIST_NEXT(key, link)) { + isc_uint16_t keyid, sigid; + dns_secalg_t keyalg, sigalg; + keyid = dst_key_id(key->key); + keyalg = dst_key_alg(key->key); + + for (result = dns_rdataset_first(&sigs); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&sigs)) { + dns_rdata_rrsig_t sig; + + dns_rdata_reset(&rdata); + dns_rdataset_current(&sigs, &rdata); + result = dns_rdata_tostruct(&rdata, &sig, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + sigalg = sig.algorithm; + sigid = sig.keyid; + if (keyid == sigid && keyalg == sigalg) { + key->is_active = ISC_TRUE; + break; + } + } + } + + if (result == ISC_R_NOMORE) + result = ISC_R_SUCCESS; + + if (dns_rdataset_isassociated(&sigs)) + dns_rdataset_disassociate(&sigs); + return (result); +} + +/*% + * Add the contents of a DNSKEY rdataset 'keyset' to 'keylist'. + */ +isc_result_t +dns_dnssec_keylistfromrdataset(dns_name_t *origin, + const char *directory, isc_mem_t *mctx, + dns_rdataset_t *keyset, dns_rdataset_t *keysigs, + dns_rdataset_t *soasigs, isc_boolean_t savekeys, + isc_boolean_t public, + dns_dnsseckeylist_t *keylist) +{ + dns_rdataset_t keys; + dns_rdata_t rdata = DNS_RDATA_INIT; + dst_key_t *pubkey = NULL, *privkey = NULL; + isc_result_t result; + + REQUIRE(keyset != NULL && dns_rdataset_isassociated(keyset)); + + dns_rdataset_init(&keys); + + dns_rdataset_clone(keyset, &keys); + for (result = dns_rdataset_first(&keys); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&keys)) { + dns_rdata_reset(&rdata); + dns_rdataset_current(&keys, &rdata); + RETERR(dns_dnssec_keyfromrdata(origin, &rdata, mctx, &pubkey)); + + if (!is_zone_key(pubkey) || + (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0) + goto skip; + + /* Corrupted .key file? */ + if (!dns_name_equal(origin, dst_key_name(pubkey))) + goto skip; + + if (public) { + addkey(keylist, &pubkey, savekeys, mctx); + goto skip; + } + + result = dst_key_fromfile(dst_key_name(pubkey), + dst_key_id(pubkey), + dst_key_alg(pubkey), + DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, + directory, mctx, &privkey); + + /* + * If the key was revoked and the private file + * doesn't exist, maybe it was revoked internally + * by named. Try loading the unrevoked version. + */ + if (result == ISC_R_FILENOTFOUND) { + isc_uint32_t flags; + flags = dst_key_flags(pubkey); + if ((flags & DNS_KEYFLAG_REVOKE) != 0) { + dst_key_setflags(pubkey, + flags & ~DNS_KEYFLAG_REVOKE); + result = dst_key_fromfile(dst_key_name(pubkey), + dst_key_id(pubkey), + dst_key_alg(pubkey), + DST_TYPE_PUBLIC| + DST_TYPE_PRIVATE, + directory, + mctx, &privkey); + if (result == ISC_R_SUCCESS && + dst_key_pubcompare(pubkey, privkey, + ISC_FALSE)) { + dst_key_setflags(privkey, flags); + } + dst_key_setflags(pubkey, flags); + } + } + + if (result != ISC_R_SUCCESS) { + char keybuf[DNS_NAME_FORMATSIZE]; + char algbuf[DNS_SECALG_FORMATSIZE]; + dns_name_format(dst_key_name(pubkey), keybuf, + sizeof(keybuf)); + dns_secalg_format(dst_key_alg(pubkey), algbuf, + sizeof(algbuf)); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING, + "dns_dnssec_keylistfromrdataset: error " + "reading private key file %s/%s/%d: %s", + keybuf, algbuf, dst_key_id(pubkey), + isc_result_totext(result)); + } + + if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) { + addkey(keylist, &pubkey, savekeys, mctx); + goto skip; + } + RETERR(result); + + /* This should never happen. */ + if ((dst_key_flags(privkey) & DNS_KEYTYPE_NOAUTH) != 0) + goto skip; + + addkey(keylist, &privkey, savekeys, mctx); + skip: + if (pubkey != NULL) + dst_key_free(&pubkey); + if (privkey != NULL) + dst_key_free(&privkey); + } + + if (result != ISC_R_NOMORE) + RETERR(result); + + if (keysigs != NULL && dns_rdataset_isassociated(keysigs)) + RETERR(mark_active_keys(keylist, keysigs)); + + if (soasigs != NULL && dns_rdataset_isassociated(soasigs)) + RETERR(mark_active_keys(keylist, soasigs)); + + result = ISC_R_SUCCESS; + + failure: + if (dns_rdataset_isassociated(&keys)) + dns_rdataset_disassociate(&keys); + if (pubkey != NULL) + dst_key_free(&pubkey); + if (privkey != NULL) + dst_key_free(&privkey); + return (result); +} + +static isc_result_t +make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize, + dns_rdata_t *target) +{ + isc_result_t result; + isc_buffer_t b; + isc_region_t r; + + isc_buffer_init(&b, buf, bufsize); + result = dst_key_todns(key, &b); + if (result != ISC_R_SUCCESS) + return (result); + + dns_rdata_reset(target); + isc_buffer_usedregion(&b, &r); + dns_rdata_fromregion(target, dst_key_class(key), + dns_rdatatype_dnskey, &r); + return (ISC_R_SUCCESS); +} + +static isc_result_t +publish_key(dns_diff_t *diff, dns_dnsseckey_t *key, dns_name_t *origin, + dns_ttl_t ttl, isc_mem_t *mctx, isc_boolean_t allzsk, + void (*report)(const char *, ...)) +{ + isc_result_t result; + dns_difftuple_t *tuple = NULL; + unsigned char buf[DST_KEY_MAXSIZE]; + dns_rdata_t dnskey = DNS_RDATA_INIT; + char alg[80]; + + dns_rdata_reset(&dnskey); + RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey)); + + dns_secalg_format(dst_key_alg(key->key), alg, sizeof(alg)); + report("Fetching %s %d/%s from key %s.", + key->ksk ? (allzsk ? "KSK/ZSK" : "KSK") : "ZSK", + dst_key_id(key->key), alg, + key->source == dns_keysource_user ? "file" : "repository"); + + if (key->prepublish && ttl > key->prepublish) { + char keystr[DST_KEY_FORMATSIZE]; + isc_stdtime_t now; + + dst_key_format(key->key, keystr, sizeof(keystr)); + report("Key %s: Delaying activation to match the DNSKEY TTL.\n", + keystr, ttl); + + isc_stdtime_get(&now); + dst_key_settime(key->key, DST_TIME_ACTIVATE, now + ttl); + } + + /* publish key */ + RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_ADD, origin, ttl, + &dnskey, &tuple)); + dns_diff_appendminimal(diff, &tuple); + result = ISC_R_SUCCESS; + + failure: + return (result); +} + +static isc_result_t +remove_key(dns_diff_t *diff, dns_dnsseckey_t *key, dns_name_t *origin, + dns_ttl_t ttl, isc_mem_t *mctx, const char *reason, + void (*report)(const char *, ...)) +{ + isc_result_t result; + dns_difftuple_t *tuple = NULL; + unsigned char buf[DST_KEY_MAXSIZE]; + dns_rdata_t dnskey = DNS_RDATA_INIT; + char alg[80]; + + dns_secalg_format(dst_key_alg(key->key), alg, sizeof(alg)); + report("Removing %s key %d/%s from DNSKEY RRset.", + reason, dst_key_id(key->key), alg); + + RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey)); + RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_DEL, origin, ttl, &dnskey, + &tuple)); + dns_diff_appendminimal(diff, &tuple); + result = ISC_R_SUCCESS; + + failure: + return (result); +} + +/* + * Update 'keys' with information from 'newkeys'. + * + * If 'removed' is not NULL, any keys that are being removed from + * the zone will be added to the list for post-removal processing. + */ +isc_result_t +dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys, + dns_dnsseckeylist_t *removed, dns_name_t *origin, + dns_ttl_t ttl, dns_diff_t *diff, isc_boolean_t allzsk, + isc_mem_t *mctx, void (*report)(const char *, ...)) +{ + isc_result_t result; + dns_dnsseckey_t *key, *key1, *key2, *next; + + /* + * First, look through the existing key list to find keys + * supplied from the command line which are not in the zone. + * Update the zone to include them. + */ + for (key = ISC_LIST_HEAD(*keys); + key != NULL; + key = ISC_LIST_NEXT(key, link)) { + if (key->source == dns_keysource_user && + (key->hint_publish || key->force_publish)) { + RETERR(publish_key(diff, key, origin, ttl, + mctx, allzsk, report)); + } + } + + /* + * Second, scan the list of newly found keys looking for matches + * with known keys, and update accordingly. + */ + for (key1 = ISC_LIST_HEAD(*newkeys); key1 != NULL; key1 = next) { + isc_boolean_t key_revoked = ISC_FALSE; + + next = ISC_LIST_NEXT(key1, link); + + for (key2 = ISC_LIST_HEAD(*keys); + key2 != NULL; + key2 = ISC_LIST_NEXT(key2, link)) { + if (dst_key_pubcompare(key1->key, key2->key, + ISC_TRUE)) { + int r1, r2; + r1 = dst_key_flags(key1->key) & + DNS_KEYFLAG_REVOKE; + r2 = dst_key_flags(key2->key) & + DNS_KEYFLAG_REVOKE; + key_revoked = ISC_TF(r1 != r2); + break; + } + } + + /* No match found in keys; add the new key. */ + if (key2 == NULL) { + dns_dnsseckey_t *next; + + next = ISC_LIST_NEXT(key1, link); + ISC_LIST_UNLINK(*newkeys, key1, link); + ISC_LIST_APPEND(*keys, key1, link); + + if (key1->source != dns_keysource_zoneapex && + (key1->hint_publish || key1->force_publish)) { + RETERR(publish_key(diff, key1, origin, ttl, + mctx, allzsk, report)); + if (key1->hint_sign || key1->force_sign) + key1->first_sign = ISC_TRUE; + } + + continue; + } + + /* Match found: remove or update it as needed */ + if (key1->hint_remove) { + RETERR(remove_key(diff, key2, origin, ttl, mctx, + "expired", report)); + ISC_LIST_UNLINK(*keys, key2, link); + if (removed != NULL) + ISC_LIST_APPEND(*removed, key2, link); + else + dns_dnsseckey_destroy(mctx, &key2); + } else if (key_revoked && + (dst_key_flags(key1->key) & DNS_KEYFLAG_REVOKE) != 0) { + + /* + * A previously valid key has been revoked. + * We need to remove the old version and pull + * in the new one. + */ + RETERR(remove_key(diff, key2, origin, ttl, mctx, + "revoked", report)); + ISC_LIST_UNLINK(*keys, key2, link); + if (removed != NULL) + ISC_LIST_APPEND(*removed, key2, link); + else + dns_dnsseckey_destroy(mctx, &key2); + + RETERR(publish_key(diff, key1, origin, ttl, + mctx, allzsk, report)); + ISC_LIST_UNLINK(*newkeys, key1, link); + ISC_LIST_APPEND(*keys, key1, link); + + /* + * XXX: The revoke flag is only defined for trust + * anchors. Setting the flag on a non-KSK is legal, + * but not defined in any RFC. It seems reasonable + * to treat it the same as a KSK: keep it in the + * zone, sign the DNSKEY set with it, but not + * sign other records with it. + */ + key1->ksk = ISC_TRUE; + continue; + } else { + if (!key2->is_active && + (key1->hint_sign || key1->force_sign)) + key2->first_sign = ISC_TRUE; + key2->hint_sign = key1->hint_sign; + key2->hint_publish = key1->hint_publish; + } + } + + /* Free any leftover keys in newkeys */ + while (!ISC_LIST_EMPTY(*newkeys)) { + key1 = ISC_LIST_HEAD(*newkeys); + ISC_LIST_UNLINK(*newkeys, key1, link); + dns_dnsseckey_destroy(mctx, &key1); + } + + result = ISC_R_SUCCESS; + + failure: + return (result); +} diff --git a/lib/dns/ds.c b/lib/dns/ds.c index 9cf5659..80e1503 100644 --- a/lib/dns/ds.c +++ b/lib/dns/ds.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2002, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ds.c,v 1.11 2007-06-19 23:47:16 tbox Exp $ */ +/* $Id: ds.c,v 1.13 2010-12-23 23:47:08 tbox Exp $ */ /*! \file */ @@ -38,6 +38,13 @@ #include +#ifdef HAVE_OPENSSL_GOST +#include +#include + +extern const EVP_MD * EVP_gost(void); +#endif + isc_result_t dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key, unsigned int digest_type, unsigned char *buffer, @@ -49,6 +56,12 @@ dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key, isc_region_t r; isc_buffer_t b; dns_rdata_ds_t ds; + isc_sha1_t sha1; + isc_sha256_t sha256; +#ifdef HAVE_OPENSSL_GOST + EVP_MD_CTX ctx; + const EVP_MD *md; +#endif REQUIRE(key != NULL); REQUIRE(key->type == dns_rdatatype_dnskey); @@ -63,8 +76,8 @@ dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key, memset(buffer, 0, DNS_DS_BUFFERSIZE); isc_buffer_init(&b, buffer, DNS_DS_BUFFERSIZE); - if (digest_type == DNS_DSDIGEST_SHA1) { - isc_sha1_t sha1; + switch (digest_type) { + case DNS_DSDIGEST_SHA1: isc_sha1_init(&sha1); dns_name_toregion(name, &r); isc_sha1_update(&sha1, r.base, r.length); @@ -72,8 +85,33 @@ dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key, INSIST(r.length >= 4); isc_sha1_update(&sha1, r.base, r.length); isc_sha1_final(&sha1, digest); - } else { - isc_sha256_t sha256; + break; +#ifdef HAVE_OPENSSL_GOST +#define CHECK(x) \ + if ((x) != 1) { \ + EVP_MD_CTX_cleanup(&ctx); \ + return (DST_R_OPENSSLFAILURE); \ + } + + case DNS_DSDIGEST_GOST: + md = EVP_gost(); + if (md == NULL) + return (DST_R_OPENSSLFAILURE); + EVP_MD_CTX_init(&ctx); + CHECK(EVP_DigestInit(&ctx, md)); + dns_name_toregion(name, &r); + CHECK(EVP_DigestUpdate(&ctx, + (const void *) r.base, + (size_t) r.length)); + dns_rdata_toregion(key, &r); + INSIST(r.length >= 4); + CHECK(EVP_DigestUpdate(&ctx, + (const void *) r.base, + (size_t) r.length)); + CHECK(EVP_DigestFinal(&ctx, digest, NULL)); + break; +#endif + default: isc_sha256_init(&sha256); dns_name_toregion(name, &r); isc_sha256_update(&sha256, r.base, r.length); @@ -81,6 +119,7 @@ dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key, INSIST(r.length >= 4); isc_sha256_update(&sha256, r.base, r.length); isc_sha256_final(digest, &sha256); + break; } ds.mctx = NULL; @@ -89,8 +128,19 @@ dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key, ds.algorithm = r.base[3]; ds.key_tag = dst_region_computeid(&r, ds.algorithm); ds.digest_type = digest_type; - ds.length = (digest_type == DNS_DSDIGEST_SHA1) ? - ISC_SHA1_DIGESTLENGTH : ISC_SHA256_DIGESTLENGTH; + switch (digest_type) { + case DNS_DSDIGEST_SHA1: + ds.length = ISC_SHA1_DIGESTLENGTH; + break; +#ifdef HAVE_OPENSSL_GOST + case DNS_DSDIGEST_GOST: + ds.length = ISC_GOST_DIGESTLENGTH; + break; +#endif + default: + ds.length = ISC_SHA256_DIGESTLENGTH; + break; + } ds.digest = digest; return (dns_rdata_fromstruct(rdata, key->rdclass, dns_rdatatype_ds, @@ -99,6 +149,12 @@ dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key, isc_boolean_t dns_ds_digest_supported(unsigned int digest_type) { +#ifdef HAVE_OPENSSL_GOST + return (ISC_TF(digest_type == DNS_DSDIGEST_SHA1 || + digest_type == DNS_DSDIGEST_SHA256 || + digest_type == DNS_DSDIGEST_GOST)); +#else return (ISC_TF(digest_type == DNS_DSDIGEST_SHA1 || digest_type == DNS_DSDIGEST_SHA256)); +#endif } diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c index 97d2657..1ece312 100644 --- a/lib/dns/dst_api.c +++ b/lib/dns/dst_api.c @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -31,7 +31,7 @@ /* * Principal Author: Brian Wellington - * $Id: dst_api.c,v 1.16.12.12 2010-12-09 01:12:55 marka Exp $ + * $Id: dst_api.c,v 1.57 2011-01-11 23:47:13 tbox Exp $ */ /*! \file */ @@ -39,6 +39,7 @@ #include #include +#include #include #include @@ -48,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -70,7 +72,9 @@ #define DST_AS_STR(t) ((t).value.as_textregion.base) static dst_func_t *dst_t_func[DST_MAX_ALGS]; +#ifdef BIND9 static isc_entropy_t *dst_entropy_pool = NULL; +#endif static unsigned int dst_entropy_flags = 0; static isc_boolean_t dst_initialized = ISC_FALSE; @@ -108,10 +112,11 @@ static isc_result_t frombuffer(dns_name_t *name, static isc_result_t algorithm_status(unsigned int alg); -static isc_result_t addsuffix(char *filename, unsigned int len, - const char *ofilename, const char *suffix); +static isc_result_t addsuffix(char *filename, int len, + const char *dirname, const char *ofilename, + const char *suffix); -#define RETERR(x) \ +#define RETERR(x) \ do { \ result = (x); \ if (result != ISC_R_SUCCESS) \ @@ -126,7 +131,7 @@ static isc_result_t addsuffix(char *filename, unsigned int len, return (_r); \ } while (0); \ -#ifdef OPENSSL +#if defined(OPENSSL) && defined(BIND9) static void * default_memalloc(void *arg, size_t size) { UNUSED(arg); @@ -144,14 +149,29 @@ default_memfree(void *arg, void *ptr) { isc_result_t dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) { + return (dst_lib_init2(mctx, ectx, NULL, eflags)); +} + +isc_result_t +dst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx, + const char *engine, unsigned int eflags) { isc_result_t result; - REQUIRE(mctx != NULL && ectx != NULL); + REQUIRE(mctx != NULL); +#ifdef BIND9 + REQUIRE(ectx != NULL); +#else + UNUSED(ectx); +#endif REQUIRE(dst_initialized == ISC_FALSE); +#ifndef OPENSSL + UNUSED(engine); +#endif + dst__memory_pool = NULL; -#ifdef OPENSSL +#if defined(OPENSSL) && defined(BIND9) UNUSED(mctx); /* * When using --with-openssl, there seems to be no good way of not @@ -166,11 +186,15 @@ dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) { if (result != ISC_R_SUCCESS) return (result); isc_mem_setname(dst__memory_pool, "dst", NULL); +#ifndef OPENSSL_LEAKS isc_mem_setdestroycheck(dst__memory_pool, ISC_FALSE); +#endif #else isc_mem_attach(mctx, &dst__memory_pool); #endif +#ifdef BIND9 isc_entropy_attach(ectx, &dst_entropy_pool); +#endif dst_entropy_flags = eflags; dst_result_register(); @@ -183,7 +207,7 @@ dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) { RETERR(dst__hmacsha384_init(&dst_t_func[DST_ALG_HMACSHA384])); RETERR(dst__hmacsha512_init(&dst_t_func[DST_ALG_HMACSHA512])); #ifdef OPENSSL - RETERR(dst__openssl_init()); + RETERR(dst__openssl_init(engine)); RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSAMD5], DST_ALG_RSAMD5)); RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA1], @@ -199,6 +223,9 @@ dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) { RETERR(dst__openssldsa_init(&dst_t_func[DST_ALG_NSEC3DSA])); #endif RETERR(dst__openssldh_init(&dst_t_func[DST_ALG_DH])); +#ifdef HAVE_OPENSSL_GOST + RETERR(dst__opensslgost_init(&dst_t_func[DST_ALG_ECCGOST])); +#endif #endif /* OPENSSL */ #ifdef GSSAPI RETERR(dst__gssapi_init(&dst_t_func[DST_ALG_GSSAPI])); @@ -207,6 +234,8 @@ dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) { return (ISC_R_SUCCESS); out: + /* avoid immediate crash! */ + dst_initialized = ISC_TRUE; dst_lib_destroy(); return (result); } @@ -225,9 +254,10 @@ dst_lib_destroy(void) { #endif if (dst__memory_pool != NULL) isc_mem_detach(&dst__memory_pool); +#ifdef BIND9 if (dst_entropy_pool != NULL) isc_entropy_detach(&dst_entropy_pool); - +#endif } isc_boolean_t @@ -402,7 +432,7 @@ dst_key_fromfile(dns_name_t *name, dns_keytag_t id, return (result); key = NULL; - result = dst_key_fromnamedfile(filename, type, mctx, &key); + result = dst_key_fromnamedfile(filename, NULL, type, mctx, &key); if (result != ISC_R_SUCCESS) return (result); @@ -424,12 +454,11 @@ dst_key_fromfile(dns_name_t *name, dns_keytag_t id, } isc_result_t -dst_key_fromnamedfile(const char *filename, int type, isc_mem_t *mctx, - dst_key_t **keyp) +dst_key_fromnamedfile(const char *filename, const char *dirname, + int type, isc_mem_t *mctx, dst_key_t **keyp) { isc_result_t result; dst_key_t *pubkey = NULL, *key = NULL; - dns_keytag_t id; char *newfilename = NULL; int newfilenamelen = 0; isc_lex_t *lex = NULL; @@ -440,11 +469,23 @@ dst_key_fromnamedfile(const char *filename, int type, isc_mem_t *mctx, REQUIRE(mctx != NULL); REQUIRE(keyp != NULL && *keyp == NULL); + /* If an absolute path is specified, don't use the key directory */ +#ifndef WIN32 + if (filename[0] == '/') + dirname = NULL; +#else /* WIN32 */ + if (filename[0] == '/' || filename[0] == '\\') + dirname = NULL; +#endif + newfilenamelen = strlen(filename) + 5; + if (dirname != NULL) + newfilenamelen += strlen(dirname) + 1; newfilename = isc_mem_get(mctx, newfilenamelen); if (newfilename == NULL) return (ISC_R_NOMEMORY); - result = addsuffix(newfilename, newfilenamelen, filename, ".key"); + result = addsuffix(newfilename, newfilenamelen, + dirname, filename, ".key"); INSIST(result == ISC_R_SUCCESS); result = dst_key_read_public(newfilename, type, mctx, &pubkey); @@ -474,38 +515,43 @@ dst_key_fromnamedfile(const char *filename, int type, isc_mem_t *mctx, key = get_key_struct(pubkey->key_name, pubkey->key_alg, pubkey->key_flags, pubkey->key_proto, 0, pubkey->key_class, mctx); - id = pubkey->key_id; - dst_key_free(&pubkey); - - if (key == NULL) + if (key == NULL) { + dst_key_free(&pubkey); return (ISC_R_NOMEMORY); + } if (key->func->parse == NULL) RETERR(DST_R_UNSUPPORTEDALG); newfilenamelen = strlen(filename) + 9; + if (dirname != NULL) + newfilenamelen += strlen(dirname) + 1; newfilename = isc_mem_get(mctx, newfilenamelen); if (newfilename == NULL) RETERR(ISC_R_NOMEMORY); - result = addsuffix(newfilename, newfilenamelen, filename, ".private"); + result = addsuffix(newfilename, newfilenamelen, + dirname, filename, ".private"); INSIST(result == ISC_R_SUCCESS); RETERR(isc_lex_create(mctx, 1500, &lex)); RETERR(isc_lex_openfile(lex, newfilename)); isc_mem_put(mctx, newfilename, newfilenamelen); - RETERR(key->func->parse(key, lex)); + RETERR(key->func->parse(key, lex, pubkey)); isc_lex_destroy(&lex); RETERR(computeid(key)); - if (id != key->key_id) + if (pubkey->key_id != key->key_id) RETERR(DST_R_INVALIDPRIVATEKEY); + dst_key_free(&pubkey); *keyp = key; return (ISC_R_SUCCESS); out: + if (pubkey != NULL) + dst_key_free(&pubkey); if (newfilename != NULL) isc_mem_put(mctx, newfilename, newfilenamelen); if (lex != NULL) @@ -640,7 +686,7 @@ dst_key_privatefrombuffer(dst_key_t *key, isc_buffer_t *buffer) { RETERR(isc_lex_create(key->mctx, 1500, &lex)); RETERR(isc_lex_openbuffer(lex, buffer)); - RETERR(key->func->parse(key, lex)); + RETERR(key->func->parse(key, lex, NULL)); out: if (lex != NULL) isc_lex_destroy(&lex); @@ -657,9 +703,10 @@ dst_key_getgssctx(const dst_key_t *key) isc_result_t dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx, - dst_key_t **keyp) + dst_key_t **keyp, isc_region_t *intoken) { dst_key_t *key; + isc_result_t result; REQUIRE(gssctx != NULL); REQUIRE(keyp != NULL && *keyp == NULL); @@ -669,9 +716,21 @@ dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx, if (key == NULL) return (ISC_R_NOMEMORY); + if (intoken != NULL) { + /* + * Keep the token for use by external ssu rules. They may need + * to examine the PAC in the kerberos ticket. + */ + RETERR(isc_buffer_allocate(key->mctx, &key->key_tkeytoken, + intoken->length)); + RETERR(isc_buffer_copyregion(key->key_tkeytoken, intoken)); + } + key->keydata.gssctx = gssctx; *keyp = key; - return (ISC_R_SUCCESS); + result = ISC_R_SUCCESS; +out: + return result; } isc_result_t @@ -723,6 +782,18 @@ dst_key_generate(dns_name_t *name, unsigned int alg, dns_rdataclass_t rdclass, isc_mem_t *mctx, dst_key_t **keyp) { + return (dst_key_generate2(name, alg, bits, param, flags, protocol, + rdclass, mctx, keyp, NULL)); +} + +isc_result_t +dst_key_generate2(dns_name_t *name, unsigned int alg, + unsigned int bits, unsigned int param, + unsigned int flags, unsigned int protocol, + dns_rdataclass_t rdclass, + isc_mem_t *mctx, dst_key_t **keyp, + void (*callback)(int)) +{ dst_key_t *key; isc_result_t ret; @@ -748,7 +819,7 @@ dst_key_generate(dns_name_t *name, unsigned int alg, return (DST_R_UNSUPPORTEDALG); } - ret = key->func->generate(key, param); + ret = key->func->generate(key, param, callback); if (ret != ISC_R_SUCCESS) { dst_key_free(&key); return (ret); @@ -764,25 +835,185 @@ dst_key_generate(dns_name_t *name, unsigned int alg, return (ISC_R_SUCCESS); } -isc_boolean_t -dst_key_compare(const dst_key_t *key1, const dst_key_t *key2) { +isc_result_t +dst_key_getnum(const dst_key_t *key, int type, isc_uint32_t *valuep) +{ + REQUIRE(VALID_KEY(key)); + REQUIRE(valuep != NULL); + REQUIRE(type <= DST_MAX_NUMERIC); + if (!key->numset[type]) + return (ISC_R_NOTFOUND); + *valuep = key->nums[type]; + return (ISC_R_SUCCESS); +} + +void +dst_key_setnum(dst_key_t *key, int type, isc_uint32_t value) +{ + REQUIRE(VALID_KEY(key)); + REQUIRE(type <= DST_MAX_NUMERIC); + key->nums[type] = value; + key->numset[type] = ISC_TRUE; +} + +void +dst_key_unsetnum(dst_key_t *key, int type) +{ + REQUIRE(VALID_KEY(key)); + REQUIRE(type <= DST_MAX_NUMERIC); + key->numset[type] = ISC_FALSE; +} + +isc_result_t +dst_key_gettime(const dst_key_t *key, int type, isc_stdtime_t *timep) { + REQUIRE(VALID_KEY(key)); + REQUIRE(timep != NULL); + REQUIRE(type <= DST_MAX_TIMES); + if (!key->timeset[type]) + return (ISC_R_NOTFOUND); + *timep = key->times[type]; + return (ISC_R_SUCCESS); +} + +void +dst_key_settime(dst_key_t *key, int type, isc_stdtime_t when) { + REQUIRE(VALID_KEY(key)); + REQUIRE(type <= DST_MAX_TIMES); + key->times[type] = when; + key->timeset[type] = ISC_TRUE; +} + +void +dst_key_unsettime(dst_key_t *key, int type) { + REQUIRE(VALID_KEY(key)); + REQUIRE(type <= DST_MAX_TIMES); + key->timeset[type] = ISC_FALSE; +} + +isc_result_t +dst_key_getprivateformat(const dst_key_t *key, int *majorp, int *minorp) { + REQUIRE(VALID_KEY(key)); + REQUIRE(majorp != NULL); + REQUIRE(minorp != NULL); + *majorp = key->fmt_major; + *minorp = key->fmt_minor; + return (ISC_R_SUCCESS); +} + +void +dst_key_setprivateformat(dst_key_t *key, int major, int minor) { + REQUIRE(VALID_KEY(key)); + key->fmt_major = major; + key->fmt_minor = minor; +} + +static isc_boolean_t +comparekeys(const dst_key_t *key1, const dst_key_t *key2, + isc_boolean_t match_revoked_key, + isc_boolean_t (*compare)(const dst_key_t *key1, + const dst_key_t *key2)) +{ REQUIRE(dst_initialized == ISC_TRUE); REQUIRE(VALID_KEY(key1)); REQUIRE(VALID_KEY(key2)); if (key1 == key2) return (ISC_TRUE); + if (key1 == NULL || key2 == NULL) return (ISC_FALSE); - if (key1->key_alg == key2->key_alg && - key1->key_id == key2->key_id && - key1->func->compare != NULL && - key1->func->compare(key1, key2) == ISC_TRUE) - return (ISC_TRUE); + + if (key1->key_alg != key2->key_alg) + return (ISC_FALSE); + + /* + * For all algorithms except RSAMD5, revoking the key + * changes the key ID, increasing it by 128. If we want to + * be able to find matching keys even if one of them is the + * revoked version of the other one, then we need to check + * for that possibility. + */ + if (key1->key_id != key2->key_id) { + if (!match_revoked_key) + return (ISC_FALSE); + if (key1->key_alg == DST_ALG_RSAMD5) + return (ISC_FALSE); + if ((key1->key_flags & DNS_KEYFLAG_REVOKE) == + (key2->key_flags & DNS_KEYFLAG_REVOKE)) + return (ISC_FALSE); + if ((key1->key_flags & DNS_KEYFLAG_REVOKE) != 0 && + key1->key_id != ((key2->key_id + 128) & 0xffff)) + return (ISC_FALSE); + if ((key2->key_flags & DNS_KEYFLAG_REVOKE) != 0 && + key2->key_id != ((key1->key_id + 128) & 0xffff)) + return (ISC_FALSE); + } + + if (compare != NULL) + return (compare(key1, key2)); else return (ISC_FALSE); } + +/* + * Compares only the public portion of two keys, by converting them + * both to wire format and comparing the results. + */ +static isc_boolean_t +pub_compare(const dst_key_t *key1, const dst_key_t *key2) { + isc_result_t result; + unsigned char buf1[DST_KEY_MAXSIZE], buf2[DST_KEY_MAXSIZE]; + isc_buffer_t b1, b2; + isc_region_t r1, r2; + + isc_buffer_init(&b1, buf1, sizeof(buf1)); + result = dst_key_todns(key1, &b1); + if (result != ISC_R_SUCCESS) + return (ISC_FALSE); + /* Zero out flags. */ + buf1[0] = buf1[1] = 0; + if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0) + isc_buffer_subtract(&b1, 2); + + isc_buffer_init(&b2, buf2, sizeof(buf2)); + result = dst_key_todns(key2, &b2); + if (result != ISC_R_SUCCESS) + return (ISC_FALSE); + /* Zero out flags. */ + buf2[0] = buf2[1] = 0; + if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0) + isc_buffer_subtract(&b2, 2); + + isc_buffer_usedregion(&b1, &r1); + /* Remove extended flags. */ + if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0) { + memmove(&buf1[4], &buf1[6], r1.length - 6); + r1.length -= 2; + } + + isc_buffer_usedregion(&b2, &r2); + /* Remove extended flags. */ + if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0) { + memmove(&buf2[4], &buf2[6], r2.length - 6); + r2.length -= 2; + } + return (ISC_TF(isc_region_compare(&r1, &r2) == 0)); +} + +isc_boolean_t +dst_key_compare(const dst_key_t *key1, const dst_key_t *key2) { + return (comparekeys(key1, key2, ISC_FALSE, key1->func->compare)); +} + +isc_boolean_t +dst_key_pubcompare(const dst_key_t *key1, const dst_key_t *key2, + isc_boolean_t match_revoked_key) +{ + return (comparekeys(key1, key2, match_revoked_key, pub_compare)); +} + + isc_boolean_t dst_key_paramcompare(const dst_key_t *key1, const dst_key_t *key2) { REQUIRE(dst_initialized == ISC_TRUE); @@ -839,6 +1070,9 @@ dst_key_free(dst_key_t **keyp) { isc_mem_free(mctx, key->label); dns_name_free(key->key_name, mctx); isc_mem_put(mctx, key->key_name, sizeof(dns_name_t)); + if (key->key_tkeytoken) { + isc_buffer_free(&key->key_tkeytoken); + } memset(key, 0, sizeof(dst_key_t)); isc_mem_put(mctx, key, sizeof(dst_key_t)); *keyp = NULL; @@ -882,6 +1116,9 @@ dst_key_sigsize(const dst_key_t *key, unsigned int *n) { case DST_ALG_NSEC3DSA: *n = DNS_SIG_DSASIGSIZE; break; + case DST_ALG_ECCGOST: + *n = DNS_SIG_GOSTSIGSIZE; + break; case DST_ALG_HMACMD5: *n = 16; break; @@ -923,6 +1160,69 @@ dst_key_secretsize(const dst_key_t *key, unsigned int *n) { return (ISC_R_SUCCESS); } +/*% + * Set the flags on a key, then recompute the key ID + */ +isc_result_t +dst_key_setflags(dst_key_t *key, isc_uint32_t flags) { + REQUIRE(VALID_KEY(key)); + key->key_flags = flags; + return (computeid(key)); +} + +void +dst_key_format(const dst_key_t *key, char *cp, unsigned int size) { + char namestr[DNS_NAME_FORMATSIZE]; + char algstr[DNS_NAME_FORMATSIZE]; + + dns_name_format(dst_key_name(key), namestr, sizeof(namestr)); + dns_secalg_format((dns_secalg_t) dst_key_alg(key), algstr, + sizeof(algstr)); + snprintf(cp, size, "%s/%s/%d", namestr, algstr, dst_key_id(key)); +} + +isc_result_t +dst_key_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length) { + + REQUIRE(buffer != NULL && *buffer == NULL); + REQUIRE(length != NULL && *length == 0); + REQUIRE(VALID_KEY(key)); + + if (key->func->isprivate == NULL) + return (ISC_R_NOTIMPLEMENTED); + return (key->func->dump(key, mctx, buffer, length)); +} + +isc_result_t +dst_key_restore(dns_name_t *name, unsigned int alg, unsigned int flags, + unsigned int protocol, dns_rdataclass_t rdclass, + isc_mem_t *mctx, const char *keystr, dst_key_t **keyp) +{ + isc_result_t result; + dst_key_t *key; + + REQUIRE(dst_initialized == ISC_TRUE); + REQUIRE(keyp != NULL && *keyp == NULL); + + if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL) + return (DST_R_UNSUPPORTEDALG); + + if (dst_t_func[alg]->restore == NULL) + return (ISC_R_NOTIMPLEMENTED); + + key = get_key_struct(name, alg, flags, protocol, 0, rdclass, mctx); + if (key == NULL) + return (ISC_R_NOMEMORY); + + result = (dst_t_func[alg]->restore)(key, keystr); + if (result == ISC_R_SUCCESS) + *keyp = key; + else + dst_key_free(&key); + + return (result); +} + /*** *** Static methods ***/ @@ -938,6 +1238,7 @@ get_key_struct(dns_name_t *name, unsigned int alg, { dst_key_t *key; isc_result_t result; + int i; key = (dst_key_t *) isc_mem_get(mctx, sizeof(dst_key_t)); if (key == NULL) @@ -974,6 +1275,12 @@ get_key_struct(dns_name_t *name, unsigned int alg, key->key_size = bits; key->key_class = rdclass; key->func = dst_t_func[alg]; + key->fmt_major = 0; + key->fmt_minor = 0; + for (i = 0; i < (DST_MAX_TIMES + 1); i++) { + key->times[i] = 0; + key->timeset[i] = ISC_FALSE; + } return (key); } @@ -1046,7 +1353,7 @@ dst_key_read_public(const char *filename, int type, isc_buffer_init(&b, DST_AS_STR(token), strlen(DST_AS_STR(token))); isc_buffer_add(&b, strlen(DST_AS_STR(token))); ret = dns_name_fromtext(dns_fixedname_name(&name), &b, dns_rootname, - ISC_FALSE, NULL); + 0, NULL); if (ret != ISC_R_SUCCESS) goto cleanup; @@ -1116,6 +1423,7 @@ issymmetric(const dst_key_t *key) { case DST_ALG_DSA: case DST_ALG_NSEC3DSA: case DST_ALG_DH: + case DST_ALG_ECCGOST: return (ISC_FALSE); case DST_ALG_HMACMD5: case DST_ALG_GSSAPI: @@ -1126,6 +1434,55 @@ issymmetric(const dst_key_t *key) { } /*% + * Write key timing metadata to a file pointer, preceded by 'tag' + */ +static void +printtime(const dst_key_t *key, int type, const char *tag, FILE *stream) { + isc_result_t result; +#ifdef ISC_PLATFORM_USETHREADS + char output[26]; /* Minimum buffer as per ctime_r() specification. */ +#else + const char *output; +#endif + isc_stdtime_t when; + time_t t; + char utc[sizeof("YYYYMMDDHHSSMM")]; + isc_buffer_t b; + isc_region_t r; + + result = dst_key_gettime(key, type, &when); + if (result == ISC_R_NOTFOUND) + return; + + /* time_t and isc_stdtime_t might be different sizes */ + t = when; +#ifdef ISC_PLATFORM_USETHREADS +#ifdef WIN32 + if (ctime_s(output, sizeof(output), &t) != 0) + goto error; +#else + if (ctime_r(&t, output) == NULL) + goto error; +#endif +#else + output = ctime(&t); +#endif + + isc_buffer_init(&b, utc, sizeof(utc)); + result = dns_time32_totext(when, &b); + if (result != ISC_R_SUCCESS) + goto error; + + isc_buffer_usedregion(&b, &r); + fprintf(stream, "%s: %.*s (%.*s)\n", tag, (int)r.length, r.base, + (int)strlen(output) - 1, output); + return; + + error: + fprintf(stream, "%s: (set, unable to display)\n", tag); +} + +/*% * Writes a public key to disk in DNS format. */ static isc_result_t @@ -1184,12 +1541,34 @@ write_public_key(const dst_key_t *key, int type, const char *directory) { (void)isc_fsaccess_set(filename, access); } - ret = dns_name_print(key->key_name, fp); - if (ret != ISC_R_SUCCESS) { - fclose(fp); - return (ret); + /* Write key information in comments */ + if ((type & DST_TYPE_KEY) == 0) { + fprintf(fp, "; This is a %s%s-signing key, keyid %d, for ", + (key->key_flags & DNS_KEYFLAG_REVOKE) != 0 ? + "revoked " : + "", + (key->key_flags & DNS_KEYFLAG_KSK) != 0 ? + "key" : + "zone", + key->key_id); + ret = dns_name_print(key->key_name, fp); + if (ret != ISC_R_SUCCESS) { + fclose(fp); + return (ret); + } + fputc('\n', fp); + + printtime(key, DST_TIME_CREATED, "; Created", fp); + printtime(key, DST_TIME_PUBLISH, "; Publish", fp); + printtime(key, DST_TIME_ACTIVATE, "; Activate", fp); + printtime(key, DST_TIME_REVOKE, "; Revoke", fp); + printtime(key, DST_TIME_INACTIVE, "; Inactive", fp); + printtime(key, DST_TIME_DELETE, "; Delete", fp); } + /* Now print the actual key */ + ret = dns_name_print(key->key_name, fp); + fprintf(fp, " "); isc_buffer_usedregion(&classb, &r); @@ -1317,15 +1696,16 @@ algorithm_status(unsigned int alg) { alg == DST_ALG_DSA || alg == DST_ALG_DH || alg == DST_ALG_HMACMD5 || alg == DST_ALG_NSEC3DSA || alg == DST_ALG_NSEC3RSASHA1 || - alg == DST_ALG_RSASHA256 || alg == DST_ALG_RSASHA512) + alg == DST_ALG_RSASHA256 || alg == DST_ALG_RSASHA512 || + alg == DST_ALG_ECCGOST) return (DST_R_NOCRYPTO); #endif return (DST_R_UNSUPPORTEDALG); } static isc_result_t -addsuffix(char *filename, unsigned int len, const char *ofilename, - const char *suffix) +addsuffix(char *filename, int len, const char *odirname, + const char *ofilename, const char *suffix) { int olen = strlen(ofilename); int n; @@ -1337,27 +1717,42 @@ addsuffix(char *filename, unsigned int len, const char *ofilename, else if (olen > 4 && strcmp(ofilename + olen - 4, ".key") == 0) olen -= 4; - n = snprintf(filename, len, "%.*s%s", olen, ofilename, suffix); + if (odirname == NULL) + n = snprintf(filename, len, "%.*s%s", olen, ofilename, suffix); + else + n = snprintf(filename, len, "%s/%.*s%s", + odirname, olen, ofilename, suffix); if (n < 0) return (ISC_R_FAILURE); - if ((unsigned int)n >= len) + if (n >= len) return (ISC_R_NOSPACE); return (ISC_R_SUCCESS); } isc_result_t dst__entropy_getdata(void *buf, unsigned int len, isc_boolean_t pseudo) { +#ifdef BIND9 unsigned int flags = dst_entropy_flags; if (len == 0) return (ISC_R_SUCCESS); if (pseudo) flags &= ~ISC_ENTROPY_GOODONLY; + else + flags |= ISC_ENTROPY_BLOCKING; return (isc_entropy_getdata(dst_entropy_pool, buf, len, NULL, flags)); +#else + UNUSED(buf); + UNUSED(len); + UNUSED(pseudo); + + return (ISC_R_NOTIMPLEMENTED); +#endif } unsigned int dst__entropy_status(void) { +#ifdef BIND9 #ifdef GSSAPI unsigned int flags = dst_entropy_flags; isc_result_t ret; @@ -1376,4 +1771,12 @@ dst__entropy_status(void) { } #endif return (isc_entropy_status(dst_entropy_pool)); +#else + return (0); +#endif +} + +isc_buffer_t * +dst_key_tkeytoken(const dst_key_t *key) { + return (key->key_tkeytoken); } diff --git a/lib/dns/dst_internal.h b/lib/dns/dst_internal.h index 01bf1f2..220b3da 100644 --- a/lib/dns/dst_internal.h +++ b/lib/dns/dst_internal.h @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 2000-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -29,7 +29,7 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dst_internal.h,v 1.11.120.3 2010-12-09 01:12:55 marka Exp $ */ +/* $Id: dst_internal.h,v 1.29 2011-01-11 23:47:13 tbox Exp $ */ #ifndef DST_DST_INTERNAL_H #define DST_DST_INTERNAL_H 1 @@ -44,9 +44,12 @@ #include #include #include +#include #include #include +#include + #include #ifdef OPENSSL @@ -60,8 +63,8 @@ ISC_LANG_BEGINDECLS -#define KEY_MAGIC ISC_MAGIC('D','S','T','K') -#define CTX_MAGIC ISC_MAGIC('D','S','T','C') +#define KEY_MAGIC ISC_MAGIC('D','S','T','K') +#define CTX_MAGIC ISC_MAGIC('D','S','T','C') #define VALID_KEY(x) ISC_MAGIC_VALID(x, KEY_MAGIC) #define VALID_CTX(x) ISC_MAGIC_VALID(x, CTX_MAGIC) @@ -74,7 +77,7 @@ extern isc_mem_t *dst__memory_pool; typedef struct dst_func dst_func_t; -typedef struct dst_hmacmd5_key dst_hmacmd5_key_t; +typedef struct dst_hmacmd5_key dst_hmacmd5_key_t; typedef struct dst_hmacsha1_key dst_hmacsha1_key_t; typedef struct dst_hmacsha224_key dst_hmacsha224_key_t; typedef struct dst_hmacsha256_key dst_hmacsha256_key_t; @@ -115,7 +118,17 @@ struct dst_key { dst_hmacsha512_key_t *hmacsha512; } keydata; /*%< pointer to key in crypto pkg fmt */ - dst_func_t * func; /*%< crypto package specific functions */ + + isc_stdtime_t times[DST_MAX_TIMES + 1]; /*%< timing metadata */ + isc_boolean_t timeset[DST_MAX_TIMES + 1]; /*%< data set? */ + isc_stdtime_t nums[DST_MAX_NUMERIC + 1]; /*%< numeric metadata */ + isc_boolean_t numset[DST_MAX_NUMERIC + 1]; /*%< data set? */ + + int fmt_major; /*%< private key format, major version */ + int fmt_minor; /*%< private key format, minor version */ + + dst_func_t * func; /*%< crypto package specific functions */ + isc_buffer_t *key_tkeytoken; /*%< TKEY token data */ }; struct dst_context { @@ -160,7 +173,8 @@ struct dst_func { isc_boolean_t (*compare)(const dst_key_t *key1, const dst_key_t *key2); isc_boolean_t (*paramcompare)(const dst_key_t *key1, const dst_key_t *key2); - isc_result_t (*generate)(dst_key_t *key, int parms); + isc_result_t (*generate)(dst_key_t *key, int parms, + void (*callback)(int)); isc_boolean_t (*isprivate)(const dst_key_t *key); void (*destroy)(dst_key_t *key); @@ -168,19 +182,24 @@ struct dst_func { isc_result_t (*todns)(const dst_key_t *key, isc_buffer_t *data); isc_result_t (*fromdns)(dst_key_t *key, isc_buffer_t *data); isc_result_t (*tofile)(const dst_key_t *key, const char *directory); - isc_result_t (*parse)(dst_key_t *key, isc_lex_t *lexer); + isc_result_t (*parse)(dst_key_t *key, + isc_lex_t *lexer, + dst_key_t *pub); /* cleanup */ void (*cleanup)(void); isc_result_t (*fromlabel)(dst_key_t *key, const char *engine, const char *label, const char *pin); + isc_result_t (*dump)(dst_key_t *key, isc_mem_t *mctx, char **buffer, + int *length); + isc_result_t (*restore)(dst_key_t *key, const char *keystr); }; /*% * Initializers */ -isc_result_t dst__openssl_init(void); +isc_result_t dst__openssl_init(const char *engine); isc_result_t dst__hmacmd5_init(struct dst_func **funcp); isc_result_t dst__hmacsha1_init(struct dst_func **funcp); @@ -193,6 +212,9 @@ isc_result_t dst__opensslrsa_init(struct dst_func **funcp, isc_result_t dst__openssldsa_init(struct dst_func **funcp); isc_result_t dst__openssldh_init(struct dst_func **funcp); isc_result_t dst__gssapi_init(struct dst_func **funcp); +#ifdef HAVE_OPENSSL_GOST +isc_result_t dst__opensslgost_init(struct dst_func **funcp); +#endif /*% * Destructors diff --git a/lib/dns/dst_openssl.h b/lib/dns/dst_openssl.h index a095d45..781085b 100644 --- a/lib/dns/dst_openssl.h +++ b/lib/dns/dst_openssl.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dst_openssl.h,v 1.7 2008-04-01 23:47:10 tbox Exp $ */ +/* $Id: dst_openssl.h,v 1.9 2009-10-06 04:40:14 tbox Exp $ */ #ifndef DST_OPENSSL_H #define DST_OPENSSL_H 1 @@ -29,10 +29,7 @@ isc_result_t dst__openssl_toresult(isc_result_t fallback); ENGINE * -dst__openssl_getengine(const char *name); - -isc_result_t -dst__openssl_setdefault(const char *name); +dst__openssl_getengine(const char *engine); ISC_LANG_ENDDECLS diff --git a/lib/dns/dst_parse.c b/lib/dns/dst_parse.c index 37264be..4d7d784 100644 --- a/lib/dns/dst_parse.c +++ b/lib/dns/dst_parse.c @@ -31,7 +31,7 @@ /*% * Principal Author: Brian Wellington - * $Id: dst_parse.c,v 1.14.120.6 2010-01-15 19:38:53 each Exp $ + * $Id: dst_parse.c,v 1.27 2010-12-23 04:07:58 marka Exp $ */ #include @@ -41,9 +41,12 @@ #include #include #include +#include #include #include +#include + #include "dst_internal.h" #include "dst_parse.h" #include "dst/result.h" @@ -53,6 +56,25 @@ #define PRIVATE_KEY_STR "Private-key-format:" #define ALGORITHM_STR "Algorithm:" +#define TIMING_NTAGS (DST_MAX_TIMES + 1) +static const char *timetags[TIMING_NTAGS] = { + "Created:", + "Publish:", + "Activate:", + "Revoke:", + "Inactive:", + "Delete:", + "DSPublish:" +}; + +#define NUMERIC_NTAGS (DST_MAX_NUMERIC + 1) +static const char *numerictags[NUMERIC_NTAGS] = { + "Predecessor:", + "Successor:", + "MaxTTL:", + "RollPeriod:" +}; + struct parse_map { const int value; const char *tag; @@ -82,6 +104,8 @@ static struct parse_map map[] = { {TAG_DSA_PRIVATE, "Private_value(x):"}, {TAG_DSA_PUBLIC, "Public_value(y):"}, + {TAG_GOST_PRIVASN1, "GostAsn1:"}, + {TAG_HMACMD5_KEY, "Key:"}, {TAG_HMACMD5_BITS, "Bits:"}, @@ -107,13 +131,12 @@ static int find_value(const char *s, const unsigned int alg) { int i; - for (i = 0; ; i++) { - if (map[i].tag == NULL) - return (-1); - else if (strcasecmp(s, map[i].tag) == 0 && - TAG_ALG(map[i].value) == alg) + for (i = 0; map[i].tag != NULL; i++) { + if (strcasecmp(s, map[i].tag) == 0 && + (TAG_ALG(map[i].value) == alg)) return (map[i].value); } + return (-1); } static const char * @@ -129,6 +152,28 @@ find_tag(const int value) { } static int +find_metadata(const char *s, const char *tags[], int ntags) { + int i; + + for (i = 0; i < ntags; i++) { + if (strcasecmp(s, tags[i]) == 0) + return (i); + } + + return (-1); +} + +static int +find_timedata(const char *s) { + return (find_metadata(s, timetags, TIMING_NTAGS)); +} + +static int +find_numericdata(const char *s) { + return (find_metadata(s, numerictags, NUMERIC_NTAGS)); +} + +static int check_rsa(const dst_private_t *priv) { int i, j; isc_boolean_t have[RSA_NTAGS]; @@ -197,6 +242,15 @@ check_dsa(const dst_private_t *priv) { } static int +check_gost(const dst_private_t *priv) { + if (priv->nelements != GOST_NTAGS) + return (-1); + if (priv->elements[0].tag != TAG(DST_ALG_ECCGOST, 0)) + return (-1); + return (0); +} + +static int check_hmac_md5(const dst_private_t *priv, isc_boolean_t old) { int i, j; @@ -253,6 +307,8 @@ check_data(const dst_private_t *priv, const unsigned int alg, return (check_dh(priv)); case DST_ALG_DSA: return (check_dsa(priv)); + case DST_ALG_ECCGOST: + return (check_gost(priv)); case DST_ALG_HMACMD5: return (check_hmac_md5(priv, old)); case DST_ALG_HMACSHA1: @@ -285,7 +341,7 @@ dst__privstruct_free(dst_private_t *priv, isc_mem_t *mctx) { priv->nelements = 0; } -int +isc_result_t dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, isc_mem_t *mctx, dst_private_t *priv) { @@ -294,6 +350,7 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, isc_token_t token; unsigned char *data = NULL; unsigned int opt = ISC_LEXOPT_EOL; + isc_stdtime_t when; isc_result_t ret; REQUIRE(priv != NULL); @@ -341,13 +398,16 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, goto fail; } - if (major > MAJOR_VERSION || - (major == MAJOR_VERSION && minor > MINOR_VERSION)) - { + if (major > DST_MAJOR_VERSION) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } + /* + * Store the private key format version number + */ + dst_key_setprivateformat(key, major, minor); + READLINE(lex, opt, &token); /* @@ -377,7 +437,6 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, for (n = 0; n < MAXFIELDS; n++) { int tag; isc_region_t r; - do { ret = isc_lex_gettoken(lex, opt, &token); if (ret == ISC_R_EOF) @@ -391,11 +450,50 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, goto fail; } + /* Numeric metadata */ + tag = find_numericdata(DST_AS_STR(token)); + if (tag >= 0) { + INSIST(tag < NUMERIC_NTAGS); + + NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token); + if (token.type != isc_tokentype_number) { + ret = DST_R_INVALIDPRIVATEKEY; + goto fail; + } + + dst_key_setnum(key, tag, token.value.as_ulong); + goto next; + } + + /* Timing metadata */ + tag = find_timedata(DST_AS_STR(token)); + if (tag >= 0) { + INSIST(tag < TIMING_NTAGS); + + NEXTTOKEN(lex, opt, &token); + if (token.type != isc_tokentype_string) { + ret = DST_R_INVALIDPRIVATEKEY; + goto fail; + } + + ret = dns_time32_fromtext(DST_AS_STR(token), &when); + if (ret != ISC_R_SUCCESS) + goto fail; + + dst_key_settime(key, tag, when); + + goto next; + } + + /* Key data */ tag = find_value(DST_AS_STR(token), alg); - if (tag < 0 || TAG_ALG(tag) != alg) { + if (tag < 0 && minor > DST_MINOR_VERSION) + goto next; + else if (tag < 0) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } + priv->elements[n].tag = tag; data = (unsigned char *) isc_mem_get(mctx, MAXFIELDSIZE); @@ -406,23 +504,23 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, ret = isc_base64_tobuffer(lex, &b, -1); if (ret != ISC_R_SUCCESS) goto fail; + isc_buffer_usedregion(&b, &r); priv->elements[n].length = r.length; priv->elements[n].data = r.base; + priv->nelements++; + next: READLINE(lex, opt, &token); data = NULL; } done: - priv->nelements = n; - if (check_data(priv, alg, ISC_TRUE) < 0) goto fail; return (ISC_R_SUCCESS); fail: - priv->nelements = n; dst__privstruct_free(priv, mctx); if (data != NULL) isc_mem_put(mctx, data, MAXFIELDSIZE); @@ -430,17 +528,21 @@ fail: return (ret); } -int +isc_result_t dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, const char *directory) { FILE *fp; int ret, i; - isc_result_t iret; + isc_result_t result; char filename[ISC_DIR_NAMEMAX]; char buffer[MAXFIELDSIZE * 2]; - isc_buffer_t b; isc_fsaccess_t access; + isc_stdtime_t when; + isc_uint32_t value; + isc_buffer_t b; + isc_region_t r; + int major, minor; REQUIRE(priv != NULL); @@ -461,11 +563,17 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, &access); (void)isc_fsaccess_set(filename, access); + dst_key_getprivateformat(key, &major, &minor); + if (major == 0 && minor == 0) { + major = DST_MAJOR_VERSION; + minor = DST_MINOR_VERSION; + } + /* XXXDCL return value should be checked for full filesystem */ - fprintf(fp, "%s v%d.%d\n", PRIVATE_KEY_STR, MAJOR_VERSION, - MINOR_VERSION); + fprintf(fp, "%s v%d.%d\n", PRIVATE_KEY_STR, major, minor); fprintf(fp, "%s %d ", ALGORITHM_STR, dst_key_alg(key)); + /* XXXVIX this switch statement is too sparse to gen a jump table. */ switch (dst_key_alg(key)) { case DST_ALG_RSAMD5: @@ -480,18 +588,21 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, case DST_ALG_RSASHA1: fprintf(fp, "(RSASHA1)\n"); break; - case DST_ALG_NSEC3DSA: - fprintf(fp, "(NSEC3DSA)\n"); - break; case DST_ALG_NSEC3RSASHA1: fprintf(fp, "(NSEC3RSASHA1)\n"); break; + case DST_ALG_NSEC3DSA: + fprintf(fp, "(NSEC3DSA)\n"); + break; case DST_ALG_RSASHA256: fprintf(fp, "(RSASHA256)\n"); break; case DST_ALG_RSASHA512: fprintf(fp, "(RSASHA512)\n"); break; + case DST_ALG_ECCGOST: + fprintf(fp, "(ECC-GOST)\n"); + break; case DST_ALG_HMACMD5: fprintf(fp, "(HMAC_MD5)\n"); break; @@ -516,8 +627,6 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, } for (i = 0; i < priv->nelements; i++) { - isc_buffer_t b; - isc_region_t r; const char *s; s = find_tag(priv->elements[i].tag); @@ -525,8 +634,8 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, r.base = priv->elements[i].data; r.length = priv->elements[i].length; isc_buffer_init(&b, buffer, sizeof(buffer)); - iret = isc_base64_totext(&r, sizeof(buffer), "", &b); - if (iret != ISC_R_SUCCESS) { + result = isc_base64_totext(&r, sizeof(buffer), "", &b); + if (result != ISC_R_SUCCESS) { fclose(fp); return (DST_R_INVALIDPRIVATEKEY); } @@ -537,10 +646,36 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, fprintf(fp, "\n"); } + /* Add the metadata tags */ + if (major > 1 || (major == 1 && minor >= 3)) { + for (i = 0; i < NUMERIC_NTAGS; i++) { + result = dst_key_getnum(key, i, &value); + if (result != ISC_R_SUCCESS) + continue; + fprintf(fp, "%s %u\n", numerictags[i], value); + } + for (i = 0; i < TIMING_NTAGS; i++) { + result = dst_key_gettime(key, i, &when); + if (result != ISC_R_SUCCESS) + continue; + + isc_buffer_init(&b, buffer, sizeof(buffer)); + result = dns_time32_totext(when, &b); + if (result != ISC_R_SUCCESS) + continue; + + isc_buffer_usedregion(&b, &r); + + fprintf(fp, "%s ", timetags[i]); + isc_util_fwrite(r.base, 1, r.length, fp); + fprintf(fp, "\n"); + } + } + fflush(fp); - iret = ferror(fp) ? DST_R_WRITEERROR : ISC_R_SUCCESS; + result = ferror(fp) ? DST_R_WRITEERROR : ISC_R_SUCCESS; fclose(fp); - return (iret); + return (result); } /*! \file */ diff --git a/lib/dns/dst_parse.h b/lib/dns/dst_parse.h index 11e2b33..d1034ce 100644 --- a/lib/dns/dst_parse.h +++ b/lib/dns/dst_parse.h @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 2000-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -29,7 +29,7 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dst_parse.h,v 1.11 2008-05-15 00:50:26 each Exp $ */ +/* $Id: dst_parse.h,v 1.17 2010-12-23 23:47:08 tbox Exp $ */ /*! \file */ #ifndef DST_DST_PARSE_H @@ -39,11 +39,13 @@ #include -#define MAJOR_VERSION 1 -#define MINOR_VERSION 2 - #define MAXFIELDSIZE 512 -#define MAXFIELDS 12 + +/* + * Maximum number of fields in a private file is 18 (12 algorithm- + * specific fields for RSA, plus 6 generic fields). + */ +#define MAXFIELDS 12+6 #define TAG_SHIFT 4 #define TAG_ALG(tag) ((unsigned int)(tag) >> TAG_SHIFT) @@ -76,6 +78,9 @@ #define TAG_DSA_PRIVATE ((DST_ALG_DSA << TAG_SHIFT) + 3) #define TAG_DSA_PUBLIC ((DST_ALG_DSA << TAG_SHIFT) + 4) +#define GOST_NTAGS 1 +#define TAG_GOST_PRIVASN1 ((DST_ALG_ECCGOST << TAG_SHIFT) + 0) + #define OLD_HMACMD5_NTAGS 1 #define HMACMD5_NTAGS 2 #define TAG_HMACMD5_KEY ((DST_ALG_HMACMD5 << TAG_SHIFT) + 0) @@ -121,11 +126,11 @@ ISC_LANG_BEGINDECLS void dst__privstruct_free(dst_private_t *priv, isc_mem_t *mctx); -int +isc_result_t dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, isc_mem_t *mctx, dst_private_t *priv); -int +isc_result_t dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, const char *directory); diff --git a/lib/dns/ecdb.c b/lib/dns/ecdb.c new file mode 100644 index 0000000..d98a3eb --- /dev/null +++ b/lib/dns/ecdb.c @@ -0,0 +1,810 @@ +/* + * Copyright (C) 2009-2011 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: ecdb.c,v 1.8 2011-01-14 00:51:43 tbox Exp $ */ + +#include "config.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define ECDB_MAGIC ISC_MAGIC('E', 'C', 'D', 'B') +#define VALID_ECDB(db) ((db) != NULL && \ + (db)->common.impmagic == ECDB_MAGIC) + +#define ECDBNODE_MAGIC ISC_MAGIC('E', 'C', 'D', 'N') +#define VALID_ECDBNODE(ecdbn) ISC_MAGIC_VALID(ecdbn, ECDBNODE_MAGIC) + +#if DNS_RDATASET_FIXED +#error "Fixed rdataset isn't supported in this implementation" +#endif + +/*% + * The 'ephemeral' cache DB (ecdb) implementation. An ecdb just provides + * temporary storage for ongoing name resolution with the common DB interfaces. + * It actually doesn't cache anything. The implementation expects any stored + * data is released within a short period, and does not care about the + * scalability in terms of the number of nodes. + */ + +typedef struct dns_ecdb { + /* Unlocked */ + dns_db_t common; + isc_mutex_t lock; + + /* Locked */ + unsigned int references; + ISC_LIST(struct dns_ecdbnode) nodes; +} dns_ecdb_t; + +typedef struct dns_ecdbnode { + /* Unlocked */ + unsigned int magic; + isc_mutex_t lock; + dns_ecdb_t *ecdb; + dns_name_t name; + ISC_LINK(struct dns_ecdbnode) link; + + /* Locked */ + ISC_LIST(struct rdatasetheader) rdatasets; + unsigned int references; +} dns_ecdbnode_t; + +typedef struct rdatasetheader { + dns_rdatatype_t type; + dns_ttl_t ttl; + dns_trust_t trust; + dns_rdatatype_t covers; + unsigned int attributes; + + ISC_LINK(struct rdatasetheader) link; +} rdatasetheader_t; + +/* Copied from rbtdb.c */ +#define RDATASET_ATTR_NXDOMAIN 0x0010 +#define NXDOMAIN(header) \ + (((header)->attributes & RDATASET_ATTR_NXDOMAIN) != 0) + +static isc_result_t dns_ecdb_create(isc_mem_t *mctx, dns_name_t *origin, + dns_dbtype_t type, + dns_rdataclass_t rdclass, + unsigned int argc, char *argv[], + void *driverarg, dns_db_t **dbp); + +static void rdataset_disassociate(dns_rdataset_t *rdataset); +static isc_result_t rdataset_first(dns_rdataset_t *rdataset); +static isc_result_t rdataset_next(dns_rdataset_t *rdataset); +static void rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata); +static void rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target); +static unsigned int rdataset_count(dns_rdataset_t *rdataset); +static void rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust); + +static dns_rdatasetmethods_t rdataset_methods = { + rdataset_disassociate, + rdataset_first, + rdataset_next, + rdataset_current, + rdataset_clone, + rdataset_count, + NULL, /* addnoqname */ + NULL, /* getnoqname */ + NULL, /* addclosest */ + NULL, /* getclosest */ + NULL, /* getadditional */ + NULL, /* setadditional */ + NULL, /* putadditional */ + rdataset_settrust, /* settrust */ + NULL /* expire */ +}; + +typedef struct ecdb_rdatasetiter { + dns_rdatasetiter_t common; + rdatasetheader_t *current; +} ecdb_rdatasetiter_t; + +static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp); +static isc_result_t rdatasetiter_first(dns_rdatasetiter_t *iterator); +static isc_result_t rdatasetiter_next(dns_rdatasetiter_t *iterator); +static void rdatasetiter_current(dns_rdatasetiter_t *iterator, + dns_rdataset_t *rdataset); + +static dns_rdatasetitermethods_t rdatasetiter_methods = { + rdatasetiter_destroy, + rdatasetiter_first, + rdatasetiter_next, + rdatasetiter_current +}; + +isc_result_t +dns_ecdb_register(isc_mem_t *mctx, dns_dbimplementation_t **dbimp) { + REQUIRE(mctx != NULL); + REQUIRE(dbimp != NULL && *dbimp == NULL); + + return (dns_db_register("ecdb", dns_ecdb_create, NULL, mctx, dbimp)); +} + +void +dns_ecdb_unregister(dns_dbimplementation_t **dbimp) { + REQUIRE(dbimp != NULL && *dbimp != NULL); + + dns_db_unregister(dbimp); +} + +/*% + * DB routines + */ + +static void +attach(dns_db_t *source, dns_db_t **targetp) { + dns_ecdb_t *ecdb = (dns_ecdb_t *)source; + + REQUIRE(VALID_ECDB(ecdb)); + REQUIRE(targetp != NULL && *targetp == NULL); + + LOCK(&ecdb->lock); + ecdb->references++; + UNLOCK(&ecdb->lock); + + *targetp = source; +} + +static void +destroy_ecdb(dns_ecdb_t **ecdbp) { + dns_ecdb_t *ecdb = *ecdbp; + isc_mem_t *mctx = ecdb->common.mctx; + + if (dns_name_dynamic(&ecdb->common.origin)) + dns_name_free(&ecdb->common.origin, mctx); + + DESTROYLOCK(&ecdb->lock); + + ecdb->common.impmagic = 0; + ecdb->common.magic = 0; + + isc_mem_putanddetach(&mctx, ecdb, sizeof(*ecdb)); + + *ecdbp = NULL; +} + +static void +detach(dns_db_t **dbp) { + dns_ecdb_t *ecdb; + isc_boolean_t need_destroy = ISC_FALSE; + + REQUIRE(dbp != NULL); + ecdb = (dns_ecdb_t *)*dbp; + REQUIRE(VALID_ECDB(ecdb)); + + LOCK(&ecdb->lock); + ecdb->references--; + if (ecdb->references == 0 && ISC_LIST_EMPTY(ecdb->nodes)) + need_destroy = ISC_TRUE; + UNLOCK(&ecdb->lock); + + if (need_destroy) + destroy_ecdb(&ecdb); + + *dbp = NULL; +} + +static void +attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) { + dns_ecdb_t *ecdb = (dns_ecdb_t *)db; + dns_ecdbnode_t *node = (dns_ecdbnode_t *)source; + + REQUIRE(VALID_ECDB(ecdb)); + REQUIRE(VALID_ECDBNODE(node)); + REQUIRE(targetp != NULL && *targetp == NULL); + + LOCK(&node->lock); + INSIST(node->references > 0); + node->references++; + INSIST(node->references != 0); /* Catch overflow. */ + UNLOCK(&node->lock); + + *targetp = node; +} + +static void +destroynode(dns_ecdbnode_t *node) { + isc_mem_t *mctx; + dns_ecdb_t *ecdb = node->ecdb; + isc_boolean_t need_destroydb = ISC_FALSE; + rdatasetheader_t *header; + + mctx = ecdb->common.mctx; + + LOCK(&ecdb->lock); + ISC_LIST_UNLINK(ecdb->nodes, node, link); + if (ecdb->references == 0 && ISC_LIST_EMPTY(ecdb->nodes)) + need_destroydb = ISC_TRUE; + UNLOCK(&ecdb->lock); + + dns_name_free(&node->name, mctx); + + while ((header = ISC_LIST_HEAD(node->rdatasets)) != NULL) { + unsigned int headersize; + + ISC_LIST_UNLINK(node->rdatasets, header, link); + headersize = + dns_rdataslab_size((unsigned char *)header, + sizeof(*header)); + isc_mem_put(mctx, header, headersize); + } + + DESTROYLOCK(&node->lock); + + node->magic = 0; + isc_mem_put(mctx, node, sizeof(*node)); + + if (need_destroydb) + destroy_ecdb(&ecdb); +} + +static void +detachnode(dns_db_t *db, dns_dbnode_t **nodep) { + dns_ecdb_t *ecdb = (dns_ecdb_t *)db; + dns_ecdbnode_t *node; + isc_boolean_t need_destroy = ISC_FALSE; + + REQUIRE(VALID_ECDB(ecdb)); + REQUIRE(nodep != NULL); + node = (dns_ecdbnode_t *)*nodep; + REQUIRE(VALID_ECDBNODE(node)); + + UNUSED(ecdb); /* in case REQUIRE() is empty */ + + LOCK(&node->lock); + INSIST(node->references > 0); + node->references--; + if (node->references == 0) + need_destroy = ISC_TRUE; + UNLOCK(&node->lock); + + if (need_destroy) + destroynode(node); + + *nodep = NULL; +} + +static isc_result_t +find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, + dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, + dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset) +{ + dns_ecdb_t *ecdb = (dns_ecdb_t *)db; + + REQUIRE(VALID_ECDB(ecdb)); + + UNUSED(name); + UNUSED(version); + UNUSED(type); + UNUSED(options); + UNUSED(now); + UNUSED(nodep); + UNUSED(foundname); + UNUSED(rdataset); + UNUSED(sigrdataset); + + return (ISC_R_NOTFOUND); +} + +static isc_result_t +findzonecut(dns_db_t *db, dns_name_t *name, + unsigned int options, isc_stdtime_t now, + dns_dbnode_t **nodep, dns_name_t *foundname, + dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) +{ + dns_ecdb_t *ecdb = (dns_ecdb_t *)db; + + REQUIRE(VALID_ECDB(ecdb)); + + UNUSED(name); + UNUSED(options); + UNUSED(now); + UNUSED(nodep); + UNUSED(foundname); + UNUSED(rdataset); + UNUSED(sigrdataset); + + return (ISC_R_NOTFOUND); +} + +static isc_result_t +findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, + dns_dbnode_t **nodep) +{ + dns_ecdb_t *ecdb = (dns_ecdb_t *)db; + isc_mem_t *mctx; + dns_ecdbnode_t *node; + isc_result_t result; + + REQUIRE(VALID_ECDB(ecdb)); + REQUIRE(nodep != NULL && *nodep == NULL); + + UNUSED(name); + + if (create != ISC_TRUE) { + /* an 'ephemeral' node is never reused. */ + return (ISC_R_NOTFOUND); + } + + mctx = ecdb->common.mctx; + node = isc_mem_get(mctx, sizeof(*node)); + if (node == NULL) + return (ISC_R_NOMEMORY); + + result = isc_mutex_init(&node->lock); + if (result != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_mutex_init() failed: %s", + isc_result_totext(result)); + isc_mem_put(mctx, node, sizeof(*node)); + return (ISC_R_UNEXPECTED); + } + + dns_name_init(&node->name, NULL); + result = dns_name_dup(name, mctx, &node->name); + if (result != ISC_R_SUCCESS) { + DESTROYLOCK(&node->lock); + isc_mem_put(mctx, node, sizeof(*node)); + return (result); + } + node->ecdb= ecdb; + node->references = 1; + ISC_LIST_INIT(node->rdatasets); + + ISC_LINK_INIT(node, link); + + LOCK(&ecdb->lock); + ISC_LIST_APPEND(ecdb->nodes, node, link); + UNLOCK(&ecdb->lock); + + node->magic = ECDBNODE_MAGIC; + + *nodep = node; + + return (ISC_R_SUCCESS); +} + +static void +bind_rdataset(dns_ecdb_t *ecdb, dns_ecdbnode_t *node, + rdatasetheader_t *header, dns_rdataset_t *rdataset) +{ + unsigned char *raw; + + /* + * Caller must be holding the node lock. + */ + + REQUIRE(!dns_rdataset_isassociated(rdataset)); + + rdataset->methods = &rdataset_methods; + rdataset->rdclass = ecdb->common.rdclass; + rdataset->type = header->type; + rdataset->covers = header->covers; + rdataset->ttl = header->ttl; + rdataset->trust = header->trust; + if (NXDOMAIN(header)) + rdataset->attributes |= DNS_RDATASETATTR_NXDOMAIN; + + rdataset->private1 = ecdb; + rdataset->private2 = node; + raw = (unsigned char *)header + sizeof(*header); + rdataset->private3 = raw; + rdataset->count = 0; + + /* + * Reset iterator state. + */ + rdataset->privateuint4 = 0; + rdataset->private5 = NULL; + + INSIST(node->references > 0); + node->references++; +} + +static isc_result_t +addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, + isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options, + dns_rdataset_t *addedrdataset) +{ + dns_ecdb_t *ecdb = (dns_ecdb_t *)db; + isc_region_t r; + isc_result_t result = ISC_R_SUCCESS; + isc_mem_t *mctx; + dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)node; + rdatasetheader_t *header; + + REQUIRE(VALID_ECDB(ecdb)); + REQUIRE(VALID_ECDBNODE(ecdbnode)); + + UNUSED(version); + UNUSED(now); + UNUSED(options); + + mctx = ecdb->common.mctx; + + LOCK(&ecdbnode->lock); + + /* + * Sanity check: this implementation does not allow overriding an + * existing rdataset of the same type. + */ + for (header = ISC_LIST_HEAD(ecdbnode->rdatasets); header != NULL; + header = ISC_LIST_NEXT(header, link)) { + INSIST(header->type != rdataset->type || + header->covers != rdataset->covers); + } + + result = dns_rdataslab_fromrdataset(rdataset, mctx, + &r, sizeof(rdatasetheader_t)); + if (result != ISC_R_SUCCESS) + goto unlock; + + header = (rdatasetheader_t *)r.base; + header->type = rdataset->type; + header->ttl = rdataset->ttl; + header->trust = rdataset->trust; + header->covers = rdataset->covers; + header->attributes = 0; + if ((rdataset->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0) + header->attributes |= RDATASET_ATTR_NXDOMAIN; + ISC_LINK_INIT(header, link); + ISC_LIST_APPEND(ecdbnode->rdatasets, header, link); + + if (addedrdataset == NULL) + goto unlock; + + bind_rdataset(ecdb, ecdbnode, header, addedrdataset); + + unlock: + UNLOCK(&ecdbnode->lock); + + return (result); +} + +static isc_result_t +deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, + dns_rdatatype_t type, dns_rdatatype_t covers) +{ + UNUSED(db); + UNUSED(node); + UNUSED(version); + UNUSED(type); + UNUSED(covers); + + return (ISC_R_NOTIMPLEMENTED); +} + +static isc_result_t +createiterator(dns_db_t *db, unsigned int options, + dns_dbiterator_t **iteratorp) +{ + UNUSED(db); + UNUSED(options); + UNUSED(iteratorp); + + return (ISC_R_NOTIMPLEMENTED); +} + +static isc_result_t +allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, + isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) +{ + dns_ecdb_t *ecdb = (dns_ecdb_t *)db; + dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)node; + isc_mem_t *mctx; + ecdb_rdatasetiter_t *iterator; + + REQUIRE(VALID_ECDB(ecdb)); + REQUIRE(VALID_ECDBNODE(ecdbnode)); + + mctx = ecdb->common.mctx; + + iterator = isc_mem_get(mctx, sizeof(ecdb_rdatasetiter_t)); + if (iterator == NULL) + return (ISC_R_NOMEMORY); + + iterator->common.magic = DNS_RDATASETITER_MAGIC; + iterator->common.methods = &rdatasetiter_methods; + iterator->common.db = db; + iterator->common.node = NULL; + attachnode(db, node, &iterator->common.node); + iterator->common.version = version; + iterator->common.now = now; + + *iteratorp = (dns_rdatasetiter_t *)iterator; + + return (ISC_R_SUCCESS); +} + +static dns_dbmethods_t ecdb_methods = { + attach, + detach, + NULL, /* beginload */ + NULL, /* endload */ + NULL, /* dump */ + NULL, /* currentversion */ + NULL, /* newversion */ + NULL, /* attachversion */ + NULL, /* closeversion */ + findnode, + find, + findzonecut, + attachnode, + detachnode, + NULL, /* expirenode */ + NULL, /* printnode */ + createiterator, /* createiterator */ + NULL, /* findrdataset */ + allrdatasets, + addrdataset, + NULL, /* subtractrdataset */ + deleterdataset, + NULL, /* issecure */ + NULL, /* nodecount */ + NULL, /* ispersistent */ + NULL, /* overmem */ + NULL, /* settask */ + NULL, /* getoriginnode */ + NULL, /* transfernode */ + NULL, /* getnsec3parameters */ + NULL, /* findnsec3node */ + NULL, /* setsigningtime */ + NULL, /* getsigningtime */ + NULL, /* resigned */ + NULL, /* isdnssec */ + NULL, /* getrrsetstats */ + NULL, /* rpz_enabled */ + NULL /* rpz_findips */ +}; + +static isc_result_t +dns_ecdb_create(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type, + dns_rdataclass_t rdclass, unsigned int argc, char *argv[], + void *driverarg, dns_db_t **dbp) +{ + dns_ecdb_t *ecdb; + isc_result_t result; + + REQUIRE(mctx != NULL); + REQUIRE(origin == dns_rootname); + REQUIRE(type == dns_dbtype_cache); + REQUIRE(dbp != NULL && *dbp == NULL); + + UNUSED(argc); + UNUSED(argv); + UNUSED(driverarg); + + ecdb = isc_mem_get(mctx, sizeof(*ecdb)); + if (ecdb == NULL) + return (ISC_R_NOMEMORY); + + ecdb->common.attributes = DNS_DBATTR_CACHE; + ecdb->common.rdclass = rdclass; + ecdb->common.methods = &ecdb_methods; + dns_name_init(&ecdb->common.origin, NULL); + result = dns_name_dupwithoffsets(origin, mctx, &ecdb->common.origin); + if (result != ISC_R_SUCCESS) { + isc_mem_put(mctx, ecdb, sizeof(*ecdb)); + return (result); + } + + result = isc_mutex_init(&ecdb->lock); + if (result != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_mutex_init() failed: %s", + isc_result_totext(result)); + if (dns_name_dynamic(&ecdb->common.origin)) + dns_name_free(&ecdb->common.origin, mctx); + isc_mem_put(mctx, ecdb, sizeof(*ecdb)); + return (ISC_R_UNEXPECTED); + } + + ecdb->references = 1; + ISC_LIST_INIT(ecdb->nodes); + + ecdb->common.mctx = NULL; + isc_mem_attach(mctx, &ecdb->common.mctx); + ecdb->common.impmagic = ECDB_MAGIC; + ecdb->common.magic = DNS_DB_MAGIC; + + *dbp = (dns_db_t *)ecdb; + + return (ISC_R_SUCCESS); +} + +/*% + * Rdataset Methods + */ + +static void +rdataset_disassociate(dns_rdataset_t *rdataset) { + dns_db_t *db = rdataset->private1; + dns_dbnode_t *node = rdataset->private2; + + dns_db_detachnode(db, &node); +} + +static isc_result_t +rdataset_first(dns_rdataset_t *rdataset) { + unsigned char *raw = rdataset->private3; + unsigned int count; + + count = raw[0] * 256 + raw[1]; + if (count == 0) { + rdataset->private5 = NULL; + return (ISC_R_NOMORE); + } + raw += 2; + /* + * The privateuint4 field is the number of rdata beyond the cursor + * position, so we decrement the total count by one before storing + * it. + */ + count--; + rdataset->privateuint4 = count; + rdataset->private5 = raw; + + return (ISC_R_SUCCESS); +} + +static isc_result_t +rdataset_next(dns_rdataset_t *rdataset) { + unsigned int count; + unsigned int length; + unsigned char *raw; + + count = rdataset->privateuint4; + if (count == 0) + return (ISC_R_NOMORE); + count--; + rdataset->privateuint4 = count; + raw = rdataset->private5; + length = raw[0] * 256 + raw[1]; + raw += length + 2; + rdataset->private5 = raw; + + return (ISC_R_SUCCESS); +} + +static void +rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { + unsigned char *raw = rdataset->private5; + isc_region_t r; + unsigned int length; + unsigned int flags = 0; + + REQUIRE(raw != NULL); + + length = raw[0] * 256 + raw[1]; + raw += 2; + if (rdataset->type == dns_rdatatype_rrsig) { + if (*raw & DNS_RDATASLAB_OFFLINE) + flags |= DNS_RDATA_OFFLINE; + length--; + raw++; + } + r.length = length; + r.base = raw; + dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r); + rdata->flags |= flags; +} + +static void +rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) { + dns_db_t *db = source->private1; + dns_dbnode_t *node = source->private2; + dns_dbnode_t *cloned_node = NULL; + + attachnode(db, node, &cloned_node); + *target = *source; + + /* + * Reset iterator state. + */ + target->privateuint4 = 0; + target->private5 = NULL; +} + +static unsigned int +rdataset_count(dns_rdataset_t *rdataset) { + unsigned char *raw = rdataset->private3; + unsigned int count; + + count = raw[0] * 256 + raw[1]; + + return (count); +} + +static void +rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) { + rdatasetheader_t *header = rdataset->private3; + + header--; + header->trust = rdataset->trust = trust; +} + +/* + * Rdataset Iterator Methods + */ + +static void +rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) { + ecdb_rdatasetiter_t *ecdbiterator; + isc_mem_t *mctx; + + REQUIRE(iteratorp != NULL); + ecdbiterator = (ecdb_rdatasetiter_t *)*iteratorp; + REQUIRE(DNS_RDATASETITER_VALID(&ecdbiterator->common)); + + mctx = ecdbiterator->common.db->mctx; + + ecdbiterator->common.magic = 0; + + dns_db_detachnode(ecdbiterator->common.db, &ecdbiterator->common.node); + isc_mem_put(mctx, ecdbiterator, sizeof(ecdb_rdatasetiter_t)); + + *iteratorp = NULL; +} + +static isc_result_t +rdatasetiter_first(dns_rdatasetiter_t *iterator) { + ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator; + dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)iterator->node; + + REQUIRE(DNS_RDATASETITER_VALID(iterator)); + + if (ISC_LIST_EMPTY(ecdbnode->rdatasets)) + return (ISC_R_NOMORE); + ecdbiterator->current = ISC_LIST_HEAD(ecdbnode->rdatasets); + return (ISC_R_SUCCESS); +} + +static isc_result_t +rdatasetiter_next(dns_rdatasetiter_t *iterator) { + ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator; + + REQUIRE(DNS_RDATASETITER_VALID(iterator)); + + ecdbiterator->current = ISC_LIST_NEXT(ecdbiterator->current, link); + if (ecdbiterator->current == NULL) + return (ISC_R_NOMORE); + else + return (ISC_R_SUCCESS); +} + +static void +rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) { + ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator; + dns_ecdb_t *ecdb; + + ecdb = (dns_ecdb_t *)iterator->db; + REQUIRE(VALID_ECDB(ecdb)); + + bind_rdataset(ecdb, iterator->node, ecdbiterator->current, rdataset); +} diff --git a/lib/dns/forward.c b/lib/dns/forward.c index 1406b46..1f9c41a 100644 --- a/lib/dns/forward.c +++ b/lib/dns/forward.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: forward.c,v 1.12 2007-06-19 23:47:16 tbox Exp $ */ +/* $Id: forward.c,v 1.14 2009-09-02 23:48:02 tbox Exp $ */ /*! \file */ @@ -133,11 +133,27 @@ dns_fwdtable_add(dns_fwdtable_t *fwdtable, dns_name_t *name, } isc_result_t +dns_fwdtable_delete(dns_fwdtable_t *fwdtable, dns_name_t *name) { + isc_result_t result; + + REQUIRE(VALID_FWDTABLE(fwdtable)); + + RWLOCK(&fwdtable->rwlock, isc_rwlocktype_write); + result = dns_rbt_deletename(fwdtable->table, name, ISC_FALSE); + RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_write); + + if (result == DNS_R_PARTIALMATCH) + result = ISC_R_NOTFOUND; + + return (result); +} + +isc_result_t dns_fwdtable_find(dns_fwdtable_t *fwdtable, dns_name_t *name, dns_forwarders_t **forwardersp) { return (dns_fwdtable_find2(fwdtable, name, NULL, forwardersp)); -} +} isc_result_t dns_fwdtable_find2(dns_fwdtable_t *fwdtable, dns_name_t *name, diff --git a/lib/dns/gen-unix.h b/lib/dns/gen-unix.h index 91cd4d5..47a343d 100644 --- a/lib/dns/gen-unix.h +++ b/lib/dns/gen-unix.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: gen-unix.h,v 1.19.332.2 2009-01-18 23:47:35 tbox Exp $ */ +/* $Id: gen-unix.h,v 1.21 2009-01-17 23:47:42 tbox Exp $ */ /*! \file * \brief diff --git a/lib/dns/gen.c b/lib/dns/gen.c index 6f8ce7d..f1d46ea 100644 --- a/lib/dns/gen.c +++ b/lib/dns/gen.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: gen.c,v 1.83 2008-09-25 04:02:38 tbox Exp $ */ +/* $Id: gen.c,v 1.85 2009-12-04 22:06:37 tbox Exp $ */ /*! \file */ @@ -631,6 +631,8 @@ main(int argc, char **argv) { TOWIRETYPE, TOWIRECLASS, TOWIREDEF); doswitch("COMPARESWITCH", "compare", COMPAREARGS, COMPARETYPE, COMPARECLASS, COMPAREDEF); + doswitch("CASECOMPARESWITCH", "casecompare", COMPAREARGS, + COMPARETYPE, COMPARECLASS, COMPAREDEF); doswitch("FROMSTRUCTSWITCH", "fromstruct", FROMSTRUCTARGS, FROMSTRUCTTYPE, FROMSTRUCTCLASS, FROMSTRUCTDEF); doswitch("TOSTRUCTSWITCH", "tostruct", TOSTRUCTARGS, diff --git a/lib/dns/gssapi_link.c b/lib/dns/gssapi_link.c index a7af67f..e14d0eb 100644 --- a/lib/dns/gssapi_link.c +++ b/lib/dns/gssapi_link.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -16,13 +16,14 @@ */ /* - * $Id: gssapi_link.c,v 1.12 2008-11-11 03:55:01 marka Exp $ + * $Id: gssapi_link.c,v 1.16 2011-01-11 23:47:13 tbox Exp $ */ #include #ifdef GSSAPI +#include #include #include #include @@ -44,6 +45,12 @@ (gb).value = (r).base; \ } while (0) +#define GBUFFER_TO_REGION(gb, r) \ + do { \ + (r).length = (gb).length; \ + (r).base = (gb).value; \ + } while (0) + struct dst_gssapi_signverifyctx { isc_buffer_t *buffer; @@ -254,9 +261,10 @@ gssapi_compare(const dst_key_t *key1, const dst_key_t *key2) { } static isc_result_t -gssapi_generate(dst_key_t *key, int unused) { +gssapi_generate(dst_key_t *key, int unused, void (*callback)(int)) { UNUSED(key); UNUSED(unused); + UNUSED(callback); /* No idea */ return (ISC_R_FAILURE); @@ -275,6 +283,79 @@ gssapi_destroy(dst_key_t *key) { key->keydata.gssctx = NULL; } +static isc_result_t +gssapi_restore(dst_key_t *key, const char *keystr) { + OM_uint32 major, minor; + size_t len; + isc_buffer_t *b = NULL; + isc_region_t r; + gss_buffer_desc gssbuffer; + isc_result_t result; + + len = strlen(keystr); + if ((len % 4) != 0) + return (ISC_R_BADBASE64); + + len = (len / 4) * 3; + + result = isc_buffer_allocate(key->mctx, &b, len); + if (result != ISC_R_SUCCESS) + return (result); + + result = isc_base64_decodestring(keystr, b); + if (result != ISC_R_SUCCESS) { + isc_buffer_free(&b); + return (result); + } + + isc_buffer_remainingregion(b, &r); + REGION_TO_GBUFFER(r, gssbuffer); + major = gss_import_sec_context(&minor, &gssbuffer, + &key->keydata.gssctx); + if (major != GSS_S_COMPLETE) { + isc_buffer_free(&b); + return (ISC_R_FAILURE); + } + + isc_buffer_free(&b); + return (ISC_R_SUCCESS); +} + +static isc_result_t +gssapi_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length) { + OM_uint32 major, minor; + gss_buffer_desc gssbuffer; + size_t len; + char *buf; + isc_buffer_t b; + isc_region_t r; + isc_result_t result; + + major = gss_export_sec_context(&minor, &key->keydata.gssctx, + &gssbuffer); + if (major != GSS_S_COMPLETE) { + fprintf(stderr, "gss_export_sec_context -> %d, %d\n", + major, minor); + return (ISC_R_FAILURE); + } + if (gssbuffer.length == 0) + return (ISC_R_FAILURE); + len = ((gssbuffer.length + 2)/3) * 4; + buf = isc_mem_get(mctx, len); + if (buf == NULL) { + gss_release_buffer(&minor, &gssbuffer); + return (ISC_R_NOMEMORY); + } + isc_buffer_init(&b, buf, len); + GBUFFER_TO_REGION(gssbuffer, r); + result = isc_base64_totext(&r, 0, "", &b); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + gss_release_buffer(&minor, &gssbuffer); + *buffer = buf; + *length = len; + return (ISC_R_SUCCESS); +} + static dst_func_t gssapi_functions = { gssapi_create_signverify_ctx, gssapi_destroy_signverify_ctx, @@ -292,7 +373,9 @@ static dst_func_t gssapi_functions = { NULL, /*%< tofile */ NULL, /*%< parse */ NULL, /*%< cleanup */ - NULL /*%< fromlabel */ + NULL, /*%< fromlabel */ + gssapi_dump, + gssapi_restore, }; isc_result_t diff --git a/lib/dns/gssapictx.c b/lib/dns/gssapictx.c index f365a64..707745c 100644 --- a/lib/dns/gssapictx.c +++ b/lib/dns/gssapictx.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,16 +15,18 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: gssapictx.c,v 1.12.118.5 2010-12-22 02:37:55 marka Exp $ */ +/* $Id: gssapictx.c,v 1.26 2011-01-10 03:49:49 marka Exp $ */ #include +#include #include #include #include #include #include +#include #include #include #include @@ -201,9 +203,12 @@ log_cred(const gss_cred_id_t cred) { * - tkey-gssapi-credential doesn't start with DNS/ * - the default realm in /etc/krb5.conf and the * tkey-gssapi-credential bind config option don't match + * + * Note that if tkey-gssapi-keytab is set then these configure checks + * are not performed, and runtime errors from gssapi are used instead */ static void -dst_gssapi_check_config(const char *gss_name) { +check_config(const char *gss_name) { const char *p; krb5_context krb5_ctx; char *krb5_realm = NULL; @@ -263,7 +268,7 @@ dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate, * here when we're in the acceptor role, which would let us * default the hostname and use a compiled in default service * name of "DNS", giving one less thing to configure in - * named.conf. Unfortunately, this creates a circular + * named.conf. Unfortunately, this creates a circular * dependency due to DNS-based realm lookup in at least one * GSSAPI implementation (Heimdal). Oh well. */ @@ -273,7 +278,7 @@ dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate, gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID, &gname); if (gret != GSS_S_COMPLETE) { - dst_gssapi_check_config((char *)array); + check_config((char *)array); gss_log(3, "failed gss_import_name: %s", gss_error_tostring(gret, minor, buf, @@ -306,7 +311,7 @@ dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate, initiate ? "initiate" : "accept", (char *)gnamebuf.value, gss_error_tostring(gret, minor, buf, sizeof(buf))); - dst_gssapi_check_config((char *)array); + check_config((char *)array); return (ISC_R_FAILURE); } @@ -361,7 +366,7 @@ dst_gssapi_identitymatchesrealmkrb5(dns_name_t *signer, dns_name_t *name, rname++; /* - * Find the host portion of the signer's name. We do this by + * Find the host portion of the signer's name. We do this by * searching for the first / character. We then check to make * certain the instance name is "host" * @@ -440,7 +445,7 @@ dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name, return (isc_boolean_false); /* - * Find the host portion of the signer's name. Zero out the $ so + * Find the host portion of the signer's name. Zero out the $ so * it terminates the signer's name, and skip past the @ for * the realm. * @@ -454,7 +459,7 @@ dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name, /* * Find the first . in the target name, and make it the end of - * the string. The rest of the name has to match the realm. + * the string. The rest of the name has to match the realm. */ if (name != NULL) { nname = strchr(nbuf, '.'); @@ -510,9 +515,34 @@ dst_gssapi_releasecred(gss_cred_id_t *cred) { #endif } +#ifdef GSSAPI +/* + * Format a gssapi error message info into a char ** on the given memory + * context. This is used to return gssapi error messages back up the + * call chain for reporting to the user. + */ +static void +gss_err_message(isc_mem_t *mctx, isc_uint32_t major, isc_uint32_t minor, + char **err_message) +{ + char buf[1024]; + char *estr; + + if (err_message == NULL || mctx == NULL) { + /* the caller doesn't want any error messages */ + return; + } + + estr = gss_error_tostring(major, minor, buf, sizeof(buf)); + if (estr) + (*err_message) = isc_mem_strdup(mctx, estr); +} +#endif + isc_result_t dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, - isc_buffer_t *outtoken, gss_ctx_id_t *gssctx) + isc_buffer_t *outtoken, gss_ctx_id_t *gssctx, + isc_mem_t *mctx, char **err_message) { #ifdef GSSAPI isc_region_t r; @@ -523,10 +553,10 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, isc_result_t result; gss_buffer_desc gnamebuf; unsigned char array[DNS_NAME_MAXTEXT + 1]; - char buf[1024]; /* Client must pass us a valid gss_ctx_id_t here */ REQUIRE(gssctx != NULL); + REQUIRE(mctx != NULL); isc_buffer_init(&namebuf, array, sizeof(array)); name_to_gbuffer(name, &namebuf, &gnamebuf); @@ -534,6 +564,7 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, /* Get the name as a GSS name */ gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID, &gname); if (gret != GSS_S_COMPLETE) { + gss_err_message(mctx, gret, minor, err_message); result = ISC_R_FAILURE; goto out; } @@ -550,8 +581,7 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, * Note that we don't set GSS_C_SEQUENCE_FLAG as Windows DNS * servers don't like it. */ - flags = GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_DELEG_FLAG | - GSS_C_INTEG_FLAG; + flags = GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG; gret = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, gssctx, gname, GSS_SPNEGO_MECHANISM, flags, @@ -559,9 +589,9 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, NULL, &gouttoken, &ret_flags, NULL); if (gret != GSS_S_COMPLETE && gret != GSS_S_CONTINUE_NEEDED) { - gss_log(3, "Failure initiating security context"); - gss_log(3, "%s", gss_error_tostring(gret, minor, - buf, sizeof(buf))); + gss_err_message(mctx, gret, minor, err_message); + gss_log(3, "Failure initiating security context: %s", + *err_message); result = ISC_R_FAILURE; goto out; } @@ -593,6 +623,8 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, UNUSED(intoken); UNUSED(outtoken); UNUSED(gssctx); + UNUSED(mctx); + UNUSED(err_message); return (ISC_R_NOTIMPLEMENTED); #endif @@ -600,6 +632,7 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, isc_result_t dst_gssapi_acceptctx(gss_cred_id_t cred, + const char *gssapi_keytab, isc_region_t *intoken, isc_buffer_t **outtoken, gss_ctx_id_t *ctxout, dns_name_t *principal, isc_mem_t *mctx) @@ -626,6 +659,34 @@ dst_gssapi_acceptctx(gss_cred_id_t cred, else context = *ctxout; + if (gssapi_keytab != NULL) { +#ifdef ISC_PLATFORM_GSSAPI_KRB5_HEADER + gret = gsskrb5_register_acceptor_identity(gssapi_keytab); + if (gret != GSS_S_COMPLETE) { + gss_log(3, "failed " + "gsskrb5_register_acceptor_identity(%s): %s", + gssapi_keytab, + gss_error_tostring(gret, minor, + buf, sizeof(buf))); + return (DNS_R_INVALIDTKEY); + } +#else + /* + * Minimize memory leakage by only setting KRB5_KTNAME + * if it needs to change. + */ + const char *old = getenv("KRB5_KTNAME"); + if (old == NULL || strcmp(old, gssapi_keytab) != 0) { + char *kt = malloc(strlen(gssapi_keytab) + 13); + if (kt == NULL) + return (ISC_R_NOMEMORY); + sprintf(kt, "KRB5_KTNAME=%s", gssapi_keytab); + if (putenv(kt) != 0) + return (ISC_R_NOMEMORY); + } +#endif + } + gret = gss_accept_sec_context(&minor, &context, cred, &gintoken, GSS_C_NO_CHANNEL_BINDINGS, &gname, NULL, &gouttoken, NULL, NULL, NULL); @@ -692,7 +753,7 @@ dst_gssapi_acceptctx(gss_cred_id_t cred, isc_buffer_add(&namebuf, r.length); RETERR(dns_name_fromtext(principal, &namebuf, dns_rootname, - ISC_FALSE, NULL)); + 0, NULL)); if (gnamebuf.length != 0) { gret = gss_release_buffer(&minor, &gnamebuf); @@ -717,6 +778,7 @@ dst_gssapi_acceptctx(gss_cred_id_t cred, return (result); #else UNUSED(cred); + UNUSED(gssapi_keytab); UNUSED(intoken); UNUSED(outtoken); UNUSED(ctxout); diff --git a/lib/dns/hmac_link.c b/lib/dns/hmac_link.c index 5d6dce7..ecc4089 100644 --- a/lib/dns/hmac_link.c +++ b/lib/dns/hmac_link.c @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -31,7 +31,7 @@ /* * Principal Author: Brian Wellington - * $Id: hmac_link.c,v 1.11 2008-04-01 23:47:10 tbox Exp $ + * $Id: hmac_link.c,v 1.19 2011-01-11 23:47:13 tbox Exp $ */ #include @@ -50,14 +50,10 @@ #include "dst_internal.h" #include "dst_parse.h" -#define HMAC_LEN 64 -#define HMAC_IPAD 0x36 -#define HMAC_OPAD 0x5c - static isc_result_t hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data); struct dst_hmacmd5_key { - unsigned char key[HMAC_LEN]; + unsigned char key[ISC_MD5_BLOCK_LENGTH]; }; static isc_result_t @@ -79,7 +75,7 @@ hmacmd5_createctx(dst_key_t *key, dst_context_t *dctx) { hmacmd5ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacmd5_t)); if (hmacmd5ctx == NULL) return (ISC_R_NOMEMORY); - isc_hmacmd5_init(hmacmd5ctx, hkey->key, HMAC_LEN); + isc_hmacmd5_init(hmacmd5ctx, hkey->key, ISC_SHA1_BLOCK_LENGTH); dctx->ctxdata.hmacmd5ctx = hmacmd5ctx; return (ISC_R_SUCCESS); } @@ -142,26 +138,28 @@ hmacmd5_compare(const dst_key_t *key1, const dst_key_t *key2) { else if (hkey1 == NULL || hkey2 == NULL) return (ISC_FALSE); - if (memcmp(hkey1->key, hkey2->key, HMAC_LEN) == 0) + if (memcmp(hkey1->key, hkey2->key, ISC_SHA1_BLOCK_LENGTH) == 0) return (ISC_TRUE); else return (ISC_FALSE); } static isc_result_t -hmacmd5_generate(dst_key_t *key, int pseudorandom_ok) { +hmacmd5_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) { isc_buffer_t b; isc_result_t ret; - int bytes; - unsigned char data[HMAC_LEN]; + unsigned int bytes; + unsigned char data[ISC_SHA1_BLOCK_LENGTH]; + + UNUSED(callback); bytes = (key->key_size + 7) / 8; - if (bytes > HMAC_LEN) { - bytes = HMAC_LEN; - key->key_size = HMAC_LEN * 8; + if (bytes > ISC_SHA1_BLOCK_LENGTH) { + bytes = ISC_SHA1_BLOCK_LENGTH; + key->key_size = ISC_SHA1_BLOCK_LENGTH * 8; } - memset(data, 0, HMAC_LEN); + memset(data, 0, ISC_SHA1_BLOCK_LENGTH); ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0)); if (ret != ISC_R_SUCCESS) @@ -170,7 +168,7 @@ hmacmd5_generate(dst_key_t *key, int pseudorandom_ok) { isc_buffer_init(&b, data, bytes); isc_buffer_add(&b, bytes); ret = hmacmd5_fromdns(key, &b); - memset(data, 0, HMAC_LEN); + memset(data, 0, ISC_SHA1_BLOCK_LENGTH); return (ret); } @@ -184,6 +182,7 @@ hmacmd5_isprivate(const dst_key_t *key) { static void hmacmd5_destroy(dst_key_t *key) { dst_hmacmd5_key_t *hkey = key->keydata.hmacmd5; + memset(hkey, 0, sizeof(dst_hmacmd5_key_t)); isc_mem_put(key->mctx, hkey, sizeof(dst_hmacmd5_key_t)); key->keydata.hmacmd5 = NULL; @@ -223,7 +222,7 @@ hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) { memset(hkey->key, 0, sizeof(hkey->key)); - if (r.length > HMAC_LEN) { + if (r.length > ISC_SHA1_BLOCK_LENGTH) { isc_md5_init(&md5ctx); isc_md5_update(&md5ctx, r.base, r.length); isc_md5_final(&md5ctx, hkey->key); @@ -268,15 +267,17 @@ hmacmd5_tofile(const dst_key_t *key, const char *directory) { } static isc_result_t -hmacmd5_parse(dst_key_t *key, isc_lex_t *lexer) { +hmacmd5_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { dst_private_t priv; isc_result_t result, tresult; isc_buffer_t b; isc_mem_t *mctx = key->mctx; unsigned int i; + UNUSED(pub); /* read private key file */ - result = dst__privstruct_parse(key, DST_ALG_HMACMD5, lexer, mctx, &priv); + result = dst__privstruct_parse(key, DST_ALG_HMACMD5, lexer, mctx, + &priv); if (result != ISC_R_SUCCESS) return (result); @@ -324,6 +325,8 @@ static dst_func_t hmacmd5_functions = { hmacmd5_parse, NULL, /*%< cleanup */ NULL, /*%< fromlabel */ + NULL, /*%< dump */ + NULL, /*%< restore */ }; isc_result_t @@ -337,7 +340,7 @@ dst__hmacmd5_init(dst_func_t **funcp) { static isc_result_t hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data); struct dst_hmacsha1_key { - unsigned char key[ISC_SHA1_DIGESTLENGTH]; + unsigned char key[ISC_SHA1_BLOCK_LENGTH]; }; static isc_result_t @@ -348,7 +351,7 @@ hmacsha1_createctx(dst_key_t *key, dst_context_t *dctx) { hmacsha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha1_t)); if (hmacsha1ctx == NULL) return (ISC_R_NOMEMORY); - isc_hmacsha1_init(hmacsha1ctx, hkey->key, ISC_SHA1_DIGESTLENGTH); + isc_hmacsha1_init(hmacsha1ctx, hkey->key, ISC_SHA1_BLOCK_LENGTH); dctx->ctxdata.hmacsha1ctx = hmacsha1ctx; return (ISC_R_SUCCESS); } @@ -411,26 +414,28 @@ hmacsha1_compare(const dst_key_t *key1, const dst_key_t *key2) { else if (hkey1 == NULL || hkey2 == NULL) return (ISC_FALSE); - if (memcmp(hkey1->key, hkey2->key, ISC_SHA1_DIGESTLENGTH) == 0) + if (memcmp(hkey1->key, hkey2->key, ISC_SHA1_BLOCK_LENGTH) == 0) return (ISC_TRUE); else return (ISC_FALSE); } static isc_result_t -hmacsha1_generate(dst_key_t *key, int pseudorandom_ok) { +hmacsha1_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) { isc_buffer_t b; isc_result_t ret; - int bytes; - unsigned char data[HMAC_LEN]; + unsigned int bytes; + unsigned char data[ISC_SHA1_BLOCK_LENGTH]; + + UNUSED(callback); bytes = (key->key_size + 7) / 8; - if (bytes > HMAC_LEN) { - bytes = HMAC_LEN; - key->key_size = HMAC_LEN * 8; + if (bytes > ISC_SHA1_BLOCK_LENGTH) { + bytes = ISC_SHA1_BLOCK_LENGTH; + key->key_size = ISC_SHA1_BLOCK_LENGTH * 8; } - memset(data, 0, HMAC_LEN); + memset(data, 0, ISC_SHA1_BLOCK_LENGTH); ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0)); if (ret != ISC_R_SUCCESS) @@ -439,7 +444,7 @@ hmacsha1_generate(dst_key_t *key, int pseudorandom_ok) { isc_buffer_init(&b, data, bytes); isc_buffer_add(&b, bytes); ret = hmacsha1_fromdns(key, &b); - memset(data, 0, ISC_SHA1_DIGESTLENGTH); + memset(data, 0, ISC_SHA1_BLOCK_LENGTH); return (ret); } @@ -453,6 +458,7 @@ hmacsha1_isprivate(const dst_key_t *key) { static void hmacsha1_destroy(dst_key_t *key) { dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1; + memset(hkey, 0, sizeof(dst_hmacsha1_key_t)); isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha1_key_t)); key->keydata.hmacsha1 = NULL; @@ -492,7 +498,7 @@ hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) { memset(hkey->key, 0, sizeof(hkey->key)); - if (r.length > ISC_SHA1_DIGESTLENGTH) { + if (r.length > ISC_SHA1_BLOCK_LENGTH) { isc_sha1_init(&sha1ctx); isc_sha1_update(&sha1ctx, r.base, r.length); isc_sha1_final(&sha1ctx, hkey->key); @@ -537,13 +543,14 @@ hmacsha1_tofile(const dst_key_t *key, const char *directory) { } static isc_result_t -hmacsha1_parse(dst_key_t *key, isc_lex_t *lexer) { +hmacsha1_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { dst_private_t priv; isc_result_t result, tresult; isc_buffer_t b; isc_mem_t *mctx = key->mctx; unsigned int i; + UNUSED(pub); /* read private key file */ result = dst__privstruct_parse(key, DST_ALG_HMACSHA1, lexer, mctx, &priv); @@ -594,6 +601,8 @@ static dst_func_t hmacsha1_functions = { hmacsha1_parse, NULL, /* cleanup */ NULL, /* fromlabel */ + NULL, /* dump */ + NULL, /* restore */ }; isc_result_t @@ -607,7 +616,7 @@ dst__hmacsha1_init(dst_func_t **funcp) { static isc_result_t hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data); struct dst_hmacsha224_key { - unsigned char key[ISC_SHA224_DIGESTLENGTH]; + unsigned char key[ISC_SHA224_BLOCK_LENGTH]; }; static isc_result_t @@ -618,7 +627,7 @@ hmacsha224_createctx(dst_key_t *key, dst_context_t *dctx) { hmacsha224ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha224_t)); if (hmacsha224ctx == NULL) return (ISC_R_NOMEMORY); - isc_hmacsha224_init(hmacsha224ctx, hkey->key, ISC_SHA224_DIGESTLENGTH); + isc_hmacsha224_init(hmacsha224ctx, hkey->key, ISC_SHA224_BLOCK_LENGTH); dctx->ctxdata.hmacsha224ctx = hmacsha224ctx; return (ISC_R_SUCCESS); } @@ -681,26 +690,30 @@ hmacsha224_compare(const dst_key_t *key1, const dst_key_t *key2) { else if (hkey1 == NULL || hkey2 == NULL) return (ISC_FALSE); - if (memcmp(hkey1->key, hkey2->key, ISC_SHA224_DIGESTLENGTH) == 0) + if (memcmp(hkey1->key, hkey2->key, ISC_SHA224_BLOCK_LENGTH) == 0) return (ISC_TRUE); else return (ISC_FALSE); } static isc_result_t -hmacsha224_generate(dst_key_t *key, int pseudorandom_ok) { +hmacsha224_generate(dst_key_t *key, int pseudorandom_ok, + void (*callback)(int)) +{ isc_buffer_t b; isc_result_t ret; - int bytes; - unsigned char data[HMAC_LEN]; + unsigned int bytes; + unsigned char data[ISC_SHA224_BLOCK_LENGTH]; + + UNUSED(callback); bytes = (key->key_size + 7) / 8; - if (bytes > HMAC_LEN) { - bytes = HMAC_LEN; - key->key_size = HMAC_LEN * 8; + if (bytes > ISC_SHA224_BLOCK_LENGTH) { + bytes = ISC_SHA224_BLOCK_LENGTH; + key->key_size = ISC_SHA224_BLOCK_LENGTH * 8; } - memset(data, 0, HMAC_LEN); + memset(data, 0, ISC_SHA224_BLOCK_LENGTH); ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0)); if (ret != ISC_R_SUCCESS) @@ -709,7 +722,7 @@ hmacsha224_generate(dst_key_t *key, int pseudorandom_ok) { isc_buffer_init(&b, data, bytes); isc_buffer_add(&b, bytes); ret = hmacsha224_fromdns(key, &b); - memset(data, 0, ISC_SHA224_DIGESTLENGTH); + memset(data, 0, ISC_SHA224_BLOCK_LENGTH); return (ret); } @@ -723,6 +736,7 @@ hmacsha224_isprivate(const dst_key_t *key) { static void hmacsha224_destroy(dst_key_t *key) { dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224; + memset(hkey, 0, sizeof(dst_hmacsha224_key_t)); isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha224_key_t)); key->keydata.hmacsha224 = NULL; @@ -762,7 +776,7 @@ hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) { memset(hkey->key, 0, sizeof(hkey->key)); - if (r.length > ISC_SHA224_DIGESTLENGTH) { + if (r.length > ISC_SHA224_BLOCK_LENGTH) { isc_sha224_init(&sha224ctx); isc_sha224_update(&sha224ctx, r.base, r.length); isc_sha224_final(hkey->key, &sha224ctx); @@ -807,13 +821,14 @@ hmacsha224_tofile(const dst_key_t *key, const char *directory) { } static isc_result_t -hmacsha224_parse(dst_key_t *key, isc_lex_t *lexer) { +hmacsha224_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { dst_private_t priv; isc_result_t result, tresult; isc_buffer_t b; isc_mem_t *mctx = key->mctx; unsigned int i; + UNUSED(pub); /* read private key file */ result = dst__privstruct_parse(key, DST_ALG_HMACSHA224, lexer, mctx, &priv); @@ -864,6 +879,8 @@ static dst_func_t hmacsha224_functions = { hmacsha224_parse, NULL, /* cleanup */ NULL, /* fromlabel */ + NULL, /* dump */ + NULL, /* restore */ }; isc_result_t @@ -877,7 +894,7 @@ dst__hmacsha224_init(dst_func_t **funcp) { static isc_result_t hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data); struct dst_hmacsha256_key { - unsigned char key[ISC_SHA256_DIGESTLENGTH]; + unsigned char key[ISC_SHA256_BLOCK_LENGTH]; }; static isc_result_t @@ -888,7 +905,7 @@ hmacsha256_createctx(dst_key_t *key, dst_context_t *dctx) { hmacsha256ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha256_t)); if (hmacsha256ctx == NULL) return (ISC_R_NOMEMORY); - isc_hmacsha256_init(hmacsha256ctx, hkey->key, ISC_SHA256_DIGESTLENGTH); + isc_hmacsha256_init(hmacsha256ctx, hkey->key, ISC_SHA256_BLOCK_LENGTH); dctx->ctxdata.hmacsha256ctx = hmacsha256ctx; return (ISC_R_SUCCESS); } @@ -951,26 +968,30 @@ hmacsha256_compare(const dst_key_t *key1, const dst_key_t *key2) { else if (hkey1 == NULL || hkey2 == NULL) return (ISC_FALSE); - if (memcmp(hkey1->key, hkey2->key, ISC_SHA256_DIGESTLENGTH) == 0) + if (memcmp(hkey1->key, hkey2->key, ISC_SHA256_BLOCK_LENGTH) == 0) return (ISC_TRUE); else return (ISC_FALSE); } static isc_result_t -hmacsha256_generate(dst_key_t *key, int pseudorandom_ok) { +hmacsha256_generate(dst_key_t *key, int pseudorandom_ok, + void (*callback)(int)) +{ isc_buffer_t b; isc_result_t ret; - int bytes; - unsigned char data[HMAC_LEN]; + unsigned int bytes; + unsigned char data[ISC_SHA256_BLOCK_LENGTH]; + + UNUSED(callback); bytes = (key->key_size + 7) / 8; - if (bytes > HMAC_LEN) { - bytes = HMAC_LEN; - key->key_size = HMAC_LEN * 8; + if (bytes > ISC_SHA256_BLOCK_LENGTH) { + bytes = ISC_SHA256_BLOCK_LENGTH; + key->key_size = ISC_SHA256_BLOCK_LENGTH * 8; } - memset(data, 0, HMAC_LEN); + memset(data, 0, ISC_SHA256_BLOCK_LENGTH); ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0)); if (ret != ISC_R_SUCCESS) @@ -979,7 +1000,7 @@ hmacsha256_generate(dst_key_t *key, int pseudorandom_ok) { isc_buffer_init(&b, data, bytes); isc_buffer_add(&b, bytes); ret = hmacsha256_fromdns(key, &b); - memset(data, 0, ISC_SHA256_DIGESTLENGTH); + memset(data, 0, ISC_SHA256_BLOCK_LENGTH); return (ret); } @@ -993,6 +1014,7 @@ hmacsha256_isprivate(const dst_key_t *key) { static void hmacsha256_destroy(dst_key_t *key) { dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256; + memset(hkey, 0, sizeof(dst_hmacsha256_key_t)); isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha256_key_t)); key->keydata.hmacsha256 = NULL; @@ -1032,7 +1054,7 @@ hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) { memset(hkey->key, 0, sizeof(hkey->key)); - if (r.length > ISC_SHA256_DIGESTLENGTH) { + if (r.length > ISC_SHA256_BLOCK_LENGTH) { isc_sha256_init(&sha256ctx); isc_sha256_update(&sha256ctx, r.base, r.length); isc_sha256_final(hkey->key, &sha256ctx); @@ -1077,13 +1099,14 @@ hmacsha256_tofile(const dst_key_t *key, const char *directory) { } static isc_result_t -hmacsha256_parse(dst_key_t *key, isc_lex_t *lexer) { +hmacsha256_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { dst_private_t priv; isc_result_t result, tresult; isc_buffer_t b; isc_mem_t *mctx = key->mctx; unsigned int i; + UNUSED(pub); /* read private key file */ result = dst__privstruct_parse(key, DST_ALG_HMACSHA256, lexer, mctx, &priv); @@ -1134,6 +1157,8 @@ static dst_func_t hmacsha256_functions = { hmacsha256_parse, NULL, /* cleanup */ NULL, /* fromlabel */ + NULL, /* dump */ + NULL, /* restore */ }; isc_result_t @@ -1147,7 +1172,7 @@ dst__hmacsha256_init(dst_func_t **funcp) { static isc_result_t hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data); struct dst_hmacsha384_key { - unsigned char key[ISC_SHA384_DIGESTLENGTH]; + unsigned char key[ISC_SHA384_BLOCK_LENGTH]; }; static isc_result_t @@ -1158,7 +1183,7 @@ hmacsha384_createctx(dst_key_t *key, dst_context_t *dctx) { hmacsha384ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha384_t)); if (hmacsha384ctx == NULL) return (ISC_R_NOMEMORY); - isc_hmacsha384_init(hmacsha384ctx, hkey->key, ISC_SHA384_DIGESTLENGTH); + isc_hmacsha384_init(hmacsha384ctx, hkey->key, ISC_SHA384_BLOCK_LENGTH); dctx->ctxdata.hmacsha384ctx = hmacsha384ctx; return (ISC_R_SUCCESS); } @@ -1221,26 +1246,30 @@ hmacsha384_compare(const dst_key_t *key1, const dst_key_t *key2) { else if (hkey1 == NULL || hkey2 == NULL) return (ISC_FALSE); - if (memcmp(hkey1->key, hkey2->key, ISC_SHA384_DIGESTLENGTH) == 0) + if (memcmp(hkey1->key, hkey2->key, ISC_SHA384_BLOCK_LENGTH) == 0) return (ISC_TRUE); else return (ISC_FALSE); } static isc_result_t -hmacsha384_generate(dst_key_t *key, int pseudorandom_ok) { +hmacsha384_generate(dst_key_t *key, int pseudorandom_ok, + void (*callback)(int)) +{ isc_buffer_t b; isc_result_t ret; - int bytes; - unsigned char data[HMAC_LEN]; + unsigned int bytes; + unsigned char data[ISC_SHA384_BLOCK_LENGTH]; + + UNUSED(callback); bytes = (key->key_size + 7) / 8; - if (bytes > HMAC_LEN) { - bytes = HMAC_LEN; - key->key_size = HMAC_LEN * 8; + if (bytes > ISC_SHA384_BLOCK_LENGTH) { + bytes = ISC_SHA384_BLOCK_LENGTH; + key->key_size = ISC_SHA384_BLOCK_LENGTH * 8; } - memset(data, 0, HMAC_LEN); + memset(data, 0, ISC_SHA384_BLOCK_LENGTH); ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0)); if (ret != ISC_R_SUCCESS) @@ -1249,7 +1278,7 @@ hmacsha384_generate(dst_key_t *key, int pseudorandom_ok) { isc_buffer_init(&b, data, bytes); isc_buffer_add(&b, bytes); ret = hmacsha384_fromdns(key, &b); - memset(data, 0, ISC_SHA384_DIGESTLENGTH); + memset(data, 0, ISC_SHA384_BLOCK_LENGTH); return (ret); } @@ -1263,6 +1292,7 @@ hmacsha384_isprivate(const dst_key_t *key) { static void hmacsha384_destroy(dst_key_t *key) { dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384; + memset(hkey, 0, sizeof(dst_hmacsha384_key_t)); isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha384_key_t)); key->keydata.hmacsha384 = NULL; @@ -1302,7 +1332,7 @@ hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) { memset(hkey->key, 0, sizeof(hkey->key)); - if (r.length > ISC_SHA384_DIGESTLENGTH) { + if (r.length > ISC_SHA384_BLOCK_LENGTH) { isc_sha384_init(&sha384ctx); isc_sha384_update(&sha384ctx, r.base, r.length); isc_sha384_final(hkey->key, &sha384ctx); @@ -1347,13 +1377,14 @@ hmacsha384_tofile(const dst_key_t *key, const char *directory) { } static isc_result_t -hmacsha384_parse(dst_key_t *key, isc_lex_t *lexer) { +hmacsha384_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { dst_private_t priv; isc_result_t result, tresult; isc_buffer_t b; isc_mem_t *mctx = key->mctx; unsigned int i; + UNUSED(pub); /* read private key file */ result = dst__privstruct_parse(key, DST_ALG_HMACSHA384, lexer, mctx, &priv); @@ -1404,6 +1435,8 @@ static dst_func_t hmacsha384_functions = { hmacsha384_parse, NULL, /* cleanup */ NULL, /* fromlabel */ + NULL, /* dump */ + NULL, /* restore */ }; isc_result_t @@ -1417,7 +1450,7 @@ dst__hmacsha384_init(dst_func_t **funcp) { static isc_result_t hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data); struct dst_hmacsha512_key { - unsigned char key[ISC_SHA512_DIGESTLENGTH]; + unsigned char key[ISC_SHA512_BLOCK_LENGTH]; }; static isc_result_t @@ -1428,7 +1461,7 @@ hmacsha512_createctx(dst_key_t *key, dst_context_t *dctx) { hmacsha512ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha512_t)); if (hmacsha512ctx == NULL) return (ISC_R_NOMEMORY); - isc_hmacsha512_init(hmacsha512ctx, hkey->key, ISC_SHA512_DIGESTLENGTH); + isc_hmacsha512_init(hmacsha512ctx, hkey->key, ISC_SHA512_BLOCK_LENGTH); dctx->ctxdata.hmacsha512ctx = hmacsha512ctx; return (ISC_R_SUCCESS); } @@ -1491,26 +1524,30 @@ hmacsha512_compare(const dst_key_t *key1, const dst_key_t *key2) { else if (hkey1 == NULL || hkey2 == NULL) return (ISC_FALSE); - if (memcmp(hkey1->key, hkey2->key, ISC_SHA512_DIGESTLENGTH) == 0) + if (memcmp(hkey1->key, hkey2->key, ISC_SHA512_BLOCK_LENGTH) == 0) return (ISC_TRUE); else return (ISC_FALSE); } static isc_result_t -hmacsha512_generate(dst_key_t *key, int pseudorandom_ok) { +hmacsha512_generate(dst_key_t *key, int pseudorandom_ok, + void (*callback)(int)) +{ isc_buffer_t b; isc_result_t ret; - int bytes; - unsigned char data[HMAC_LEN]; + unsigned int bytes; + unsigned char data[ISC_SHA512_BLOCK_LENGTH]; + + UNUSED(callback); bytes = (key->key_size + 7) / 8; - if (bytes > HMAC_LEN) { - bytes = HMAC_LEN; - key->key_size = HMAC_LEN * 8; + if (bytes > ISC_SHA512_BLOCK_LENGTH) { + bytes = ISC_SHA512_BLOCK_LENGTH; + key->key_size = ISC_SHA512_BLOCK_LENGTH * 8; } - memset(data, 0, HMAC_LEN); + memset(data, 0, ISC_SHA512_BLOCK_LENGTH); ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0)); if (ret != ISC_R_SUCCESS) @@ -1519,7 +1556,7 @@ hmacsha512_generate(dst_key_t *key, int pseudorandom_ok) { isc_buffer_init(&b, data, bytes); isc_buffer_add(&b, bytes); ret = hmacsha512_fromdns(key, &b); - memset(data, 0, ISC_SHA512_DIGESTLENGTH); + memset(data, 0, ISC_SHA512_BLOCK_LENGTH); return (ret); } @@ -1533,6 +1570,7 @@ hmacsha512_isprivate(const dst_key_t *key) { static void hmacsha512_destroy(dst_key_t *key) { dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512; + memset(hkey, 0, sizeof(dst_hmacsha512_key_t)); isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha512_key_t)); key->keydata.hmacsha512 = NULL; @@ -1572,7 +1610,7 @@ hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) { memset(hkey->key, 0, sizeof(hkey->key)); - if (r.length > ISC_SHA512_DIGESTLENGTH) { + if (r.length > ISC_SHA512_BLOCK_LENGTH) { isc_sha512_init(&sha512ctx); isc_sha512_update(&sha512ctx, r.base, r.length); isc_sha512_final(hkey->key, &sha512ctx); @@ -1617,13 +1655,14 @@ hmacsha512_tofile(const dst_key_t *key, const char *directory) { } static isc_result_t -hmacsha512_parse(dst_key_t *key, isc_lex_t *lexer) { +hmacsha512_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { dst_private_t priv; isc_result_t result, tresult; isc_buffer_t b; isc_mem_t *mctx = key->mctx; unsigned int i; + UNUSED(pub); /* read private key file */ result = dst__privstruct_parse(key, DST_ALG_HMACSHA512, lexer, mctx, &priv); @@ -1674,6 +1713,8 @@ static dst_func_t hmacsha512_functions = { hmacsha512_parse, NULL, /* cleanup */ NULL, /* fromlabel */ + NULL, /* dump */ + NULL, /* restore */ }; isc_result_t diff --git a/lib/dns/include/dns/Makefile.in b/lib/dns/include/dns/Makefile.in index a4cd810..e13d084 100644 --- a/lib/dns/include/dns/Makefile.in +++ b/lib/dns/include/dns/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2007-2009 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 1998-2003 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.55 2008-11-14 23:47:33 tbox Exp $ +# $Id: Makefile.in,v 1.57 2009-10-08 23:48:10 tbox Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -21,19 +21,17 @@ top_srcdir = @top_srcdir@ @BIND9_VERSION@ -HEADERS = acl.h adb.h byaddr.h cache.h callbacks.h \ - cert.h compress.h \ +HEADERS = acl.h adb.h byaddr.h cache.h callbacks.h cert.h compress.h \ db.h dbiterator.h dbtable.h diff.h dispatch.h dlz.h \ - dnssec.h ds.h events.h fixedname.h iptable.h journal.h keyflags.h \ - keytable.h keyvalues.h lib.h log.h master.h masterdump.h \ - message.h name.h ncache.h \ - nsec.h peer.h portlist.h rbt.h rcode.h \ + dnssec.h ds.h events.h fixedname.h iptable.h journal.h \ + keyflags.h keytable.h keyvalues.h lib.h log.h \ + master.h masterdump.h message.h name.h ncache.h nsec.h \ + peer.h portlist.h private.h rbt.h rcode.h \ rdata.h rdataclass.h rdatalist.h rdataset.h rdatasetiter.h \ rdataslab.h rdatatype.h request.h resolver.h result.h \ rootns.h sdb.h sdlz.h secalg.h secproto.h soa.h ssu.h \ - tcpmsg.h time.h tkey.h \ - tsig.h ttl.h types.h validator.h version.h view.h xfrin.h \ - zone.h zonekey.h zt.h + tcpmsg.h time.h tkey.h tsig.h ttl.h types.h \ + validator.h version.h view.h xfrin.h zone.h zonekey.h zt.h GENHEADERS = enumclass.h enumtype.h rdatastruct.h diff --git a/lib/dns/include/dns/acl.h b/lib/dns/include/dns/acl.h index 1045cd2..04f5577 100644 --- a/lib/dns/include/dns/acl.h +++ b/lib/dns/include/dns/acl.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: acl.h,v 1.31.206.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: acl.h,v 1.33 2009-01-17 23:47:43 tbox Exp $ */ #ifndef DNS_ACL_H #define DNS_ACL_H 1 diff --git a/lib/dns/include/dns/cache.h b/lib/dns/include/dns/cache.h index 94077d6..e4ea5f4 100644 --- a/lib/dns/include/dns/cache.h +++ b/lib/dns/include/dns/cache.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: cache.h,v 1.26 2007-06-19 23:47:16 tbox Exp $ */ +/* $Id: cache.h,v 1.28 2009-01-09 23:47:46 tbox Exp $ */ #ifndef DNS_CACHE_H #define DNS_CACHE_H 1 @@ -65,8 +65,15 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr, dns_rdataclass_t rdclass, const char *db_type, unsigned int db_argc, char **db_argv, dns_cache_t **cachep); +isc_result_t +dns_cache_create2(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, + isc_timermgr_t *timermgr, dns_rdataclass_t rdclass, + const char *cachename, const char *db_type, + unsigned int db_argc, char **db_argv, dns_cache_t **cachep); /*%< - * Create a new DNS cache. + * Create a new DNS cache. dns_cache_create2() will create a named cache. + * dns_cache_create() is a backward compatible version that internally specifies + * an empty name. * * Requires: * @@ -76,6 +83,8 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, * manager, or both are NULL. If NULL, no periodic cleaning of the * cache will take place. * + *\li 'cachename' is a valid string. This must not be NULL. + * *\li 'cachep' is a valid pointer, and *cachep == NULL * * Ensures: @@ -217,12 +226,36 @@ dns_cache_setcleaninginterval(dns_cache_t *cache, unsigned int interval); * Set the periodic cache cleaning interval to 'interval' seconds. */ +unsigned int +dns_cache_getcleaninginterval(dns_cache_t *cache); +/*%< + * Get the periodic cache cleaning interval to 'interval' seconds. + */ + +isc_uint32_t +dns_cache_getcachesize(dns_cache_t *cache); +/*%< + * Get the maximum cache size. + */ + +const char * +dns_cache_getname(dns_cache_t *cache); +/*%< + * Get the cache name. + */ + void dns_cache_setcachesize(dns_cache_t *cache, isc_uint32_t size); /*%< * Set the maximum cache size. 0 means unlimited. */ +isc_uint32_t +dns_cache_getcachesize(dns_cache_t *cache); +/*%< + * Get the maximum cache size. + */ + isc_result_t dns_cache_flush(dns_cache_t *cache); /*%< diff --git a/lib/dns/include/dns/client.h b/lib/dns/include/dns/client.h new file mode 100644 index 0000000..13cdf8f --- /dev/null +++ b/lib/dns/include/dns/client.h @@ -0,0 +1,621 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: client.h,v 1.3 2009-09-02 23:48:02 tbox Exp $ */ + +#ifndef DNS_CLIENT_H +#define DNS_CLIENT_H 1 + +/***** + ***** Module Info + *****/ + +/*! \file + * + * \brief + * The DNS client module provides convenient programming interfaces to various + * DNS services, such as name resolution with or without DNSSEC validation or + * dynamic DNS update. This module is primarily expected to be used by other + * applications than BIND9-related ones that need such advanced DNS features. + * + * MP: + *\li In the typical usage of this module, application threads will not share + * the same data structures created and manipulated in this module. + * However, the module still ensures appropriate synchronization of such + * data structures. + * + * Resources: + *\li TBS + * + * Security: + *\li This module does not handle any low-level data directly, and so no + * security issue specific to this module is anticipated. + */ + +#include +#include + +#include +#include + +#include + +typedef enum { + updateop_none = 0, + updateop_add = 1, + updateop_delete = 2, + updateop_exist = 3, + updateop_notexist = 4, + updateop_max = 5 +} dns_client_updateop_t; + +ISC_LANG_BEGINDECLS + +/*** + *** Types + ***/ + +/*% + * Optional flags for dns_client_create(x). + */ +/*%< Enable caching resolution results (experimental). */ +#define DNS_CLIENTCREATEOPT_USECACHE 0x8000 + +/*% + * Optional flags for dns_client_(start)resolve. + */ +/*%< Disable DNSSEC validation. */ +#define DNS_CLIENTRESOPT_NODNSSEC 0x01 +/*%< Allow running external context. */ +#define DNS_CLIENTRESOPT_ALLOWRUN 0x02 + +/*% + * Optional flags for dns_client_(start)request. + */ +/*%< Allow running external context. */ +#define DNS_CLIENTREQOPT_ALLOWRUN 0x01 + +/*% + * A dns_clientresevent_t is sent when name resolution performed by a client + * completes. 'result' stores the result code of the entire resolution + * procedure. 'vresult' specifically stores the result code of DNSSEC + * validation if it is performed. When name resolution successfully completes, + * 'answerlist' is typically non empty, containing answer names along with + * RRsets. It is the receiver's responsibility to free this list by calling + * dns_client_freeresanswer() before freeing the event structure. + */ +typedef struct dns_clientresevent { + ISC_EVENT_COMMON(struct dns_clientresevent); + isc_result_t result; + isc_result_t vresult; + dns_namelist_t answerlist; +} dns_clientresevent_t; /* too long? */ + +/*% + * Status of a dynamic update procedure. + */ +typedef enum { + dns_clientupdatestate_prepare, /*%< no updates have been sent */ + dns_clientupdatestate_sent, /*%< updates were sent, no response */ + dns_clientupdatestate_done /*%< update was sent and succeeded */ +} dns_clientupdatestate_t; + +/*% + * A dns_clientreqevent_t is sent when a DNS request is completed by a client. + * 'result' stores the result code of the entire transaction. + * If the transaction is successfully completed but the response packet cannot + * be parsed, 'result' will store the result code of dns_message_parse(). + * If the response packet is received, 'rmessage' will contain the response + * message, whether it is successfully parsed or not. + */ +typedef struct dns_clientreqevent { + ISC_EVENT_COMMON(struct dns_clientreqevent); + isc_result_t result; + dns_message_t *rmessage; +} dns_clientreqevent_t; /* too long? */ + +/*% + * A dns_clientupdateevent_t is sent when dynamic update performed by a client + * completes. 'result' stores the result code of the entire update procedure. + * 'state' specifies the status of the update procedure when this event is + * sent. This can be used as a hint by the receiver to determine whether + * the update attempt was ever made. In particular, if the state is + * dns_clientupdatestate_prepare, the receiver can be sure that the requested + * update was not applied. + */ +typedef struct dns_clientupdateevent { + ISC_EVENT_COMMON(struct dns_clientupdateevent); + isc_result_t result; + dns_clientupdatestate_t state; +} dns_clientupdateevent_t; /* too long? */ + +isc_result_t +dns_client_create(dns_client_t **clientp, unsigned int options); + +isc_result_t +dns_client_createx(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr, + isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr, + unsigned int options, dns_client_t **clientp); +/*%< + * Create a DNS client. These functions create a new client object with + * minimal internal resources such as the default 'view' for the IN class and + * IPv4/IPv6 dispatches for the view. + * + * dns_client_createx() takes 'manager' arguments so that the caller can + * control the behavior of the client through the underlying event framework. + * On the other hand, dns_client_create() simplifies the interface and creates + * the managers internally. A DNS client object created via + * dns_client_create() is expected to be used by an application that only needs + * simple synchronous services or by a thread-based application. + * + * If the DNS_CLIENTCREATEOPT_USECACHE flag is set in 'options', + * dns_client_create(x) will create a cache database with the view. + * + * Requires: + * + *\li 'mctx' is a valid memory context. + * + *\li 'actx' is a valid application context. + * + *\li 'taskmgr' is a valid task manager. + * + *\li 'socketmgr' is a valid socket manager. + * + *\li 'timermgr' is a valid timer manager. + * + *\li clientp != NULL && *clientp == NULL. + * + * Returns: + * + *\li #ISC_R_SUCCESS On success. + * + *\li Anything else Failure. + */ + +void +dns_client_destroy(dns_client_t **clientp); +/*%< + * Destroy 'client'. + * + * Requires: + * + *\li '*clientp' is a valid client. + * + * Ensures: + * + *\li *clientp == NULL. + */ + +isc_result_t +dns_client_setservers(dns_client_t *client, dns_rdataclass_t rdclass, + dns_name_t *namespace, isc_sockaddrlist_t *addrs); +/*%< + * Specify a list of addresses of recursive name servers that the client will + * use for name resolution. A view for the 'rdclass' class must be created + * beforehand. If 'namespace' is non NULL, the specified server will be used + * if and only if the query name is a subdomain of 'namespace'. When servers + * for multiple 'namespace's are provided, and a query name is covered by + * more than one 'namespace', the servers for the best (longest) matching + * namespace will be used. If 'namespace' is NULL, it works as if + * dns_rootname (.) were specified. + * + * Requires: + * + *\li 'client' is a valid client. + * + *\li 'namespace' is NULL or a valid name. + * + *\li 'addrs' != NULL. + * + * Returns: + * + *\li #ISC_R_SUCCESS On success. + * + *\li Anything else Failure. + */ + +isc_result_t +dns_client_clearservers(dns_client_t *client, dns_rdataclass_t rdclass, + dns_name_t *namespace); +/*%< + * Remove configured recursive name servers for the 'rdclass' and 'namespace' + * from the client. See the description of dns_client_setservers() for + * the requirements about 'rdclass' and 'namespace'. + * + * Requires: + * + *\li 'client' is a valid client. + * + *\li 'namespace' is NULL or a valid name. + * + * Returns: + * + *\li #ISC_R_SUCCESS On success. + * + *\li Anything else Failure. + */ + +isc_result_t +dns_client_resolve(dns_client_t *client, dns_name_t *name, + dns_rdataclass_t rdclass, dns_rdatatype_t type, + unsigned int options, dns_namelist_t *namelist); + +isc_result_t +dns_client_startresolve(dns_client_t *client, dns_name_t *name, + dns_rdataclass_t rdclass, dns_rdatatype_t type, + unsigned int options, isc_task_t *task, + isc_taskaction_t action, void *arg, + dns_clientrestrans_t **transp); +/*%< + * Perform name resolution for 'name', 'rdclass', and 'type'. + * + * If any trusted keys are configured and the query name is considered to + * belong to a secure zone, these functions also validate the responses + * using DNSSEC by default. If the DNS_CLIENTRESOPT_NODNSSEC flag is set + * in 'options', DNSSEC validation is disabled regardless of the configured + * trusted keys or the query name. + * + * dns_client_resolve() provides a synchronous service. This function starts + * name resolution internally and blocks until it completes. On success, + * 'namelist' will contain a list of answer names, each of which has + * corresponding RRsets. The caller must provide a valid empty list, and + * is responsible for freeing the list content via dns_client_freeresanswer(). + * If the name resolution fails due to an error in DNSSEC validation, + * dns_client_resolve() returns the result code indicating the validation + * error. Otherwise, it returns the result code of the entire resolution + * process, either success or failure. + * + * It is typically expected that the client object passed to + * dns_client_resolve() was created via dns_client_create() and has its own + * managers and contexts. However, if the DNS_CLIENTRESOPT_ALLOWRUN flag is + * set in 'options', this function performs the synchronous service even if + * it does not have its own manager and context structures. + * + * dns_client_startresolve() is an asynchronous version of dns_client_resolve() + * and does not block. When name resolution is completed, 'action' will be + * called with the argument of a 'dns_clientresevent_t' object, which contains + * the resulting list of answer names (on success). On return, '*transp' is + * set to an opaque transaction ID so that the caller can cancel this + * resolution process. + * + * Requires: + * + *\li 'client' is a valid client. + * + *\li 'addrs' != NULL. + * + *\li 'name' is a valid name. + * + *\li 'namelist' != NULL and is not empty. + * + *\li 'task' is a valid task. + * + *\li 'transp' != NULL && *transp == NULL; + * + * Returns: + * + *\li #ISC_R_SUCCESS On success. + * + *\li Anything else Failure. + */ + +void +dns_client_cancelresolve(dns_clientrestrans_t *trans); +/*%< + * Cancel an ongoing resolution procedure started via + * dns_client_startresolve(). + * + * Notes: + * + *\li If the resolution procedure has not completed, post its CLIENTRESDONE + * event with a result code of #ISC_R_CANCELED. + * + * Requires: + * + *\li 'trans' is a valid transaction ID. + */ + +void +dns_client_destroyrestrans(dns_clientrestrans_t **transp); +/*%< + * Destroy name resolution transaction state identified by '*transp'. + * + * Requires: + * + *\li '*transp' is a valid transaction ID. + * + *\li The caller has received the CLIENTRESDONE event (either because the + * resolution completed or because dns_client_cancelresolve() was called). + * + * Ensures: + * + *\li *transp == NULL. + */ + +void +dns_client_freeresanswer(dns_client_t *client, dns_namelist_t *namelist); +/*%< + * Free resources allocated for the content of 'namelist'. + * + * Requires: + * + *\li 'client' is a valid client. + * + *\li 'namelist' != NULL. + */ + +isc_result_t +dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass, + dns_name_t *keyname, isc_buffer_t *keydatabuf); +/*%< + * Add a DNSSEC trusted key for the 'rdclass' class. A view for the 'rdclass' + * class must be created beforehand. 'keyname' is the DNS name of the key, + * and 'keydatabuf' stores the resource data of the key. + * + * Requires: + * + *\li 'client' is a valid client. + * + *\li 'keyname' is a valid name. + * + *\li 'keydatabuf' is a valid buffer. + * + * Returns: + * + *\li #ISC_R_SUCCESS On success. + * + *\li Anything else Failure. + */ + +isc_result_t +dns_client_request(dns_client_t *client, dns_message_t *qmessage, + dns_message_t *rmessage, isc_sockaddr_t *server, + unsigned int options, unsigned int parseoptions, + dns_tsec_t *tsec, unsigned int timeout, + unsigned int udptimeout, unsigned int udpretries); + +isc_result_t +dns_client_startrequest(dns_client_t *client, dns_message_t *qmessage, + dns_message_t *rmessage, isc_sockaddr_t *server, + unsigned int options, unsigned int parseoptions, + dns_tsec_t *tsec, unsigned int timeout, + unsigned int udptimeout, unsigned int udpretries, + isc_task_t *task, isc_taskaction_t action, void *arg, + dns_clientreqtrans_t **transp); + +/*%< + * Send a DNS request containig a query message 'query' to 'server'. + * + * 'parseoptions' will be used when the response packet is parsed, and will be + * passed to dns_message_parse() via dns_request_getresponse(). See + * dns_message_parse() for more details. + * + * 'tsec' is a transaction security object containing, e.g. a TSIG key for + * authenticating the request/response transaction. This is optional and can + * be NULL, in which case this library performs the transaction without any + * transaction authentication. + * + * 'timeout', 'udptimeout', and 'udpretries' are passed to + * dns_request_createvia3(). See dns_request_createvia3() for more details. + * + * dns_client_request() provides a synchronous service. This function sends + * the request and blocks until a response is received. On success, + * 'rmessage' will contain the response message. The caller must provide a + * valid initialized message. + * + * It is usually expected that the client object passed to + * dns_client_request() was created via dns_client_create() and has its own + * managers and contexts. However, if the DNS_CLIENTREQOPT_ALLOWRUN flag is + * set in 'options', this function performs the synchronous service even if + * it does not have its own manager and context structures. + * + * dns_client_startrequest() is an asynchronous version of dns_client_request() + * and does not block. When the transaction is completed, 'action' will be + * called with the argument of a 'dns_clientreqevent_t' object, which contains + * the response message (on success). On return, '*transp' is set to an opaque + * transaction ID so that the caller can cancel this request. + * + * Requires: + * + *\li 'client' is a valid client. + * + *\li 'qmessage' and 'rmessage' are valid initialized message. + * + *\li 'server' is a valid socket address structure. + * + *\li 'task' is a valid task. + * + *\li 'transp' != NULL && *transp == NULL; + * + * Returns: + * + *\li #ISC_R_SUCCESS On success. + * + *\li Anything else Failure. + * + *\li Any result that dns_message_parse() can return. + */ + +void +dns_client_cancelrequest(dns_clientreqtrans_t *transp); +/*%< + * Cancel an ongoing DNS request procedure started via + * dns_client_startrequest(). + * + * Notes: + * + *\li If the request procedure has not completed, post its CLIENTREQDONE + * event with a result code of #ISC_R_CANCELED. + * + * Requires: + * + *\li 'trans' is a valid transaction ID. + */ + +void +dns_client_destroyreqtrans(dns_clientreqtrans_t **transp); +/*% + * Destroy DNS request transaction state identified by '*transp'. + * + * Requires: + * + *\li '*transp' is a valid transaction ID. + * + *\li The caller has received the CLIENTREQDONE event (either because the + * request completed or because dns_client_cancelrequest() was called). + * + * Ensures: + * + *\li *transp == NULL. + */ + +isc_result_t +dns_client_update(dns_client_t *client, dns_rdataclass_t rdclass, + dns_name_t *zonename, dns_namelist_t *prerequisites, + dns_namelist_t *updates, isc_sockaddrlist_t *servers, + dns_tsec_t *tsec, unsigned int options); + +isc_result_t +dns_client_startupdate(dns_client_t *client, dns_rdataclass_t rdclass, + dns_name_t *zonename, dns_namelist_t *prerequisites, + dns_namelist_t *updates, isc_sockaddrlist_t *servers, + dns_tsec_t *tsec, unsigned int options, + isc_task_t *task, isc_taskaction_t action, void *arg, + dns_clientupdatetrans_t **transp); +/*%< + * Perform DNS dynamic update for 'updates' of the 'rdclass' class with + * optional 'prerequisites'. + * + * 'updates' are a list of names with associated RRsets to be updated. + * + * 'prerequisites' are a list of names with associated RRsets corresponding to + * the prerequisites of the updates. This is optional and can be NULL, in + * which case the prerequisite section of the update message will be empty. + * + * Both 'updates' and 'prerequisites' must be constructed as specified in + * RFC2136. + * + * 'zonename' is the name of the zone in which the updated names exist. + * This is optional and can be NULL. In this case, these functions internally + * identify the appropriate zone through some queries for the SOA RR starting + * with the first name in prerequisites or updates. + * + * 'servers' is a list of authoritative servers to which the update message + * should be sent. This is optional and can be NULL. In this case, these + * functions internally identify the appropriate primary server name and its + * addresses through some queries for the SOA RR (like the case of zonename) + * and supplemental A/AAAA queries for the server name. + * Note: The client module generally assumes the given addresses are of the + * primary server of the corresponding zone. It will work even if a secondary + * server address is specified as long as the server allows update forwarding, + * it is generally discouraged to include secondary server addresses unless + * there's strong reason to do so. + * + * 'tsec' is a transaction security object containing, e.g. a TSIG key for + * authenticating the update transaction (and the supplemental query/response + * transactions if the server is specified). This is optional and can be + * NULL, in which case the library tries the update without any transaction + * authentication. + * + * dns_client_update() provides a synchronous service. This function blocks + * until the entire update procedure completes, including the additional + * queries when necessary. + * + * dns_client_startupdate() is an asynchronous version of dns_client_update(). + * It immediately returns (typically with *transp being set to a non-NULL + * pointer), and performs the update procedure through a set of internal + * events. All transactions including the additional query exchanges are + * performed as a separate event, so none of these events cause blocking + * operation. When the update procedure completes, the specified function + * 'action' will be called with the argument of a 'dns_clientupdateevent_t' + * structure. On return, '*transp' is set to an opaque transaction ID so that + * the caller can cancel this update process. + * + * Notes: + *\li No options are currently defined. + * + * Requires: + * + *\li 'client' is a valid client. + * + *\li 'updates' != NULL. + * + *\li 'task' is a valid task. + * + *\li 'transp' != NULL && *transp == NULL; + * + * Returns: + * + *\li #ISC_R_SUCCESS On success. + * + *\li Anything else Failure. + */ + +void +dns_client_cancelupdate(dns_clientupdatetrans_t *trans); +/*%< + * Cancel an ongoing dynamic update procedure started via + * dns_client_startupdate(). + * + * Notes: + * + *\li If the update procedure has not completed, post its UPDATEDONE + * event with a result code of #ISC_R_CANCELED. + * + * Requires: + * + *\li 'trans' is a valid transaction ID. + */ + +void +dns_client_destroyupdatetrans(dns_clientupdatetrans_t **transp); +/*%< + * Destroy dynamic update transaction identified by '*transp'. + * + * Requires: + * + *\li '*transp' is a valid transaction ID. + * + *\li The caller has received the UPDATEDONE event (either because the + * update completed or because dns_client_cancelupdate() was called). + * + * Ensures: + * + *\li *transp == NULL. + */ + +isc_result_t +dns_client_updaterec(dns_client_updateop_t op, dns_name_t *owner, + dns_rdatatype_t type, dns_rdata_t *source, + dns_ttl_t ttl, dns_name_t *target, + dns_rdataset_t *rdataset, dns_rdatalist_t *rdatalist, + dns_rdata_t *rdata, isc_mem_t *mctx); +/*%< + * TBD + */ + +void +dns_client_freeupdate(dns_name_t **namep); +/*%< + * TBD + */ + +isc_mem_t * +dns_client_mctx(dns_client_t *client); + +ISC_LANG_ENDDECLS + +#endif /* DNS_CLIENT_H */ diff --git a/lib/dns/include/dns/compress.h b/lib/dns/include/dns/compress.h index 4181c77..ebe543b 100644 --- a/lib/dns/include/dns/compress.h +++ b/lib/dns/include/dns/compress.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: compress.h,v 1.40.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: compress.h,v 1.42 2009-01-17 23:47:43 tbox Exp $ */ #ifndef DNS_COMPRESS_H #define DNS_COMPRESS_H 1 diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h index f622834..edb1263 100644 --- a/lib/dns/include/dns/db.h +++ b/lib/dns/include/dns/db.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: db.h,v 1.93.50.5 2009-11-25 23:48:42 tbox Exp $ */ +/* $Id: db.h,v 1.104 2011-01-13 04:59:25 tbox Exp $ */ #ifndef DNS_DB_H #define DNS_DB_H 1 @@ -59,7 +59,11 @@ #include #include +#include #include +#include +#include +#include #include ISC_LANG_BEGINDECLS @@ -167,6 +171,13 @@ typedef struct dns_dbmethods { dns_dbversion_t *version); isc_boolean_t (*isdnssec)(dns_db_t *db); dns_stats_t *(*getrrsetstats)(dns_db_t *db); + void (*rpz_enabled)(dns_db_t *db, dns_rpz_st_t *st); + isc_result_t (*rpz_findips)(dns_rpz_zone_t *rpz, + dns_rpz_type_t rpz_type, + dns_zone_t *zone, dns_db_t *db, + dns_dbversion_t *version, + dns_rdataset_t *ardataset, + dns_rpz_st_t *st); } dns_dbmethods_t; typedef isc_result_t @@ -491,6 +502,10 @@ dns_db_load(dns_db_t *db, const char *filename); isc_result_t dns_db_load2(dns_db_t *db, const char *filename, dns_masterformat_t format); + +isc_result_t +dns_db_load3(dns_db_t *db, const char *filename, dns_masterformat_t format, + unsigned int options); /*%< * Load master file 'filename' into 'db'. * @@ -614,7 +629,7 @@ dns_db_closeversion(dns_db_t *db, dns_dbversion_t **versionp, * * Note: if '*versionp' is a read-write version and 'commit' is ISC_TRUE, * then all changes made in the version will take effect, otherwise they - * will be rolled back. The value if 'commit' is ignored for read-only + * will be rolled back. The value of 'commit' is ignored for read-only * versions. * * Requires: @@ -841,6 +856,9 @@ dns_db_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, * \li #DNS_R_COVERINGNSEC The returned data is a NSEC * that potentially covers 'name'. * + * \li #DNS_R_EMPTYWILD The name is a wildcard without + * resource records. + * * Error results: * * \li #ISC_R_NOMEMORY @@ -1477,6 +1495,31 @@ dns_db_getrrsetstats(dns_db_t *db); * dns_rdatasetstats_create(); otherwise NULL. */ +void +dns_db_rpz_enabled(dns_db_t *db, dns_rpz_st_t *st); +/*%< + * See if a policy database has DNS_RPZ_TYPE_IP, DNS_RPZ_TYPE_NSIP, or + * DNS_RPZ_TYPE_NSDNAME records. + */ + +isc_result_t +dns_db_rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, + dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version, + dns_rdataset_t *ardataset, dns_rpz_st_t *st); +/*%< + * Search the CDIR block tree of a response policy tree of trees for the best + * match to any of the IP addresses in an A or AAAA rdataset. + * + * Requires: + * \li search in policy zone 'rpz' for a match of 'rpz_type' either + * DNS_RPZ_TYPE_IP or DNS_RPZ_TYPE_NSIP + * \li 'zone' and 'db' are the database corresponding to 'rpz' + * \li 'version' is the required version of the database + * \li 'ardataset' is an A or AAAA rdataset of addresses to check + * \li 'found' specifies the previous best match if any or + * or NULL, an empty name, 0, DNS_RPZ_POLICY_MISS, and 0 + */ + ISC_LANG_ENDDECLS #endif /* DNS_DB_H */ diff --git a/lib/dns/include/dns/diff.h b/lib/dns/include/dns/diff.h index f5e25ee..b6c929f 100644 --- a/lib/dns/include/dns/diff.h +++ b/lib/dns/include/dns/diff.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: diff.h,v 1.15.120.4 2010-06-04 23:48:25 tbox Exp $ */ +/* $Id: diff.h,v 1.19 2010-06-04 23:51:14 tbox Exp $ */ #ifndef DNS_DIFF_H #define DNS_DIFF_H 1 diff --git a/lib/dns/include/dns/dispatch.h b/lib/dns/include/dns/dispatch.h index 6e2f3e1..3d252a1 100644 --- a/lib/dns/include/dns/dispatch.h +++ b/lib/dns/include/dns/dispatch.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dispatch.h,v 1.60.82.2 2009-01-29 23:47:44 tbox Exp $ */ +/* $Id: dispatch.h,v 1.62 2009-01-27 23:47:54 tbox Exp $ */ #ifndef DNS_DISPATCH_H #define DNS_DISPATCH_H 1 diff --git a/lib/dns/include/dns/dlz.h b/lib/dns/include/dns/dlz.h index 28a24a9..e04b1b1 100644 --- a/lib/dns/include/dns/dlz.h +++ b/lib/dns/include/dns/dlz.h @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2005-2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2005-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -50,7 +50,7 @@ * USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dlz.h,v 1.7.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: dlz.h,v 1.12 2010-12-20 23:47:21 tbox Exp $ */ /*! \file dns/dlz.h */ @@ -87,6 +87,7 @@ #include #include #include +#include #include @@ -166,12 +167,37 @@ typedef isc_result_t * return a result code indicating the type of error. */ + +typedef isc_result_t +(*dns_dlzconfigure_t)(void *driverarg, void *dbdata, dns_view_t *view); +/*%< + * Method prototype. Drivers implementing the DLZ interface may + * optionally supply a configure method. If supplied, this will be + * called immediately after the create method is called. The driver + * may call configuration functions during the configure call + */ + + +typedef isc_boolean_t (*dns_dlzssumatch_t)(dns_name_t *signer, + dns_name_t *name, + isc_netaddr_t *tcpaddr, + dns_rdatatype_t type, + const dst_key_t *key, + void *driverarg, void *dbdata); +/*%< + * Method prototype. Drivers implementing the DLZ interface may + * optionally supply a ssumatch method. If supplied, this will be + * called to authorize update requests + */ + /*% the methods supplied by a DLZ driver */ typedef struct dns_dlzmethods { dns_dlzcreate_t create; dns_dlzdestroy_t destroy; dns_dlzfindzone_t findzone; dns_dlzallowzonexfr_t allowzonexfr; + dns_dlzconfigure_t configure; + dns_dlzssumatch_t ssumatch; } dns_dlzmethods_t; /*% information about a DLZ driver */ @@ -183,12 +209,18 @@ struct dns_dlzimplementation { ISC_LINK(dns_dlzimplementation_t) link; }; -/*% an instance of a DLZ driver */ +typedef isc_result_t (*dlzconfigure_callback_t)(dns_view_t *, dns_zone_t *); + +/*% An instance of a DLZ driver */ struct dns_dlzdb { unsigned int magic; isc_mem_t *mctx; dns_dlzimplementation_t *implementation; void *dbdata; + dlzconfigure_callback_t configure_callback; +#ifdef BIND9 + dns_ssutable_t *ssutable; +#endif }; @@ -285,6 +317,30 @@ dns_dlzunregister(dns_dlzimplementation_t **dlzimp); * is called. */ + +isc_result_t +dns_dlz_writeablezone(dns_view_t *view, const char *zone_name); + +/*%< + * creates a writeable DLZ zone. Must be called from within the + * configure() method of a DLZ driver. + */ + + +isc_result_t +dns_dlzconfigure(dns_view_t *view, dlzconfigure_callback_t callback); +/*%< + * call a DLZ drivers configure method, if supplied + */ + +isc_boolean_t +dns_dlz_ssumatch(dns_dlzdb_t *dlzdatabase, + dns_name_t *signer, dns_name_t *name, isc_netaddr_t *tcpaddr, + dns_rdatatype_t type, const dst_key_t *key); +/*%< + * call a DLZ drivers ssumatch method, if supplied. Otherwise return ISC_FALSE + */ + ISC_LANG_ENDDECLS #endif /* DLZ_H */ diff --git a/lib/dns/include/dns/dns64.h b/lib/dns/include/dns/dns64.h new file mode 100644 index 0000000..5fd32e8 --- /dev/null +++ b/lib/dns/include/dns/dns64.h @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: dns64.h,v 1.3 2010-12-08 23:51:56 tbox Exp $ */ + +#ifndef DNS_DNS64_H +#define DNS_DNS64_H 1 + +#include + +#include + +ISC_LANG_BEGINDECLS + +/* + * dns_dns64_create() flags. + */ +#define DNS_DNS64_RECURSIVE_ONLY 0x01 /* If set then this record + * only applies to recursive + * queries. + */ +#define DNS_DNS64_BREAK_DNSSEC 0x02 /* If set then still perform + * DNSSEC synthesis even + * though the result would + * fail validation. + */ + +/* + * dns_dns64_aaaaok() and dns_dns64_aaaafroma() flags. + */ +#define DNS_DNS64_RECURSIVE 0x01 /* Recursive query. */ +#define DNS_DNS64_DNSSEC 0x02 /* DNSSEC sensitive query. */ + +isc_result_t +dns_dns64_create(isc_mem_t *mctx, isc_netaddr_t *prefix, + unsigned int prefixlen, isc_netaddr_t *suffix, + dns_acl_t *client, dns_acl_t *mapped, dns_acl_t *excluded, + unsigned int flags, dns_dns64_t **dns64); +/* + * Create a dns64 record which is used to identify the set of clients + * it applies to and how to perform the DNS64 synthesis. + * + * 'prefix' and 'prefixlen' defined the leading bits of the AAAA records + * to be synthesised. 'suffix' defines the bits after the A records bits. + * If suffix is NULL zeros will be used for these bits. 'client' defines + * for which clients this record applies. If 'client' is NULL then all + * clients apply. 'mapped' defines which A records are candidated for + * mapping. If 'mapped' is NULL then all A records will be mapped. + * 'excluded' defines which AAAA are to be treated as non-existent for the + * purposed of determining whether to perform syntesis. If 'excluded' is + * NULL then no AAAA records prevent synthesis. + * + * If DNS_DNS64_RECURSIVE_ONLY is set then the record will only match if + * DNS_DNS64_RECURSIVE is set when calling dns_dns64_aaaaok() and + * dns_dns64_aaaafroma(). + * + * If DNS_DNS64_BREAK_DNSSEC is set then the record will still apply if + * DNS_DNS64_DNSSEC is set when calling dns_dns64_aaaaok() and + * dns_dns64_aaaafroma() otherwise the record will be ignored. + * + * Requires: + * 'mctx' to be valid. + * 'prefix' to be valid and the address family to AF_INET6. + * 'prefixlen' to be one of 32, 40, 48, 56, 72 and 96. + * the bits not covered by prefixlen in prefix to + * be zero. + * 'suffix' to be NULL or the address family be set to AF_INET6 + * and the leading 'prefixlen' + 32 bits of the 'suffix' + * to be zero. If 'prefixlen' is 40, 48 or 56 then the + * the leading 'prefixlen' + 40 bits of 'suffix' must be + * zero. + * 'client' to be NULL or a valid acl. + * 'mapped' to be NULL or a valid acl. + * 'exculded' to be NULL or a valid acl. + * + * Returns: + * ISC_R_SUCCESS + * ISC_R_NOMEMORY + */ + +void +dns_dns64_destroy(dns_dns64_t **dns64p); +/* + * Destroys a dns64 record. + * + * Requires the record to not be linked. + */ + +isc_result_t +dns_dns64_aaaafroma(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr, + const dns_name_t *reqsigner, const dns_aclenv_t *env, + unsigned int flags, unsigned char *a, unsigned char *aaaa); +/* + * dns_dns64_aaaafroma() determines whether to perform a DNS64 address + * synthesis from 'a' based on 'dns64', 'reqaddr', 'reqsigner', 'env', + * 'flags' and 'aaaa'. If synthesis is performed then the result is + * written to '*aaaa'. + * + * The synthesised address will be of the form: + * + * + * + * If straddle bits 64-71 of the AAAA record, then 8 zero bits will + * be inserted at bits 64-71. + * + * Requires: + * 'dns64' to be valid. + * 'reqaddr' to be valid. + * 'reqsigner' to be NULL or valid. + * 'env' to be valid. + * 'a' to point to a IPv4 address in network order. + * 'aaaa' to point to a IPv6 address buffer in network order. + * + * Returns: + * ISC_R_SUCCESS if synthesis was performed. + * DNS_R_DISALLOWED if there is no match. + */ + +dns_dns64_t * +dns_dns64_next(dns_dns64_t *dns64); +/* + * Return the next dns64 record in the list. + */ + +void +dns_dns64_append(dns_dns64list_t *list, dns_dns64_t *dns64); +/* + * Append the dns64 record to the list. + */ + +void +dns_dns64_unlink(dns_dns64list_t *list, dns_dns64_t *dns64); +/* + * Unlink the dns64 record from the list. + */ + +isc_boolean_t +dns_dns64_aaaaok(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr, + const dns_name_t *reqsigner, const dns_aclenv_t *env, + unsigned int flags, dns_rdataset_t *rdataset, + isc_boolean_t *aaaaok, size_t aaaaoklen); +/* + * Determine if there are any non-excluded AAAA records in from the + * matching dns64 records in the list starting at 'dns64'. If there + * is a non-exluded address return ISC_TRUE. If all addresses are + * excluded in the matched records return ISC_FALSE. If no records + * match then return ISC_TRUE. + * + * If aaaaok is defined then dns_dns64_aaaaok() return a array of which + * addresses in 'rdataset' were deemed to not be exclude by any matching + * record. If there are no matching records then all entries are set + * to ISC_TRUE. + * + * Requires + * 'rdataset' to be valid and to be for type AAAA and class IN. + * 'aaaaoklen' must match the number of records in 'rdataset' + * if 'aaaaok' in non NULL. + */ + +ISC_LANG_ENDDECLS + +#endif /* DNS_DNS64_H */ diff --git a/lib/dns/include/dns/dnssec.h b/lib/dns/include/dns/dnssec.h index 5a1468a..c6d910b 100644 --- a/lib/dns/include/dns/dnssec.h +++ b/lib/dns/include/dns/dnssec.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec.h,v 1.32.332.6 2009-06-22 23:47:18 tbox Exp $ */ +/* $Id: dnssec.h,v 1.42 2010-01-09 23:48:45 tbox Exp $ */ #ifndef DNS_DNSSEC_H #define DNS_DNSSEC_H 1 @@ -25,12 +25,48 @@ #include #include +#include #include #include ISC_LANG_BEGINDECLS +/* + * Indicates how the signer found this key: in the key repository, at the + * zone apex, or specified by the user. + */ +typedef enum { + dns_keysource_unknown, + dns_keysource_repository, + dns_keysource_zoneapex, + dns_keysource_user +} dns_keysource_t; + +/* + * A DNSSEC key and hints about its intended use gleaned from metadata + */ +struct dns_dnsseckey { + dst_key_t *key; + isc_boolean_t hint_publish; /*% metadata says to publish */ + isc_boolean_t force_publish; /*% publish regardless of metadata */ + isc_boolean_t hint_sign; /*% metadata says to sign with this key */ + isc_boolean_t force_sign; /*% sign with key regardless of metadata */ + isc_boolean_t hint_remove; /*% metadata says *don't* publish */ + isc_boolean_t is_active; /*% key is already active */ + isc_boolean_t first_sign; /*% key is newly becoming active */ + unsigned int prepublish; /*% how long until active? */ + dns_keysource_t source; /*% how the key was found */ + isc_boolean_t ksk; /*% this is a key-signing key */ + isc_boolean_t legacy; /*% this is old-style key with no + metadata (possibly generated by + an older version of BIND9) and + should be ignored when searching + for keys to import into the zone */ + unsigned int index; /*% position in list */ + ISC_LINK(dns_dnsseckey_t) link; +}; + isc_result_t dns_dnssec_keyfromrdata(dns_name_t *name, dns_rdata_t *rdata, isc_mem_t *mctx, dst_key_t **key); @@ -184,6 +220,103 @@ dns_dnssec_selfsigns(dns_rdata_t *rdata, dns_name_t *name, isc_boolean_t ignoretime, isc_mem_t *mctx); +isc_result_t +dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey, + dns_dnsseckey_t **dkp); +/*%< + * Create and initialize a dns_dnsseckey_t structure. + * + * Requires: + *\li 'dkp' is not NULL and '*dkp' is NULL. + * + * Returns: + *\li #ISC_R_SUCCESS + *\li #ISC_R_NOMEMORY + */ + +void +dns_dnsseckey_destroy(isc_mem_t *mctx, dns_dnsseckey_t **dkp); +/*%< + * Reclaim a dns_dnsseckey_t structure. + * + * Requires: + *\li 'dkp' is not NULL and '*dkp' is not NULL. + * + * Ensures: + *\li '*dkp' is NULL. + */ + +isc_result_t +dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory, + isc_mem_t *mctx, dns_dnsseckeylist_t *keylist); +/*%< + * Search 'directory' for K* key files matching the name in 'origin'. + * Append all such keys, along with use hints gleaned from their + * metadata, onto 'keylist'. + * + * Requires: + *\li 'keylist' is not NULL + * + * Returns: + *\li #ISC_R_SUCCESS + *\li #ISC_R_NOTFOUND + *\li #ISC_R_NOMEMORY + *\li any error returned by dns_name_totext(), isc_dir_open(), or + * dst_key_fromnamedfile() + * + * Ensures: + *\li On error, keylist is unchanged + */ + +isc_result_t +dns_dnssec_keylistfromrdataset(dns_name_t *origin, + const char *directory, isc_mem_t *mctx, + dns_rdataset_t *keyset, dns_rdataset_t *keysigs, + dns_rdataset_t *soasigs, isc_boolean_t savekeys, + isc_boolean_t public, + dns_dnsseckeylist_t *keylist); +/*%< + * Append the contents of a DNSKEY rdataset 'keyset' to 'keylist'. + * Omit duplicates. If 'public' is ISC_FALSE, search 'directory' for + * matching key files, and load the private keys that go with + * the public ones. If 'savekeys' is ISC_TRUE, mark the keys so + * they will not be deleted or inactivated regardless of metadata. + * + * 'keysigs' and 'soasigs', if not NULL and associated, contain the + * RRSIGS for the DNSKEY and SOA records respectively and are used to mark + * whether a key is already active in the zone. + */ + +isc_result_t +dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys, + dns_dnsseckeylist_t *removed, dns_name_t *origin, + dns_ttl_t ttl, dns_diff_t *diff, isc_boolean_t allzsk, + isc_mem_t *mctx, void (*report)(const char *, ...)); +/*%< + * Update the list of keys in 'keys' with new key information in 'newkeys'. + * + * For each key in 'newkeys', see if it has a match in 'keys'. + * - If not, and if the metadata says the key should be published: + * add it to 'keys', and place a dns_difftuple into 'diff' so + * the key can be added to the DNSKEY set. If the metadata says it + * should be active, set the first_sign flag. + * - If so, and if the metadata says it should be removed: + * remove it from 'keys', and place a dns_difftuple into 'diff' so + * the key can be removed from the DNSKEY set. if 'removed' is non-NULL, + * copy the key into that list; otherwise destroy it. + * - Otherwise, make sure keys has current metadata. + * + * If 'allzsk' is true, we are allowing KSK-flagged keys to be used as + * ZSKs. + * + * 'ttl' is the TTL of the DNSKEY RRset; if it is longer than the + * time until a new key will be activated, then we have to delay the + * key's activation. + * + * 'report' points to a function for reporting status. + * + * On completion, any remaining keys in 'newkeys' are freed. + */ ISC_LANG_ENDDECLS #endif /* DNS_DNSSEC_H */ diff --git a/lib/dns/include/dns/ds.h b/lib/dns/include/dns/ds.h index 77a2cb8..04e4bab 100644 --- a/lib/dns/include/dns/ds.h +++ b/lib/dns/include/dns/ds.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ds.h,v 1.10 2007-06-19 23:47:16 tbox Exp $ */ +/* $Id: ds.h,v 1.12 2010-12-23 23:47:08 tbox Exp $ */ #ifndef DNS_DS_H #define DNS_DS_H 1 @@ -26,6 +26,11 @@ #define DNS_DSDIGEST_SHA1 (1) #define DNS_DSDIGEST_SHA256 (2) +#define DNS_DSDIGEST_GOST (3) + +/* should not be here... */ + +#define ISC_GOST_DIGESTLENGTH 32U /* * Assuming SHA-256 digest type. diff --git a/lib/dns/include/dns/ecdb.h b/lib/dns/include/dns/ecdb.h new file mode 100644 index 0000000..be71a52 --- /dev/null +++ b/lib/dns/include/dns/ecdb.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: ecdb.h,v 1.3 2009-09-02 23:48:02 tbox Exp $ */ + +#ifndef DNS_ECDB_H +#define DNS_ECDB_H 1 + +/***** + ***** Module Info + *****/ + +/* TBD */ + +/*** + *** Imports + ***/ + +#include + +/*** + *** Types + ***/ + +/*** + *** Functions + ***/ + +/* TBD: describe those */ + +isc_result_t +dns_ecdb_register(isc_mem_t *mctx, dns_dbimplementation_t **dbimp); + +void +dns_ecdb_unregister(dns_dbimplementation_t **dbimp); + +ISC_LANG_ENDDECLS + +#endif /* DNS_ECDB_H */ diff --git a/lib/dns/include/dns/events.h b/lib/dns/include/dns/events.h index 689566b..d985833 100644 --- a/lib/dns/include/dns/events.h +++ b/lib/dns/include/dns/events.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: events.h,v 1.49.332.4 2010-05-10 23:48:14 tbox Exp $ */ +/* $Id: events.h,v 1.56 2010-12-21 03:11:42 marka Exp $ */ #ifndef DNS_EVENTS_H #define DNS_EVENTS_H 1 @@ -69,6 +69,11 @@ #define DNS_EVENT_ACACHECLEAN (ISC_EVENTCLASS_DNS + 39) #define DNS_EVENT_ACACHEOVERMEM (ISC_EVENTCLASS_DNS + 40) #define DNS_EVENT_RBTPRUNE (ISC_EVENTCLASS_DNS + 41) +#define DNS_EVENT_MANAGEKEYS (ISC_EVENTCLASS_DNS + 42) +#define DNS_EVENT_CLIENTRESDONE (ISC_EVENTCLASS_DNS + 43) +#define DNS_EVENT_CLIENTREQDONE (ISC_EVENTCLASS_DNS + 44) +#define DNS_EVENT_ADBGROWENTRIES (ISC_EVENTCLASS_DNS + 45) +#define DNS_EVENT_ADBGROWNAMES (ISC_EVENTCLASS_DNS + 46) #define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0) #define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535) diff --git a/lib/dns/include/dns/forward.h b/lib/dns/include/dns/forward.h index 5fbe898..683969d 100644 --- a/lib/dns/include/dns/forward.h +++ b/lib/dns/include/dns/forward.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: forward.h,v 1.11 2007-06-19 23:47:16 tbox Exp $ */ +/* $Id: forward.h,v 1.13 2009-09-02 23:48:02 tbox Exp $ */ #ifndef DNS_FORWARD_H #define DNS_FORWARD_H 1 @@ -67,6 +67,21 @@ dns_fwdtable_add(dns_fwdtable_t *fwdtable, dns_name_t *name, */ isc_result_t +dns_fwdtable_delete(dns_fwdtable_t *fwdtable, dns_name_t *name); +/*%< + * Removes an entry for 'name' from the forwarding table. If an entry + * that exactly matches 'name' does not exist, ISC_R_NOTFOUND will be returned. + * + * Requires: + * \li fwdtable is a valid forwarding table. + * \li name is a valid name + * + * Returns: + * \li #ISC_R_SUCCESS + * \li #ISC_R_NOTFOUND + */ + +isc_result_t dns_fwdtable_find(dns_fwdtable_t *fwdtable, dns_name_t *name, dns_forwarders_t **forwardersp); /*%< diff --git a/lib/dns/include/dns/journal.h b/lib/dns/include/dns/journal.h index 9e56c19..28a7dbe 100644 --- a/lib/dns/include/dns/journal.h +++ b/lib/dns/include/dns/journal.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: journal.h,v 1.33.120.4 2009-11-04 23:47:25 tbox Exp $ */ +/* $Id: journal.h,v 1.37 2009-11-04 23:48:18 tbox Exp $ */ #ifndef DNS_JOURNAL_H #define DNS_JOURNAL_H 1 diff --git a/lib/dns/include/dns/keydata.h b/lib/dns/include/dns/keydata.h new file mode 100644 index 0000000..36bf590 --- /dev/null +++ b/lib/dns/include/dns/keydata.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: keydata.h,v 1.2 2009-06-30 02:52:32 each Exp $ */ + +#ifndef DNS_KEYDATA_H +#define DNS_KEYDATA_H 1 + +/***** + ***** Module Info + *****/ + +/*! \file dns/keydata.h + * \brief + * KEYDATA utilities. + */ + +/*** + *** Imports + ***/ + +#include +#include + +#include +#include + +ISC_LANG_BEGINDECLS + +isc_result_t +dns_keydata_todnskey(dns_rdata_keydata_t *keydata, + dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx); + +isc_result_t +dns_keydata_fromdnskey(dns_rdata_keydata_t *keydata, + dns_rdata_dnskey_t *dnskey, + isc_uint32_t refresh, isc_uint32_t addhd, + isc_uint32_t removehd, isc_mem_t *mctx); + +ISC_LANG_ENDDECLS + +#endif /* DNS_KEYDATA_H */ diff --git a/lib/dns/include/dns/keytable.h b/lib/dns/include/dns/keytable.h index 40c4b16..a53ec08 100644 --- a/lib/dns/include/dns/keytable.h +++ b/lib/dns/include/dns/keytable.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: keytable.h,v 1.16 2007-06-19 23:47:16 tbox Exp $ */ +/* $Id: keytable.h,v 1.23 2010-06-25 03:24:05 marka Exp $ */ #ifndef DNS_KEYTABLE_H #define DNS_KEYTABLE_H 1 @@ -42,6 +42,10 @@ */ #include +#include +#include +#include +#include #include @@ -49,6 +53,33 @@ ISC_LANG_BEGINDECLS +struct dns_keytable { + /* Unlocked. */ + unsigned int magic; + isc_mem_t *mctx; + isc_mutex_t lock; + isc_rwlock_t rwlock; + /* Locked by lock. */ + isc_uint32_t active_nodes; + /* Locked by rwlock. */ + isc_uint32_t references; + dns_rbt_t *table; +}; + +#define KEYTABLE_MAGIC ISC_MAGIC('K', 'T', 'b', 'l') +#define VALID_KEYTABLE(kt) ISC_MAGIC_VALID(kt, KEYTABLE_MAGIC) + +struct dns_keynode { + unsigned int magic; + isc_refcount_t refcount; + dst_key_t * key; + isc_boolean_t managed; + struct dns_keynode * next; +}; + +#define KEYNODE_MAGIC ISC_MAGIC('K', 'N', 'o', 'd') +#define VALID_KEYNODE(kn) ISC_MAGIC_VALID(kn, KEYNODE_MAGIC) + isc_result_t dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep); /*%< @@ -106,16 +137,22 @@ dns_keytable_detach(dns_keytable_t **keytablep); */ isc_result_t -dns_keytable_add(dns_keytable_t *keytable, dst_key_t **keyp); +dns_keytable_add(dns_keytable_t *keytable, isc_boolean_t managed, + dst_key_t **keyp); /*%< - * Add '*keyp' to 'keytable'. + * Add '*keyp' to 'keytable' (using the name in '*keyp'). + * The value of keynode->managed is set to 'managed' * * Notes: * *\li Ownership of *keyp is transferred to the keytable. + *\li If the key already exists in the table, ISC_R_EXISTS is + * returned and the new key is freed. * * Requires: * + *\li 'keytable' points to a valid keytable. + * *\li keyp != NULL && *keyp is a valid dst_key_t *. * * Ensures: @@ -125,11 +162,124 @@ dns_keytable_add(dns_keytable_t *keytable, dst_key_t **keyp); * Returns: * *\li ISC_R_SUCCESS + *\li ISC_R_EXISTS + * + *\li Any other result indicates failure. + */ + +isc_result_t +dns_keytable_marksecure(dns_keytable_t *keytable, dns_name_t *name); +/*%< + * Add a null key to 'keytable' for name 'name'. This marks the + * name as a secure domain, but doesn't supply any key data to allow the + * domain to be validated. (Used when automated trust anchor management + * has gotten broken by a zone misconfiguration; for example, when the + * active key has been revoked but the stand-by key was still in its 30-day + * waiting period for validity.) + * + * Notes: + * + *\li If a key already exists in the table, ISC_R_EXISTS is + * returned and nothing is done. + * + * Requires: + * + *\li 'keytable' points to a valid keytable. + * + *\li keyp != NULL && *keyp is a valid dst_key_t *. + * + * Returns: + * + *\li ISC_R_SUCCESS + *\li ISC_R_EXISTS + * + *\li Any other result indicates failure. + */ + +isc_result_t +dns_keytable_delete(dns_keytable_t *keytable, dns_name_t *keyname); +/*%< + * Delete node(s) from 'keytable' matching name 'keyname' + * + * Requires: + * + *\li 'keytable' points to a valid keytable. + * + *\li 'name' is not NULL + * + * Returns: + * + *\li ISC_R_SUCCESS + * + *\li Any other result indicates failure. + */ + +isc_result_t +dns_keytable_deletekeynode(dns_keytable_t *keytable, dst_key_t *dstkey); +/*%< + * Delete node(s) from 'keytable' containing copies of the key pointed + * to by 'dstkey' + * + * Requires: + * + *\li 'keytable' points to a valid keytable. + *\li 'dstkey' is not NULL + * + * Returns: + * + *\li ISC_R_SUCCESS * *\li Any other result indicates failure. */ isc_result_t +dns_keytable_find(dns_keytable_t *keytable, dns_name_t *keyname, + dns_keynode_t **keynodep); +/*%< + * Search for the first instance of a key named 'name' in 'keytable', + * without regard to keyid and algorithm. Use dns_keytable_nextkeynode() + * to find subsequent instances. + * + * Requires: + * + *\li 'keytable' is a valid keytable. + * + *\li 'name' is a valid absolute name. + * + *\li keynodep != NULL && *keynodep == NULL + * + * Returns: + * + *\li ISC_R_SUCCESS + *\li ISC_R_NOTFOUND + * + *\li Any other result indicates an error. + */ + +isc_result_t +dns_keytable_nextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode, + dns_keynode_t **nextnodep); +/*%< + * Return for the next key after 'keynode' in 'keytable', without regard to + * keyid and algorithm. + * + * Requires: + * + *\li 'keytable' is a valid keytable. + * + *\li 'keynode' is a valid keynode. + * + *\li nextnodep != NULL && *nextnodep == NULL + * + * Returns: + * + *\li ISC_R_SUCCESS + *\li ISC_R_NOTFOUND + * + *\li Any other result indicates an error. + */ + +isc_result_t dns_keytable_findkeynode(dns_keytable_t *keytable, dns_name_t *name, dns_secalg_t algorithm, dns_keytag_t tag, dns_keynode_t **keynodep); @@ -157,7 +307,7 @@ dns_keytable_findkeynode(dns_keytable_t *keytable, dns_name_t *name, isc_result_t dns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode, - dns_keynode_t **nextnodep); + dns_keynode_t **nextnodep); /*%< * Search for the next key with the same properties as 'keynode' in * 'keytable' as found by dns_keytable_findkeynode(). @@ -201,6 +351,22 @@ dns_keytable_finddeepestmatch(dns_keytable_t *keytable, dns_name_t *name, */ void +dns_keytable_attachkeynode(dns_keytable_t *keytable, dns_keynode_t *source, + dns_keynode_t **target); +/*%< + * Attach a keynode and and increment the active_nodes counter in a + * corresponding keytable. + * + * Requires: + * + *\li 'keytable' is a valid keytable. + * + *\li 'source' is a valid keynode. + * + *\li 'target' is not null and '*target' is null. + */ + +void dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep); /*%< @@ -244,12 +410,48 @@ dns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name, *\li Any other result is an error. */ +isc_result_t +dns_keytable_dump(dns_keytable_t *keytable, FILE *fp); +/*%< + * Dump the keytable on fp. + */ + dst_key_t * dns_keynode_key(dns_keynode_t *keynode); /*%< * Get the DST key associated with keynode. */ +isc_boolean_t +dns_keynode_managed(dns_keynode_t *keynode); +/*%< + * Is this flagged as a managed key? + */ + +isc_result_t +dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target); +/*%< + * Allocate space for a keynode + */ + +void +dns_keynode_attach(dns_keynode_t *source, dns_keynode_t **target); +/*%< + * Attach keynode 'source' to '*target' + */ + +void +dns_keynode_detach(isc_mem_t *mctx, dns_keynode_t **target); +/*%< + * Detach a single keynode, without touching any keynodes that + * may be pointed to by its 'next' pointer + */ + +void +dns_keynode_detachall(isc_mem_t *mctx, dns_keynode_t **target); +/*%< + * Detach a keynode and all its succesors. + */ ISC_LANG_ENDDECLS #endif /* DNS_KEYTABLE_H */ diff --git a/lib/dns/include/dns/keyvalues.h b/lib/dns/include/dns/keyvalues.h index 70ca3fa..2107657 100644 --- a/lib/dns/include/dns/keyvalues.h +++ b/lib/dns/include/dns/keyvalues.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: keyvalues.h,v 1.23.48.4 2010-01-15 23:47:33 tbox Exp $ */ +/* $Id: keyvalues.h,v 1.29 2010-12-23 23:47:08 tbox Exp $ */ #ifndef DNS_KEYVALUES_H #define DNS_KEYVALUES_H 1 @@ -42,7 +42,7 @@ #define DNS_KEYOWNER_ENTITY 0x0200 /*%< key is assoc. with entity eg host */ #define DNS_KEYOWNER_ZONE 0x0100 /*%< key is zone key */ #define DNS_KEYOWNER_RESERVED 0x0300 /*%< reserved meaning */ -#define DNS_KEYFLAG_REVOKE 0x0080 /*%< key revoked (per rfc5001) */ +#define DNS_KEYFLAG_REVOKE 0x0080 /*%< key revoked (per rfc5011) */ #define DNS_KEYFLAG_RESERVED9 0x0040 /*%< reserved - must be zero */ #define DNS_KEYFLAG_RESERVED10 0x0020 /*%< reserved - must be zero */ #define DNS_KEYFLAG_RESERVED11 0x0010 /*%< reserved - must be zero */ @@ -51,7 +51,6 @@ #define DNS_KEYFLAG_RESERVEDMASK (DNS_KEYFLAG_RESERVED2 | \ DNS_KEYFLAG_RESERVED4 | \ DNS_KEYFLAG_RESERVED5 | \ - DNS_KEYFLAG_RESERVED8 | \ DNS_KEYFLAG_RESERVED9 | \ DNS_KEYFLAG_RESERVED10 | \ DNS_KEYFLAG_RESERVED11 ) @@ -71,6 +70,7 @@ #define DNS_KEYALG_NSEC3RSASHA1 7 #define DNS_KEYALG_RSASHA256 8 #define DNS_KEYALG_RSASHA512 10 +#define DNS_KEYALG_ECCGOST 12 #define DNS_KEYALG_INDIRECT 252 #define DNS_KEYALG_PRIVATEDNS 253 #define DNS_KEYALG_PRIVATEOID 254 /*%< Key begins with OID giving alg */ @@ -99,4 +99,6 @@ #define DNS_SIG_DSAMINBYTES 213 #define DNS_SIG_DSAMAXBYTES 405 +#define DNS_SIG_GOSTSIGSIZE 64 + #endif /* DNS_KEYVALUES_H */ diff --git a/lib/dns/include/dns/lib.h b/lib/dns/include/dns/lib.h index 361ef8f..70874b7 100644 --- a/lib/dns/include/dns/lib.h +++ b/lib/dns/include/dns/lib.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lib.h,v 1.16 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: lib.h,v 1.18 2009-09-02 23:48:02 tbox Exp $ */ #ifndef DNS_LIB_H #define DNS_LIB_H 1 @@ -40,6 +40,20 @@ dns_lib_initmsgcat(void); * has not already been initialized. */ +isc_result_t +dns_lib_init(void); +/*%< + * A set of initialization procedure used in the DNS library. This function + * is provided for an application that is not aware of the underlying ISC or + * DNS libraries much. + */ + +void +dns_lib_shutdown(void); +/*%< + * Free temporary resources allocated in dns_lib_init(). + */ + ISC_LANG_ENDDECLS #endif /* DNS_LIB_H */ diff --git a/lib/dns/include/dns/log.h b/lib/dns/include/dns/log.h index 4b648ff..a5650ed 100644 --- a/lib/dns/include/dns/log.h +++ b/lib/dns/include/dns/log.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: log.h,v 1.42.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: log.h,v 1.45 2009-12-18 22:16:49 each Exp $ */ /*! \file dns/log.h * \author Principal Authors: DCL */ @@ -73,6 +73,7 @@ LIBDNS_EXTERNAL_DATA extern isc_logmodule_t dns_modules[]; #define DNS_LOGMODULE_HINTS (&dns_modules[24]) #define DNS_LOGMODULE_ACACHE (&dns_modules[25]) #define DNS_LOGMODULE_DLZ (&dns_modules[26]) +#define DNS_LOGMODULE_DNSSEC (&dns_modules[27]) ISC_LANG_BEGINDECLS diff --git a/lib/dns/include/dns/lookup.h b/lib/dns/include/dns/lookup.h index 81bb9b9..7e6a566 100644 --- a/lib/dns/include/dns/lookup.h +++ b/lib/dns/include/dns/lookup.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lookup.h,v 1.12.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: lookup.h,v 1.14 2009-01-17 23:47:43 tbox Exp $ */ #ifndef DNS_LOOKUP_H #define DNS_LOOKUP_H 1 diff --git a/lib/dns/include/dns/master.h b/lib/dns/include/dns/master.h index 3f3a4de..2ee6374 100644 --- a/lib/dns/include/dns/master.h +++ b/lib/dns/include/dns/master.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: master.h,v 1.51 2008-04-02 02:37:42 marka Exp $ */ +/* $Id: master.h,v 1.53 2009-07-01 23:47:36 tbox Exp $ */ #ifndef DNS_MASTER_H #define DNS_MASTER_H 1 @@ -56,6 +56,7 @@ #define DNS_MASTER_CHECKMXFAIL 0x00001000 #define DNS_MASTER_RESIGN 0x00002000 +#define DNS_MASTER_KEY 0x00004000 /*%< Loading a key zone master file. */ ISC_LANG_BEGINDECLS diff --git a/lib/dns/include/dns/masterdump.h b/lib/dns/include/dns/masterdump.h index 96a198d..684dd82 100644 --- a/lib/dns/include/dns/masterdump.h +++ b/lib/dns/include/dns/masterdump.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: masterdump.h,v 1.42.602.2 2011-06-02 23:46:22 tbox Exp $ */ +/* $Id: masterdump.h,v 1.42.596.2 2011-06-02 23:47:35 tbox Exp $ */ #ifndef DNS_MASTERDUMP_H #define DNS_MASTERDUMP_H 1 diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index 98fb321..438de1e 100644 --- a/lib/dns/include/dns/message.h +++ b/lib/dns/include/dns/message.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: message.h,v 1.125.118.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: message.h,v 1.132 2010-03-04 23:50:34 tbox Exp $ */ #ifndef DNS_MESSAGE_H #define DNS_MESSAGE_H 1 @@ -81,8 +81,7 @@ * name = NULL; * name = dns_message_gettempname(message, &name); * dns_name_init(name, NULL); - * result = dns_name_fromtext(name, &source, dns_rootname, ISC_FALSE, - * buffer); + * result = dns_name_fromtext(name, &source, dns_rootname, 0, buffer); * dns_message_takebuffer(message, &buffer); * \endcode * @@ -137,6 +136,8 @@ typedef int dns_pseudosection_t; typedef int dns_messagetextflag_t; #define DNS_MESSAGETEXTFLAG_NOCOMMENTS 0x0001 #define DNS_MESSAGETEXTFLAG_NOHEADERS 0x0002 +#define DNS_MESSAGETEXTFLAG_ONESOA 0x0004 +#define DNS_MESSAGETEXTFLAG_OMITSOA 0x0008 /* * Dynamic update names for these sections. @@ -174,6 +175,9 @@ typedef int dns_messagetextflag_t; additional section. */ #define DNS_MESSAGERENDER_PREFER_AAAA 0x0010 /*%< prefer AAAA records in additional section. */ +#ifdef ALLOW_FILTER_AAAA_ON_V4 +#define DNS_MESSAGERENDER_FILTER_AAAA 0x0020 /*%< filter AAAA records */ +#endif typedef struct dns_msgblock dns_msgblock_t; @@ -369,6 +373,14 @@ dns_message_totext(dns_message_t *msg, const dns_master_style_t *style, * #DNS_MESSAGETEXTFLAG_NOHEADERS is cleared, header lines will * be emitted. * + * If #DNS_MESSAGETEXTFLAG_ONESOA is set then only print the + * first SOA record in the answer section. If + * #DNS_MESSAGETEXTFLAG_OMITSOA is set don't print any SOA records + * in the answer section. These are useful for suppressing the + * display of the second SOA record in a AXFR by setting + * #DNS_MESSAGETEXTFLAG_ONESOA on the first message in a AXFR stream + * and #DNS_MESSAGETEXTFLAG_OMITSOA on subsequent messages. + * * Requires: * *\li 'msg' is a valid message. diff --git a/lib/dns/include/dns/name.h b/lib/dns/include/dns/name.h index 801c9ac..c13a85d 100644 --- a/lib/dns/include/dns/name.h +++ b/lib/dns/include/dns/name.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: name.h,v 1.126.332.5 2010-07-09 23:45:55 tbox Exp $ */ +/* $Id: name.h,v 1.137 2011-01-13 04:59:26 tbox Exp $ */ #ifndef DNS_NAME_H #define DNS_NAME_H 1 @@ -121,21 +121,27 @@ struct dns_name { #define DNS_NAME_MAGIC ISC_MAGIC('D','N','S','n') -#define DNS_NAMEATTR_ABSOLUTE 0x0001 -#define DNS_NAMEATTR_READONLY 0x0002 -#define DNS_NAMEATTR_DYNAMIC 0x0004 -#define DNS_NAMEATTR_DYNOFFSETS 0x0008 -#define DNS_NAMEATTR_NOCOMPRESS 0x0010 +#define DNS_NAMEATTR_ABSOLUTE 0x00000001 +#define DNS_NAMEATTR_READONLY 0x00000002 +#define DNS_NAMEATTR_DYNAMIC 0x00000004 +#define DNS_NAMEATTR_DYNOFFSETS 0x00000008 +#define DNS_NAMEATTR_NOCOMPRESS 0x00000010 /* * Attributes below 0x0100 reserved for name.c usage. */ -#define DNS_NAMEATTR_CACHE 0x0100 /*%< Used by resolver. */ -#define DNS_NAMEATTR_ANSWER 0x0200 /*%< Used by resolver. */ -#define DNS_NAMEATTR_NCACHE 0x0400 /*%< Used by resolver. */ -#define DNS_NAMEATTR_CHAINING 0x0800 /*%< Used by resolver. */ -#define DNS_NAMEATTR_CHASE 0x1000 /*%< Used by resolver. */ -#define DNS_NAMEATTR_WILDCARD 0x2000 /*%< Used by server. */ +#define DNS_NAMEATTR_CACHE 0x00000100 /*%< Used by resolver. */ +#define DNS_NAMEATTR_ANSWER 0x00000200 /*%< Used by resolver. */ +#define DNS_NAMEATTR_NCACHE 0x00000400 /*%< Used by resolver. */ +#define DNS_NAMEATTR_CHAINING 0x00000800 /*%< Used by resolver. */ +#define DNS_NAMEATTR_CHASE 0x00001000 /*%< Used by resolver. */ +#define DNS_NAMEATTR_WILDCARD 0x00002000 /*%< Used by server. */ +#define DNS_NAMEATTR_PREREQUISITE 0x00004000 /*%< Used by client. */ +#define DNS_NAMEATTR_UPDATE 0x00008000 /*%< Used by client. */ +#define DNS_NAMEATTR_HASUPDATEREC 0x00010000 /*%< Used by client. */ +/* + * Various flags. + */ #define DNS_NAME_DOWNCASE 0x0001 #define DNS_NAME_CHECKNAMES 0x0002 /*%< Used by rdata. */ #define DNS_NAME_CHECKNAMESFAIL 0x0004 /*%< Used by rdata. */ @@ -750,7 +756,7 @@ dns_name_towire(const dns_name_t *name, dns_compress_t *cctx, isc_result_t dns_name_fromtext(dns_name_t *name, isc_buffer_t *source, - dns_name_t *origin, unsigned int options, + const dns_name_t *origin, unsigned int options, isc_buffer_t *target); /*%< * Convert the textual representation of a DNS name at source @@ -1139,6 +1145,56 @@ dns_name_format(dns_name_t *name, char *cp, unsigned int size); */ isc_result_t +dns_name_tostring(dns_name_t *source, char **target, isc_mem_t *mctx); +/*%< + * Convert 'name' to string format, allocating sufficient memory to + * hold it (free with isc_mem_free()). + * + * Differs from dns_name_format in that it allocates its own memory. + * + * Requires: + * + *\li 'name' is a valid name. + *\li 'target' is not NULL. + *\li '*target' is NULL. + * + * Returns: + * + *\li ISC_R_SUCCESS + * + *\li Any error that dns_name_totext() can return. + */ + +isc_result_t +dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options, + isc_mem_t *mctx); +isc_result_t +dns_name_fromstring2(dns_name_t *target, const char *src, + const dns_name_t *origin, unsigned int options, + isc_mem_t *mctx); +/*%< + * Convert a string to a name and place it in target, allocating memory + * as necessary. 'options' has the same semantics as that of + * dns_name_fromtext(). + * + * If 'target' has a buffer then the name will be copied into it rather than + * memory being allocated. + * + * Requires: + * + * \li 'target' is a valid name that is not read-only. + * \li 'src' is not NULL. + * + * Returns: + * + *\li #ISC_R_SUCCESS + * + *\li Any error that dns_name_fromtext() can return. + * + *\li Any error that dns_name_dup() can return. + */ + +isc_result_t dns_name_settotextfilter(dns_name_totextfilter_t proc); /*%< * Set / clear a thread specific function 'proc' to be called at the diff --git a/lib/dns/include/dns/ncache.h b/lib/dns/include/dns/ncache.h index 0c1d950..32345cf 100644 --- a/lib/dns/include/dns/ncache.h +++ b/lib/dns/include/dns/ncache.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ncache.h,v 1.25.48.4 2010-05-14 23:47:50 tbox Exp $ */ +/* $Id: ncache.h,v 1.29 2010-05-14 23:50:40 tbox Exp $ */ #ifndef DNS_NCACHE_H #define DNS_NCACHE_H 1 diff --git a/lib/dns/include/dns/nsec3.h b/lib/dns/include/dns/nsec3.h index ba808e4..ac0c8f2 100644 --- a/lib/dns/include/dns/nsec3.h +++ b/lib/dns/include/dns/nsec3.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2008-2010 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nsec3.h,v 1.5.48.3 2009-10-06 21:20:18 each Exp $ */ +/* $Id: nsec3.h,v 1.12 2010-05-18 02:38:10 tbox Exp $ */ #ifndef DNS_NSEC3_H #define DNS_NSEC3_H 1 @@ -110,6 +110,12 @@ isc_result_t dns_nsec3_addnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, dns_ttl_t nsecttl, isc_boolean_t unsecure, dns_diff_t *diff); + +isc_result_t +dns_nsec3_addnsec3sx(dns_db_t *db, dns_dbversion_t *version, + dns_name_t *name, dns_ttl_t nsecttl, + isc_boolean_t unsecure, dns_rdatatype_t private, + dns_diff_t *diff); /*%< * Add NSEC3 records for 'name', recording the change in 'diff'. * Adjust previous NSEC3 records, if any, to reflect the addition. @@ -130,6 +136,10 @@ dns_nsec3_addnsec3s(dns_db_t *db, dns_dbversion_t *version, * NSEC3PARAM record otherwise OPTOUT will be inherited from the previous * record in the chain. * + * dns_nsec3_addnsec3sx() is similar to dns_nsec3_addnsec3s() but 'private' + * specifies the type of the private rdataset to be checked in addition to + * the nsec3param rdataset at the zone apex. + * * Requires: * 'db' to be valid. * 'version' to be valid or NULL. @@ -145,6 +155,10 @@ dns_nsec3_delnsec3(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, isc_result_t dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, dns_diff_t *diff); + +isc_result_t +dns_nsec3_delnsec3sx(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, + dns_rdatatype_t private, dns_diff_t *diff); /*%< * Remove NSEC3 records for 'name', recording the change in 'diff'. * Adjust previous NSEC3 records, if any, to reflect the removal. @@ -156,6 +170,10 @@ dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, * to dns_nsec3_addnsec3s(). Unlike dns_nsec3_addnsec3s() updated NSEC3 * records have the OPTOUT flag preserved. * + * dns_nsec3_delnsec3sx() is similar to dns_nsec3_delnsec3s() but 'private' + * specifies the type of the private rdataset to be checked in addition to + * the nsec3param rdataset at the zone apex. + * * Requires: * 'db' to be valid. * 'version' to be valid or NULL. @@ -167,10 +185,19 @@ dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, isc_result_t dns_nsec3_active(dns_db_t *db, dns_dbversion_t *version, isc_boolean_t complete, isc_boolean_t *answer); + +isc_result_t +dns_nsec3_activex(dns_db_t *db, dns_dbversion_t *version, + isc_boolean_t complete, dns_rdatatype_t private, + isc_boolean_t *answer); /*%< * Check if there are any complete/to be built NSEC3 chains. * If 'complete' is ISC_TRUE only complete chains will be recognized. * + * dns_nsec3_activex() is similar to dns_nsec3_active() but 'private' + * specifies the type of the private rdataset to be checked in addition to + * the nsec3param rdataset at the zone apex. + * * Requires: * 'db' to be valid. * 'version' to be valid or NULL. @@ -191,6 +218,36 @@ dns_nsec3_maxiterations(dns_db_t *db, dns_dbversion_t *version, * 'iterationsp' to be non NULL. */ +isc_boolean_t +dns_nsec3param_fromprivate(dns_rdata_t *src, dns_rdata_t *target, + unsigned char *buf, size_t buflen); +/*%< + * Convert a private rdata to a nsec3param rdata. + * + * Return ISC_TRUE if 'src' could be successfully converted. + * + * 'buf' should be at least DNS_NSEC3PARAM_BUFFERSIZE in size. + */ + +void +dns_nsec3param_toprivate(dns_rdata_t *src, dns_rdata_t *target, + dns_rdatatype_t privatetype, + unsigned char *buf, size_t buflen); +/*%< + * Convert a nsec3param rdata to a private rdata. + * + * 'buf' should be at least src->length + 1 in size. + */ + +isc_result_t +dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver, + dns_zone_t *zone, dns_diff_t *diff); + +/*%< + * Mark NSEC3PARAM for deletion. + */ + + ISC_LANG_ENDDECLS #endif /* DNS_NSEC3_H */ diff --git a/lib/dns/include/dns/peer.h b/lib/dns/include/dns/peer.h index 1f8a42e..a1a3e34 100644 --- a/lib/dns/include/dns/peer.h +++ b/lib/dns/include/dns/peer.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: peer.h,v 1.33.118.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: peer.h,v 1.35 2009-01-17 23:47:43 tbox Exp $ */ #ifndef DNS_PEER_H #define DNS_PEER_H 1 diff --git a/lib/dns/include/dns/private.h b/lib/dns/include/dns/private.h new file mode 100644 index 0000000..ffedb5f --- /dev/null +++ b/lib/dns/include/dns/private.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: private.h,v 1.3 2009-10-09 23:48:09 tbox Exp $ */ + +#include +#include + +#include +#include + +#ifndef DNS_PRIVATE_H +#define DNS_PRIVATE_H + +ISC_LANG_BEGINDECLS + +isc_result_t +dns_private_chains(dns_db_t *db, dns_dbversion_t *ver, + dns_rdatatype_t privatetype, + isc_boolean_t *build_nsec, isc_boolean_t *build_nsec3); +/*%< + * Examine the NSEC, NSEC3PARAM and privatetype RRsets at the apex of the + * database to determine which of NSEC or NSEC3 chains we are currently + * maintaining. In normal operations only one of NSEC or NSEC3 is being + * maintained but when we are transitiong between NSEC and NSEC3 we need + * to update both sets of chains. If 'privatetype' is zero then the + * privatetype RRset will not be examined. + * + * Requires: + * \li 'db' is valid. + * \li 'version' is valid or NULL. + * \li 'build_nsec' is a pointer to a isc_boolean_t or NULL. + * \li 'build_nsec3' is a pointer to a isc_boolean_t or NULL. + * + * Returns: + * \li ISC_R_SUCCESS, 'build_nsec' and 'build_nsec3' will be valid. + * \li other on error + */ + +ISC_LANG_ENDDECLS + +#endif diff --git a/lib/dns/include/dns/rbt.h b/lib/dns/include/dns/rbt.h index 72ef2f1..6149e8d 100644 --- a/lib/dns/include/dns/rbt.h +++ b/lib/dns/include/dns/rbt.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rbt.h,v 1.71.48.3 2009-10-20 05:06:04 marka Exp $ */ +/* $Id: rbt.h,v 1.77 2009-11-04 01:18:19 marka Exp $ */ #ifndef DNS_RBT_H #define DNS_RBT_H 1 @@ -70,6 +70,12 @@ ISC_LANG_BEGINDECLS * multiple dns_rbtnode structures will not work. */ typedef struct dns_rbtnode dns_rbtnode_t; +enum { + DNS_RBT_NSEC_NORMAL=0, /* in main tree */ + DNS_RBT_NSEC_HAS_NSEC=1, /* also has node in nsec tree */ + DNS_RBT_NSEC_NSEC=2, /* in nsec tree */ + DNS_RBT_NSEC_NSEC3=3 /* in nsec3 tree */ +}; struct dns_rbtnode { #if DNS_RBT_USEMAGIC unsigned int magic; @@ -94,10 +100,7 @@ struct dns_rbtnode { * The following bitfields add up to a total bitwidth of 32. * The range of values necessary for each item is indicated, * but in the case of "attributes" the field is wider to accommodate - * possible future expansion. "offsetlen" could be one bit - * narrower by always adjusting its value by 1 to find the real - * offsetlen, but doing so does not gain anything (except perhaps - * another bit for "attributes", which doesn't yet need any more). + * possible future expansion. * * In each case below the "range" indicated is what's _necessary_ for * the bitfield to hold, not what it actually _can_ hold. @@ -105,8 +108,8 @@ struct dns_rbtnode { unsigned int is_root : 1; /*%< range is 0..1 */ unsigned int color : 1; /*%< range is 0..1 */ unsigned int find_callback : 1; /*%< range is 0..1 */ - unsigned int attributes : 4; /*%< range is 0..2 */ - unsigned int nsec3 : 1; /*%< range is 0..1 */ + unsigned int attributes : 3; /*%< range is 0..2 */ + unsigned int nsec : 2; /*%< range is 0..3 */ unsigned int namelen : 8; /*%< range is 1..255 */ unsigned int offsetlen : 8; /*%< range is 1..128 */ unsigned int oldnamelen : 8; /*%< range is 1..255 */ @@ -909,7 +912,7 @@ dns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name); } while (0) #else /* DNS_RBT_USEISCREFCOUNT */ #define dns_rbtnode_refinit(node, n) ((node)->references = (n)) -#define dns_rbtnode_refdestroy(node) (REQUIRE((node)->references == 0)) +#define dns_rbtnode_refdestroy(node) REQUIRE((node)->references == 0) #define dns_rbtnode_refcurrent(node) ((node)->references) #define dns_rbtnode_refincrement0(node, refs) \ do { \ diff --git a/lib/dns/include/dns/rdata.h b/lib/dns/include/dns/rdata.h index 1674b0c..b70a353 100644 --- a/lib/dns/include/dns/rdata.h +++ b/lib/dns/include/dns/rdata.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdata.h,v 1.70.120.3 2009-02-16 00:29:27 marka Exp $ */ +/* $Id: rdata.h,v 1.77 2009-12-04 21:09:33 marka Exp $ */ #ifndef DNS_RDATA_H #define DNS_RDATA_H 1 @@ -95,6 +95,7 @@ #include #include +#include ISC_LANG_BEGINDECLS @@ -124,9 +125,27 @@ struct dns_rdata { #define DNS_RDATA_INIT { NULL, 0, 0, 0, 0, {(void*)(-1), (void *)(-1)}} +#define DNS_RDATA_CHECKINITIALIZED +#ifdef DNS_RDATA_CHECKINITIALIZED +#define DNS_RDATA_INITIALIZED(rdata) \ + ((rdata)->data == NULL && (rdata)->length == 0 && \ + (rdata)->rdclass == 0 && (rdata)->type == 0 && (rdata)->flags == 0 && \ + !ISC_LINK_LINKED((rdata), link)) +#else +#ifdef ISC_LIST_CHECKINIT +#define DNS_RDATA_INITIALIZED(rdata) \ + (!ISC_LINK_LINKED((rdata), link)) +#else +#define DNS_RDATA_INITIALIZED(rdata) ISC_TRUE +#endif +#endif + #define DNS_RDATA_UPDATE 0x0001 /*%< update pseudo record. */ #define DNS_RDATA_OFFLINE 0x0002 /*%< RRSIG has a offline key. */ +#define DNS_RDATA_VALIDFLAGS(rdata) \ + (((rdata)->flags & ~(DNS_RDATA_UPDATE|DNS_RDATA_OFFLINE)) == 0) + /* * Flags affecting rdata formatting style. Flags 0xFFFF0000 * are used by masterfile-level formatting and defined elsewhere. @@ -201,6 +220,25 @@ dns_rdata_compare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2); *\li > 0 'rdata1' is greater than 'rdata2' */ +int +dns_rdata_casecompare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2); +/*%< + * dns_rdata_casecompare() is similar to dns_rdata_compare() but also + * compares domain names case insensitively in known rdata types that + * are treated as opaque data by dns_rdata_compare(). + * + * Requires: + * + *\li 'rdata1' is a valid, non-empty rdata + * + *\li 'rdata2' is a valid, non-empty rdata + * + * Returns: + *\li < 0 'rdata1' is less than 'rdata2' + *\li 0 'rdata1' is equal to 'rdata2' + *\li > 0 'rdata1' is greater than 'rdata2' + */ + /*** *** Conversions ***/ @@ -698,6 +736,21 @@ dns_rdata_checknames(dns_rdata_t *rdata, dns_name_t *owner, dns_name_t *bad); * 'bad' to be NULL or valid. */ +void +dns_rdata_exists(dns_rdata_t *rdata, dns_rdatatype_t type); + +void +dns_rdata_notexist(dns_rdata_t *rdata, dns_rdatatype_t type); + +void +dns_rdata_deleterrset(dns_rdata_t *rdata, dns_rdatatype_t type); + +void +dns_rdata_makedelete(dns_rdata_t *rdata); + +const char * +dns_rdata_updateop(dns_rdata_t *rdata, dns_section_t section); + ISC_LANG_ENDDECLS #endif /* DNS_RDATA_H */ diff --git a/lib/dns/include/dns/rdataset.h b/lib/dns/include/dns/rdataset.h index a8c3e9c..7f50c12 100644 --- a/lib/dns/include/dns/rdataset.h +++ b/lib/dns/include/dns/rdataset.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdataset.h,v 1.65.50.4.6.3 2011-06-21 20:13:23 each Exp $ */ +/* $Id: rdataset.h,v 1.69.270.3 2011-06-21 20:15:54 each Exp $ */ #ifndef DNS_RDATASET_H #define DNS_RDATASET_H 1 diff --git a/lib/dns/include/dns/request.h b/lib/dns/include/dns/request.h index 8808c0a..f2db1031b 100644 --- a/lib/dns/include/dns/request.h +++ b/lib/dns/include/dns/request.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: request.h,v 1.27.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: request.h,v 1.31 2010-03-04 23:50:34 tbox Exp $ */ #ifndef DNS_REQUEST_H #define DNS_REQUEST_H 1 @@ -47,6 +47,7 @@ #include #define DNS_REQUESTOPT_TCP 0x00000001U +#define DNS_REQUESTOPT_CASE 0x00000002U typedef struct dns_requestevent { ISC_EVENT_COMMON(struct dns_requestevent); @@ -175,6 +176,9 @@ dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message, * #DNS_REQUESTOPT_TCP option is set, TCP will be used. The request * will timeout after 'timeout' seconds. * + *\li If the #DNS_REQUESTOPT_CASE option is set, use case sensitive + * compression. + * *\li When the request completes, successfully, due to a timeout, or * because it was canceled, a completion event will be sent to 'task'. * @@ -227,6 +231,9 @@ dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message, * will timeout after 'timeout' seconds. UDP requests will be resent * at 'udptimeout' intervals if non-zero or 'udpretries' is non-zero. * + *\li If the #DNS_REQUESTOPT_CASE option is set, use case sensitive + * compression. + * *\li When the request completes, successfully, due to a timeout, or * because it was canceled, a completion event will be sent to 'task'. * diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h index c9034bf..2db1770 100644 --- a/lib/dns/include/dns/resolver.h +++ b/lib/dns/include/dns/resolver.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resolver.h,v 1.60.56.5 2010-02-25 10:56:41 tbox Exp $ */ +/* $Id: resolver.h,v 1.67.86.1.2.1 2011-06-02 23:47:36 tbox Exp $ */ #ifndef DNS_RESOLVER_H #define DNS_RESOLVER_H 1 @@ -81,6 +81,7 @@ typedef struct dns_fetchevent { dns_fixedname_t foundname; isc_sockaddr_t * client; dns_messageid_t id; + isc_result_t vresult; } dns_fetchevent_t; /* @@ -179,7 +180,7 @@ dns_resolver_freeze(dns_resolver_t *res); * * Requires: * - *\li 'res' is a valid, unfrozen resolver. + *\li 'res' is a valid resolver. * * Ensures: * @@ -491,6 +492,27 @@ dns_resolver_setmustbesecure(dns_resolver_t *resolver, dns_name_t *name, isc_boolean_t dns_resolver_getmustbesecure(dns_resolver_t *resolver, dns_name_t *name); + +void +dns_resolver_settimeout(dns_resolver_t *resolver, unsigned int seconds); +/*%< + * Set the length of time the resolver will work on a query, in seconds. + * + * If timeout is 0, the default timeout will be applied. + * + * Requires: + * \li resolver to be valid. + */ + +unsigned int +dns_resolver_gettimeout(dns_resolver_t *resolver); +/*%< + * Get the current length of time the resolver will work on a query, in seconds. + * + * Requires: + * \li resolver to be valid. + */ + void dns_resolver_setclientsperquery(dns_resolver_t *resolver, isc_uint32_t min, isc_uint32_t max); diff --git a/lib/dns/include/dns/result.h b/lib/dns/include/dns/result.h index 74b84d6..adc1215 100644 --- a/lib/dns/include/dns/result.h +++ b/lib/dns/include/dns/result.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: result.h,v 1.116.48.2 2010-02-25 10:56:41 tbox Exp $ */ +/* $Id: result.h,v 1.122 2011-01-11 23:47:13 tbox Exp $ */ #ifndef DNS_RESULT_H #define DNS_RESULT_H 1 @@ -148,10 +148,11 @@ #define DNS_R_MXISADDRESS (ISC_RESULTCLASS_DNS + 102) #define DNS_R_DUPLICATE (ISC_RESULTCLASS_DNS + 103) #define DNS_R_INVALIDNSEC3 (ISC_RESULTCLASS_DNS + 104) -#define DNS_R_NOTMASTER (ISC_RESULTCLASS_DNS + 105) +#define DNS_R_NOTMASTER (ISC_RESULTCLASS_DNS + 105) #define DNS_R_BROKENCHAIN (ISC_RESULTCLASS_DNS + 106) +#define DNS_R_EXPIRED (ISC_RESULTCLASS_DNS + 107) -#define DNS_R_NRESULTS 107 /*%< Number of results */ +#define DNS_R_NRESULTS 108 /*%< Number of results */ /* * DNS wire format rcodes. diff --git a/lib/dns/include/dns/rpz.h b/lib/dns/include/dns/rpz.h new file mode 100644 index 0000000..404f517 --- /dev/null +++ b/lib/dns/include/dns/rpz.h @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: rpz.h,v 1.3 2011-01-13 04:59:26 tbox Exp $ */ + +#ifndef DNS_RPZ_H +#define DNS_RPZ_H 1 + +#include + +#include +#include +#include + +ISC_LANG_BEGINDECLS + +#define DNS_RPZ_IP_ZONE "rpz-ip" +#define DNS_RPZ_NSIP_ZONE "rpz-nsip" +#define DNS_RPZ_NSDNAME_ZONE "rpz-nsdname" + +typedef isc_uint8_t dns_rpz_cidr_bits_t; + +typedef enum { + DNS_RPZ_TYPE_BAD, + DNS_RPZ_TYPE_QNAME, + DNS_RPZ_TYPE_IP, + DNS_RPZ_TYPE_NSIP, + DNS_RPZ_TYPE_NSDNAME +} dns_rpz_type_t; + +/* + * Require DNS_RPZ_POLICY_NO_OP < DNS_RPZ_POLICY_NXDOMAIN < + * DNS_RPZ_POLICY_NODATA < DNS_RPZ_POLICY_CNAME. + */ +typedef enum { + DNS_RPZ_POLICY_GIVEN = 0, /* 'given': what something else says */ + DNS_RPZ_POLICY_NO_OP = 1, /* 'no-op': do not rewrite */ + DNS_RPZ_POLICY_NXDOMAIN = 2, /* 'nxdomain': answer with NXDOMAIN */ + DNS_RPZ_POLICY_NODATA = 3, /* 'nodata': answer with ANCOUNT=0 */ + DNS_RPZ_POLICY_CNAME = 4, /* 'cname x': answer with x's rrsets */ + DNS_RPZ_POLICY_RECORD = 5, + DNS_RPZ_POLICY_MISS, + DNS_RPZ_POLICY_ERROR +} dns_rpz_policy_t; + +/* + * Specify a response policy zone. + */ +typedef struct dns_rpz_zone dns_rpz_zone_t; + +struct dns_rpz_zone { + ISC_LINK(dns_rpz_zone_t) link; + int num; + dns_name_t origin; /* Policy zone name */ + dns_name_t nsdname; /* RPZ_NSDNAME_ZONE.origin */ + dns_rpz_policy_t policy; /* RPZ_POLICY_GIVEN or override */ + dns_name_t cname; /* override name for + RPZ_POLICY_CNAME */ +}; + +/* + * Radix trees for response policy IP addresses. + */ +typedef struct dns_rpz_cidr dns_rpz_cidr_t; + +/* + * context for finding the best policy + */ +typedef struct { + unsigned int state; +# define DNS_RPZ_REWRITTEN 0x0001 +# define DNS_RPZ_DONE_QNAME 0x0002 +# define DNS_RPZ_DONE_A 0x0004 +# define DNS_RPZ_RECURSING 0x0008 +# define DNS_RPZ_HAVE_IP 0x0010 +# define DNS_RPZ_HAVE_NSIPv4 0x0020 +# define DNS_RPZ_HAVE_NSIPv6 0x0040 +# define DNS_RPZ_HAD_NSDNAME 0x0080 + /* + * Best match so far. + */ + struct { + dns_rpz_type_t type; + dns_rpz_zone_t *rpz; + dns_rpz_cidr_bits_t prefix; + dns_rpz_policy_t policy; + dns_ttl_t ttl; + isc_result_t result; + dns_zone_t *zone; + dns_db_t *db; + dns_dbnode_t *node; + dns_rdataset_t *rdataset; + } m; + /* + * State for chasing NS names and addresses including recursion. + */ + struct { + unsigned int label; + dns_db_t *db; + dns_rdataset_t *ns_rdataset; + dns_rdatatype_t r_type; + isc_result_t r_result; + dns_rdataset_t *r_rdataset; + } ns; + /* + * State of real query while recursing for NSIP or NSDNAME. + */ + struct { + isc_result_t result; + isc_boolean_t is_zone; + isc_boolean_t authoritative; + dns_zone_t *zone; + dns_db_t *db; + dns_dbnode_t *node; + dns_rdataset_t *rdataset; + dns_rdataset_t *sigrdataset; + dns_rdatatype_t qtype; + } q; + dns_name_t *qname; + dns_name_t *r_name; + dns_name_t *fname; + dns_fixedname_t _qnamef; + dns_fixedname_t _r_namef; + dns_fixedname_t _fnamef; +} dns_rpz_st_t; + +#define DNS_RPZ_TTL_DEFAULT 5 + +/* + * So various response policy zone messages can be turned up or down. + */ +#define DNS_RPZ_ERROR_LEVEL ISC_LOG_WARNING +#define DNS_RPZ_INFO_LEVEL ISC_LOG_INFO +#define DNS_RPZ_DEBUG_LEVEL1 ISC_LOG_DEBUG(1) +#define DNS_RPZ_DEBUG_LEVEL2 ISC_LOG_DEBUG(2) + +const char * +dns_rpz_type2str(dns_rpz_type_t type); + +dns_rpz_policy_t +dns_rpz_str2policy(const char *str); + +void +dns_rpz_set_need(isc_boolean_t need); + +isc_boolean_t +dns_rpz_needed(void); + +void +dns_rpz_cidr_free(dns_rpz_cidr_t **cidr); + +void +dns_rpz_view_destroy(dns_view_t *view); + +isc_result_t +dns_rpz_new_cidr(isc_mem_t *mctx, dns_name_t *origin, + dns_rpz_cidr_t **rbtdb_cidr); +void +dns_rpz_enabled(dns_rpz_cidr_t *cidr, dns_rpz_st_t *st); + +void +dns_rpz_cidr_deleteip(dns_rpz_cidr_t *cidr, dns_name_t *name); + +void +dns_rpz_cidr_addip(dns_rpz_cidr_t *cidr, dns_name_t *name); + +isc_result_t +dns_rpz_cidr_find(dns_rpz_cidr_t *cidr, const isc_netaddr_t *netaddr, + dns_rpz_type_t type, dns_name_t *canon_name, + dns_name_t *search_name, dns_rpz_cidr_bits_t *prefix); + +dns_rpz_policy_t +dns_rpz_decode_cname(dns_rdataset_t *, dns_name_t *selfname); + +#endif /* DNS_RPZ_H */ + diff --git a/lib/dns/include/dns/rriterator.h b/lib/dns/include/dns/rriterator.h new file mode 100644 index 0000000..0087349 --- /dev/null +++ b/lib/dns/include/dns/rriterator.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: rriterator.h,v 1.2 2009-06-30 02:52:32 each Exp $ */ + +#ifndef DNS_RRITERATOR_H +#define DNS_RRITERATOR_H 1 + +/***** + ***** Module Info + *****/ + +/*! \file dns/rriterator.h + * \brief + * Functions for "walking" a zone database, visiting each RR or RRset in turn. + */ + +/***** + ***** Imports + *****/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +ISC_LANG_BEGINDECLS + +/***** + ***** Types + *****/ + +/*% + * A dns_rriterator_t is an iterator that iterates over an entire database, + * returning one RR at a time, in some arbitrary order. + */ + +typedef struct dns_rriterator { + unsigned int magic; + isc_result_t result; + dns_db_t *db; + dns_dbiterator_t *dbit; + dns_dbversion_t *ver; + isc_stdtime_t now; + dns_dbnode_t *node; + dns_fixedname_t fixedname; + dns_rdatasetiter_t *rdatasetit; + dns_rdataset_t rdataset; + dns_rdata_t rdata; +} dns_rriterator_t; + +#define RRITERATOR_MAGIC ISC_MAGIC('R', 'R', 'I', 't') +#define VALID_RRITERATOR(m) ISC_MAGIC_VALID(m, RRITERATOR_MAGIC) + +isc_result_t +dns_rriterator_init(dns_rriterator_t *it, dns_db_t *db, + dns_dbversion_t *ver, isc_stdtime_t now); + +isc_result_t +dns_rriterator_first(dns_rriterator_t *it); + +isc_result_t +dns_rriterator_nextrrset(dns_rriterator_t *it); + +isc_result_t +dns_rriterator_next(dns_rriterator_t *it); + +void +dns_rriterator_current(dns_rriterator_t *it, dns_name_t **name, + isc_uint32_t *ttl, dns_rdataset_t **rdataset, + dns_rdata_t **rdata); + +void +dns_rriterator_pause(dns_rriterator_t *it); + +void +dns_rriterator_destroy(dns_rriterator_t *it); + +ISC_LANG_ENDDECLS + +#endif /* DNS_RRITERATOR_H */ diff --git a/lib/dns/include/dns/sdb.h b/lib/dns/include/dns/sdb.h index 18995ed..5744837 100644 --- a/lib/dns/include/dns/sdb.h +++ b/lib/dns/include/dns/sdb.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sdb.h,v 1.21.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: sdb.h,v 1.23 2009-01-17 23:47:43 tbox Exp $ */ #ifndef DNS_SDB_H #define DNS_SDB_H 1 diff --git a/lib/dns/include/dns/sdlz.h b/lib/dns/include/dns/sdlz.h index 9d2a0ed..b917cc0 100644 --- a/lib/dns/include/dns/sdlz.h +++ b/lib/dns/include/dns/sdlz.h @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2005-2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2005-2007, 2009-2011 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -50,7 +50,7 @@ * USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sdlz.h,v 1.7.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: sdlz.h,v 1.14 2011-01-13 08:50:29 tbox Exp $ */ /*! \file dns/sdlz.h */ @@ -74,11 +74,10 @@ typedef struct dns_sdlzlookup dns_sdlzlookup_t; /* A simple DLZ database traversal in progress. */ typedef struct dns_sdlzallnodes dns_sdlzallnodes_t; - -typedef isc_result_t -(*dns_sdlzallnodesfunc_t)(const char *zone, void *driverarg, void *dbdata, - dns_sdlzallnodes_t *allnodes); - +typedef isc_result_t (*dns_sdlzallnodesfunc_t)(const char *zone, + void *driverarg, + void *dbdata, + dns_sdlzallnodes_t *allnodes); /*%< * Method prototype. Drivers implementing the SDLZ interface may * supply an all nodes method. This method is called when the DNS @@ -92,9 +91,9 @@ typedef isc_result_t * does not have to implement an all nodes method. */ -typedef isc_result_t -(*dns_sdlzallowzonexfr_t)(void *driverarg, void *dbdata, const char *name, - const char *client); +typedef isc_result_t (*dns_sdlzallowzonexfr_t)(void *driverarg, + void *dbdata, const char *name, + const char *client); /*%< * Method prototype. Drivers implementing the SDLZ interface may @@ -117,9 +116,9 @@ typedef isc_result_t * error. */ -typedef isc_result_t -(*dns_sdlzauthorityfunc_t)(const char *zone, void *driverarg, void *dbdata, - dns_sdlzlookup_t *lookup); +typedef isc_result_t (*dns_sdlzauthorityfunc_t)(const char *zone, + void *driverarg, void *dbdata, + dns_sdlzlookup_t *lookup); /*%< * Method prototype. Drivers implementing the SDLZ interface may @@ -131,9 +130,9 @@ typedef isc_result_t * method. */ -typedef isc_result_t -(*dns_sdlzcreate_t)(const char *dlzname, unsigned int argc, char *argv[], - void *driverarg, void **dbdata); +typedef isc_result_t (*dns_sdlzcreate_t)(const char *dlzname, + unsigned int argc, char *argv[], + void *driverarg, void **dbdata); /*%< * Method prototype. Drivers implementing the SDLZ interface may @@ -142,8 +141,7 @@ typedef isc_result_t * does not have to implement a create method. */ -typedef void -(*dns_sdlzdestroy_t)(void *driverarg, void *dbdata); +typedef void (*dns_sdlzdestroy_t)(void *driverarg, void *dbdata); /*%< * Method prototype. Drivers implementing the SDLZ interface may @@ -198,6 +196,87 @@ typedef isc_result_t * lookup method. */ +typedef isc_result_t (*dns_sdlznewversion_t)(const char *zone, + void *driverarg, void *dbdata, + void **versionp); +/*%< + * Method prototype. Drivers implementing the SDLZ interface may + * supply a newversion method. This method is called to start a + * write transaction on a zone and should only be implemented by + * writeable backends. + * When implemented, the driver should create a new transaction, and + * fill *versionp with a pointer to the transaction state. The + * closeversion function will be called to close the transaction. + */ + +typedef void (*dns_sdlzcloseversion_t)(const char *zone, isc_boolean_t commit, + void *driverarg, void *dbdata, + void **versionp); +/*%< + * Method prototype. Drivers implementing the SDLZ interface must + * supply a closeversion method if they supply a newversion method. + * When implemented, the driver should close the given transaction, + * committing changes if 'commit' is ISC_TRUE. If 'commit' is not true + * then all changes should be discarded and the database rolled back. + * If the call is successful then *versionp should be set to NULL + */ + +typedef isc_result_t (*dns_sdlzconfigure_t)(dns_view_t *view, void *driverarg, + void *dbdata); +/*%< + * Method prototype. Drivers implementing the SDLZ interface may + * supply a configure method. When supplied, it will be called + * immediately after the create method to give the driver a chance + * to configure writeable zones + */ + + +typedef isc_boolean_t (*dns_sdlzssumatch_t)(const char *signer, + const char *name, + const char *tcpaddr, + const char *type, + const char *key, + isc_uint32_t keydatalen, + unsigned char *keydata, + void *driverarg, + void *dbdata); + +/*%< + * Method prototype. Drivers implementing the SDLZ interface may + * supply a ssumatch method. If supplied, then ssumatch will be + * called to authorize any zone updates. The driver should return + * ISC_TRUE to allow the update, and ISC_FALSE to deny it. For a DLZ + * controlled zone, this is the only access control on updates. + */ + + +typedef isc_result_t (*dns_sdlzmodrdataset_t)(const char *name, + const char *rdatastr, + void *driverarg, void *dbdata, + void *version); +/*%< + * Method prototype. Drivers implementing the SDLZ interface may + * supply addrdataset and subtractrdataset methods. If supplied, then these + * will be called when rdatasets are added/subtracted during + * updates. The version parameter comes from a call to the sdlz + * newversion() method from the driver. The rdataset parameter is a + * linearise string representation of the rdataset change. The format + * is the same as used by dig when displaying records. The fields are + * tab delimited. + */ + +typedef isc_result_t (*dns_sdlzdelrdataset_t)(const char *name, + const char *type, + void *driverarg, void *dbdata, + void *version); +/*%< + * Method prototype. Drivers implementing the SDLZ interface may + * supply a delrdataset method. If supplied, then this + * function will be called when rdatasets are deleted during + * updates. The call should remove all rdatasets of the given type for + * the specified name. + */ + typedef struct dns_sdlzmethods { dns_sdlzcreate_t create; dns_sdlzdestroy_t destroy; @@ -206,6 +285,13 @@ typedef struct dns_sdlzmethods { dns_sdlzauthorityfunc_t authority; dns_sdlzallnodesfunc_t allnodes; dns_sdlzallowzonexfr_t allowzonexfr; + dns_sdlznewversion_t newversion; + dns_sdlzcloseversion_t closeversion; + dns_sdlzconfigure_t configure; + dns_sdlzssumatch_t ssumatch; + dns_sdlzmodrdataset_t addrdataset; + dns_sdlzmodrdataset_t subtractrdataset; + dns_sdlzdelrdataset_t delrdataset; } dns_sdlzmethods_t; isc_result_t @@ -261,6 +347,14 @@ dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname, */ +isc_result_t +dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass, + dns_name_t *name, dns_db_t **dbp); +/*%< + * Create the database pointers for a writeable SDLZ zone + */ + + ISC_LANG_ENDDECLS #endif /* SDLZ_H */ diff --git a/lib/dns/include/dns/secalg.h b/lib/dns/include/dns/secalg.h index 0eb0333..49613d5 100644 --- a/lib/dns/include/dns/secalg.h +++ b/lib/dns/include/dns/secalg.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: secalg.h,v 1.19 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: secalg.h,v 1.21 2009-10-12 23:48:02 tbox Exp $ */ #ifndef DNS_SECALG_H #define DNS_SECALG_H 1 @@ -66,6 +66,13 @@ dns_secalg_totext(dns_secalg_t secalg, isc_buffer_t *target); *\li ISC_R_NOSPACE target buffer is too small */ +#define DNS_SECALG_FORMATSIZE 20 +void +dns_secalg_format(dns_secalg_t alg, char *cp, unsigned int size); +/*%< + * Wrapper for dns_secalg_totext(), writing text into 'cp' + */ + ISC_LANG_ENDDECLS #endif /* DNS_SECALG_H */ diff --git a/lib/dns/include/dns/soa.h b/lib/dns/include/dns/soa.h index c1ad706..6ebf61d 100644 --- a/lib/dns/include/dns/soa.h +++ b/lib/dns/include/dns/soa.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: soa.h,v 1.9 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: soa.h,v 1.12 2009-09-10 01:47:09 each Exp $ */ #ifndef DNS_SOA_H #define DNS_SOA_H 1 @@ -40,6 +40,28 @@ ISC_LANG_BEGINDECLS +#define DNS_SOA_BUFFERSIZE ((2 * DNS_NAME_MAXWIRE) + (4 * 5)) + +isc_result_t +dns_soa_buildrdata(dns_name_t *origin, dns_name_t *contact, + dns_rdataclass_t rdclass, + isc_uint32_t serial, isc_uint32_t refresh, + isc_uint32_t retry, isc_uint32_t expire, + isc_uint32_t minimum, unsigned char *buffer, + dns_rdata_t *rdata); +/*%< + * Build the rdata of an SOA record. + * + * Requires: + *\li buffer Points to a temporary buffer of at least + * DNS_SOA_BUFFERSIZE bytes. + *\li rdata Points to an initialized dns_rdata_t. + * + * Ensures: + * \li *rdata Contains a valid SOA rdata. The 'data' member + * refers to 'buffer'. + */ + isc_uint32_t dns_soa_getserial(dns_rdata_t *rdata); isc_uint32_t diff --git a/lib/dns/include/dns/ssu.h b/lib/dns/include/dns/ssu.h index 686928b..5d6c178 100644 --- a/lib/dns/include/dns/ssu.h +++ b/lib/dns/include/dns/ssu.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2008, 2010, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ssu.h,v 1.24 2008-01-18 23:46:58 tbox Exp $ */ +/* $Id: ssu.h,v 1.28 2011-01-06 23:47:00 tbox Exp $ */ #ifndef DNS_SSU_H #define DNS_SSU_H 1 @@ -25,6 +25,7 @@ #include #include +#include ISC_LANG_BEGINDECLS @@ -40,7 +41,9 @@ ISC_LANG_BEGINDECLS #define DNS_SSUMATCHTYPE_SUBDOMAINKRB5 9 #define DNS_SSUMATCHTYPE_TCPSELF 10 #define DNS_SSUMATCHTYPE_6TO4SELF 11 -#define DNS_SSUMATCHTYPE_MAX 11 /* max value */ +#define DNS_SSUMATCHTYPE_EXTERNAL 12 +#define DNS_SSUMATCHTYPE_DLZ 13 +#define DNS_SSUMATCHTYPE_MAX 12 /* max value */ isc_result_t dns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **table); @@ -57,6 +60,16 @@ dns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **table); *\li ISC_R_NOMEMORY */ +isc_result_t +dns_ssutable_createdlz(isc_mem_t *mctx, dns_ssutable_t **tablep, + dns_dlzdb_t *dlzdatabase); +/*%< + * Create an SSU table that contains a dlzdatabase pointer, and a + * single rule with matchtype DNS_SSUMATCHTYPE_DLZ. This type of SSU + * table is used by writeable DLZ drivers to offload authorization for + * updates to the driver. + */ + void dns_ssutable_attach(dns_ssutable_t *source, dns_ssutable_t **targetp); /*%< @@ -120,7 +133,7 @@ dns_ssutable_addrule(dns_ssutable_t *table, isc_boolean_t grant, isc_boolean_t dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer, dns_name_t *name, isc_netaddr_t *tcpaddr, - dns_rdatatype_t type); + dns_rdatatype_t type, const dst_key_t *key); /*%< * Checks that the attempted update of (name, type) is allowed according * to the rules specified in the simple-secure-update rule table. If @@ -184,6 +197,16 @@ isc_result_t dns_ssutable_nextrule(dns_ssurule_t *rule, *\li #ISC_R_NOMORE */ + +/*%< + * Check a policy rule via an external application + */ +isc_boolean_t +dns_ssu_external_match(dns_name_t *identity, dns_name_t *signer, + dns_name_t *name, isc_netaddr_t *tcpaddr, + dns_rdatatype_t type, const dst_key_t *key, + isc_mem_t *mctx); + ISC_LANG_ENDDECLS #endif /* DNS_SSU_H */ diff --git a/lib/dns/include/dns/stats.h b/lib/dns/include/dns/stats.h index 853c1e9..c19b0c7 100644 --- a/lib/dns/include/dns/stats.h +++ b/lib/dns/include/dns/stats.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: stats.h,v 1.18.56.2 2009-01-29 23:47:44 tbox Exp $ */ +/* $Id: stats.h,v 1.20 2009-01-27 23:47:54 tbox Exp $ */ #ifndef DNS_STATS_H #define DNS_STATS_H 1 diff --git a/lib/dns/include/dns/tkey.h b/lib/dns/include/dns/tkey.h index cb1fe0e..f9e34f8 100644 --- a/lib/dns/include/dns/tkey.h +++ b/lib/dns/include/dns/tkey.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: tkey.h,v 1.26.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: tkey.h,v 1.32 2011-01-08 23:47:01 tbox Exp $ */ #ifndef DNS_TKEY_H #define DNS_TKEY_H 1 @@ -44,6 +44,7 @@ struct dns_tkeyctx { gss_cred_id_t gsscred; isc_mem_t *mctx; isc_entropy_t *ectx; + char *gssapi_keytab; }; isc_result_t @@ -123,7 +124,8 @@ dns_tkey_builddhquery(dns_message_t *msg, dst_key_t *key, dns_name_t *name, isc_result_t dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname, isc_buffer_t *intoken, isc_uint32_t lifetime, - gss_ctx_id_t *context, isc_boolean_t win2k); + gss_ctx_id_t *context, isc_boolean_t win2k, + isc_mem_t *mctx, char **err_message); /*%< * Builds a query containing a TKEY that will generate a GSSAPI context. * The key is requested to have the specified lifetime (in seconds). @@ -141,6 +143,7 @@ dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname, *\li ISC_R_SUCCESS msg was successfully updated to include the * query to be sent *\li other an error occurred while building the message + *\li *err_message optional error message */ @@ -187,7 +190,7 @@ isc_result_t dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg, dns_name_t *gname, gss_ctx_id_t *context, isc_buffer_t *outtoken, dns_tsigkey_t **outkey, - dns_tsig_keyring_t *ring); + dns_tsig_keyring_t *ring, char **err_message); /*%< * XXX */ @@ -211,12 +214,11 @@ dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg, * component of the query or response */ - isc_result_t dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg, dns_name_t *server, gss_ctx_id_t *context, dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring, - isc_boolean_t win2k); + isc_boolean_t win2k, char **err_message); /* * Client side negotiation of GSS-TSIG. Process the response diff --git a/lib/dns/include/dns/tsec.h b/lib/dns/include/dns/tsec.h new file mode 100644 index 0000000..698634e --- /dev/null +++ b/lib/dns/include/dns/tsec.h @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: tsec.h,v 1.6 2010-12-09 00:54:34 marka Exp $ */ + +#ifndef DNS_TSEC_H +#define DNS_TSEC_H 1 + +/***** + ***** Module Info + *****/ + +/*! \file + * + * \brief + * The TSEC (Transaction Security) module is an abstraction layer for managing + * DNS transaction mechanisms such as TSIG or SIG(0). A TSEC structure is a + * mechanism-independent object containing key information specific to the + * mechanism, and is expected to be used as an argument to other modules + * that use transaction security in a mechanism-independent manner. + * + * MP: + *\li A TSEC structure is expected to be thread-specific. No inter-thread + * synchronization is ensured in multiple access to a single TSEC + * structure. + * + * Resources: + *\li TBS + * + * Security: + *\li This module does not handle any low-level data directly, and so no + * security issue specific to this module is anticipated. + */ + +#include + +#include + +ISC_LANG_BEGINDECLS + +/*** + *** Types + ***/ + +/*% + * Transaction security types. + */ +typedef enum { + dns_tsectype_none, + dns_tsectype_tsig, + dns_tsectype_sig0 +} dns_tsectype_t; + +isc_result_t +dns_tsec_create(isc_mem_t *mctx, dns_tsectype_t type, dst_key_t *key, + dns_tsec_t **tsecp); +/*%< + * Create a TSEC structure and stores a type-dependent key structure in it. + * For a TSIG key (type is dns_tsectype_tsig), dns_tsec_create() creates a + * TSIG key structure from '*key' and keeps it in the structure. For other + * types, this function simply retains '*key' in the structure. In either + * case, the ownership of '*key' is transferred to the TSEC module; the caller + * must not modify or destroy it after the call to dns_tsec_create(). + * + * Requires: + * + *\li 'mctx' is a valid memory context. + * + *\li 'type' is a valid value of dns_tsectype_t (see above). + * + *\li 'key' is a valid key. + * + *\li tsecp != NULL && *tsecp == NULL. + * + * Returns: + * + *\li #ISC_R_SUCCESS On success. + * + *\li Anything else Failure. + */ + +void +dns_tsec_destroy(dns_tsec_t **tsecp); +/*%< + * Destroy the TSEC structure. The stored key is also detached or destroyed. + * + * Requires + * + *\li '*tsecp' is a valid TSEC structure. + * + * Ensures + * + *\li *tsecp == NULL. + * + */ + +dns_tsectype_t +dns_tsec_gettype(dns_tsec_t *tsec); +/*%< + * Return the TSEC type of '*tsec'. + * + * Requires + * + *\li 'tsec' is a valid TSEC structure. + * + */ + +void +dns_tsec_getkey(dns_tsec_t *tsec, void *keyp); +/*%< + * Return the TSEC key of '*tsec' in '*keyp'. + * + * Requires + * + *\li keyp != NULL + * + * Ensures + * + *\li *tsecp points to a valid key structure depending on the TSEC type. + */ + +#endif /* DNS_TSEC_H */ diff --git a/lib/dns/include/dns/tsig.h b/lib/dns/include/dns/tsig.h index 5161fb3..ef9423b 100644 --- a/lib/dns/include/dns/tsig.h +++ b/lib/dns/include/dns/tsig.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: tsig.h,v 1.51.332.4 2010-12-09 01:12:55 marka Exp $ */ +/* $Id: tsig.h,v 1.59 2011-01-11 23:47:13 tbox Exp $ */ #ifndef DNS_TSIG_H #define DNS_TSIG_H 1 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -69,6 +70,7 @@ struct dns_tsig_keyring { unsigned int generated; unsigned int maxgenerated; ISC_LIST(dns_tsigkey_t) lru; + unsigned int references; }; struct dns_tsigkey { @@ -253,9 +255,30 @@ dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp); *\li #ISC_R_NOMEMORY */ +isc_result_t +dns_tsigkeyring_add(dns_tsig_keyring_t *ring, dns_name_t *name, + dns_tsigkey_t *tkey); +/*%< + * Place a TSIG key onto a key ring. + * + * Requires: + *\li 'ring', 'name' and 'tkey' are not NULL + * + * Returns: + *\li #ISC_R_SUCCESS + *\li Any other value indicates failure. + */ + + +void +dns_tsigkeyring_attach(dns_tsig_keyring_t *source, dns_tsig_keyring_t **target); void -dns_tsigkeyring_destroy(dns_tsig_keyring_t **ringp); +dns_tsigkeyring_detach(dns_tsig_keyring_t **ringp); + +isc_result_t +dns_tsigkeyring_dumpanddetach(dns_tsig_keyring_t **ringp, FILE *fp); + /*%< * Destroy a TSIG key ring. * @@ -263,6 +286,9 @@ dns_tsigkeyring_destroy(dns_tsig_keyring_t **ringp); *\li 'ringp' is not NULL */ +void +dns_keyring_restore(dns_tsig_keyring_t *ring, FILE *fp); + ISC_LANG_ENDDECLS #endif /* DNS_TSIG_H */ diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h index 4e4c195..dc02c86 100644 --- a/lib/dns/include/dns/types.h +++ b/lib/dns/include/dns/types.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: types.h,v 1.130.50.7 2010-05-14 23:47:50 tbox Exp $ */ +/* $Id: types.h,v 1.143 2010-12-08 02:46:16 marka Exp $ */ #ifndef DNS_TYPES_H #define DNS_TYPES_H 1 @@ -44,6 +44,10 @@ typedef struct dns_adbentry dns_adbentry_t; typedef struct dns_adbfind dns_adbfind_t; typedef ISC_LIST(dns_adbfind_t) dns_adbfindlist_t; typedef struct dns_byaddr dns_byaddr_t; +typedef struct dns_client dns_client_t; +typedef void dns_clientrestrans_t; +typedef void dns_clientreqtrans_t; +typedef void dns_clientupdatetrans_t; typedef struct dns_cache dns_cache_t; typedef isc_uint16_t dns_cert_t; typedef struct dns_compress dns_compress_t; @@ -63,6 +67,10 @@ typedef struct dns_dispatchevent dns_dispatchevent_t; typedef struct dns_dispatchlist dns_dispatchlist_t; typedef struct dns_dispatchmgr dns_dispatchmgr_t; typedef struct dns_dispentry dns_dispentry_t; +typedef struct dns_dns64 dns_dns64_t; +typedef ISC_LIST(dns_dns64_t) dns_dns64list_t; +typedef struct dns_dnsseckey dns_dnsseckey_t; +typedef ISC_LIST(dns_dnsseckey_t) dns_dnsseckeylist_t; typedef struct dns_dumpctx dns_dumpctx_t; typedef struct dns_fetch dns_fetch_t; typedef struct dns_fixedname dns_fixedname_t; @@ -72,6 +80,7 @@ typedef struct dns_iptable dns_iptable_t; typedef isc_uint32_t dns_iterations_t; typedef isc_uint16_t dns_keyflags_t; typedef struct dns_keynode dns_keynode_t; +typedef ISC_LIST(dns_keynode_t) dns_keynodelist_t; typedef struct dns_keytable dns_keytable_t; typedef isc_uint16_t dns_keytag_t; typedef struct dns_loadctx dns_loadctx_t; @@ -111,6 +120,7 @@ typedef struct dns_stats dns_stats_t; typedef isc_uint32_t dns_rdatastatstype_t; typedef struct dns_tkeyctx dns_tkeyctx_t; typedef isc_uint16_t dns_trust_t; +typedef struct dns_tsec dns_tsec_t; typedef struct dns_tsig_keyring dns_tsig_keyring_t; typedef struct dns_tsigkey dns_tsigkey_t; typedef isc_uint32_t dns_ttl_t; @@ -179,6 +189,12 @@ typedef enum { dns_masterformat_raw = 2 } dns_masterformat_t; +typedef enum { + dns_v4_aaaa_ok = 0, + dns_v4_aaaa_filter = 1, + dns_v4_aaaa_break_dnssec = 2 +} dns_v4_aaaa_t; + /* * These are generated by gen.c. */ diff --git a/lib/dns/include/dns/validator.h b/lib/dns/include/dns/validator.h index fb5b834..5fec135 100644 --- a/lib/dns/include/dns/validator.h +++ b/lib/dns/include/dns/validator.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: validator.h,v 1.41.48.5 2010-02-25 10:56:41 tbox Exp $ */ +/* $Id: validator.h,v 1.46 2010-02-25 05:08:01 tbox Exp $ */ #ifndef DNS_VALIDATOR_H #define DNS_VALIDATOR_H 1 diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index ec96d4c..4b24023 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: view.h,v 1.111.88.6 2010-09-24 08:30:28 tbox Exp $ */ +/* $Id: view.h,v 1.132 2011-01-13 01:59:28 marka Exp $ */ #ifndef DNS_VIEW_H #define DNS_VIEW_H 1 @@ -73,6 +73,8 @@ #include #include +#include +#include #include ISC_LANG_BEGINDECLS @@ -92,8 +94,13 @@ struct dns_view { dns_cache_t * cache; dns_db_t * cachedb; dns_db_t * hints; - dns_keytable_t * secroots; - dns_keytable_t * trustedkeys; + + /* + * security roots. + * internal use only; access via * dns_view_getsecroots() + */ + dns_keytable_t * secroots_priv; + isc_mutex_t lock; isc_boolean_t frozen; isc_task_t * task; @@ -102,6 +109,7 @@ struct dns_view { isc_event_t reqevent; isc_stats_t * resstats; dns_stats_t * resquerystats; + isc_boolean_t cacheshared; /* Configurable data. */ dns_tsig_keyring_t * statickeys; @@ -129,6 +137,10 @@ struct dns_view { dns_acl_t * transferacl; dns_acl_t * updateacl; dns_acl_t * upfwdacl; + dns_acl_t * denyansweracl; + dns_rbt_t * answeracl_exclude; + dns_rbt_t * denyanswernames; + dns_rbt_t * answernames_exclude; isc_boolean_t requestixfr; isc_boolean_t provideixfr; isc_boolean_t requestnsid; @@ -145,6 +157,11 @@ struct dns_view { dns_name_t * dlv; dns_fixedname_t dlv_fixed; isc_uint16_t maxudp; + dns_v4_aaaa_t v4_aaaa; + dns_acl_t * v4_aaaa_acl; + dns_dns64list_t dns64; + unsigned int dns64cnt; + ISC_LIST(dns_rpz_zone_t) rpz_zones; /* * Configurable data for server use only, @@ -162,6 +179,17 @@ struct dns_view { unsigned int attributes; /* Under owner's locking control. */ ISC_LINK(struct dns_view) link; + dns_viewlist_t * viewlist; + + dns_zone_t * managed_keys; + +#ifdef BIND9 + /* File in which to store configuration for newly added zones */ + char * new_zone_file; + + void * new_zone_config; + void (*cfg_destroy)(void **); +#endif }; #define DNS_VIEW_MAGIC ISC_MAGIC('V','i','e','w') @@ -310,8 +338,12 @@ dns_view_createresolver(dns_view_t *view, void dns_view_setcache(dns_view_t *view, dns_cache_t *cache); +void +dns_view_setcache2(dns_view_t *view, dns_cache_t *cache, isc_boolean_t shared); /*%< - * Set the view's cache database. + * Set the view's cache database. If 'shared' is true, this means the cache + * is created by another view and is shared with that view. dns_view_setcache() + * is a backward compatible version equivalent to setcache2(..., ISC_FALSE). * * Requires: * @@ -346,6 +378,8 @@ dns_view_sethints(dns_view_t *view, dns_db_t *hints); void dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring); +void +dns_view_setdynamickeyring(dns_view_t *view, dns_tsig_keyring_t *ring); /*%< * Set the view's static TSIG keys * @@ -362,6 +396,15 @@ dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring); */ void +dns_view_getdynamickeyring(dns_view_t *view, dns_tsig_keyring_t **ringp); +/*%< + * Return the views dynamic keys. + * + * \li 'view' is a valid, unfrozen view. + * \li 'ringp' != NULL && ringp == NULL. + */ + +void dns_view_setdstport(dns_view_t *view, in_port_t dstport); /*%< * Set the view's destination port. This is the port to @@ -398,7 +441,7 @@ dns_view_addzone(dns_view_t *view, dns_zone_t *zone); void dns_view_freeze(dns_view_t *view); /*%< - * Freeze view. + * Freeze view. No changes can be made to view configuration while frozen. * * Requires: * @@ -409,14 +452,44 @@ dns_view_freeze(dns_view_t *view); *\li 'view' is frozen. */ +void +dns_view_thaw(dns_view_t *view); +/*%< + * Thaw view. This allows zones to be added or removed at runtime. This is + * NOT thread-safe; the caller MUST have run isc_task_exclusive() prior to + * thawing the view. + * + * Requires: + * + *\li 'view' is a valid, frozen view. + * + * Ensures: + * + *\li 'view' is no longer frozen. + */ isc_result_t dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, isc_stdtime_t now, unsigned int options, isc_boolean_t use_hints, dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset); +isc_result_t +dns_view_find2(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, + isc_stdtime_t now, unsigned int options, + isc_boolean_t use_hints, isc_boolean_t use_static_stub, + dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname, + dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset); /*%< * Find an rdataset whose owner name is 'name', and whose type is * 'type'. + * In general, this function first searches view's zone and cache DBs for the + * best match data against 'name'. If nothing found there, and if 'use_hints' + * is ISC_TRUE, the view's hint DB (if configured) is searched. + * If the view is configured with a static-stub zone which gives the longest + * match for 'name' among the zones, however, the cache DB is not consulted + * unless 'use_static_stub' is ISC_FALSE (see below about this argument). + * + * dns_view_find() is a backward compatible version equivalent to + * dns_view_find2() with use_static_stub argument being ISC_FALSE. * * Notes: * @@ -432,6 +505,23 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, * in the hints database but not the type, the result code will be * #DNS_R_HINTNXRRSET. * + *\li If 'use_static_stub' is ISC_FALSE and the longest match zone for 'name' + * is a static-stub zone, it's ignored and the cache and/or hints will be + * searched. In the majority of the cases this argument should be + * ISC_FALSE. The only known usage of this argument being ISC_TRUE is + * if this search is for a "bailiwick" glue A or AAAA RRset that may + * best match a static-stub zone. Consider the following example: + * this view is configured with a static-stub zone "example.com", + * and an attempt of recursive resolution needs to send a query for the + * zone. In this case it's quite likely that the resolver is trying to + * find A/AAAA RRs for the apex name "example.com". And, to honor the + * static-stub configuration it needs to return the glue RRs in the + * static-stub zone even if that exact RRs coming from the authoritative + * zone has been cached. + * In other general cases, the requested data is better to be + * authoritative, either locally configured or retrieved from an external + * server, and the data in the static-stub zone should better be ignored. + * *\li 'foundname' must meet the requirements of dns_db_find(). * *\li If 'sigrdataset' is not NULL, and there is a SIG rdataset which @@ -728,8 +818,14 @@ dns_view_dumpdbtostream(dns_view_t *view, FILE *fp); isc_result_t dns_view_flushcache(dns_view_t *view); +isc_result_t +dns_view_flushcache2(dns_view_t *view, isc_boolean_t fixuponly); /*%< - * Flush the view's cache (and ADB). + * Flush the view's cache (and ADB). If 'fixuponly' is true, it only updates + * the internal reference to the cache DB with omitting actual flush operation. + * 'fixuponly' is intended to be used for a view that shares a cache with + * a different view. dns_view_flushcache() is a backward compatible version + * that always sets fixuponly to false. * * Requires: * 'view' is valid. @@ -878,4 +974,105 @@ dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp); *\li 'statsp' != NULL && '*statsp' != NULL */ +isc_boolean_t +dns_view_iscacheshared(dns_view_t *view); +/*%< + * Check if the view shares the cache created by another view. + * + * Requires: + * \li 'view' is valid. + * + * Returns: + *\li #ISC_TRUE if the cache is shared. + *\li #ISC_FALSE otherwise. + */ + +isc_result_t +dns_view_initsecroots(dns_view_t *view, isc_mem_t *mctx); +/*%< + * Initialize security roots for the view. (Note that secroots is + * NULL until this function is called, so any function using + * secroots must check its validity first. One way to do this is + * use dns_view_getsecroots() and check its return value.) + * + * Requires: + * \li 'view' is valid. + * \li 'view->secroots' is NULL. + * + * Returns: + *\li ISC_R_SUCCESS + *\li Any other result indicates failure + */ + +isc_result_t +dns_view_getsecroots(dns_view_t *view, dns_keytable_t **ktp); +/*%< + * Get the security roots for this view. Returns ISC_R_NOTFOUND if + * the security roots keytable has not been initialized for the view. + * + * '*ktp' is attached on success; the caller is responsible for + * detaching it with dns_keytable_detach(). + * + * Requires: + * \li 'view' is valid. + * \li 'ktp' is not NULL and '*ktp' is NULL. + * + * Returns: + *\li ISC_R_SUCCESS + *\li ISC_R_NOTFOUND + */ + +isc_result_t +dns_view_issecuredomain(dns_view_t *view, dns_name_t *name, + isc_boolean_t *secure_domain); +/*%< + * Is 'name' at or beneath a trusted key? Put answer in + * '*secure_domain'. + * + * Requires: + * \li 'view' is valid. + * + * Returns: + *\li ISC_R_SUCCESS + *\li Any other value indicates failure + */ + +void +dns_view_untrust(dns_view_t *view, dns_name_t *keyname, + dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx); +/*%< + * Remove keys that match 'keyname' and 'dnskey' from the views trust + * anchors. + * + * Requires: + * \li 'view' is valid. + * \li 'keyname' is valid. + * \li 'mctx' is valid. + * \li 'dnskey' is valid. + */ + +void +dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx, + void (*cfg_destroy)(void **)); +/*%< + * Set whether or not to allow zones to be created or deleted at runtime. + * + * If 'allow' is ISC_TRUE, determines the filename into which new zone + * configuration will be written. Preserves the configuration context + * (a pointer to which is passed in 'cfgctx') for use when parsing new + * zone configuration. 'cfg_destroy' points to a callback routine to + * destroy the configuration context when the view is destroyed. (This + * roundabout method is used in order to avoid libdns having a dependency + * on libisccfg and libbind9.) + * + * If 'allow' is ISC_FALSE, removes any existing references to + * configuration context and frees any memory. + * + * Requires: + * \li 'view' is valid. + */ + +void +dns_view_restorekeyring(dns_view_t *view); + #endif /* DNS_VIEW_H */ diff --git a/lib/dns/include/dns/xfrin.h b/lib/dns/include/dns/xfrin.h index b957e25..58910d2 100644 --- a/lib/dns/include/dns/xfrin.h +++ b/lib/dns/include/dns/xfrin.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: xfrin.h,v 1.28.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: xfrin.h,v 1.30 2009-01-17 23:47:43 tbox Exp $ */ #ifndef DNS_XFRIN_H #define DNS_XFRIN_H 1 diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index 96cb998..67756d9 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.h,v 1.160.50.8 2010-12-14 23:46:09 tbox Exp $ */ +/* $Id: zone.h,v 1.182 2010-12-18 01:56:22 each Exp $ */ #ifndef DNS_ZONE_H #define DNS_ZONE_H 1 @@ -40,7 +40,10 @@ typedef enum { dns_zone_none, dns_zone_master, dns_zone_slave, - dns_zone_stub + dns_zone_stub, + dns_zone_staticstub, + dns_zone_key, + dns_zone_dlz } dns_zonetype_t; #define DNS_ZONEOPT_SERVERS 0x00000001U /*%< perform server checks */ @@ -70,6 +73,10 @@ typedef enum { #define DNS_ZONEOPT_TRYTCPREFRESH 0x01000000U /*%< try tcp refresh on udp failure */ #define DNS_ZONEOPT_NOTIFYTOSOA 0x02000000U /*%< Notify the SOA MNAME */ #define DNS_ZONEOPT_NSEC3TESTZONE 0x04000000U /*%< nsec3-test-zone */ +#define DNS_ZONEOPT_SECURETOINSECURE 0x08000000U /*%< dnssec-secure-to-insecure */ +#define DNS_ZONEOPT_DNSKEYKSKONLY 0x10000000U /*%< dnssec-dnskey-kskonly */ +#define DNS_ZONEOPT_CHECKDUPRR 0x20000000U /*%< check-dup-records */ +#define DNS_ZONEOPT_CHECKDUPRRFAIL 0x40000000U /*%< fatal check-dup-records failures */ #ifndef NOMINUM_PUBLIC /* @@ -78,6 +85,14 @@ typedef enum { #define DNS_ZONEOPT_NOTIFYFORWARD 0x80000000U /* forward notify to master */ #endif /* NOMINUM_PUBLIC */ +/* + * Zone key maintenance options + */ +#define DNS_ZONEKEY_ALLOW 0x00000001U /*%< fetch keys on command */ +#define DNS_ZONEKEY_MAINTAIN 0x00000002U /*%< publish/sign on schedule */ +#define DNS_ZONEKEY_CREATE 0x00000004U /*%< make keys when needed */ +#define DNS_ZONEKEY_FULLSIGN 0x00000008U /*%< roll to new keys immediately */ + #ifndef DNS_ZONE_MINREFRESH #define DNS_ZONE_MINREFRESH 300 /*%< 5 minutes */ #endif @@ -367,6 +382,22 @@ dns_zone_getdb(dns_zone_t *zone, dns_db_t **dbp); *\li DNS_R_NOTLOADED */ +void +dns_zone_setdb(dns_zone_t *zone, dns_db_t *db); +/*%< + * Sets the zone database to 'db'. + * + * This function is expected to be used to configure a zone with a + * database which is not loaded from a file or zone transfer. + * It can be used for a general purpose zone, but right now its use + * is limited to static-stub zones to avoid possible undiscovered + * problems in the general cases. + * + * Require: + *\li 'zone' to be a valid zone of static-stub. + *\li zone doesn't have a database. + */ + isc_result_t dns_zone_setdbtype(dns_zone_t *zone, unsigned int dbargc, const char * const *dbargv); @@ -568,6 +599,25 @@ dns_zone_getoptions(dns_zone_t *zone); */ void +dns_zone_setkeyopt(dns_zone_t *zone, unsigned int option, isc_boolean_t value); +/*%< + * Set key options on ('value' == ISC_TRUE) or off ('value' == + * #ISC_FALSE). + * + * Require: + *\li 'zone' to be a valid zone. + */ + +unsigned int +dns_zone_getkeyopts(dns_zone_t *zone); +/*%< + * Returns the current zone key options. + * + * Require: + *\li 'zone' to be a valid zone. + */ + +void dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val); /*%< * Set the minimum refresh time. @@ -1747,6 +1797,61 @@ dns_zone_getprivatetype(dns_zone_t *zone); * will not be permanent. */ +void +dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign); +/*%< + * Update the zone's DNSKEY set from the key repository. + * + * If 'fullsign' is true, trigger an immediate full signing of + * the zone with the new key. Otherwise, if there are no keys or + * if the new keys are for algorithms that have already signed the + * zone, then the zone can be re-signed incrementally. + */ + +isc_result_t +dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version, + unsigned int *errors); +/*% + * Check if the name servers for the zone are sane (have address, don't + * refer to CNAMEs/DNAMEs. The number of constiancy errors detected in + * returned in '*errors' + * + * Requires: + * \li 'zone' to be valid. + * \li 'db' to be valid. + * \li 'version' to be valid or NULL. + * \li 'errors' to be non NULL. + * + * Returns: + * ISC_R_SUCCESS if there were no errors examining the zone contents. + */ + +void +dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added); +/*% + * Sets the value of zone->added, which should be ISC_TRUE for + * zones that were originally added by "rndc addzone". + * + * Requires: + * \li 'zone' to be valid. + */ + +isc_boolean_t +dns_zone_getadded(dns_zone_t *zone); +/*% + * Returns ISC_TRUE if the zone was originally added at runtime + * using "rndc addzone". + * + * Requires: + * \li 'zone' to be valid. + */ + +isc_result_t +dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db); +/*% + * Load the origin names for a writeable DLZ database. + */ + ISC_LANG_ENDDECLS #endif /* DNS_ZONE_H */ diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h index 1a30d2b..3c999f6 100644 --- a/lib/dns/include/dst/dst.h +++ b/lib/dns/include/dst/dst.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dst.h,v 1.12.50.3 2010-12-09 01:12:55 marka Exp $ */ +/* $Id: dst.h,v 1.31 2011-01-11 23:47:14 tbox Exp $ */ #ifndef DST_DST_H #define DST_DST_H 1 @@ -23,8 +23,11 @@ /*! \file dst/dst.h */ #include +#include #include +#include +#include #include @@ -55,6 +58,7 @@ typedef struct dst_context dst_context_t; #define DST_ALG_NSEC3RSASHA1 7 #define DST_ALG_RSASHA256 8 #define DST_ALG_RSASHA512 10 +#define DST_ALG_ECCGOST 12 #define DST_ALG_HMACMD5 157 #define DST_ALG_GSSAPI 160 #define DST_ALG_HMACSHA1 161 /* XXXMPA */ @@ -80,12 +84,55 @@ typedef struct dst_context dst_context_t; #define DST_TYPE_PRIVATE 0x2000000 #define DST_TYPE_PUBLIC 0x4000000 +/* Key timing metadata definitions */ +#define DST_TIME_CREATED 0 +#define DST_TIME_PUBLISH 1 +#define DST_TIME_ACTIVATE 2 +#define DST_TIME_REVOKE 3 +#define DST_TIME_INACTIVE 4 +#define DST_TIME_DELETE 5 +#define DST_TIME_DSPUBLISH 6 +#define DST_MAX_TIMES 6 + +/* Numeric metadata definitions */ +#define DST_NUM_PREDECESSOR 0 +#define DST_NUM_SUCCESSOR 1 +#define DST_NUM_MAXTTL 2 +#define DST_NUM_ROLLPERIOD 3 +#define DST_MAX_NUMERIC 3 + +/* + * Current format version number of the private key parser. + * + * When parsing a key file with the same major number but a higher minor + * number, the key parser will ignore any fields it does not recognize. + * Thus, DST_MINOR_VERSION should be incremented whenever new + * fields are added to the private key file (such as new metadata). + * + * When rewriting these keys, those fields will be dropped, and the + * format version set back to the current one.. + * + * When a key is seen with a higher major number, the key parser will + * reject it as invalid. Thus, DST_MAJOR_VERSION should be incremented + * and DST_MINOR_VERSION set to zero whenever there is a format change + * which is not backward compatible to previous versions of the dst_key + * parser, such as change in the syntax of an existing field, the removal + * of a currently mandatory field, or a new field added which would + * alter the functioning of the key if it were absent. + */ +#define DST_MAJOR_VERSION 1 +#define DST_MINOR_VERSION 3 + /*** *** Functions ***/ isc_result_t dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags); + +isc_result_t +dst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx, + const char *engine, unsigned int eflags); /*%< * Initializes the DST subsystem. * @@ -96,6 +143,7 @@ dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags); * Returns: * \li ISC_R_SUCCESS * \li ISC_R_NOMEMORY + * \li DST_R_NOENGINE * * Ensures: * \li DST is properly initialized. @@ -244,13 +292,17 @@ dst_key_fromfile(dns_name_t *name, dns_keytag_t id, unsigned int alg, int type, */ isc_result_t -dst_key_fromnamedfile(const char *filename, int type, isc_mem_t *mctx, - dst_key_t **keyp); +dst_key_fromnamedfile(const char *filename, const char *dirname, + int type, isc_mem_t *mctx, dst_key_t **keyp); /*%< * Reads a key from permanent storage. The key can either be a public or * key, and is specified by filename. If a private key is specified, the * public key must also be present. * + * If 'dirname' is not NULL, and 'filename' is a relative path, + * then the file is looked up relative to the given directory. + * If 'filename' is an absolute path, 'dirname' is ignored. + * * Requires: * \li "filename" is not NULL * \li "type" is DST_TYPE_PUBLIC, DST_TYPE_PRIVATE, or the bitwise union @@ -419,7 +471,7 @@ dst_key_getgssctx(const dst_key_t *key); isc_result_t dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx, - dst_key_t **keyp); + dst_key_t **keyp, isc_region_t *intoken); /*%< * Converts a GSSAPI opaque context id into a DST key. * @@ -450,6 +502,14 @@ dst_key_generate(dns_name_t *name, unsigned int alg, unsigned int flags, unsigned int protocol, dns_rdataclass_t rdclass, isc_mem_t *mctx, dst_key_t **keyp); + +isc_result_t +dst_key_generate2(dns_name_t *name, unsigned int alg, + unsigned int bits, unsigned int param, + unsigned int flags, unsigned int protocol, + dns_rdataclass_t rdclass, + isc_mem_t *mctx, dst_key_t **keyp, + void (*callback)(int)); /*%< * Generate a DST key (or keypair) with the supplied parameters. The * interpretation of the "param" field depends on the algorithm: @@ -482,7 +542,31 @@ dst_key_generate(dns_name_t *name, unsigned int alg, isc_boolean_t dst_key_compare(const dst_key_t *key1, const dst_key_t *key2); /*%< - * Compares two DST keys. + * Compares two DST keys. Returns true if they match, false otherwise. + * + * Keys ARE NOT considered to match if one of them is the revoked version + * of the other. + * + * Requires: + *\li "key1" is a valid key. + *\li "key2" is a valid key. + * + * Returns: + *\li ISC_TRUE + * \li ISC_FALSE + */ + +isc_boolean_t +dst_key_pubcompare(const dst_key_t *key1, const dst_key_t *key2, + isc_boolean_t match_revoked_key); +/*%< + * Compares only the public portions of two DST keys. Returns true + * if they match, false otherwise. This allows us, for example, to + * determine whether a public key found in a zone matches up with a + * key pair found on disk. + * + * If match_revoked_key is TRUE, then keys ARE considered to match if one + * of them is the revoked version of the other. Otherwise, they are not. * * Requires: *\li "key1" is a valid key. @@ -521,10 +605,12 @@ dst_key_attach(dst_key_t *source, dst_key_t **target); void dst_key_free(dst_key_t **keyp); /*%< - * Release all memory associated with the key. + * Decrement the key's reference counter and, when it reaches zero, + * release all memory associated with the key. * * Requires: *\li "keyp" is not NULL and "*keyp" is a valid key. + *\li reference counter greater than zero. * * Ensures: *\li All memory associated with "*keyp" will be freed. @@ -633,7 +719,7 @@ dst_region_computeid(const isc_region_t *source, unsigned int alg); isc_uint16_t dst_key_getbits(const dst_key_t *key); -/* +/*%< * Get the number of digest bits required (0 == MAX). * * Requires: @@ -642,13 +728,150 @@ dst_key_getbits(const dst_key_t *key); void dst_key_setbits(dst_key_t *key, isc_uint16_t bits); -/* +/*%< * Set the number of digest bits required (0 == MAX). * * Requires: * "key" is a valid key. */ +isc_result_t +dst_key_setflags(dst_key_t *key, isc_uint32_t flags); +/* + * Set the key flags, and recompute the key ID. + * + * Requires: + * "key" is a valid key. + */ + +isc_result_t +dst_key_getnum(const dst_key_t *key, int type, isc_uint32_t *valuep); +/*%< + * Get a member of the numeric metadata array and place it in '*valuep'. + * + * Requires: + * "key" is a valid key. + * "type" is no larger than DST_MAX_NUMERIC + * "timep" is not null. + */ + +void +dst_key_setnum(dst_key_t *key, int type, isc_uint32_t value); +/*%< + * Set a member of the numeric metadata array. + * + * Requires: + * "key" is a valid key. + * "type" is no larger than DST_MAX_NUMERIC + */ + +void +dst_key_unsetnum(dst_key_t *key, int type); +/*%< + * Flag a member of the numeric metadata array as "not set". + * + * Requires: + * "key" is a valid key. + * "type" is no larger than DST_MAX_NUMERIC + */ + +isc_result_t +dst_key_gettime(const dst_key_t *key, int type, isc_stdtime_t *timep); +/*%< + * Get a member of the timing metadata array and place it in '*timep'. + * + * Requires: + * "key" is a valid key. + * "type" is no larger than DST_MAX_TIMES + * "timep" is not null. + */ + +void +dst_key_settime(dst_key_t *key, int type, isc_stdtime_t when); +/*%< + * Set a member of the timing metadata array. + * + * Requires: + * "key" is a valid key. + * "type" is no larger than DST_MAX_TIMES + */ + +void +dst_key_unsettime(dst_key_t *key, int type); +/*%< + * Flag a member of the timing metadata array as "not set". + * + * Requires: + * "key" is a valid key. + * "type" is no larger than DST_MAX_TIMES + */ + +isc_result_t +dst_key_getprivateformat(const dst_key_t *key, int *majorp, int *minorp); +/*%< + * Get the private key format version number. (If the key does not have + * a private key associated with it, the version will be 0.0.) The major + * version number is placed in '*majorp', and the minor version number in + * '*minorp'. + * + * Requires: + * "key" is a valid key. + * "majorp" is not NULL. + * "minorp" is not NULL. + */ + +void +dst_key_setprivateformat(dst_key_t *key, int major, int minor); +/*%< + * Set the private key format version number. + * + * Requires: + * "key" is a valid key. + */ + +#define DST_KEY_FORMATSIZE (DNS_NAME_FORMATSIZE + DNS_SECALG_FORMATSIZE + 7) + +void +dst_key_format(const dst_key_t *key, char *cp, unsigned int size); +/*%< + * Write the uniquely identifying information about the key (name, + * algorithm, key ID) into a string 'cp' of size 'size'. + */ + + +isc_buffer_t * +dst_key_tkeytoken(const dst_key_t *key); +/*%< + * Return the token from the TKEY request, if any. If this key was + * not negotiated via TKEY, return NULL. + */ + + +isc_result_t +dst_key_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length); +/*%< + * Allocate 'buffer' and dump the key into it in base64 format. The buffer + * is not NUL terminated. The length of the buffer is returned in *length. + * + * 'buffer' needs to be freed using isc_mem_put(mctx, buffer, length); + * + * Requires: + * 'buffer' to be non NULL and *buffer to be NULL. + * 'length' to be non NULL and *length to be zero. + * + * Returns: + * ISC_R_SUCCESS + * ISC_R_NOMEMORY + * ISC_R_NOTIMPLEMENTED + * others. + */ + +isc_result_t +dst_key_restore(dns_name_t *name, unsigned int alg, unsigned int flags, + unsigned int protocol, dns_rdataclass_t rdclass, + isc_mem_t *mctx, const char *keystr, dst_key_t **keyp); + + ISC_LANG_ENDDECLS #endif /* DST_DST_H */ diff --git a/lib/dns/include/dst/gssapi.h b/lib/dns/include/dst/gssapi.h index 0a468d3..189e6b5 100644 --- a/lib/dns/include/dst/gssapi.h +++ b/lib/dns/include/dst/gssapi.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: gssapi.h,v 1.9.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: gssapi.h,v 1.16 2011-01-08 23:47:01 tbox Exp $ */ #ifndef DST_GSSAPI_H #define DST_GSSAPI_H 1 @@ -34,8 +34,12 @@ * MSVC does not like macros in #include lines. */ #include +#include #else #include ISC_PLATFORM_GSSAPIHEADER +#ifdef ISC_PLATFORM_GSSAPI_KRB5_HEADER +#include ISC_PLATFORM_GSSAPI_KRB5_HEADER +#endif #endif #ifndef GSS_SPNEGO_MECHANISM #define GSS_SPNEGO_MECHANISM ((void*)0) @@ -90,7 +94,8 @@ dst_gssapi_releasecred(gss_cred_id_t *cred); isc_result_t dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, - isc_buffer_t *outtoken, gss_ctx_id_t *gssctx); + isc_buffer_t *outtoken, gss_ctx_id_t *gssctx, + isc_mem_t *mctx, char **err_message); /* * Initiates a GSS context. * @@ -108,10 +113,12 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, * ISC_R_SUCCESS msg was successfully updated to include the * query to be sent * other an error occurred while building the message + * *err_message optional error message */ isc_result_t dst_gssapi_acceptctx(gss_cred_id_t cred, + const char *gssapi_keytab, isc_region_t *intoken, isc_buffer_t **outtoken, gss_ctx_id_t *context, dns_name_t *principal, isc_mem_t *mctx); diff --git a/lib/dns/iptable.c b/lib/dns/iptable.c index 071f9a6..7c334dd 100644 --- a/lib/dns/iptable.c +++ b/lib/dns/iptable.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: iptable.c,v 1.12.44.3 2009-02-18 23:47:12 tbox Exp $ */ +/* $Id: iptable.c,v 1.15 2009-02-18 23:47:48 tbox Exp $ */ #include diff --git a/lib/dns/journal.c b/lib/dns/journal.c index 520083e..a6d630e 100644 --- a/lib/dns/journal.c +++ b/lib/dns/journal.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: journal.c,v 1.103.48.8 2010-11-17 23:45:45 tbox Exp $ */ +/* $Id: journal.c,v 1.112 2010-11-17 23:47:08 tbox Exp $ */ #include @@ -562,11 +562,9 @@ journal_open(isc_mem_t *mctx, const char *filename, isc_boolean_t write, if (result == ISC_R_FILENOTFOUND) { if (create) { - isc_log_write(JOURNAL_COMMON_LOGARGS, - ISC_LOG_INFO, + isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_DEBUG(1), "journal file %s does not exist, " - "creating it", - j->filename); + "creating it", j->filename); CHECK(journal_file_create(mctx, filename)); /* * Retry. diff --git a/lib/dns/keydata.c b/lib/dns/keydata.c new file mode 100644 index 0000000..c2f82c8 --- /dev/null +++ b/lib/dns/keydata.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: keydata.c,v 1.3 2009-07-01 23:47:36 tbox Exp $ */ + +/*! \file */ + +#include + + +#include +#include +#include +#include + +#include +#include +#include + +isc_result_t +dns_keydata_todnskey(dns_rdata_keydata_t *keydata, + dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) +{ + REQUIRE(keydata != NULL && dnskey != NULL); + + dnskey->common.rdtype = dns_rdatatype_dnskey; + dnskey->common.rdclass = keydata->common.rdclass; + dnskey->mctx = mctx; + dnskey->flags = keydata->flags; + dnskey->protocol = keydata->protocol; + dnskey->algorithm = keydata->algorithm; + + dnskey->datalen = keydata->datalen; + + if (mctx == NULL) + dnskey->data = keydata->data; + else { + dnskey->data = isc_mem_allocate(mctx, dnskey->datalen); + if (dnskey->data == NULL) + return (ISC_R_NOMEMORY); + memcpy(dnskey->data, keydata->data, dnskey->datalen); + } + + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_keydata_fromdnskey(dns_rdata_keydata_t *keydata, + dns_rdata_dnskey_t *dnskey, + isc_uint32_t refresh, isc_uint32_t addhd, + isc_uint32_t removehd, isc_mem_t *mctx) +{ + REQUIRE(keydata != NULL && dnskey != NULL); + + keydata->common.rdtype = dns_rdatatype_keydata; + keydata->common.rdclass = dnskey->common.rdclass; + keydata->mctx = mctx; + keydata->refresh = refresh; + keydata->addhd = addhd; + keydata->removehd = removehd; + keydata->flags = dnskey->flags; + keydata->protocol = dnskey->protocol; + keydata->algorithm = dnskey->algorithm; + + keydata->datalen = dnskey->datalen; + if (mctx == NULL) + keydata->data = dnskey->data; + else { + keydata->data = isc_mem_allocate(mctx, keydata->datalen); + if (keydata->data == NULL) + return (ISC_R_NOMEMORY); + memcpy(keydata->data, dnskey->data, keydata->datalen); + } + + return (ISC_R_SUCCESS); +} diff --git a/lib/dns/keytable.c b/lib/dns/keytable.c index 874868d..3edc3d6 100644 --- a/lib/dns/keytable.c +++ b/lib/dns/keytable.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: keytable.c,v 1.34 2007-06-19 23:47:16 tbox Exp $ */ +/* $Id: keytable.c,v 1.41 2010-06-25 23:46:51 tbox Exp $ */ /*! \file */ @@ -31,41 +31,12 @@ #include #include -struct dns_keytable { - /* Unlocked. */ - unsigned int magic; - isc_mem_t *mctx; - isc_mutex_t lock; - isc_rwlock_t rwlock; - /* Locked by lock. */ - isc_uint32_t active_nodes; - /* Locked by rwlock. */ - isc_uint32_t references; - dns_rbt_t *table; -}; - -#define KEYTABLE_MAGIC ISC_MAGIC('K', 'T', 'b', 'l') -#define VALID_KEYTABLE(kt) ISC_MAGIC_VALID(kt, KEYTABLE_MAGIC) - -struct dns_keynode { - unsigned int magic; - dst_key_t * key; - struct dns_keynode * next; -}; - -#define KEYNODE_MAGIC ISC_MAGIC('K', 'N', 'o', 'd') -#define VALID_KEYNODE(kn) ISC_MAGIC_VALID(kn, KEYNODE_MAGIC) - static void free_keynode(void *node, void *arg) { dns_keynode_t *keynode = node; isc_mem_t *mctx = arg; - REQUIRE(VALID_KEYNODE(keynode)); - dst_key_free(&keynode->key); - if (keynode->next != NULL) - free_keynode(keynode->next, mctx); - isc_mem_put(mctx, keynode, sizeof(dns_keynode_t)); + dns_keynode_detachall(mctx, &keynode); } isc_result_t @@ -116,7 +87,6 @@ dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep) { return (result); } - void dns_keytable_attach(dns_keytable_t *source, dns_keytable_t **targetp) { @@ -173,50 +143,224 @@ dns_keytable_detach(dns_keytable_t **keytablep) { *keytablep = NULL; } -isc_result_t -dns_keytable_add(dns_keytable_t *keytable, dst_key_t **keyp) { +static isc_result_t +insert(dns_keytable_t *keytable, isc_boolean_t managed, + dns_name_t *keyname, dst_key_t **keyp) +{ isc_result_t result; - dns_keynode_t *knode; + dns_keynode_t *knode = NULL; dns_rbtnode_t *node; - dns_name_t *keyname; - - /* - * Add '*keyp' to 'keytable'. - */ + REQUIRE(keyp == NULL || *keyp != NULL); REQUIRE(VALID_KEYTABLE(keytable)); - REQUIRE(keyp != NULL); - keyname = dst_key_name(*keyp); + result = dns_keynode_create(keytable->mctx, &knode); + if (result != ISC_R_SUCCESS) + return (result); - knode = isc_mem_get(keytable->mctx, sizeof(*knode)); - if (knode == NULL) - return (ISC_R_NOMEMORY); + knode->managed = managed; RWLOCK(&keytable->rwlock, isc_rwlocktype_write); node = NULL; result = dns_rbt_addnode(keytable->table, keyname, &node); - if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) { - knode->magic = KEYNODE_MAGIC; - knode->key = *keyp; - knode->next = node->data; + if (keyp != NULL) { + if (result == ISC_R_EXISTS) { + /* Key already in table? */ + dns_keynode_t *k; + for (k = node->data; k != NULL; k = k->next) { + if (k->key == NULL) { + k->key = *keyp; + break; + } + if (dst_key_compare(k->key, *keyp) == ISC_TRUE) + break; + } + + if (k == NULL) + result = ISC_R_SUCCESS; + else + dst_key_free(keyp); + } + + if (result == ISC_R_SUCCESS) { + knode->key = *keyp; + knode->next = node->data; + *keyp = NULL; + } + } + + if (result == ISC_R_SUCCESS) { node->data = knode; - *keyp = NULL; knode = NULL; - result = ISC_R_SUCCESS; } + /* Key was already there? That's the same as a success */ + if (result == ISC_R_EXISTS) + result = ISC_R_SUCCESS; + RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write); if (knode != NULL) - isc_mem_put(keytable->mctx, knode, sizeof(*knode)); + dns_keynode_detach(keytable->mctx, &knode); + + return (result); +} + +isc_result_t +dns_keytable_add(dns_keytable_t *keytable, isc_boolean_t managed, + dst_key_t **keyp) +{ + REQUIRE(keyp != NULL && *keyp != NULL); + return (insert(keytable, managed, dst_key_name(*keyp), keyp)); +} + +isc_result_t +dns_keytable_marksecure(dns_keytable_t *keytable, dns_name_t *name) { + return (insert(keytable, ISC_TRUE, name, NULL)); +} + +isc_result_t +dns_keytable_delete(dns_keytable_t *keytable, dns_name_t *keyname) { + isc_result_t result; + dns_rbtnode_t *node = NULL; + + REQUIRE(VALID_KEYTABLE(keytable)); + REQUIRE(keyname != NULL); + + RWLOCK(&keytable->rwlock, isc_rwlocktype_write); + result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL, + DNS_RBTFIND_NOOPTIONS, NULL, NULL); + if (result == ISC_R_SUCCESS) { + if (node->data != NULL) + result = dns_rbt_deletenode(keytable->table, + node, ISC_FALSE); + else + result = ISC_R_NOTFOUND; + } else if (result == DNS_R_PARTIALMATCH) + result = ISC_R_NOTFOUND; + RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write); return (result); } isc_result_t +dns_keytable_deletekeynode(dns_keytable_t *keytable, dst_key_t *dstkey) { + isc_result_t result; + dns_name_t *keyname; + dns_rbtnode_t *node = NULL; + dns_keynode_t *knode = NULL, **kprev = NULL; + + REQUIRE(VALID_KEYTABLE(keytable)); + REQUIRE(dstkey != NULL); + + keyname = dst_key_name(dstkey); + + RWLOCK(&keytable->rwlock, isc_rwlocktype_write); + result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL, + DNS_RBTFIND_NOOPTIONS, NULL, NULL); + + if (result == DNS_R_PARTIALMATCH) + result = ISC_R_NOTFOUND; + if (result != ISC_R_SUCCESS) + goto finish; + + if (node->data == NULL) { + result = ISC_R_NOTFOUND; + goto finish; + } + + knode = node->data; + if (knode->next == NULL && + (knode->key == NULL || + dst_key_compare(knode->key, dstkey) == ISC_TRUE)) { + result = dns_rbt_deletenode(keytable->table, node, ISC_FALSE); + goto finish; + } + + kprev = (dns_keynode_t **) &node->data; + while (knode != NULL) { + if (dst_key_compare(knode->key, dstkey) == ISC_TRUE) + break; + kprev = &knode->next; + knode = knode->next; + } + + if (knode != NULL) { + if (knode->key != NULL) + dst_key_free(&knode->key); + /* + * This is equivalent to: + * dns_keynode_attach(knode->next, &tmp); + * dns_keynode_detach(kprev); + * dns_keynode_attach(tmp, &kprev); + * dns_keynode_detach(&tmp); + */ + *kprev = knode->next; + knode->next = NULL; + dns_keynode_detach(keytable->mctx, &knode); + } else + result = DNS_R_PARTIALMATCH; + finish: + RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write); + return (result); +} + +isc_result_t +dns_keytable_find(dns_keytable_t *keytable, dns_name_t *keyname, + dns_keynode_t **keynodep) +{ + isc_result_t result; + dns_rbtnode_t *node = NULL; + + REQUIRE(VALID_KEYTABLE(keytable)); + REQUIRE(keyname != NULL); + REQUIRE(keynodep != NULL && *keynodep == NULL); + + RWLOCK(&keytable->rwlock, isc_rwlocktype_read); + result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL, + DNS_RBTFIND_NOOPTIONS, NULL, NULL); + if (result == ISC_R_SUCCESS) { + if (node->data != NULL) { + LOCK(&keytable->lock); + keytable->active_nodes++; + UNLOCK(&keytable->lock); + dns_keynode_attach(node->data, keynodep); + } else + result = ISC_R_NOTFOUND; + } else if (result == DNS_R_PARTIALMATCH) + result = ISC_R_NOTFOUND; + RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read); + + return (result); +} + +isc_result_t +dns_keytable_nextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode, + dns_keynode_t **nextnodep) +{ + /* + * Return the next key after 'keynode', regardless of + * properties. + */ + + REQUIRE(VALID_KEYTABLE(keytable)); + REQUIRE(VALID_KEYNODE(keynode)); + REQUIRE(nextnodep != NULL && *nextnodep == NULL); + + if (keynode->next == NULL) + return (ISC_R_NOTFOUND); + + dns_keynode_attach(keynode->next, nextnodep); + LOCK(&keytable->lock); + keytable->active_nodes++; + UNLOCK(&keytable->lock); + + return (ISC_R_SUCCESS); +} + +isc_result_t dns_keytable_findkeynode(dns_keytable_t *keytable, dns_name_t *name, dns_secalg_t algorithm, dns_keytag_t tag, dns_keynode_t **keynodep) @@ -250,6 +394,10 @@ dns_keytable_findkeynode(dns_keytable_t *keytable, dns_name_t *name, if (result == ISC_R_SUCCESS) { INSIST(data != NULL); for (knode = data; knode != NULL; knode = knode->next) { + if (knode->key == NULL) { + knode = NULL; + break; + } if (algorithm == dst_key_alg(knode->key) && tag == dst_key_id(knode->key)) break; @@ -258,7 +406,7 @@ dns_keytable_findkeynode(dns_keytable_t *keytable, dns_name_t *name, LOCK(&keytable->lock); keytable->active_nodes++; UNLOCK(&keytable->lock); - *keynodep = knode; + dns_keynode_attach(knode, keynodep); } else result = DNS_R_PARTIALMATCH; } else if (result == DNS_R_PARTIALMATCH) @@ -286,6 +434,10 @@ dns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode, REQUIRE(nextnodep != NULL && *nextnodep == NULL); for (knode = keynode->next; knode != NULL; knode = knode->next) { + if (knode->key == NULL) { + knode = NULL; + break; + } if (dst_key_alg(keynode->key) == dst_key_alg(knode->key) && dst_key_id(keynode->key) == dst_key_id(knode->key)) break; @@ -295,7 +447,7 @@ dns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode, keytable->active_nodes++; UNLOCK(&keytable->lock); result = ISC_R_SUCCESS; - *nextnodep = knode; + dns_keynode_attach(knode, nextnodep); } else result = ISC_R_NOTFOUND; @@ -331,6 +483,25 @@ dns_keytable_finddeepestmatch(dns_keytable_t *keytable, dns_name_t *name, } void +dns_keytable_attachkeynode(dns_keytable_t *keytable, dns_keynode_t *source, + dns_keynode_t **target) +{ + /* + * Give back a keynode found via dns_keytable_findkeynode(). + */ + + REQUIRE(VALID_KEYTABLE(keytable)); + REQUIRE(VALID_KEYNODE(source)); + REQUIRE(target != NULL && *target == NULL); + + LOCK(&keytable->lock); + keytable->active_nodes++; + UNLOCK(&keytable->lock); + + dns_keynode_attach(source, target); +} + +void dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep) { /* @@ -345,7 +516,7 @@ dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep) keytable->active_nodes--; UNLOCK(&keytable->lock); - *keynodep = NULL; + dns_keynode_detach(keytable->mctx, keynodep); } isc_result_t @@ -382,6 +553,44 @@ dns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name, return (result); } +isc_result_t +dns_keytable_dump(dns_keytable_t *keytable, FILE *fp) +{ + isc_result_t result; + dns_keynode_t *knode; + dns_rbtnode_t *node; + dns_rbtnodechain_t chain; + + REQUIRE(VALID_KEYTABLE(keytable)); + + RWLOCK(&keytable->rwlock, isc_rwlocktype_read); + dns_rbtnodechain_init(&chain, keytable->mctx); + result = dns_rbtnodechain_first(&chain, keytable->table, NULL, NULL); + if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) + goto cleanup; + for (;;) { + char pbuf[DST_KEY_FORMATSIZE]; + + dns_rbtnodechain_current(&chain, NULL, NULL, &node); + for (knode = node->data; knode != NULL; knode = knode->next) { + dst_key_format(knode->key, pbuf, sizeof(pbuf)); + fprintf(fp, "%s ; %s\n", pbuf, + knode->managed ? "managed" : "trusted"); + } + result = dns_rbtnodechain_next(&chain, NULL, NULL); + if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { + if (result == ISC_R_NOMORE) + result = ISC_R_SUCCESS; + break; + } + } + + cleanup: + dns_rbtnodechain_invalidate(&chain); + RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read); + return (result); +} + dst_key_t * dns_keynode_key(dns_keynode_t *keynode) { @@ -393,3 +602,71 @@ dns_keynode_key(dns_keynode_t *keynode) { return (keynode->key); } + +isc_boolean_t +dns_keynode_managed(dns_keynode_t *keynode) { + /* + * Is this a managed key? + */ + REQUIRE(VALID_KEYNODE(keynode)); + + return (keynode->managed); +} + +isc_result_t +dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target) { + isc_result_t result; + dns_keynode_t *knode = NULL; + + REQUIRE(target != NULL && *target == NULL); + + knode = isc_mem_get(mctx, sizeof(dns_keynode_t)); + if (knode == NULL) + return (ISC_R_NOMEMORY); + + knode->magic = KEYNODE_MAGIC; + knode->managed = ISC_FALSE; + knode->key = NULL; + knode->next = NULL; + + result = isc_refcount_init(&knode->refcount, 1); + if (result != ISC_R_SUCCESS) + return (result); + + *target = knode; + return (ISC_R_SUCCESS); +} + +void +dns_keynode_attach(dns_keynode_t *source, dns_keynode_t **target) { + REQUIRE(VALID_KEYNODE(source)); + isc_refcount_increment(&source->refcount, NULL); + *target = source; +} + +void +dns_keynode_detach(isc_mem_t *mctx, dns_keynode_t **keynode) { + unsigned int refs; + dns_keynode_t *node = *keynode; + REQUIRE(VALID_KEYNODE(node)); + isc_refcount_decrement(&node->refcount, &refs); + if (refs == 0) { + if (node->key != NULL) + dst_key_free(&node->key); + isc_refcount_destroy(&node->refcount); + isc_mem_put(mctx, node, sizeof(dns_keynode_t)); + } + *keynode = NULL; +} + +void +dns_keynode_detachall(isc_mem_t *mctx, dns_keynode_t **keynode) { + dns_keynode_t *next = NULL, *node = *keynode; + REQUIRE(VALID_KEYNODE(node)); + while (node != NULL) { + next = node->next; + dns_keynode_detach(mctx, &node); + node = next; + } + *keynode = NULL; +} diff --git a/lib/dns/lib.c b/lib/dns/lib.c index 761be56..6953c88 100644 --- a/lib/dns/lib.c +++ b/lib/dns/lib.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lib.c,v 1.16 2007-06-19 23:47:16 tbox Exp $ */ +/* $Id: lib.c,v 1.19 2009-09-03 00:12:23 each Exp $ */ /*! \file */ @@ -23,11 +23,20 @@ #include -#include +#include +#include #include +#include +#include #include +#include +#include #include +#include + +#include + /*** *** Globals @@ -63,3 +72,97 @@ dns_lib_initmsgcat(void) { RUNTIME_CHECK(isc_once_do(&msgcat_once, open_msgcat) == ISC_R_SUCCESS); } + +static isc_once_t init_once = ISC_ONCE_INIT; +static isc_mem_t *dns_g_mctx = NULL; +#ifndef BIND9 +static dns_dbimplementation_t *dbimp = NULL; +#endif +static isc_boolean_t initialize_done = ISC_FALSE; +static isc_mutex_t reflock; +static unsigned int references = 0; + +static void +initialize(void) { + isc_result_t result; + + REQUIRE(initialize_done == ISC_FALSE); + + result = isc_mem_create(0, 0, &dns_g_mctx); + if (result != ISC_R_SUCCESS) + return; + dns_result_register(); +#ifndef BIND9 + result = dns_ecdb_register(dns_g_mctx, &dbimp); + if (result != ISC_R_SUCCESS) + goto cleanup_mctx; +#endif + result = isc_hash_create(dns_g_mctx, NULL, DNS_NAME_MAXWIRE); + if (result != ISC_R_SUCCESS) + goto cleanup_db; + + result = dst_lib_init(dns_g_mctx, NULL, 0); + if (result != ISC_R_SUCCESS) + goto cleanup_hash; + + result = isc_mutex_init(&reflock); + if (result != ISC_R_SUCCESS) + goto cleanup_dst; + + initialize_done = ISC_TRUE; + return; + + cleanup_dst: + dst_lib_destroy(); + cleanup_hash: + isc_hash_destroy(); + cleanup_db: +#ifndef BIND9 + dns_ecdb_unregister(&dbimp); + cleanup_mctx: +#endif + isc_mem_detach(&dns_g_mctx); +} + +isc_result_t +dns_lib_init(void) { + isc_result_t result; + + /* + * Since this routine is expected to be used by a normal application, + * it should be better to return an error, instead of an emergency + * abort, on any failure. + */ + result = isc_once_do(&init_once, initialize); + if (result != ISC_R_SUCCESS) + return (result); + + if (!initialize_done) + return (ISC_R_FAILURE); + + LOCK(&reflock); + references++; + UNLOCK(&reflock); + + return (ISC_R_SUCCESS); +} + +void +dns_lib_shutdown(void) { + isc_boolean_t cleanup_ok = ISC_FALSE; + + LOCK(&reflock); + if (--references == 0) + cleanup_ok = ISC_TRUE; + UNLOCK(&reflock); + + if (!cleanup_ok) + return; + + dst_lib_destroy(); + isc_hash_destroy(); +#ifndef BIND9 + dns_ecdb_unregister(&dbimp); +#endif + isc_mem_detach(&dns_g_mctx); +} diff --git a/lib/dns/log.c b/lib/dns/log.c index 5b3ee32..9de5976 100644 --- a/lib/dns/log.c +++ b/lib/dns/log.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: log.c,v 1.45 2007-06-18 23:47:40 tbox Exp $ */ +/* $Id: log.c,v 1.47 2009-12-18 23:49:03 tbox Exp $ */ /*! \file */ @@ -79,6 +79,7 @@ LIBDNS_EXTERNAL_DATA isc_logmodule_t dns_modules[] = { { "dns/hints", 0 }, { "dns/acache", 0 }, { "dns/dlz", 0 }, + { "dns/dnssec", 0 }, { NULL, 0 } }; diff --git a/lib/dns/master.c b/lib/dns/master.c index 9c6d3b8..e90a74c 100644 --- a/lib/dns/master.c +++ b/lib/dns/master.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: master.c,v 1.171.120.2 2009-01-18 23:47:40 tbox Exp $ */ +/* $Id: master.c,v 1.178 2009-09-01 00:22:26 jinmei Exp $ */ /*! \file */ @@ -85,7 +85,11 @@ */ #define TOKENSIZ (8*1024) -#define DNS_MASTER_BUFSZ 2048 +/*% + * Buffers sizes for $GENERATE. + */ +#define DNS_MASTER_LHS 2048 +#define DNS_MASTER_RHS MINTSIZ typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t; @@ -614,6 +618,57 @@ loadctx_create(dns_masterformat_t format, isc_mem_t *mctx, return (result); } +static const char *hex = "0123456789abcdef0123456789ABCDEF"; + +/*% + * Convert value into a nibble sequence from least significant to most + * significant nibble. Zero fill upper most significant nibbles if + * required to make the width. + * + * Returns the number of characters that should have been written without + * counting the terminating NUL. + */ +static unsigned int +nibbles(char *numbuf, size_t length, unsigned int width, char mode, int value) { + unsigned int count = 0; + + /* + * This reserve space for the NUL string terminator. + */ + if (length > 0U) { + *numbuf = '\0'; + length--; + } + do { + char val = hex[(value & 0x0f) + ((mode == 'n') ? 0 : 16)]; + value >>= 4; + if (length > 0U) { + *numbuf++ = val; + *numbuf = '\0'; + length--; + } + if (width > 0) + width--; + count++; + /* + * If width is non zero then we need to add a label seperator. + * If value is non zero then we need to add another label and + * that requires a label seperator. + */ + if (width > 0 || value != 0) { + if (length > 0U) { + *numbuf++ = '.'; + *numbuf = '\0'; + length--; + } + if (width > 0) + width--; + count++; + } + } while (value != 0 || width > 0); + return (count); +} + static isc_result_t genname(char *name, int it, char *buffer, size_t length) { char fmt[sizeof("%04000000000d")]; @@ -624,6 +679,7 @@ genname(char *name, int it, char *buffer, size_t length) { isc_textregion_t r; unsigned int n; unsigned int width; + isc_boolean_t nibblemode; r.base = buffer; r.length = length; @@ -638,10 +694,11 @@ genname(char *name, int it, char *buffer, size_t length) { isc_textregion_consume(&r, 1); continue; } + nibblemode = ISC_FALSE; strcpy(fmt, "%d"); /* Get format specifier. */ if (*name == '{' ) { - n = sscanf(name, "{%d,%u,%1[doxX]}", + n = sscanf(name, "{%d,%u,%1[doxXnN]}", &delta, &width, mode); switch (n) { case 1: @@ -651,6 +708,8 @@ genname(char *name, int it, char *buffer, size_t length) { "%%0%ud", width); break; case 3: + if (mode[0] == 'n' || mode[0] == 'N') + nibblemode = ISC_TRUE; n = snprintf(fmt, sizeof(fmt), "%%0%u%c", width, mode[0]); break; @@ -663,7 +722,12 @@ genname(char *name, int it, char *buffer, size_t length) { while (*name != '\0' && *name++ != '}') continue; } - n = snprintf(numbuf, sizeof(numbuf), fmt, it + delta); + if (nibblemode) + n = nibbles(numbuf, sizeof(numbuf), width, + mode[0], it + delta); + else + n = snprintf(numbuf, sizeof(numbuf), fmt, + it + delta); if (n >= sizeof(numbuf)) return (ISC_R_NOSPACE); cp = numbuf; @@ -746,8 +810,8 @@ generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs, ISC_LIST_INIT(head); target_mem = isc_mem_get(lctx->mctx, target_size); - rhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_BUFSZ); - lhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_BUFSZ); + rhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_RHS); + lhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_LHS); if (target_mem == NULL || rhsbuf == NULL || lhsbuf == NULL) { result = ISC_R_NOMEMORY; goto error_cleanup; @@ -778,35 +842,13 @@ generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs, goto insist_cleanup; } - switch (type) { - case dns_rdatatype_ns: - case dns_rdatatype_ptr: - case dns_rdatatype_cname: - case dns_rdatatype_dname: - break; - - case dns_rdatatype_a: - case dns_rdatatype_aaaa: - if (lctx->zclass == dns_rdataclass_in || - lctx->zclass == dns_rdataclass_ch || - lctx->zclass == dns_rdataclass_hs) - break; - /* FALLTHROUGH */ - default: - (*callbacks->error)(callbacks, - "%s: %s:%lu: unsupported type '%s'", - "$GENERATE", source, line, gtype); - result = ISC_R_NOTIMPLEMENTED; - goto error_cleanup; - } - ISC_LIST_INIT(rdatalist.rdata); ISC_LINK_INIT(&rdatalist, link); for (i = start; i <= stop; i += step) { - result = genname(lhs, i, lhsbuf, DNS_MASTER_BUFSZ); + result = genname(lhs, i, lhsbuf, DNS_MASTER_LHS); if (result != ISC_R_SUCCESS) goto error_cleanup; - result = genname(rhs, i, rhsbuf, DNS_MASTER_BUFSZ); + result = genname(rhs, i, rhsbuf, DNS_MASTER_RHS); if (result != ISC_R_SUCCESS) goto error_cleanup; @@ -820,6 +862,7 @@ generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs, if ((lctx->options & DNS_MASTER_ZONE) != 0 && (lctx->options & DNS_MASTER_SLAVE) == 0 && + (lctx->options & DNS_MASTER_KEY) == 0 && !dns_name_issubdomain(owner, lctx->top)) { char namebuf[DNS_NAME_FORMATSIZE]; @@ -880,9 +923,9 @@ generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs, if (target_mem != NULL) isc_mem_put(lctx->mctx, target_mem, target_size); if (lhsbuf != NULL) - isc_mem_put(lctx->mctx, lhsbuf, DNS_MASTER_BUFSZ); + isc_mem_put(lctx->mctx, lhsbuf, DNS_MASTER_LHS); if (rhsbuf != NULL) - isc_mem_put(lctx->mctx, rhsbuf, DNS_MASTER_BUFSZ); + isc_mem_put(lctx->mctx, rhsbuf, DNS_MASTER_RHS); return (result); } @@ -1270,7 +1313,8 @@ load_text(dns_loadctx_t *lctx) { goto log_and_cleanup; } /* RHS */ - GETTOKEN(lctx->lex, 0, &token, ISC_FALSE); + GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING, + &token, ISC_FALSE); rhs = isc_mem_strdup(mctx, DNS_AS_STR(token)); if (rhs == NULL) { result = ISC_R_NOMEMORY; @@ -1338,7 +1382,7 @@ load_text(dns_loadctx_t *lctx) { isc_buffer_setactive(&buffer, token.value.as_region.length); result = dns_name_fromtext(new_name, &buffer, - ictx->origin, ISC_FALSE, NULL); + ictx->origin, 0, NULL); if (MANYERRS(lctx, result)) { SETRESULT(lctx, result); LOGIT(result); @@ -1459,6 +1503,7 @@ load_text(dns_loadctx_t *lctx) { } if ((lctx->options & DNS_MASTER_ZONE) != 0 && (lctx->options & DNS_MASTER_SLAVE) == 0 && + (lctx->options & DNS_MASTER_KEY) == 0 && !dns_name_issubdomain(new_name, lctx->top)) { char namebuf[DNS_NAME_FORMATSIZE]; diff --git a/lib/dns/masterdump.c b/lib/dns/masterdump.c index d6befb5..e2adf9b 100644 --- a/lib/dns/masterdump.c +++ b/lib/dns/masterdump.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: masterdump.c,v 1.94.50.3.18.3 2011-06-21 20:13:22 each Exp $ */ +/* $Id: masterdump.c,v 1.99.328.3 2011-06-21 20:15:47 each Exp $ */ /*! \file */ @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -60,6 +61,11 @@ return (_r); \ } while (0) +#define CHECK(x) do { \ + if ((x) != ISC_R_SUCCESS) \ + goto cleanup; \ + } while (0) + struct dns_master_style { unsigned int flags; /* DNS_STYLEFLAG_* */ unsigned int ttl_column; @@ -156,6 +162,7 @@ static char spaces[N_SPACES+1] = " "; #define N_TABS 10 static char tabs[N_TABS+1] = "\t\t\t\t\t\t\t\t\t\t"; +#ifdef BIND9 struct dns_dumpctx { unsigned int magic; isc_mem_t *mctx; @@ -183,6 +190,7 @@ struct dns_dumpctx { dns_totext_ctx_t *ctx, isc_buffer_t *buffer, FILE *f); }; +#endif /* BIND9 */ #define NXDOMAIN(x) (((x)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0) @@ -336,6 +344,52 @@ str_totext(const char *source, isc_buffer_t *target) { return (ISC_R_SUCCESS); } +static isc_result_t +ncache_summary(dns_rdataset_t *rdataset, isc_boolean_t omit_final_dot, + isc_buffer_t *target) +{ + isc_result_t result = ISC_R_SUCCESS; + dns_rdataset_t rds; + dns_name_t name; + + dns_rdataset_init(&rds); + dns_name_init(&name, NULL); + + do { + dns_ncache_current(rdataset, &name, &rds); + for (result = dns_rdataset_first(&rds); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&rds)) { + CHECK(str_totext("; ", target)); + CHECK(dns_name_totext(&name, omit_final_dot, target)); + CHECK(str_totext(" ", target)); + CHECK(dns_rdatatype_totext(rds.type, target)); + if (rds.type == dns_rdatatype_rrsig) { + CHECK(str_totext(" ", target)); + CHECK(dns_rdatatype_totext(rds.covers, target)); + CHECK(str_totext(" ...\n", target)); + } else { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_current(&rds, &rdata); + CHECK(str_totext(" ", target)); + CHECK(dns_rdata_tofmttext(&rdata, dns_rootname, + 0, 0, " ", target)); + CHECK(str_totext("\n", target)); + } + } + dns_rdataset_disassociate(&rds); + result = dns_rdataset_next(rdataset); + } while (result == ISC_R_SUCCESS); + + if (result == ISC_R_NOMORE) + result = ISC_R_SUCCESS; + cleanup: + if (dns_rdataset_isassociated(&rds)) + dns_rdataset_disassociate(&rds); + + return (result); +} + /* * Convert 'rdataset' to master file text format according to 'ctx', * storing the result in 'target'. If 'owner_name' is NULL, it @@ -462,6 +516,13 @@ rdataset_totext(dns_rdataset_t *rdataset, RETERR(str_totext(";-$NXDOMAIN\n", target)); else RETERR(str_totext(";-$NXRRSET\n", target)); + /* + * Print a summary of the cached records which make + * up the negative response. + */ + RETERR(ncache_summary(rdataset, omit_final_dot, + target)); + break; } else { dns_rdata_t rdata = DNS_RDATA_INIT; isc_region_t r; @@ -637,6 +698,7 @@ dns_master_questiontotext(dns_name_t *owner_name, ISC_FALSE, target)); } +#ifdef BIND9 /* * Print an rdataset. 'buffer' is a scratch buffer, which must have been * dynamically allocated by the caller. It must be large enough to @@ -1692,6 +1754,7 @@ dns_master_dumpnode(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, return (result); } +#endif /* BIND9 */ isc_result_t dns_master_stylecreate(dns_master_style_t **stylep, unsigned int flags, diff --git a/lib/dns/message.c b/lib/dns/message.c index 2023741..b58c139 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: message.c,v 1.245.50.7.6.3 2011-06-21 20:13:22 each Exp $ */ +/* $Id: message.c,v 1.254.186.3 2011-06-21 20:15:47 each Exp $ */ /*! \file */ @@ -1804,6 +1804,36 @@ wrong_priority(dns_rdataset_t *rds, int pass, dns_rdatatype_t preferred_glue) { return (ISC_TRUE); } +#ifdef ALLOW_FILTER_AAAA_ON_V4 +/* + * Decide whether to not answer with an AAAA record and its RRSIG + */ +static inline isc_boolean_t +norender_rdataset(const dns_rdataset_t *rdataset, unsigned int options) +{ + switch (rdataset->type) { + case dns_rdatatype_aaaa: + if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0) + return (ISC_FALSE); + break; + + case dns_rdatatype_rrsig: + if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0 || + rdataset->covers != dns_rdatatype_aaaa) + return (ISC_FALSE); + break; + + default: + return (ISC_FALSE); + } + + if (rdataset->rdclass != dns_rdataclass_in) + return (ISC_FALSE); + + return (ISC_TRUE); +} + +#endif isc_result_t dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid, unsigned int options) @@ -1931,6 +1961,23 @@ dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid, preferred_glue)) goto next; +#ifdef ALLOW_FILTER_AAAA_ON_V4 + /* + * Suppress AAAAs if asked and we are + * not doing DNSSEC or are breaking DNSSEC. + * Say so in the AD bit if we break DNSSEC. + */ + if (norender_rdataset(rdataset, options) && + sectionid != DNS_SECTION_QUESTION) { + if (sectionid == DNS_SECTION_ANSWER || + sectionid == DNS_SECTION_AUTHORITY) + msg->flags &= ~DNS_MESSAGEFLAG_AD; + if (OPTOUT(rdataset)) + msg->flags &= ~DNS_MESSAGEFLAG_AD; + goto next; + } + +#endif st = *(msg->buffer); count = 0; @@ -3071,6 +3118,7 @@ dns_message_sectiontotext(dns_message_t *msg, dns_section_t section, dns_name_t *name, empty_name; dns_rdataset_t *rdataset; isc_result_t result; + isc_boolean_t seensoa = ISC_FALSE; REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(target != NULL); @@ -3100,6 +3148,15 @@ dns_message_sectiontotext(dns_message_t *msg, dns_section_t section, for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { + if (section == DNS_SECTION_ANSWER && + rdataset->type == dns_rdatatype_soa) { + if ((flags & DNS_MESSAGETEXTFLAG_OMITSOA) != 0) + continue; + if (seensoa && + (flags & DNS_MESSAGETEXTFLAG_ONESOA) != 0) + continue; + seensoa = ISC_TRUE; + } if (section == DNS_SECTION_QUESTION) { ADD_STRING(target, ";"); result = dns_master_questiontotext(name, diff --git a/lib/dns/name.c b/lib/dns/name.c index 80864b8..f88f281 100644 --- a/lib/dns/name.c +++ b/lib/dns/name.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: name.c,v 1.165.120.3 2010-07-09 05:15:05 each Exp $ */ +/* $Id: name.c,v 1.174 2011-01-13 04:59:25 tbox Exp $ */ /*! \file */ @@ -34,6 +34,7 @@ #include #include +#include #include #include @@ -1018,10 +1019,9 @@ dns_name_toregion(dns_name_t *name, isc_region_t *r) { DNS_NAME_TOREGION(name, r); } - isc_result_t dns_name_fromtext(dns_name_t *name, isc_buffer_t *source, - dns_name_t *origin, unsigned int options, + const dns_name_t *origin, unsigned int options, isc_buffer_t *target) { unsigned char *ndata, *label; @@ -2360,6 +2360,75 @@ dns_name_format(dns_name_t *name, char *cp, unsigned int size) { snprintf(cp, size, ""); } +/* + * dns_name_tostring() -- similar to dns_name_format() but allocates its own + * memory. + */ +isc_result_t +dns_name_tostring(dns_name_t *name, char **target, isc_mem_t *mctx) { + isc_result_t result; + isc_buffer_t buf; + isc_region_t reg; + char *p, txt[DNS_NAME_FORMATSIZE]; + + REQUIRE(VALID_NAME(name)); + REQUIRE(target != NULL && *target == NULL); + + isc_buffer_init(&buf, txt, sizeof(txt)); + result = dns_name_totext(name, ISC_FALSE, &buf); + if (result != ISC_R_SUCCESS) + return (result); + + isc_buffer_usedregion(&buf, ®); + p = isc_mem_allocate(mctx, reg.length + 1); + memcpy(p, (char *) reg.base, (int) reg.length); + p[reg.length] = '\0'; + + *target = p; + return (ISC_R_SUCCESS); +} + +/* + * dns_name_fromstring() -- convert directly from a string to a name, + * allocating memory as needed + */ +isc_result_t +dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options, + isc_mem_t *mctx) +{ + return (dns_name_fromstring2(target, src, dns_rootname, options, mctx)); +} + +isc_result_t +dns_name_fromstring2(dns_name_t *target, const char *src, + const dns_name_t *origin, unsigned int options, + isc_mem_t *mctx) +{ + isc_result_t result; + isc_buffer_t buf; + dns_fixedname_t fn; + dns_name_t *name; + + REQUIRE(src != NULL); + + isc_buffer_init(&buf, src, strlen(src)); + isc_buffer_add(&buf, strlen(src)); + if (BINDABLE(target) && target->buffer != NULL) + name = target; + else { + dns_fixedname_init(&fn); + name = dns_fixedname_name(&fn); + } + + result = dns_name_fromtext(name, &buf, origin, options, NULL); + if (result != ISC_R_SUCCESS) + return (result); + + if (name != target) + result = dns_name_dupwithoffsets(name, mctx, target); + return (result); +} + isc_result_t dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) { unsigned char *ndata; diff --git a/lib/dns/ncache.c b/lib/dns/ncache.c index f1fc323..420a118 100644 --- a/lib/dns/ncache.c +++ b/lib/dns/ncache.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ncache.c,v 1.43.48.7.6.3 2011-06-21 20:13:22 each Exp $ */ +/* $Id: ncache.c,v 1.50.124.1.2.3 2011-06-21 20:15:47 each Exp $ */ /*! \file */ @@ -35,7 +35,7 @@ #define DNS_NCACHE_RDATA 20U /* - * The format of an ncache rdata is a sequence of one or more records of + * The format of an ncache rdata is a sequence of zero or more records of * the following format: * * owner name @@ -223,42 +223,6 @@ dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache, return (result); if (trust == 0xffff) { - /* - * We didn't find any authority data from which to create a - * negative cache rdataset. In particular, we have no SOA. - * - * We trust that the caller wants negative caching, so this - * means we have a "type 3 nxdomain" or "type 3 nodata" - * response (see RFC2308 for details). - * - * We will now build a suitable negative cache rdataset that - * will cause zero bytes to be emitted when converted to - * wire format. - */ - - /* - * The ownername must exist, but it doesn't matter what value - * it has. We use the root name. - */ - dns_name_toregion(dns_rootname, &r); - result = isc_buffer_copyregion(&buffer, &r); - if (result != ISC_R_SUCCESS) - return (result); - /* - * Copy the type and a zero rdata count to the buffer. - */ - isc_buffer_availableregion(&buffer, &r); - if (r.length < 5) - return (ISC_R_NOSPACE); - isc_buffer_putuint16(&buffer, 0); /* type */ - /* - * RFC2308, section 5, says that negative answers without - * SOAs should not be cached. - */ - ttl = 0; - /* - * Set trust. - */ if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 && message->counts[DNS_SECTION_ANSWER] == 0) { /* @@ -268,22 +232,7 @@ dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache, trust = dns_trust_authauthority; } else trust = dns_trust_additional; - isc_buffer_putuint8(&buffer, (unsigned char)trust); /* trust */ - isc_buffer_putuint16(&buffer, 0); /* count */ - - /* - * Now add it to the cache. - */ - if (next >= DNS_NCACHE_RDATA) - return (ISC_R_NOSPACE); - dns_rdata_init(&rdata[next]); - isc_buffer_remainingregion(&buffer, &r); - rdata[next].data = r.base; - rdata[next].length = r.length; - rdata[next].rdclass = ncrdatalist.rdclass; - rdata[next].type = 0; - rdata[next].flags = 0; - ISC_LIST_APPEND(ncrdatalist.rdata, &rdata[next], link); + ttl = 0; } INSIST(trust != 0xffff); diff --git a/lib/dns/nsec.c b/lib/dns/nsec.c index 7d93ecc..94c5163 100644 --- a/lib/dns/nsec.c +++ b/lib/dns/nsec.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nsec.c,v 1.11.48.2 2009-01-06 23:47:26 tbox Exp $ */ +/* $Id: nsec.c,v 1.13 2009-01-06 23:47:57 tbox Exp $ */ /*! \file */ diff --git a/lib/dns/nsec3.c b/lib/dns/nsec3.c index 9c85781..e75e744 100644 --- a/lib/dns/nsec3.c +++ b/lib/dns/nsec3.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2008, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2006, 2008-2010 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nsec3.c,v 1.6.12.4 2009-11-03 23:47:46 tbox Exp $ */ +/* $Id: nsec3.c,v 1.19.96.1 2011-06-21 20:15:48 each Exp $ */ #include @@ -28,6 +28,8 @@ #include #include +#include +#include #include #include #include @@ -472,7 +474,6 @@ delete(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, return (result); } -#ifndef RFC5155_STRICT static isc_boolean_t better_param(dns_rdataset_t *nsec3paramset, dns_rdata_t *param) { dns_rdataset_t rdataset; @@ -487,7 +488,17 @@ better_param(dns_rdataset_t *nsec3paramset, dns_rdata_t *param) { result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { dns_rdata_t rdata = DNS_RDATA_INIT; - dns_rdataset_current(&rdataset, &rdata); + unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; + + if (rdataset.type != dns_rdatatype_nsec3param) { + dns_rdata_t tmprdata = DNS_RDATA_INIT; + dns_rdataset_current(&rdataset, &tmprdata); + if (!dns_nsec3param_fromprivate(&tmprdata, &rdata, + buf, sizeof(buf))) + continue; + } else + dns_rdataset_current(&rdataset, &rdata); + if (rdata.length != param->length) continue; if (rdata.data[0] != param->data[0] || @@ -505,7 +516,6 @@ better_param(dns_rdataset_t *nsec3paramset, dns_rdata_t *param) { dns_rdataset_disassociate(&rdataset); return (ISC_FALSE); } -#endif static isc_result_t find_nsec3(dns_rdata_nsec3_t *nsec3, dns_rdataset_t *rdataset, @@ -548,7 +558,7 @@ dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version, dns_rdataset_t rdataset; int pass; isc_boolean_t exists; - isc_boolean_t remove_unsecure = ISC_FALSE; + isc_boolean_t maybe_remove_unsecure = ISC_FALSE; isc_uint8_t flags; isc_buffer_t buffer; isc_result_t result; @@ -629,8 +639,12 @@ dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version, */ if (!unsecure) goto addnsec3; - else - remove_unsecure = ISC_TRUE; + else if (CREATE(nsec3param->flags) && OPTOUT(flags)) { + result = dns_nsec3_delnsec3(db, version, name, + nsec3param, diff); + goto failure; + } else + maybe_remove_unsecure = ISC_TRUE; } else { dns_rdataset_disassociate(&rdataset); if (result != ISC_R_NOMORE) @@ -666,26 +680,19 @@ dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version, if (result != ISC_R_SUCCESS) goto failure; - if (remove_unsecure) { + if (maybe_remove_unsecure) { dns_rdataset_disassociate(&rdataset); /* - * We have found the previous NSEC3 record and can now - * see if the existing NSEC3 record needs to be - * updated or deleted. + * If we have OPTOUT set in the previous NSEC3 record + * we actually need to delete the NSEC3 record. + * Otherwise we just need to replace the NSEC3 record. */ - if (!OPTOUT(nsec3.flags)) { - /* - * Just update the NSEC3 record. - */ - goto addnsec3; - } else { - /* - * This is actually a deletion not a add. - */ + if (OPTOUT(nsec3.flags)) { result = dns_nsec3_delnsec3(db, version, name, nsec3param, diff); goto failure; } + goto addnsec3; } else { /* * Is this is a unsecure delegation we are adding? @@ -928,17 +935,323 @@ dns_nsec3_addnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdataset_current(&rdataset, &rdata); - dns_rdata_tostruct(&rdata, &nsec3param, NULL); + CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL)); + + if (nsec3param.flags != 0) + continue; + /* + * We have a active chain. Update it. + */ + CHECK(dns_nsec3_addnsec3(db, version, name, &nsec3param, + nsecttl, unsecure, diff)); + } + if (result == ISC_R_NOMORE) + result = ISC_R_SUCCESS; + + failure: + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); + if (node != NULL) + dns_db_detachnode(db, &node); + + return (result); +} + +isc_boolean_t +dns_nsec3param_fromprivate(dns_rdata_t *src, dns_rdata_t *target, + unsigned char *buf, size_t buflen) +{ + dns_decompress_t dctx; + isc_result_t result; + isc_buffer_t buf1; + isc_buffer_t buf2; + + /* + * Algorithm 0 (reserved by RFC 4034) is used to identify + * NSEC3PARAM records from DNSKEY pointers. + */ + if (src->length < 1 || src->data[0] != 0) + return (ISC_FALSE); + + isc_buffer_init(&buf1, src->data + 1, src->length - 1); + isc_buffer_add(&buf1, src->length - 1); + isc_buffer_setactive(&buf1, src->length - 1); + isc_buffer_init(&buf2, buf, buflen); + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE); + result = dns_rdata_fromwire(target, src->rdclass, + dns_rdatatype_nsec3param, + &buf1, &dctx, 0, &buf2); + dns_decompress_invalidate(&dctx); + + return (ISC_TF(result == ISC_R_SUCCESS)); +} + +void +dns_nsec3param_toprivate(dns_rdata_t *src, dns_rdata_t *target, + dns_rdatatype_t privatetype, + unsigned char *buf, size_t buflen) +{ + REQUIRE(buflen >= src->length + 1); + + REQUIRE(DNS_RDATA_INITIALIZED(target)); + + memcpy(buf + 1, src->data, src->length); + buf[0] = 0; + target->data = buf; + target->length = src->length + 1; + target->type = privatetype; + target->rdclass = src->rdclass; + target->flags = 0; + ISC_LINK_INIT(target, link); +} + +#ifdef BIND9 +static isc_result_t +rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, + const dns_rdata_t *rdata, isc_boolean_t *flag) +{ + dns_rdataset_t rdataset; + dns_dbnode_t *node = NULL; + isc_result_t result; + + dns_rdataset_init(&rdataset); + if (rdata->type == dns_rdatatype_nsec3) + CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node)); + else + CHECK(dns_db_findnode(db, name, ISC_FALSE, &node)); + result = dns_db_findrdataset(db, node, ver, rdata->type, 0, + (isc_stdtime_t) 0, &rdataset, NULL); + if (result == ISC_R_NOTFOUND) { + *flag = ISC_FALSE; + result = ISC_R_SUCCESS; + goto failure; + } + + for (result = dns_rdataset_first(&rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&rdataset)) { + dns_rdata_t myrdata = DNS_RDATA_INIT; + dns_rdataset_current(&rdataset, &myrdata); + if (!dns_rdata_casecompare(&myrdata, rdata)) + break; + } + dns_rdataset_disassociate(&rdataset); + if (result == ISC_R_SUCCESS) { + *flag = ISC_TRUE; + } else if (result == ISC_R_NOMORE) { + *flag = ISC_FALSE; + result = ISC_R_SUCCESS; + } + + failure: + if (node != NULL) + dns_db_detachnode(db, &node); + return (result); +} +#endif + +#ifdef BIND9 +isc_result_t +dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver, + dns_zone_t *zone, dns_diff_t *diff) +{ + dns_dbnode_t *node = NULL; + dns_difftuple_t *tuple = NULL; + dns_name_t next; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_t rdataset; + isc_boolean_t flag; + isc_result_t result = ISC_R_SUCCESS; + unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE + 1]; + dns_name_t *origin = dns_zone_getorigin(zone); + dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); + + dns_name_init(&next, NULL); + dns_rdataset_init(&rdataset); + + result = dns_db_getoriginnode(db, &node); + if (result != ISC_R_SUCCESS) + return (result); + + /* + * Cause all NSEC3 chains to be deleted. + */ + result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, + 0, (isc_stdtime_t) 0, &rdataset, NULL); + if (result == ISC_R_NOTFOUND) + goto try_private; + if (result != ISC_R_SUCCESS) + goto failure; + + for (result = dns_rdataset_first(&rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&rdataset)) { + dns_rdata_t private = DNS_RDATA_INIT; + + dns_rdataset_current(&rdataset, &rdata); + + CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, origin, + rdataset.ttl, &rdata, &tuple)); + CHECK(do_one_tuple(&tuple, db, ver, diff)); + INSIST(tuple == NULL); + + dns_nsec3param_toprivate(&rdata, &private, privatetype, + buf, sizeof(buf)); + buf[2] = DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC; + + CHECK(rr_exists(db, ver, origin, &private, &flag)); + + if (!flag) { + CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, + origin, 0, &private, + &tuple)); + CHECK(do_one_tuple(&tuple, db, ver, diff)); + INSIST(tuple == NULL); + } + dns_rdata_reset(&rdata); + } + if (result != ISC_R_NOMORE) + goto failure; + + dns_rdataset_disassociate(&rdataset); + + try_private: + if (privatetype == 0) + goto success; + result = dns_db_findrdataset(db, node, ver, privatetype, 0, + (isc_stdtime_t) 0, &rdataset, NULL); + if (result == ISC_R_NOTFOUND) + goto success; + if (result != ISC_R_SUCCESS) + goto failure; + + for (result = dns_rdataset_first(&rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&rdataset)) { + dns_rdataset_current(&rdataset, &rdata); + INSIST(rdata.length <= sizeof(buf)); + memcpy(buf, rdata.data, rdata.length); + + if (buf[0] != 0 || + buf[2] == (DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC)) { + dns_rdata_reset(&rdata); + continue; + } + + CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, origin, + 0, &rdata, &tuple)); + CHECK(do_one_tuple(&tuple, db, ver, diff)); + INSIST(tuple == NULL); + + rdata.data = buf; + buf[2] = DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC; + + CHECK(rr_exists(db, ver, origin, &rdata, &flag)); + + if (!flag) { + CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, + origin, 0, &rdata, &tuple)); + CHECK(do_one_tuple(&tuple, db, ver, diff)); + INSIST(tuple == NULL); + } + dns_rdata_reset(&rdata); + } + if (result != ISC_R_NOMORE) + goto failure; + success: + result = ISC_R_SUCCESS; + + failure: + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); + dns_db_detachnode(db, &node); + return (result); +} +#endif + +isc_result_t +dns_nsec3_addnsec3sx(dns_db_t *db, dns_dbversion_t *version, + dns_name_t *name, dns_ttl_t nsecttl, + isc_boolean_t unsecure, dns_rdatatype_t type, + dns_diff_t *diff) +{ + dns_dbnode_t *node = NULL; + dns_rdata_nsec3param_t nsec3param; + dns_rdataset_t rdataset; + dns_rdataset_t prdataset; + isc_result_t result; + + dns_rdataset_init(&rdataset); + dns_rdataset_init(&prdataset); + + /* + * Find the NSEC3 parameters for this zone. + */ + result = dns_db_getoriginnode(db, &node); + if (result != ISC_R_SUCCESS) + return (result); + + result = dns_db_findrdataset(db, node, version, type, 0, 0, + &prdataset, NULL); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) + goto failure; + + result = dns_db_findrdataset(db, node, version, + dns_rdatatype_nsec3param, 0, 0, + &rdataset, NULL); + if (result == ISC_R_NOTFOUND) + goto try_private; + if (result != ISC_R_SUCCESS) + goto failure; + + /* + * Update each active NSEC3 chain. + */ + for (result = dns_rdataset_first(&rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&rdataset)) { + dns_rdata_t rdata = DNS_RDATA_INIT; + + dns_rdataset_current(&rdataset, &rdata); + CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL)); -#ifdef RFC5155_STRICT if (nsec3param.flags != 0) continue; -#else + + /* + * We have a active chain. Update it. + */ + CHECK(dns_nsec3_addnsec3(db, version, name, &nsec3param, + nsecttl, unsecure, diff)); + } + if (result != ISC_R_NOMORE) + goto failure; + + dns_rdataset_disassociate(&rdataset); + + try_private: + if (!dns_rdataset_isassociated(&prdataset)) + goto success; + /* + * Update each active NSEC3 chain. + */ + for (result = dns_rdataset_first(&prdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&prdataset)) { + dns_rdata_t rdata1 = DNS_RDATA_INIT; + dns_rdata_t rdata2 = DNS_RDATA_INIT; + unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; + + dns_rdataset_current(&prdataset, &rdata1); + if (!dns_nsec3param_fromprivate(&rdata1, &rdata2, + buf, sizeof(buf))) + continue; + CHECK(dns_rdata_tostruct(&rdata2, &nsec3param, NULL)); + if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) continue; - if (better_param(&rdataset, &rdata)) + if (better_param(&prdataset, &rdata2)) continue; -#endif /* * We have a active chain. Update it. @@ -947,11 +1260,13 @@ dns_nsec3_addnsec3s(dns_db_t *db, dns_dbversion_t *version, nsecttl, unsecure, diff)); } if (result == ISC_R_NOMORE) + success: result = ISC_R_SUCCESS; - failure: if (dns_rdataset_isassociated(&rdataset)) dns_rdataset_disassociate(&rdataset); + if (dns_rdataset_isassociated(&prdataset)) + dns_rdataset_disassociate(&prdataset); if (node != NULL) dns_db_detachnode(db, &node); @@ -1120,6 +1435,8 @@ dns_nsec3_delnsec3(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, */ nsec3.next = nexthash; nsec3.next_length = next_length; + if (CREATE(nsec3param->flags)) + nsec3.flags = nsec3param->flags & DNS_NSEC3FLAG_OPTOUT; isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf)); CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass, dns_rdatatype_nsec3, &nsec3, @@ -1257,6 +1574,13 @@ isc_result_t dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, dns_diff_t *diff) { + return (dns_nsec3_delnsec3sx(db, version, name, 0, diff)); +} + +isc_result_t +dns_nsec3_delnsec3sx(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, + dns_rdatatype_t privatetype, dns_diff_t *diff) +{ dns_dbnode_t *node = NULL; dns_rdata_nsec3param_t nsec3param; dns_rdataset_t rdataset; @@ -1274,11 +1598,10 @@ dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec3param, 0, 0, &rdataset, NULL); - dns_db_detachnode(db, &node); if (result == ISC_R_NOTFOUND) - return (ISC_R_SUCCESS); + goto try_private; if (result != ISC_R_SUCCESS) - return (result); + goto failure; /* * Update each active NSEC3 chain. @@ -1289,17 +1612,47 @@ dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdataset_current(&rdataset, &rdata); - dns_rdata_tostruct(&rdata, &nsec3param, NULL); + CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL)); -#ifdef RFC5155_STRICT if (nsec3param.flags != 0) continue; -#else + /* + * We have a active chain. Update it. + */ + CHECK(dns_nsec3_delnsec3(db, version, name, &nsec3param, diff)); + } + dns_rdataset_disassociate(&rdataset); + + try_private: + if (privatetype == 0) + goto success; + result = dns_db_findrdataset(db, node, version, privatetype, 0, 0, + &rdataset, NULL); + if (result == ISC_R_NOTFOUND) + goto success; + if (result != ISC_R_SUCCESS) + goto failure; + + /* + * Update each NSEC3 chain being built. + */ + for (result = dns_rdataset_first(&rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&rdataset)) { + dns_rdata_t rdata1 = DNS_RDATA_INIT; + dns_rdata_t rdata2 = DNS_RDATA_INIT; + unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; + + dns_rdataset_current(&rdataset, &rdata1); + if (!dns_nsec3param_fromprivate(&rdata1, &rdata2, + buf, sizeof(buf))) + continue; + CHECK(dns_rdata_tostruct(&rdata2, &nsec3param, NULL)); + if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) continue; - if (better_param(&rdataset, &rdata)) + if (better_param(&rdataset, &rdata2)) continue; -#endif /* * We have a active chain. Update it. @@ -1307,6 +1660,7 @@ dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, CHECK(dns_nsec3_delnsec3(db, version, name, &nsec3param, diff)); } if (result == ISC_R_NOMORE) + success: result = ISC_R_SUCCESS; failure: @@ -1322,6 +1676,14 @@ isc_result_t dns_nsec3_active(dns_db_t *db, dns_dbversion_t *version, isc_boolean_t complete, isc_boolean_t *answer) { + return (dns_nsec3_activex(db, version, complete, 0, answer)); +} + +isc_result_t +dns_nsec3_activex(dns_db_t *db, dns_dbversion_t *version, + isc_boolean_t complete, dns_rdatatype_t privatetype, + isc_boolean_t *answer) +{ dns_dbnode_t *node = NULL; dns_rdataset_t rdataset; dns_rdata_nsec3param_t nsec3param; @@ -1338,34 +1700,78 @@ dns_nsec3_active(dns_db_t *db, dns_dbversion_t *version, result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec3param, 0, 0, &rdataset, NULL); - dns_db_detachnode(db, &node); + if (result == ISC_R_NOTFOUND) + goto try_private; + + if (result != ISC_R_SUCCESS) { + dns_db_detachnode(db, &node); + return (result); + } + for (result = dns_rdataset_first(&rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&rdataset)) { + dns_rdata_t rdata = DNS_RDATA_INIT; + + dns_rdataset_current(&rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &nsec3param, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + if (nsec3param.flags == 0) + break; + } + dns_rdataset_disassociate(&rdataset); + if (result == ISC_R_SUCCESS) { + dns_db_detachnode(db, &node); + *answer = ISC_TRUE; + return (ISC_R_SUCCESS); + } + if (result == ISC_R_NOMORE) + *answer = ISC_FALSE; + + try_private: + if (privatetype == 0 || complete) { + *answer = ISC_FALSE; + return (ISC_R_SUCCESS); + } + result = dns_db_findrdataset(db, node, version, privatetype, 0, 0, + &rdataset, NULL); + + dns_db_detachnode(db, &node); if (result == ISC_R_NOTFOUND) { *answer = ISC_FALSE; return (ISC_R_SUCCESS); } if (result != ISC_R_SUCCESS) return (result); + for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { - dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_t rdata1 = DNS_RDATA_INIT; + dns_rdata_t rdata2 = DNS_RDATA_INIT; + unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; - dns_rdataset_current(&rdataset, &rdata); - result = dns_rdata_tostruct(&rdata, &nsec3param, NULL); + dns_rdataset_current(&rdataset, &rdata1); + if (!dns_nsec3param_fromprivate(&rdata1, &rdata2, + buf, sizeof(buf))) + continue; + result = dns_rdata_tostruct(&rdata2, &nsec3param, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); - if ((nsec3param.flags) == 0 || - (!complete && CREATE(nsec3param.flags))) + if (!complete && CREATE(nsec3param.flags)) break; } dns_rdataset_disassociate(&rdataset); - if (result == ISC_R_SUCCESS) + if (result == ISC_R_SUCCESS) { *answer = ISC_TRUE; + result = ISC_R_SUCCESS; + } if (result == ISC_R_NOMORE) { *answer = ISC_FALSE; result = ISC_R_SUCCESS; } + return (result); } diff --git a/lib/dns/openssl_link.c b/lib/dns/openssl_link.c index 081e3c6..8c733f6 100644 --- a/lib/dns/openssl_link.c +++ b/lib/dns/openssl_link.c @@ -31,7 +31,7 @@ /* * Principal Author: Brian Wellington - * $Id: openssl_link.c,v 1.22.112.5 2010-09-15 12:37:35 tbox Exp $ + * $Id: openssl_link.c,v 1.29 2010-09-15 12:38:36 tbox Exp $ */ #ifdef OPENSSL @@ -45,6 +45,8 @@ #include #include +#include + #include "dst_internal.h" #include "dst_openssl.h" @@ -60,12 +62,6 @@ #ifdef USE_ENGINE #include - -#ifdef ENGINE_ID -const char *engine_id = ENGINE_ID; -#else -const char *engine_id; -#endif #endif static RAND_METHOD *rm = NULL; @@ -74,15 +70,7 @@ static isc_mutex_t *locks = NULL; static int nlocks; #ifdef USE_ENGINE -static ENGINE *e; -static ENGINE *he; -#endif - -#ifdef USE_PKCS11 -static isc_result_t -dst__openssl_load_engine(const char *name, const char *engine_id, - const char **pre_cmds, int pre_num, - const char **post_cmds, int post_num); +static ENGINE *e = NULL; #endif static int @@ -135,8 +123,16 @@ id_callback(void) { static void * mem_alloc(size_t size) { +#ifdef OPENSSL_LEAKS + void *ptr; + + INSIST(dst__memory_pool != NULL); + ptr = isc_mem_allocate(dst__memory_pool, size); + return (ptr); +#else INSIST(dst__memory_pool != NULL); return (isc_mem_allocate(dst__memory_pool, size)); +#endif } static void @@ -148,16 +144,26 @@ mem_free(void *ptr) { static void * mem_realloc(void *ptr, size_t size) { +#ifdef OPENSSL_LEAKS + void *rptr; + + INSIST(dst__memory_pool != NULL); + rptr = isc_mem_reallocate(dst__memory_pool, ptr, size); + return (rptr); +#else INSIST(dst__memory_pool != NULL); return (isc_mem_reallocate(dst__memory_pool, ptr, size)); +#endif } isc_result_t -dst__openssl_init() { +dst__openssl_init(const char *engine) { isc_result_t result; #ifdef USE_ENGINE - /* const char *name; */ ENGINE *re; +#else + + UNUSED(engine); #endif #ifdef DNS_CRYPTO_LEAKS @@ -187,70 +193,26 @@ dst__openssl_init() { rm->add = entropy_add; rm->pseudorand = entropy_getpseudo; rm->status = entropy_status; + #ifdef USE_ENGINE OPENSSL_config(NULL); -#ifdef USE_PKCS11 -#ifndef PKCS11_SO_PATH -#define PKCS11_SO_PATH "/usr/local/lib/engines/engine_pkcs11.so" -#endif -#ifndef PKCS11_MODULE_PATH -#define PKCS11_MODULE_PATH "/usr/lib/libpkcs11.so" -#endif - { - /* - * to use this to config the PIN, add in openssl.cnf: - * - at the beginning: "openssl_conf = openssl_def" - * - at any place these sections: - * [ openssl_def ] - * engines = engine_section - * [ engine_section ] - * pkcs11 = pkcs11_section - * [ pkcs11_section ] - * PIN = my___pin - */ - - const char *pre_cmds[] = { - "SO_PATH", PKCS11_SO_PATH, - "LOAD", NULL, - "MODULE_PATH", PKCS11_MODULE_PATH - }; - const char *post_cmds[] = { - /* "PIN", "my___pin" */ - }; - result = dst__openssl_load_engine("pkcs11", "pkcs11", - pre_cmds, 0, - post_cmds, /*1*/ 0); - if (result != ISC_R_SUCCESS) - goto cleanup_rm; - } -#endif /* USE_PKCS11 */ - if (engine_id != NULL) { - e = ENGINE_by_id(engine_id); + + if (engine != NULL && *engine == '\0') + engine = NULL; + + if (engine != NULL) { + e = ENGINE_by_id(engine); if (e == NULL) { - result = ISC_R_NOTFOUND; + result = DST_R_NOENGINE; goto cleanup_rm; } - if (!ENGINE_init(e)) { - result = ISC_R_FAILURE; - ENGINE_free(e); + /* This will init the engine. */ + if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { + result = DST_R_NOENGINE; goto cleanup_rm; } - ENGINE_set_default(e, ENGINE_METHOD_ALL); - ENGINE_free(e); - } else { - ENGINE_register_all_complete(); - for (e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) { - - /* - * Something weird here. If we call ENGINE_finish() - * ENGINE_get_default_RAND() will fail. - */ - if (ENGINE_init(e)) { - if (he == NULL) - he = e; - } - } } + re = ENGINE_get_default_RAND(); if (re == NULL) { re = ENGINE_new(); @@ -263,7 +225,6 @@ dst__openssl_init() { ENGINE_free(re); } else ENGINE_finish(re); - #else RAND_set_rand_method(rm); #endif /* USE_ENGINE */ @@ -271,13 +232,18 @@ dst__openssl_init() { #ifdef USE_ENGINE cleanup_rm: + if (e != NULL) + ENGINE_free(e); + e = NULL; mem_free(rm); + rm = NULL; #endif cleanup_mutexinit: CRYPTO_set_locking_callback(NULL); DESTROYMUTEXBLOCK(locks, nlocks); cleanup_mutexalloc: mem_free(locks); + locks = NULL; return (result); } @@ -287,15 +253,22 @@ dst__openssl_destroy() { /* * Sequence taken from apps_shutdown() in . */ + if (rm != NULL) { +#if OPENSSL_VERSION_NUMBER >= 0x00907000L + RAND_cleanup(); +#endif + mem_free(rm); + rm = NULL; + } #if (OPENSSL_VERSION_NUMBER >= 0x00907000L) - CONF_modules_unload(1); + CONF_modules_free(); #endif + OBJ_cleanup(); EVP_cleanup(); #if defined(USE_ENGINE) - if (e != NULL) { - ENGINE_finish(e); - e = NULL; - } + if (e != NULL) + ENGINE_free(e); + e = NULL; #if defined(USE_ENGINE) && OPENSSL_VERSION_NUMBER >= 0x00907000L ENGINE_cleanup(); #endif @@ -304,23 +277,18 @@ dst__openssl_destroy() { CRYPTO_cleanup_all_ex_data(); #endif ERR_clear_error(); - ERR_free_strings(); ERR_remove_state(0); + ERR_free_strings(); #ifdef DNS_CRYPTO_LEAKS CRYPTO_mem_leaks_fp(stderr); #endif - if (rm != NULL) { -#if OPENSSL_VERSION_NUMBER >= 0x00907000L - RAND_cleanup(); -#endif - mem_free(rm); - } if (locks != NULL) { CRYPTO_set_locking_callback(NULL); DESTROYMUTEXBLOCK(locks, nlocks); mem_free(locks); + locks = NULL; } } @@ -341,91 +309,18 @@ dst__openssl_toresult(isc_result_t fallback) { } ENGINE * -dst__openssl_getengine(const char *name) { - - UNUSED(name); - +dst__openssl_getengine(const char *engine) { + if (engine == NULL) + return (NULL); #if defined(USE_ENGINE) - return (he); -#else - return (NULL); -#endif -} - -isc_result_t -dst__openssl_setdefault(const char *name) { - - UNUSED(name); - -#if defined(USE_ENGINE) - ENGINE_set_default(e, ENGINE_METHOD_ALL); -#endif - /* - * XXXMPA If the engine does not have a default RAND method - * restore our method. - */ - return (ISC_R_SUCCESS); -} - -#ifdef USE_PKCS11 -/* - * 'name' is the name the engine is known by to the dst library. - * This may or may not match the name the engine is known by to - * openssl. It is the name that is stored in the private key file. - * - * 'engine_id' is the openssl engine name. - * - * pre_cmds and post_cmds a sequence if command argument pairs - * pre_num and post_num are a count of those pairs. - * - * "SO_PATH", PKCS11_SO_PATH ("/usr/local/lib/engines/engine_pkcs11.so") - * "LOAD", NULL - * "MODULE_PATH", PKCS11_MODULE_PATH ("/usr/lib/libpkcs11.so") - */ -static isc_result_t -dst__openssl_load_engine(const char *name, const char *engine_id, - const char **pre_cmds, int pre_num, - const char **post_cmds, int post_num) -{ - ENGINE *e; - - UNUSED(name); - - if (!strcasecmp(engine_id, "dynamic")) - ENGINE_load_dynamic(); - e = ENGINE_by_id(engine_id); if (e == NULL) - return (ISC_R_NOTFOUND); - while (pre_num--) { - if (!ENGINE_ctrl_cmd_string(e, pre_cmds[0], pre_cmds[1], 0)) { - ENGINE_free(e); - return (ISC_R_FAILURE); - } - pre_cmds += 2; - } - if (!ENGINE_init(e)) { - ENGINE_free(e); - return (ISC_R_FAILURE); - } - /* - * ENGINE_init() returned a functional reference, so free the - * structural reference from ENGINE_by_id(). - */ - ENGINE_free(e); - while (post_num--) { - if (!ENGINE_ctrl_cmd_string(e, post_cmds[0], post_cmds[1], 0)) { - ENGINE_free(e); - return (ISC_R_FAILURE); - } - post_cmds += 2; - } - if (he != NULL) - ENGINE_finish(he); - he = e; - return (ISC_R_SUCCESS); + return (NULL); + if (strcmp(engine, ENGINE_get_id(e)) == 0) + return (e); +#endif + return (NULL); } -#endif /* USE_PKCS11 */ #else /* OPENSSL */ diff --git a/lib/dns/openssldh_link.c b/lib/dns/openssldh_link.c index e31137f..9deda6b 100644 --- a/lib/dns/openssldh_link.c +++ b/lib/dns/openssldh_link.c @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2004-2009, 2011 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -31,7 +31,7 @@ /* * Principal Author: Brian Wellington - * $Id: openssldh_link.c,v 1.14 2008-04-01 23:47:10 tbox Exp $ + * $Id: openssldh_link.c,v 1.20 2011-01-11 23:47:13 tbox Exp $ */ #ifdef OPENSSL @@ -149,12 +149,37 @@ openssldh_paramcompare(const dst_key_t *key1, const dst_key_t *key2) { return (ISC_TRUE); } +#if OPENSSL_VERSION_NUMBER > 0x00908000L +static int +progress_cb(int p, int n, BN_GENCB *cb) +{ + union { + void *dptr; + void (*fptr)(int); + } u; + + UNUSED(n); + + u.dptr = cb->arg; + if (u.fptr != NULL) + u.fptr(p); + return (1); +} +#endif + static isc_result_t -openssldh_generate(dst_key_t *key, int generator) { +openssldh_generate(dst_key_t *key, int generator, void (*callback)(int)) { + DH *dh = NULL; #if OPENSSL_VERSION_NUMBER > 0x00908000L BN_GENCB cb; + union { + void *dptr; + void (*fptr)(int); + } u; +#else + + UNUSED(callback); #endif - DH *dh = NULL; if (generator == 0) { if (key->key_size == 768 || @@ -181,7 +206,12 @@ openssldh_generate(dst_key_t *key, int generator) { if (dh == NULL) return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); - BN_GENCB_set_old(&cb, NULL, NULL); + if (callback == NULL) { + BN_GENCB_set_old(&cb, NULL, NULL); + } else { + u.fptr = callback; + BN_GENCB_set(&cb, &progress_cb, u.dptr); + } if (!DH_generate_parameters_ex(dh, key->key_size, generator, &cb)) { @@ -476,7 +506,7 @@ openssldh_tofile(const dst_key_t *key, const char *directory) { } static isc_result_t -openssldh_parse(dst_key_t *key, isc_lex_t *lexer) { +openssldh_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { dst_private_t priv; isc_result_t ret; int i; @@ -484,6 +514,7 @@ openssldh_parse(dst_key_t *key, isc_lex_t *lexer) { isc_mem_t *mctx; #define DST_RET(a) {ret = a; goto err;} + UNUSED(pub); mctx = key->mctx; /* read private key file */ @@ -609,6 +640,8 @@ static dst_func_t openssldh_functions = { openssldh_parse, openssldh_cleanup, NULL, /*%< fromlabel */ + NULL, /*%< dump */ + NULL, /*%< restore */ }; isc_result_t diff --git a/lib/dns/openssldsa_link.c b/lib/dns/openssldsa_link.c index c563d9b..ae88d4c 100644 --- a/lib/dns/openssldsa_link.c +++ b/lib/dns/openssldsa_link.c @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2004-2009, 2011 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -29,7 +29,7 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: openssldsa_link.c,v 1.13.120.2 2009-01-14 23:47:26 tbox Exp $ */ +/* $Id: openssldsa_link.c,v 1.20 2011-01-11 23:47:13 tbox Exp $ */ #ifdef OPENSSL #ifndef USE_EVP @@ -313,15 +313,40 @@ openssldsa_compare(const dst_key_t *key1, const dst_key_t *key2) { return (ISC_TRUE); } -static isc_result_t -openssldsa_generate(dst_key_t *key, int unused) { #if OPENSSL_VERSION_NUMBER > 0x00908000L - BN_GENCB cb; +static int +progress_cb(int p, int n, BN_GENCB *cb) +{ + union { + void *dptr; + void (*fptr)(int); + } u; + + UNUSED(n); + + u.dptr = cb->arg; + if (u.fptr != NULL) + u.fptr(p); + return (1); +} #endif + +static isc_result_t +openssldsa_generate(dst_key_t *key, int unused, void (*callback)(int)) { DSA *dsa; unsigned char rand_array[ISC_SHA1_DIGESTLENGTH]; isc_result_t result; +#if OPENSSL_VERSION_NUMBER > 0x00908000L + BN_GENCB cb; + union { + void *dptr; + void (*fptr)(int); + } u; + +#else + UNUSED(callback); +#endif UNUSED(unused); result = dst__entropy_getdata(rand_array, sizeof(rand_array), @@ -334,7 +359,12 @@ openssldsa_generate(dst_key_t *key, int unused) { if (dsa == NULL) return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); - BN_GENCB_set_old(&cb, NULL, NULL); + if (callback == NULL) { + BN_GENCB_set_old(&cb, NULL, NULL); + } else { + u.fptr = callback; + BN_GENCB_set(&cb, &progress_cb, u.dptr); + } if (!DSA_generate_parameters_ex(dsa, key->key_size, rand_array, ISC_SHA1_DIGESTLENGTH, NULL, NULL, @@ -512,7 +542,7 @@ openssldsa_tofile(const dst_key_t *key, const char *directory) { } static isc_result_t -openssldsa_parse(dst_key_t *key, isc_lex_t *lexer) { +openssldsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { dst_private_t priv; isc_result_t ret; int i; @@ -520,6 +550,7 @@ openssldsa_parse(dst_key_t *key, isc_lex_t *lexer) { isc_mem_t *mctx = key->mctx; #define DST_RET(a) {ret = a; goto err;} + UNUSED(pub); /* read private key file */ ret = dst__privstruct_parse(key, DST_ALG_DSA, lexer, mctx, &priv); if (ret != ISC_R_SUCCESS) @@ -587,6 +618,8 @@ static dst_func_t openssldsa_functions = { openssldsa_parse, NULL, /*%< cleanup */ NULL, /*%< fromlabel */ + NULL, /*%< dump */ + NULL, /*%< restore */ }; isc_result_t diff --git a/lib/dns/opensslgost_link.c b/lib/dns/opensslgost_link.c new file mode 100644 index 0000000..1b029db --- /dev/null +++ b/lib/dns/opensslgost_link.c @@ -0,0 +1,418 @@ +/* + * Copyright (C) 2010, 2011 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: opensslgost_link.c,v 1.5 2011-01-19 23:47:12 tbox Exp $ */ + +#include + +#ifdef HAVE_OPENSSL_GOST + +#include +#include +#include +#include + +#include + +#include "dst_internal.h" +#include "dst_openssl.h" +#include "dst_parse.h" + +#include +#include +#include +#include + +static ENGINE *e = NULL; +static const EVP_MD *opensslgost_digest; +extern const EVP_MD *EVP_gost(void); + +const EVP_MD *EVP_gost(void) { + return (opensslgost_digest); +} + +#define DST_RET(a) {ret = a; goto err;} + +static isc_result_t opensslgost_todns(const dst_key_t *key, + isc_buffer_t *data); + +static isc_result_t +opensslgost_createctx(dst_key_t *key, dst_context_t *dctx) { + EVP_MD_CTX *evp_md_ctx; + const EVP_MD *md = EVP_gost(); + + UNUSED(key); + + if (md == NULL) + return (DST_R_OPENSSLFAILURE); + + evp_md_ctx = EVP_MD_CTX_create(); + if (evp_md_ctx == NULL) + return (ISC_R_NOMEMORY); + + if (!EVP_DigestInit_ex(evp_md_ctx, md, NULL)) { + EVP_MD_CTX_destroy(evp_md_ctx); + return (ISC_R_FAILURE); + } + dctx->ctxdata.evp_md_ctx = evp_md_ctx; + + return (ISC_R_SUCCESS); +} + +static void +opensslgost_destroyctx(dst_context_t *dctx) { + EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; + + if (evp_md_ctx != NULL) { + EVP_MD_CTX_destroy(evp_md_ctx); + dctx->ctxdata.evp_md_ctx = NULL; + } +} + +static isc_result_t +opensslgost_adddata(dst_context_t *dctx, const isc_region_t *data) { + EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; + + if (!EVP_DigestUpdate(evp_md_ctx, data->base, data->length)) + return (ISC_R_FAILURE); + + return (ISC_R_SUCCESS); +} + +static isc_result_t +opensslgost_sign(dst_context_t *dctx, isc_buffer_t *sig) { + dst_key_t *key = dctx->key; + isc_region_t r; + unsigned int siglen = 0; + EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; + EVP_PKEY *pkey = key->keydata.pkey; + + isc_buffer_availableregion(sig, &r); + + if (r.length < (unsigned int) EVP_PKEY_size(pkey)) + return (ISC_R_NOSPACE); + + if (!EVP_SignFinal(evp_md_ctx, r.base, &siglen, pkey)) + return (ISC_R_FAILURE); + + isc_buffer_add(sig, siglen); + + return (ISC_R_SUCCESS); +} + +static isc_result_t +opensslgost_verify(dst_context_t *dctx, const isc_region_t *sig) { + dst_key_t *key = dctx->key; + int status = 0; + EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; + EVP_PKEY *pkey = key->keydata.pkey; + + status = EVP_VerifyFinal(evp_md_ctx, sig->base, sig->length, pkey); + if (status != 1) + return (dst__openssl_toresult(DST_R_VERIFYFAILURE)); + + return (ISC_R_SUCCESS); +} + +static isc_boolean_t +opensslgost_compare(const dst_key_t *key1, const dst_key_t *key2) { + EVP_PKEY *pkey1, *pkey2; + + pkey1 = key1->keydata.pkey; + pkey2 = key2->keydata.pkey; + + if (pkey1 == NULL && pkey2 == NULL) + return (ISC_TRUE); + else if (pkey1 == NULL || pkey2 == NULL) + return (ISC_FALSE); + + if (EVP_PKEY_cmp(pkey1, pkey2) != 1) + return (ISC_FALSE); + return (ISC_TRUE); +} + +static int +progress_cb(EVP_PKEY_CTX *ctx) +{ + union { + void *dptr; + void (*fptr)(int); + } u; + int p; + + u.dptr = EVP_PKEY_CTX_get_app_data(ctx); + p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); + if (u.fptr != NULL) + u.fptr(p); + return (1); +} + +static isc_result_t +opensslgost_generate(dst_key_t *key, int unused, void (*callback)(int)) { + EVP_PKEY_CTX *ctx; + union { + void *dptr; + void (*fptr)(int); + } u; + EVP_PKEY *pkey = NULL; + + UNUSED(unused); + ctx = EVP_PKEY_CTX_new_id(NID_id_GostR3410_2001, NULL); + if (ctx == NULL) + goto err; + if (callback != NULL) { + u.fptr = callback; + EVP_PKEY_CTX_set_app_data(ctx, u.dptr); + EVP_PKEY_CTX_set_cb(ctx, &progress_cb); + } + if (EVP_PKEY_keygen_init(ctx) <= 0) + goto err; + if (EVP_PKEY_CTX_ctrl_str(ctx, "paramset", "A") <= 0) + goto err; + if (EVP_PKEY_keygen(ctx, &pkey) <= 0) + goto err; + key->keydata.pkey = pkey; + EVP_PKEY_CTX_free(ctx); + return (ISC_R_SUCCESS); + +err: + if (pkey != NULL) + EVP_PKEY_free(pkey); + if (ctx != NULL) + EVP_PKEY_CTX_free(ctx); + return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); +} + +static isc_boolean_t +opensslgost_isprivate(const dst_key_t *key) { + EVP_PKEY *pkey = key->keydata.pkey; + EC_KEY *ec; + + INSIST(pkey != NULL); + + ec = EVP_PKEY_get0(pkey); + return (ISC_TF(ec != NULL && EC_KEY_get0_private_key(ec) != NULL)); +} + +static void +opensslgost_destroy(dst_key_t *key) { + EVP_PKEY *pkey = key->keydata.pkey; + + EVP_PKEY_free(pkey); + key->keydata.pkey = NULL; +} + +unsigned char gost_prefix[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 +}; + +static isc_result_t +opensslgost_todns(const dst_key_t *key, isc_buffer_t *data) { + EVP_PKEY *pkey; + isc_region_t r; + unsigned char der[37 + 64], *p; + int len; + + REQUIRE(key->keydata.pkey != NULL); + + pkey = key->keydata.pkey; + + isc_buffer_availableregion(data, &r); + if (r.length < 64) + return (ISC_R_NOSPACE); + + p = der; + len = i2d_PUBKEY(pkey, &p); + INSIST(len == sizeof(der)); + INSIST(memcmp(gost_prefix, der, 37) == 0); + memcpy(r.base, der + 37, 64); + isc_buffer_add(data, 64); + + return (ISC_R_SUCCESS); +} + +static isc_result_t +opensslgost_fromdns(dst_key_t *key, isc_buffer_t *data) { + isc_region_t r; + EVP_PKEY *pkey = NULL; + unsigned char der[37 + 64]; + const unsigned char *p; + + isc_buffer_remainingregion(data, &r); + if (r.length == 0) + return (ISC_R_SUCCESS); + + if (r.length != 64) + return (DST_R_INVALIDPUBLICKEY); + memcpy(der, gost_prefix, 37); + memcpy(der + 37, r.base, 64); + isc_buffer_forward(data, 64); + + p = der; + if (d2i_PUBKEY(&pkey, &p, (long) sizeof(der)) == NULL) + return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); + key->keydata.pkey = pkey; + + return (ISC_R_SUCCESS); +} + +static isc_result_t +opensslgost_tofile(const dst_key_t *key, const char *directory) { + EVP_PKEY *pkey; + dst_private_t priv; + isc_result_t result; + unsigned char *der, *p; + int len; + + if (key->keydata.pkey == NULL) + return (DST_R_NULLKEY); + + pkey = key->keydata.pkey; + + len = i2d_PrivateKey(pkey, NULL); + der = isc_mem_get(key->mctx, (size_t) len); + if (der == NULL) + return (ISC_R_NOMEMORY); + + p = der; + if (i2d_PrivateKey(pkey, &p) != len) { + result = dst__openssl_toresult(DST_R_OPENSSLFAILURE); + goto fail; + } + + priv.elements[0].tag = TAG_GOST_PRIVASN1; + priv.elements[0].length = len; + priv.elements[0].data = der; + priv.nelements = GOST_NTAGS; + + result = dst__privstruct_writefile(key, &priv, directory); + fail: + if (der != NULL) + isc_mem_put(key->mctx, der, (size_t) len); + return (result); +} + +static isc_result_t +opensslgost_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { + dst_private_t priv; + isc_result_t ret; + isc_mem_t *mctx = key->mctx; + EVP_PKEY *pkey = NULL; + const unsigned char *p; + + UNUSED(pub); + + /* read private key file */ + ret = dst__privstruct_parse(key, DST_ALG_ECCGOST, lexer, mctx, &priv); + if (ret != ISC_R_SUCCESS) + return (ret); + + INSIST(priv.elements[0].tag == TAG_GOST_PRIVASN1); + p = priv.elements[0].data; + if (d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p, + (long) priv.elements[0].length) == NULL) + DST_RET(DST_R_INVALIDPRIVATEKEY); + key->keydata.pkey = pkey; + key->key_size = EVP_PKEY_bits(pkey); + dst__privstruct_free(&priv, mctx); + memset(&priv, 0, sizeof(priv)); + return (ISC_R_SUCCESS); + + err: + if (pkey != NULL) + EVP_PKEY_free(pkey); + opensslgost_destroy(key); + dst__privstruct_free(&priv, mctx); + memset(&priv, 0, sizeof(priv)); + return (ret); +} + +static void +opensslgost_cleanup(void) { + if (e != NULL) { + ENGINE_finish(e); + ENGINE_free(e); + e = NULL; + } +} + +static dst_func_t opensslgost_functions = { + opensslgost_createctx, + opensslgost_destroyctx, + opensslgost_adddata, + opensslgost_sign, + opensslgost_verify, + NULL, /*%< computesecret */ + opensslgost_compare, + NULL, /*%< paramcompare */ + opensslgost_generate, + opensslgost_isprivate, + opensslgost_destroy, + opensslgost_todns, + opensslgost_fromdns, + opensslgost_tofile, + opensslgost_parse, + opensslgost_cleanup, + NULL, /*%< fromlabel */ + NULL, /*%< dump */ + NULL /*%< restore */ +}; + +isc_result_t +dst__opensslgost_init(dst_func_t **funcp) { + REQUIRE(funcp != NULL); + + /* check if the gost engine works properly */ + e = ENGINE_by_id("gost"); + if (e == NULL) + return (DST_R_OPENSSLFAILURE); + if (ENGINE_init(e) <= 0) { + ENGINE_free(e); + e = NULL; + return (DST_R_OPENSSLFAILURE); + } + /* better than to rely on digest_gost symbol */ + opensslgost_digest = ENGINE_get_digest(e, NID_id_GostR3411_94); + /* from openssl.cnf */ + if ((opensslgost_digest == NULL) || + (ENGINE_register_pkey_asn1_meths(e) <= 0) || + (ENGINE_ctrl_cmd_string(e, + "CRYPT_PARAMS", + "id-Gost28147-89-CryptoPro-A-ParamSet", + 0) <= 0)) { + ENGINE_finish(e); + ENGINE_free(e); + e = NULL; + return (DST_R_OPENSSLFAILURE); + } + + if (*funcp == NULL) + *funcp = &opensslgost_functions; + return (ISC_R_SUCCESS); +} + +#else /* HAVE_OPENSSL_GOST */ + +#include + +EMPTY_TRANSLATION_UNIT + +#endif /* HAVE_OPENSSL_GOST */ +/*! \file */ diff --git a/lib/dns/opensslrsa_link.c b/lib/dns/opensslrsa_link.c index 1e3c5c2..fcdc9f0 100644 --- a/lib/dns/opensslrsa_link.c +++ b/lib/dns/opensslrsa_link.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -17,7 +17,7 @@ /* * Principal Author: Brian Wellington - * $Id: opensslrsa_link.c,v 1.20.50.8 2010-01-22 02:36:49 marka Exp $ + * $Id: opensslrsa_link.c,v 1.39 2011-01-11 23:47:13 tbox Exp $ */ #ifdef OPENSSL #include @@ -30,6 +30,7 @@ #endif #endif + #include #include #include @@ -368,7 +369,7 @@ opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { RSA *rsa = key->keydata.rsa; /* note: ISC_SHA512_DIGESTLENGTH >= ISC_*_DIGESTLENGTH */ unsigned char digest[PREFIXLEN + ISC_SHA512_DIGESTLENGTH]; - int status = 0; + int status; int type = 0; unsigned int digestlen = 0; char *message; @@ -703,10 +704,32 @@ opensslrsa_compare(const dst_key_t *key1, const dst_key_t *key2) { return (ISC_TRUE); } +#if OPENSSL_VERSION_NUMBER > 0x00908000L +static int +progress_cb(int p, int n, BN_GENCB *cb) +{ + union { + void *dptr; + void (*fptr)(int); + } u; + + UNUSED(n); + + u.dptr = cb->arg; + if (u.fptr != NULL) + u.fptr(p); + return (1); +} +#endif + static isc_result_t -opensslrsa_generate(dst_key_t *key, int exp) { +opensslrsa_generate(dst_key_t *key, int exp, void (*callback)(int)) { #if OPENSSL_VERSION_NUMBER > 0x00908000L BN_GENCB cb; + union { + void *dptr; + void (*fptr)(int); + } u; RSA *rsa = RSA_new(); BIGNUM *e = BN_new(); #if USE_EVP @@ -732,7 +755,12 @@ opensslrsa_generate(dst_key_t *key, int exp) { BN_set_bit(e, 32); } - BN_GENCB_set_old(&cb, NULL, NULL); + if (callback == NULL) { + BN_GENCB_set_old(&cb, NULL, NULL); + } else { + u.fptr = callback; + BN_GENCB_set(&cb, &progress_cb, u.dptr); + } if (RSA_generate_key_ex(rsa, key->key_size, e, &cb)) { BN_free(e); @@ -763,8 +791,12 @@ err: #if USE_EVP EVP_PKEY *pkey = EVP_PKEY_new(); + UNUSED(callback); + if (pkey == NULL) return (ISC_R_NOMEMORY); +#else + UNUSED(callback); #endif if (exp == 0) @@ -1059,8 +1091,9 @@ opensslrsa_tofile(const dst_key_t *key, const char *directory) { i++; } + priv.nelements = i; - result = dst__privstruct_writefile(key, &priv, directory); + result = dst__privstruct_writefile(key, &priv, directory); fail: #if USE_EVP RSA_free(rsa); @@ -1074,16 +1107,52 @@ opensslrsa_tofile(const dst_key_t *key, const char *directory) { } static isc_result_t -opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer) { +rsa_check(RSA *rsa, RSA *pub) +{ + /* Public parameters should be the same but if they are not set + * copy them from the public key. */ + if (pub != NULL) { + if (rsa->n != NULL) { + if (BN_cmp(rsa->n, pub->n) != 0) + return (DST_R_INVALIDPRIVATEKEY); + } else { + rsa->n = pub->n; + pub->n = NULL; + } + if (rsa->e != NULL) { + if (BN_cmp(rsa->e, pub->e) != 0) + return (DST_R_INVALIDPRIVATEKEY); + } else { + rsa->e = pub->e; + pub->e = NULL; + } + } + if (rsa->n == NULL || rsa->e == NULL) + return (DST_R_INVALIDPRIVATEKEY); + return (ISC_R_SUCCESS); +} + +static isc_result_t +opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { dst_private_t priv; isc_result_t ret; int i; - RSA *rsa = NULL; + RSA *rsa = NULL, *pubrsa = NULL; ENGINE *e = NULL; isc_mem_t *mctx = key->mctx; - const char *name = NULL, *label = NULL; + const char *engine = NULL, *label = NULL; EVP_PKEY *pkey = NULL; +#if USE_EVP + if (pub != NULL && pub->keydata.pkey != NULL) + pubrsa = EVP_PKEY_get1_RSA(pub->keydata.pkey); +#else + if (pub != NULL && pub->keydata.rsa != NULL) { + pubrsa = pub->keydata.rsa; + pub->keydata.rsa = NULL; + } +#endif + /* read private key file */ ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv); if (ret != ISC_R_SUCCESS) @@ -1092,7 +1161,7 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer) { for (i = 0; i < priv.nelements; i++) { switch (priv.elements[i].tag) { case TAG_RSA_ENGINE: - name = (char *)priv.elements[i].data; + engine = (char *)priv.elements[i].data; break; case TAG_RSA_LABEL: label = (char *)priv.elements[i].data; @@ -1105,10 +1174,10 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer) { * Is this key is stored in a HSM? * See if we can fetch it. */ - if (name != NULL || label != NULL) { - INSIST(name != NULL); - INSIST(label != NULL); - e = dst__openssl_getengine(name); + if (label != NULL) { + if (engine == NULL) + DST_RET(DST_R_NOENGINE); + e = dst__openssl_getengine(engine); if (e == NULL) DST_RET(DST_R_NOENGINE); pkey = ENGINE_load_private_key(e, label, NULL, NULL); @@ -1116,22 +1185,29 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer) { /* ERR_print_errors_fp(stderr); */ DST_RET(ISC_R_NOTFOUND); } - key->engine = isc_mem_strdup(key->mctx, name); + key->engine = isc_mem_strdup(key->mctx, engine); if (key->engine == NULL) DST_RET(ISC_R_NOMEMORY); key->label = isc_mem_strdup(key->mctx, label); if (key->label == NULL) DST_RET(ISC_R_NOMEMORY); + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa == NULL) + DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE)); + if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS) + DST_RET(DST_R_INVALIDPRIVATEKEY); + if (pubrsa != NULL) + RSA_free(pubrsa); key->key_size = EVP_PKEY_bits(pkey); #if USE_EVP key->keydata.pkey = pkey; + RSA_free(rsa); #else - key->keydata.rsa = EVP_PKEY_get1_RSA(pkey); - if (rsa == NULL) - DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE)); + key->keydata.rsa = rsa; EVP_PKEY_free(pkey); #endif dst__privstruct_free(&priv, mctx); + memset(&priv, 0, sizeof(priv)); return (ISC_R_SUCCESS); } @@ -1144,9 +1220,8 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer) { pkey = EVP_PKEY_new(); if (pkey == NULL) DST_RET(ISC_R_NOMEMORY); - if (!EVP_PKEY_set1_RSA(pkey, rsa)) { + if (!EVP_PKEY_set1_RSA(pkey, rsa)) DST_RET(ISC_R_FAILURE); - } key->keydata.pkey = pkey; #else key->keydata.rsa = rsa; @@ -1196,8 +1271,13 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer) { } } dst__privstruct_free(&priv, mctx); + memset(&priv, 0, sizeof(priv)); + if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS) + DST_RET(DST_R_INVALIDPRIVATEKEY); key->key_size = BN_num_bits(rsa->n); + if (pubrsa != NULL) + RSA_free(pubrsa); #if USE_EVP RSA_free(rsa); #endif @@ -1211,6 +1291,8 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer) { #endif if (rsa != NULL) RSA_free(rsa); + if (pubrsa != NULL) + RSA_free(pubrsa); opensslrsa_destroy(key); dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); @@ -1224,33 +1306,63 @@ opensslrsa_fromlabel(dst_key_t *key, const char *engine, const char *label, ENGINE *e = NULL; isc_result_t ret; EVP_PKEY *pkey = NULL; + RSA *rsa = NULL, *pubrsa = NULL; + char *colon; UNUSED(pin); + if (engine == NULL) + DST_RET(DST_R_NOENGINE); e = dst__openssl_getengine(engine); if (e == NULL) DST_RET(DST_R_NOENGINE); + pkey = ENGINE_load_public_key(e, label, NULL, NULL); + if (pkey != NULL) { + pubrsa = EVP_PKEY_get1_RSA(pkey); + EVP_PKEY_free(pkey); + if (pubrsa == NULL) + DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE)); + } pkey = ENGINE_load_private_key(e, label, NULL, NULL); if (pkey == NULL) DST_RET(ISC_R_NOTFOUND); - key->engine = isc_mem_strdup(key->mctx, label); - if (key->engine == NULL) - DST_RET(ISC_R_NOMEMORY); + if (engine != NULL) { + key->engine = isc_mem_strdup(key->mctx, engine); + if (key->engine == NULL) + DST_RET(ISC_R_NOMEMORY); + } else { + key->engine = isc_mem_strdup(key->mctx, label); + if (key->engine == NULL) + DST_RET(ISC_R_NOMEMORY); + colon = strchr(key->engine, ':'); + if (colon != NULL) + *colon = '\0'; + } key->label = isc_mem_strdup(key->mctx, label); if (key->label == NULL) DST_RET(ISC_R_NOMEMORY); + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa == NULL) + DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE)); + if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS) + DST_RET(DST_R_INVALIDPRIVATEKEY); + if (pubrsa != NULL) + RSA_free(pubrsa); key->key_size = EVP_PKEY_bits(pkey); #if USE_EVP key->keydata.pkey = pkey; + RSA_free(rsa); #else - key->keydata.rsa = EVP_PKEY_get1_RSA(pkey); + key->keydata.rsa = rsa; EVP_PKEY_free(pkey); - if (key->keydata.rsa == NULL) - return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); #endif return (ISC_R_SUCCESS); err: + if (rsa != NULL) + RSA_free(rsa); + if (pubrsa != NULL) + RSA_free(pubrsa); if (pkey != NULL) EVP_PKEY_free(pkey); return (ret); @@ -1274,6 +1386,8 @@ static dst_func_t opensslrsa_functions = { opensslrsa_parse, NULL, /*%< cleanup */ opensslrsa_fromlabel, + NULL, /*%< dump */ + NULL, /*%< restore */ }; isc_result_t diff --git a/lib/dns/peer.c b/lib/dns/peer.c index 1e81023..3851c3e 100644 --- a/lib/dns/peer.c +++ b/lib/dns/peer.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: peer.c,v 1.31 2008-04-03 06:09:04 tbox Exp $ */ +/* $Id: peer.c,v 1.33 2009-09-02 23:48:02 tbox Exp $ */ /*! \file */ @@ -536,7 +536,7 @@ dns_peer_setkeybycharp(dns_peer_t *peer, const char *keyval) { isc_buffer_init(&b, keyval, strlen(keyval)); isc_buffer_add(&b, strlen(keyval)); result = dns_name_fromtext(dns_fixedname_name(&fname), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) return (result); diff --git a/lib/dns/private.c b/lib/dns/private.c new file mode 100644 index 0000000..ba3e8ed --- /dev/null +++ b/lib/dns/private.c @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: private.c,v 1.3 2009-10-09 23:48:09 tbox Exp $ */ + +#include "config.h" + +#include +#include +#include +#include + +#include +#include + +/* + * We need to build the relevant chain if there exists a NSEC/NSEC3PARAM + * at the apex; normally only one or the other of NSEC/NSEC3PARAM will exist. + * + * If a NSEC3PARAM RRset exists then we will need to build a NSEC chain + * if all the NSEC3PARAM records (and associated chains) are slated for + * destruction and we have not been told to NOT build the NSEC chain. + * + * If the NSEC set exist then check to see if there is a request to create + * a NSEC3 chain. + * + * If neither NSEC/NSEC3PARAM RRsets exist at the origin and the private + * type exists then we need to examine it to determine if NSEC3 chain has + * been requested to be built otherwise a NSEC chain needs to be built. + */ + +#define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0) +#define CREATE(x) (((x) & DNS_NSEC3FLAG_CREATE) != 0) +#define NONSEC(x) (((x) & DNS_NSEC3FLAG_NONSEC) != 0) + +#define CHECK(x) do { \ + result = (x); \ + if (result != ISC_R_SUCCESS) \ + goto failure; \ + } while (0) + +/* + * Work out if 'param' should be ignored or not (i.e. it is in the process + * of being removed). + * + * Note: we 'belt-and-braces' here by also checking for a CREATE private + * record and keep the param record in this case. + */ + +static isc_boolean_t +ignore(dns_rdata_t *param, dns_rdataset_t *privateset) { + isc_result_t result; + + for (result = dns_rdataset_first(privateset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(privateset)) { + unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; + dns_rdata_t private = DNS_RDATA_INIT; + dns_rdata_t rdata = DNS_RDATA_INIT; + + dns_rdataset_current(privateset, &private); + if (!dns_nsec3param_fromprivate(&private, &rdata, + buf, sizeof(buf))) + continue; + /* + * We are going to create a new NSEC3 chain so it + * doesn't matter if we are removing this one. + */ + if (CREATE(rdata.data[1])) + return (ISC_FALSE); + if (rdata.data[0] != param->data[0] || + rdata.data[2] != param->data[2] || + rdata.data[3] != param->data[3] || + rdata.data[4] != param->data[4] || + memcmp(&rdata.data[5], ¶m->data[5], param->data[4])) + continue; + /* + * The removal of this NSEC3 chain does NOT cause a + * NSEC chain to be created so we don't need to tell + * the caller that it will be removed. + */ + if (NONSEC(rdata.data[1])) + return (ISC_FALSE); + return (ISC_TRUE); + } + return (ISC_FALSE); +} + +isc_result_t +dns_private_chains(dns_db_t *db, dns_dbversion_t *ver, + dns_rdatatype_t privatetype, + isc_boolean_t *build_nsec, isc_boolean_t *build_nsec3) +{ + dns_dbnode_t *node; + dns_rdataset_t nsecset, nsec3paramset, privateset; + isc_boolean_t nsec3chain; + isc_boolean_t signing; + isc_result_t result; + unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; + unsigned int count; + + node = NULL; + dns_rdataset_init(&nsecset); + dns_rdataset_init(&nsec3paramset); + dns_rdataset_init(&privateset); + + CHECK(dns_db_getoriginnode(db, &node)); + + result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, + 0, (isc_stdtime_t) 0, &nsecset, NULL); + + if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) + goto failure; + + result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, + 0, (isc_stdtime_t) 0, &nsec3paramset, + NULL); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) + goto failure; + + if (dns_rdataset_isassociated(&nsecset) && + dns_rdataset_isassociated(&nsec3paramset)) { + if (build_nsec != NULL) + *build_nsec = ISC_TRUE; + if (build_nsec3 != NULL) + *build_nsec3 = ISC_TRUE; + goto success; + } + + if (privatetype != (dns_rdatatype_t)0) { + result = dns_db_findrdataset(db, node, ver, privatetype, + 0, (isc_stdtime_t) 0, + &privateset, NULL); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) + goto failure; + } + + /* + * Look to see if we also need to be creating a NSEC3 chains. + */ + if (dns_rdataset_isassociated(&nsecset)) { + if (build_nsec != NULL) + *build_nsec = ISC_TRUE; + if (build_nsec3 != NULL) + *build_nsec3 = ISC_FALSE; + if (!dns_rdataset_isassociated(&privateset)) + goto success; + for (result = dns_rdataset_first(&privateset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&privateset)) { + unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; + dns_rdata_t private = DNS_RDATA_INIT; + dns_rdata_t rdata = DNS_RDATA_INIT; + + dns_rdataset_current(&privateset, &private); + if (!dns_nsec3param_fromprivate(&private, &rdata, + buf, sizeof(buf))) + continue; + if (REMOVE(rdata.data[1])) + continue; + if (build_nsec3 != NULL) + *build_nsec3 = ISC_TRUE; + break; + } + goto success; + } + + if (dns_rdataset_isassociated(&nsec3paramset)) { + if (build_nsec3 != NULL) + *build_nsec3 = ISC_TRUE; + if (build_nsec != NULL) + *build_nsec = ISC_FALSE; + if (!dns_rdataset_isassociated(&privateset)) + goto success; + /* + * If we are in the process of building a new NSEC3 chain + * then we don't need to build a NSEC chain. + */ + for (result = dns_rdataset_first(&privateset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&privateset)) { + dns_rdata_t private = DNS_RDATA_INIT; + dns_rdata_t rdata = DNS_RDATA_INIT; + + dns_rdataset_current(&privateset, &private); + if (!dns_nsec3param_fromprivate(&private, &rdata, + buf, sizeof(buf))) + continue; + if (CREATE(rdata.data[1])) + goto success; + } + + /* + * Check to see if there will be a active NSEC3CHAIN once + * the changes queued complete. + */ + count = 0; + for (result = dns_rdataset_first(&nsec3paramset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&nsec3paramset)) { + dns_rdata_t rdata = DNS_RDATA_INIT; + + /* + * If there is more that one NSEC3 chain present then + * we don't need to construct a NSEC chain. + */ + if (++count > 1) + goto success; + dns_rdataset_current(&nsec3paramset, &rdata); + if (ignore(&rdata, &privateset)) + continue; + /* + * We still have a good NSEC3 chain or we are + * not creating a NSEC chain as NONSEC is set. + */ + goto success; + } + + /* + * The last NSEC3 chain is being removed and does not have + * have NONSEC set. + */ + if (build_nsec != NULL) + *build_nsec = ISC_TRUE; + goto success; + } + + if (build_nsec != NULL) + *build_nsec = ISC_FALSE; + if (build_nsec3 != NULL) + *build_nsec3 = ISC_FALSE; + if (!dns_rdataset_isassociated(&privateset)) + goto success; + + signing = ISC_FALSE; + nsec3chain = ISC_FALSE; + + for (result = dns_rdataset_first(&privateset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&privateset)) { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_t private = DNS_RDATA_INIT; + + dns_rdataset_current(&privateset, &private); + if (!dns_nsec3param_fromprivate(&private, &rdata, + buf, sizeof(buf))) { + /* + * Look for record that says we are signing the + * zone with a key. + */ + if (private.length == 5 && private.data[0] != 0 && + private.data[3] == 0 && private.data[4] == 0) + signing = ISC_TRUE; + } else { + if (CREATE(rdata.data[1])) + nsec3chain = ISC_TRUE; + } + } + + if (signing) { + if (nsec3chain) { + if (build_nsec3 != NULL) + *build_nsec3 = ISC_TRUE; + } else { + if (build_nsec != NULL) + *build_nsec = ISC_TRUE; + } + } + + success: + result = ISC_R_SUCCESS; + failure: + if (dns_rdataset_isassociated(&nsecset)) + dns_rdataset_disassociate(&nsecset); + if (dns_rdataset_isassociated(&nsec3paramset)) + dns_rdataset_disassociate(&nsec3paramset); + if (dns_rdataset_isassociated(&privateset)) + dns_rdataset_disassociate(&privateset); + if (node != NULL) + dns_db_detachnode(db, &node); + return (result); +} diff --git a/lib/dns/rbt.c b/lib/dns/rbt.c index 5e09db3..6c14e8e 100644 --- a/lib/dns/rbt.c +++ b/lib/dns/rbt.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rbt.c,v 1.142.50.3 2009-10-20 05:06:04 marka Exp $ */ +/* $Id: rbt.c,v 1.146 2009-10-27 04:46:58 marka Exp $ */ /*! \file */ @@ -537,7 +537,10 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) { * current node. */ new_current->is_root = current->is_root; - new_current->nsec3 = current->nsec3; + if (current->nsec == DNS_RBT_NSEC_HAS_NSEC) + new_current->nsec = DNS_RBT_NSEC_NORMAL; + else + new_current->nsec = current->nsec; PARENT(new_current) = PARENT(current); LEFT(new_current) = LEFT(current); RIGHT(new_current) = RIGHT(current); @@ -1451,7 +1454,7 @@ create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep) { DIRTY(node) = 0; dns_rbtnode_refinit(node, 0); node->find_callback = 0; - node->nsec3 = 0; + node->nsec = DNS_RBT_NSEC_NORMAL; MAKE_BLACK(node); diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 87b70e3..d4415d8 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rbtdb.c,v 1.270.12.26.4.1 2011-06-21 20:13:23 each Exp $ */ +/* $Id: rbtdb.c,v 1.310.8.1.2.1 2011-06-21 20:15:48 each Exp $ */ /*! \file */ @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -441,7 +442,9 @@ typedef struct { /* Locked by tree_lock. */ dns_rbt_t * tree; + dns_rbt_t * nsec; dns_rbt_t * nsec3; + dns_rpz_cidr_t * rpz_cidr; /* Unlocked */ unsigned int quantum; @@ -621,8 +624,9 @@ typedef struct rbtdb_dbiterator { static void free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event); static void overmem(dns_db_t *db, isc_boolean_t overmem); -static void setnsec3parameters(dns_db_t *db, rbtdb_version_t *version, - isc_boolean_t *nsec3createflag); +#ifdef BIND9 +static void setnsec3parameters(dns_db_t *db, rbtdb_version_t *version); +#endif /*% * 'init_count' is used to initialize 'newheader->count' which inturn @@ -830,6 +834,7 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) { isc_ondestroy_t ondest; isc_result_t result; char buf[DNS_NAME_FORMATSIZE]; + dns_rbt_t **treep; isc_time_t start; if (IS_CACHE(rbtdb) && rbtdb->common.rdclass == dns_rdataclass_in) @@ -866,33 +871,26 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) { if (event == NULL) rbtdb->quantum = (rbtdb->task != NULL) ? 100 : 0; - again: - if (rbtdb->tree != NULL) { - isc_time_now(&start); - result = dns_rbt_destroy2(&rbtdb->tree, rbtdb->quantum); - if (result == ISC_R_QUOTA) { - INSIST(rbtdb->task != NULL); - if (rbtdb->quantum != 0) - rbtdb->quantum = adjust_quantum(rbtdb->quantum, - &start); - if (event == NULL) - event = isc_event_allocate(rbtdb->common.mctx, - NULL, - DNS_EVENT_FREESTORAGE, - free_rbtdb_callback, - rbtdb, - sizeof(isc_event_t)); - if (event == NULL) - goto again; - isc_task_send(rbtdb->task, &event); - return; + + for (;;) { + /* + * pick the next tree to (start to) destroy + */ + treep = &rbtdb->tree; + if (*treep == NULL) { + treep = &rbtdb->nsec; + if (*treep == NULL) { + treep = &rbtdb->nsec3; + /* + * we're finished after clear cutting + */ + if (*treep == NULL) + break; + } } - INSIST(result == ISC_R_SUCCESS && rbtdb->tree == NULL); - } - if (rbtdb->nsec3 != NULL) { isc_time_now(&start); - result = dns_rbt_destroy2(&rbtdb->nsec3, rbtdb->quantum); + result = dns_rbt_destroy2(treep, rbtdb->quantum); if (result == ISC_R_QUOTA) { INSIST(rbtdb->task != NULL); if (rbtdb->quantum != 0) @@ -906,11 +904,11 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) { rbtdb, sizeof(isc_event_t)); if (event == NULL) - goto again; + continue; isc_task_send(rbtdb->task, &event); return; } - INSIST(result == ISC_R_SUCCESS && rbtdb->nsec3 == NULL); + INSIST(result == ISC_R_SUCCESS && *treep == NULL); } if (event != NULL) @@ -965,6 +963,11 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) { if (rbtdb->rrsetstats != NULL) dns_stats_detach(&rbtdb->rrsetstats); +#ifdef BIND9 + if (rbtdb->rpz_cidr != NULL) + dns_rpz_cidr_free(&rbtdb->rpz_cidr); +#endif + isc_mem_put(rbtdb->common.mctx, rbtdb->node_locks, rbtdb->node_lock_count * sizeof(rbtdb_nodelock_t)); isc_rwlock_destroy(&rbtdb->tree_lock); @@ -1488,6 +1491,82 @@ clean_zone_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, node->dirty = 0; } +static void +delete_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) +{ + dns_rbtnode_t *nsecnode; + dns_fixedname_t fname; + dns_name_t *name; + isc_result_t result = ISC_R_UNEXPECTED; + + INSIST(!ISC_LINK_LINKED(node, deadlink)); + + switch (node->nsec) { + case DNS_RBT_NSEC_NORMAL: +#ifdef BIND9 + if (rbtdb->rpz_cidr != NULL) { + dns_fixedname_init(&fname); + name = dns_fixedname_name(&fname); + dns_rbt_fullnamefromnode(node, name); + dns_rpz_cidr_deleteip(rbtdb->rpz_cidr, name); + } +#endif + result = dns_rbt_deletenode(rbtdb->tree, node, ISC_FALSE); + break; + case DNS_RBT_NSEC_HAS_NSEC: + dns_fixedname_init(&fname); + name = dns_fixedname_name(&fname); + dns_rbt_fullnamefromnode(node, name); + /* + * Delete the corresponding node from the auxiliary NSEC + * tree before deleting from the main tree. + */ + nsecnode = NULL; + result = dns_rbt_findnode(rbtdb->nsec, name, NULL, &nsecnode, + NULL, DNS_RBTFIND_EMPTYDATA, + NULL, NULL); + if (result != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_CACHE, ISC_LOG_WARNING, + "delete_node: " + "dns_rbt_findnode(nsec): %s", + isc_result_totext(result)); + } else { + result = dns_rbt_deletenode(rbtdb->nsec, nsecnode, + ISC_FALSE); + if (result != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, + DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_CACHE, + ISC_LOG_WARNING, + "delete_nsecnode(): " + "dns_rbt_deletenode(nsecnode): %s", + isc_result_totext(result)); + } + } + result = dns_rbt_deletenode(rbtdb->tree, node, ISC_FALSE); +#ifdef BIND9 + dns_rpz_cidr_deleteip(rbtdb->rpz_cidr, name); +#endif + break; + case DNS_RBT_NSEC_NSEC: + result = dns_rbt_deletenode(rbtdb->nsec, node, ISC_FALSE); + break; + case DNS_RBT_NSEC_NSEC3: + result = dns_rbt_deletenode(rbtdb->nsec3, node, ISC_FALSE); + break; + } + if (result != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, + DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_CACHE, + ISC_LOG_WARNING, + "delete_nsecnode(): " + "dns_rbt_deletenode: %s", + isc_result_totext(result)); + } +} + /*% * Clean up dead nodes. These are nodes which have no references, and * have no data. They are dead but we could not or chose not to delete @@ -1499,7 +1578,6 @@ clean_zone_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, static void cleanup_dead_nodes(dns_rbtdb_t *rbtdb, int bucketnum) { dns_rbtnode_t *node; - isc_result_t result; int count = 10; /* XXXJT: should be adjustable */ node = ISC_LIST_HEAD(rbtdb->deadnodes[bucketnum]); @@ -1513,19 +1591,8 @@ cleanup_dead_nodes(dns_rbtdb_t *rbtdb, int bucketnum) { INSIST(dns_rbtnode_refcurrent(node) == 0 && node->data == NULL); - INSIST(!ISC_LINK_LINKED(node, deadlink)); - if (node->nsec3) - result = dns_rbt_deletenode(rbtdb->nsec3, node, - ISC_FALSE); - else - result = dns_rbt_deletenode(rbtdb->tree, node, - ISC_FALSE); - if (result != ISC_R_SUCCESS) - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_CACHE, ISC_LOG_WARNING, - "cleanup_dead_nodes: " - "dns_rbt_deletenode: %s", - isc_result_totext(result)); + delete_node(rbtdb, node); + node = ISC_LIST_HEAD(rbtdb->deadnodes[bucketnum]); count--; } @@ -1774,22 +1841,7 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, sizeof(printname))); } - INSIST(!ISC_LINK_LINKED(node, deadlink)); - if (node->nsec3) - result = dns_rbt_deletenode(rbtdb->nsec3, node, - ISC_FALSE); - else - result = dns_rbt_deletenode(rbtdb->tree, node, - ISC_FALSE); - if (result != ISC_R_SUCCESS) { - isc_log_write(dns_lctx, - DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_CACHE, - ISC_LOG_WARNING, - "decrement_reference: " - "dns_rbt_deletenode: %s", - isc_result_totext(result)); - } + delete_node(rbtdb, node); } } else if (dns_rbtnode_refcurrent(node) == 0) { INSIST(!ISC_LINK_LINKED(node, deadlink)); @@ -1925,13 +1977,17 @@ cleanup_nondirty(rbtdb_version_t *version, rbtdb_changedlist_t *cleanup_list) { static void iszonesecure(dns_db_t *db, rbtdb_version_t *version, dns_dbnode_t *origin) { +#ifndef BIND9 + UNUSED(db); + UNUSED(version); + UNUSED(origin); + + return; +#else dns_rdataset_t keyset; dns_rdataset_t nsecset, signsecset; - dns_rdata_t rdata = DNS_RDATA_INIT; isc_boolean_t haszonekey = ISC_FALSE; isc_boolean_t hasnsec = ISC_FALSE; - isc_boolean_t hasoptbit = ISC_FALSE; - isc_boolean_t nsec3createflag = ISC_FALSE; isc_result_t result; dns_rdataset_init(&keyset); @@ -1963,41 +2019,30 @@ iszonesecure(dns_db_t *db, rbtdb_version_t *version, dns_dbnode_t *origin) { if (result == ISC_R_SUCCESS) { if (dns_rdataset_isassociated(&signsecset)) { hasnsec = ISC_TRUE; - result = dns_rdataset_first(&nsecset); - if (result == ISC_R_SUCCESS) { - dns_rdataset_current(&nsecset, &rdata); - hasoptbit = dns_nsec_typepresent(&rdata, - dns_rdatatype_opt); - } dns_rdataset_disassociate(&signsecset); } dns_rdataset_disassociate(&nsecset); } - setnsec3parameters(db, version, &nsec3createflag); + setnsec3parameters(db, version); /* * Do we have a valid NSEC/NSEC3 chain? */ - if (version->havensec3 || (hasnsec && !hasoptbit)) + if (version->havensec3 || hasnsec) version->secure = dns_db_secure; - /* - * Do we have a NSEC/NSEC3 chain under creation? - */ - else if (hasoptbit || nsec3createflag) - version->secure = dns_db_partial; else version->secure = dns_db_insecure; +#endif } /*%< * Walk the origin node looking for NSEC3PARAM records. * Cache the nsec3 parameters. */ +#ifdef BIND9 static void -setnsec3parameters(dns_db_t *db, rbtdb_version_t *version, - isc_boolean_t *nsec3createflag) -{ +setnsec3parameters(dns_db_t *db, rbtdb_version_t *version) { dns_rbtnode_t *node; dns_rdata_nsec3param_t nsec3param; dns_rdata_t rdata = DNS_RDATA_INIT; @@ -2028,7 +2073,7 @@ setnsec3parameters(dns_db_t *db, rbtdb_version_t *version, } while (header != NULL); if (header != NULL && - header->type == dns_rdatatype_nsec3param) { + (header->type == dns_rdatatype_nsec3param)) { /* * Find A NSEC3PARAM with a supported algorithm. */ @@ -2063,17 +2108,8 @@ setnsec3parameters(dns_db_t *db, rbtdb_version_t *version, !dns_nsec3_supportedhash(nsec3param.hash)) continue; -#ifdef RFC5155_STRICT if (nsec3param.flags != 0) continue; -#else - if ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) - != 0) - *nsec3createflag = ISC_TRUE; - if ((nsec3param.flags & ~DNS_NSEC3FLAG_OPTOUT) - != 0) - continue; -#endif memcpy(version->salt, nsec3param.salt, nsec3param.salt_length); @@ -2096,6 +2132,7 @@ setnsec3parameters(dns_db_t *db, rbtdb_version_t *version, isc_rwlocktype_read); RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); } +#endif static void cleanup_dead_nodes_callback(isc_task_t *task, isc_event_t *event) { @@ -2415,7 +2452,8 @@ add_wildcard_magic(dns_rbtdb_t *rbtdb, dns_name_t *name) { result = dns_rbt_addnode(rbtdb->tree, &foundname, &node); if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) return (result); - node->nsec3 = 0; + if (result == ISC_R_SUCCESS) + node->nsec = DNS_RBT_NSEC_NORMAL; node->find_callback = 1; node->wild = 1; return (ISC_R_SUCCESS); @@ -2443,7 +2481,8 @@ add_empty_wildcards(dns_rbtdb_t *rbtdb, dns_name_t *name) { &node); if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) return (result); - node->nsec3 = 0; + if (result == ISC_R_SUCCESS) + node->nsec = DNS_RBT_NSEC_NORMAL; } i++; } @@ -2482,6 +2521,17 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, node = NULL; result = dns_rbt_addnode(rbtdb->tree, name, &node); if (result == ISC_R_SUCCESS) { +#ifdef BIND9 + if (rbtdb->rpz_cidr != NULL) { + dns_fixedname_t fnamef; + dns_name_t *fname; + + dns_fixedname_init(&fnamef); + fname = dns_fixedname_name(&fnamef); + dns_rbt_fullnamefromnode(node, fname); + dns_rpz_cidr_addip(rbtdb->rpz_cidr, fname); + } +#endif dns_rbt_namefromnode(node, &nodename); #ifdef DNS_RBT_USEHASH node->locknum = node->hashval % rbtdb->node_lock_count; @@ -2489,7 +2539,6 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, node->locknum = dns_name_hash(&nodename, ISC_TRUE) % rbtdb->node_lock_count; #endif - node->nsec3 = 0; add_empty_wildcards(rbtdb, name); if (dns_name_iswildcard(name)) { @@ -2551,13 +2600,14 @@ findnsec3node(dns_db_t *db, dns_name_t *name, isc_boolean_t create, node->locknum = dns_name_hash(&nodename, ISC_TRUE) % rbtdb->node_lock_count; #endif - node->nsec3 = 1U; + node->nsec = DNS_RBT_NSEC_NSEC3; } else if (result != ISC_R_EXISTS) { RWUNLOCK(&rbtdb->tree_lock, locktype); return (result); } - } else - INSIST(node->nsec3); + } else { + INSIST(node->nsec == DNS_RBT_NSEC_NSEC3); + } NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock); new_reference(rbtdb, node); NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock); @@ -3268,13 +3318,125 @@ matchparams(rdatasetheader_t *header, rbtdb_search_t *search) * Find node of the NSEC/NSEC3 record that is 'name'. */ static inline isc_result_t +previous_closest_nsec(dns_rdatatype_t type, rbtdb_search_t *search, + dns_name_t *name, dns_name_t *origin, + dns_rbtnode_t **nodep, dns_rbtnodechain_t *nsecchain, + isc_boolean_t *firstp) +{ + dns_fixedname_t ftarget; + dns_name_t *target; + dns_rbtnode_t *nsecnode; + isc_result_t result; + + REQUIRE(nodep != NULL && *nodep == NULL); + + if (type == dns_rdatatype_nsec3) { + result = dns_rbtnodechain_prev(&search->chain, NULL, NULL); + if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) + return (result); + result = dns_rbtnodechain_current(&search->chain, name, origin, + nodep); + return (result); + } + + dns_fixedname_init(&ftarget); + target = dns_fixedname_name(&ftarget); + + for (;;) { + if (*firstp) { + /* + * Construct the name of the second node to check. + * It is the first node sought in the NSEC tree. + */ + *firstp = ISC_FALSE; + dns_rbtnodechain_init(nsecchain, NULL); + result = dns_name_concatenate(name, origin, + target, NULL); + if (result != ISC_R_SUCCESS) + return (result); + nsecnode = NULL; + result = dns_rbt_findnode(search->rbtdb->nsec, + target, NULL, + &nsecnode, nsecchain, + DNS_RBTFIND_NOOPTIONS, + NULL, NULL); + if (result == ISC_R_SUCCESS) { + /* + * Since this was the first loop, finding the + * name in the NSEC tree implies that the first + * node checked in the main tree had an + * unacceptable NSEC record. + * Try the previous node in the NSEC tree. + */ + result = dns_rbtnodechain_prev(nsecchain, + name, origin); + if (result == DNS_R_NEWORIGIN) + result = ISC_R_SUCCESS; + } else if (result == ISC_R_NOTFOUND || + result == DNS_R_PARTIALMATCH) { + result = dns_rbtnodechain_current(nsecchain, + name, origin, NULL); + if (result == ISC_R_NOTFOUND) + result = ISC_R_NOMORE; + } + } else { + /* + * This is a second or later trip through the auxiliary + * tree for the name of a third or earlier NSEC node in + * the main tree. Previous trips through the NSEC tree + * must have found nodes in the main tree with NSEC + * records. Perhaps they lacked signature records. + */ + result = dns_rbtnodechain_prev(nsecchain, name, origin); + if (result == DNS_R_NEWORIGIN) + result = ISC_R_SUCCESS; + } + if (result != ISC_R_SUCCESS) + return (result); + + /* + * Construct the name to seek in the main tree. + */ + result = dns_name_concatenate(name, origin, target, NULL); + if (result != ISC_R_SUCCESS) + return (result); + + *nodep = NULL; + result = dns_rbt_findnode(search->rbtdb->tree, target, NULL, + nodep, &search->chain, + DNS_RBTFIND_NOOPTIONS, NULL, NULL); + if (result == ISC_R_SUCCESS) + return (result); + + /* + * There should always be a node in the main tree with the + * same name as the node in the auxiliary NSEC tree, except for + * nodes in the auxiliary tree that are awaiting deletion. + */ + if (result != DNS_R_PARTIALMATCH && result != ISC_R_NOTFOUND) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_CACHE, ISC_LOG_ERROR, + "previous_closest_nsec(): %s", + isc_result_totext(result)); + return (DNS_R_BADDB); + } + } +} + +/* + * Find the NSEC/NSEC3 which is or before the current point on the + * search chain. For NSEC3 records only NSEC3 records that match the + * current NSEC3PARAM record are considered. + */ +static inline isc_result_t find_closest_nsec(rbtdb_search_t *search, dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, dns_rbt_t *tree, dns_db_secure_t secure) { - dns_rbtnode_t *node; + dns_rbtnode_t *node, *prevnode; rdatasetheader_t *header, *header_next, *found, *foundsig; + dns_rbtnodechain_t nsecchain; isc_boolean_t empty_node; isc_result_t result; dns_fixedname_t fname, forigin; @@ -3282,6 +3444,7 @@ find_closest_nsec(rbtdb_search_t *search, dns_dbnode_t **nodep, dns_rdatatype_t type; rbtdb_rdatatype_t sigtype; isc_boolean_t wraps; + isc_boolean_t first = ISC_TRUE; isc_boolean_t need_sig = ISC_TF(secure == dns_db_secure); if (tree == search->rbtdb->nsec3) { @@ -3294,17 +3457,21 @@ find_closest_nsec(rbtdb_search_t *search, dns_dbnode_t **nodep, wraps = ISC_FALSE; } + /* + * Use the auxiliary tree only starting with the second node in the + * hope that the original node will be right much of the time. + */ + dns_fixedname_init(&fname); + name = dns_fixedname_name(&fname); + dns_fixedname_init(&forigin); + origin = dns_fixedname_name(&forigin); again: + node = NULL; + prevnode = NULL; + result = dns_rbtnodechain_current(&search->chain, name, origin, &node); + if (result != ISC_R_SUCCESS) + return (result); do { - node = NULL; - dns_fixedname_init(&fname); - name = dns_fixedname_name(&fname); - dns_fixedname_init(&forigin); - origin = dns_fixedname_name(&forigin); - result = dns_rbtnodechain_current(&search->chain, name, - origin, &node); - if (result != ISC_R_SUCCESS) - return (result); NODE_LOCK(&(search->rbtdb->node_locks[node->locknum].lock), isc_rwlocktype_read); found = NULL; @@ -3354,11 +3521,12 @@ find_closest_nsec(rbtdb_search_t *search, dns_dbnode_t **nodep, empty_node = ISC_TRUE; found = NULL; foundsig = NULL; - result = dns_rbtnodechain_prev(&search->chain, - NULL, NULL); + result = previous_closest_nsec(type, search, + name, origin, + &prevnode, NULL, + NULL); } else if (found != NULL && - (foundsig != NULL || !need_sig)) - { + (foundsig != NULL || !need_sig)) { /* * We've found the right NSEC/NSEC3 record. * @@ -3395,8 +3563,11 @@ find_closest_nsec(rbtdb_search_t *search, dns_dbnode_t **nodep, * node as if it were empty and keep looking. */ empty_node = ISC_TRUE; - result = dns_rbtnodechain_prev(&search->chain, - NULL, NULL); + result = previous_closest_nsec(type, search, + name, origin, + &prevnode, + &nsecchain, + &first); } else { /* * We found an active node, but either the @@ -3410,13 +3581,19 @@ find_closest_nsec(rbtdb_search_t *search, dns_dbnode_t **nodep, * This node isn't active. We've got to keep * looking. */ - result = dns_rbtnodechain_prev(&search->chain, NULL, - NULL); + result = previous_closest_nsec(type, search, + name, origin, &prevnode, + &nsecchain, &first); } NODE_UNLOCK(&(search->rbtdb->node_locks[node->locknum].lock), isc_rwlocktype_read); + node = prevnode; + prevnode = NULL; } while (empty_node && result == ISC_R_SUCCESS); + if (!first) + dns_rbtnodechain_invalidate(&nsecchain); + if (result == ISC_R_NOMORE && wraps) { result = dns_rbtnodechain_last(&search->chain, tree, NULL, NULL); @@ -3960,6 +4137,7 @@ zone_findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options, FATAL_ERROR(__FILE__, __LINE__, "zone_findzonecut() called!"); + /* NOTREACHED */ return (ISC_R_NOTIMPLEMENTED); } @@ -4371,6 +4549,200 @@ find_coveringnsec(rbtdb_search_t *search, dns_dbnode_t **nodep, return (result); } +/* + * Mark a database for response policy rewriting. + */ +#ifdef BIND9 +static void +get_rpz_enabled(dns_db_t *db, dns_rpz_st_t *st) +{ + dns_rbtdb_t *rbtdb; + + rbtdb = (dns_rbtdb_t *)db; + REQUIRE(VALID_RBTDB(rbtdb)); + RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); + dns_rpz_enabled(rbtdb->rpz_cidr, st); + RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); +} + +/* + * Search the CDIR block tree of a response policy tree of trees for all of + * the IP addresses in an A or AAAA rdataset. + * Among the policies for all IPv4 and IPv6 addresses for a name, choose + * the longest prefix. Among those with the longest prefix, the first + * configured policy. Among answers for with the longest prefixes for + * two or more IP addresses in the A and AAAA rdatasets the lexically + * smallest address. + */ +static isc_result_t +rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, + dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version, + dns_rdataset_t *ardataset, dns_rpz_st_t *st) +{ + dns_rbtdb_t *rbtdb; + struct in_addr ina; + struct in6_addr in6a; + isc_netaddr_t netaddr; + dns_fixedname_t selfnamef, qnamef; + dns_name_t *selfname, *qname; + dns_rbtnode_t *node; + dns_rdataset_t zrdataset; + dns_rpz_cidr_bits_t prefix; + isc_result_t result; + dns_rpz_policy_t rpz_policy; + dns_ttl_t ttl; + + rbtdb = (dns_rbtdb_t *)db; + REQUIRE(VALID_RBTDB(rbtdb)); + RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); + + if (rbtdb->rpz_cidr == NULL) { + RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); + dns_db_detach(&db); + dns_zone_detach(&zone); + return (ISC_R_UNEXPECTED); + } + + dns_fixedname_init(&selfnamef); + dns_fixedname_init(&qnamef); + selfname = dns_fixedname_name(&selfnamef); + qname = dns_fixedname_name(&qnamef); + + for (result = dns_rdataset_first(ardataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(ardataset)) { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_current(ardataset, &rdata); + switch (rdata.type) { + case dns_rdatatype_a: + INSIST(rdata.length == 4); + memcpy(&ina.s_addr, rdata.data, 4); + isc_netaddr_fromin(&netaddr, &ina); + break; + case dns_rdatatype_aaaa: + INSIST(rdata.length == 16); + memcpy(in6a.s6_addr, rdata.data, 16); + isc_netaddr_fromin6(&netaddr, &in6a); + break; + default: + continue; + } + + result = dns_rpz_cidr_find(rbtdb->rpz_cidr, &netaddr, rpz_type, + selfname, qname, &prefix); + if (result != ISC_R_SUCCESS) + continue; + + /* + * Choose the policy with the longest matching prefix. + * Between policies with the same prefix, choose the first + * configured. + */ + if (st->m.policy != DNS_RPZ_POLICY_MISS) { + if (prefix < st->m.prefix) + continue; + if (prefix == st->m.prefix && + rpz->num > st->m.rpz->num) + continue; + } + + /* + * We have rpz_st an entry with a prefix at least as long as + * the prefix of the entry we had before. Find the node + * corresponding to CDIR tree entry. + */ + node = NULL; + result = dns_rbt_findnode(rbtdb->tree, qname, NULL, + &node, NULL, 0, NULL, NULL); + if (result != ISC_R_SUCCESS) { + char namebuf[DNS_NAME_FORMATSIZE]; + + dns_name_format(qname, namebuf, sizeof(namebuf)); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_CACHE, DNS_RPZ_ERROR_LEVEL, + "rpz_findips findnode(%s): %s", + namebuf, isc_result_totext(result)); + continue; + } + /* + * First look for a simple rewrite of the IP address. + * If that fails, look for a CNAME. If we cannot find + * a CNAME or the CNAME is neither of the special forms + * "*" or ".", treat it like a real CNAME. + */ + dns_rdataset_init(&zrdataset); + result = dns_db_findrdataset(db, node, version, ardataset->type, + 0, 0, &zrdataset, NULL); + if (result != ISC_R_SUCCESS) + result = dns_db_findrdataset(db, node, version, + dns_rdatatype_cname, + 0, 0, &zrdataset, NULL); + if (result == ISC_R_SUCCESS) { + if (zrdataset.type != dns_rdatatype_cname) { + rpz_policy = DNS_RPZ_POLICY_RECORD; + } else { + rpz_policy = dns_rpz_decode_cname(&zrdataset, + selfname); + if (rpz_policy == DNS_RPZ_POLICY_RECORD) + result = DNS_R_CNAME; + } + ttl = zrdataset.ttl; + } else { + rpz_policy = DNS_RPZ_POLICY_RECORD; + result = DNS_R_NXRRSET; + ttl = DNS_RPZ_TTL_DEFAULT; + } + + /* + * Use an overriding action specified in the configuration file + */ + if (rpz->policy != DNS_RPZ_POLICY_GIVEN && + rpz_policy != DNS_RPZ_POLICY_NO_OP) + rpz_policy = rpz->policy; + + /* + * We know the new prefix is at least as long as the current. + * Prefer the new answer if the new prefix is longer. + * Prefer the zone configured first if the prefixes are equal. + * With two actions from the same zone, prefer the action + * on the "smallest" name. + */ + if (st->m.policy == DNS_RPZ_POLICY_MISS || + prefix > st->m.prefix || + rpz->num <= st->m.rpz->num || + 0 > dns_name_compare(qname, st->qname)) { + if (dns_rdataset_isassociated(st->m.rdataset)) + dns_rdataset_disassociate(st->m.rdataset); + if (st->m.node != NULL) + dns_db_detachnode(st->m.db, &st->m.node); + if (st->m.db != NULL) + dns_db_detach(&st->m.db); + if (st->m.zone != NULL) + dns_zone_detach(&st->m.zone); + st->m.rpz = rpz; + st->m.type = rpz_type; + st->m.prefix = prefix; + st->m.policy = rpz_policy; + st->m.ttl = ttl; + st->m.result = result; + dns_name_copy(qname, st->qname, NULL); + if (rpz_policy == DNS_RPZ_POLICY_RECORD && + result != DNS_R_NXRRSET) { + dns_rdataset_clone(&zrdataset,st->m.rdataset); + dns_db_attachnode(db, node, &st->m.node); + } + dns_db_attach(db, &st->m.db); + dns_zone_attach(zone, &st->m.zone); + } + if (dns_rdataset_isassociated(&zrdataset)) + dns_rdataset_disassociate(&zrdataset); + } + + RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); + return (ISC_R_SUCCESS); +} +#endif + static isc_result_t cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, @@ -5693,6 +6065,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, free_rdataset(rbtdb, rbtdb->common.mctx, newheader); newheader = (rdatasetheader_t *)merged; + init_rdataset(rbtdb, newheader); if (loading && RESIGN(newheader) && RESIGN(header) && header->resign < newheader->resign) @@ -6015,16 +6388,17 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, rdatasetheader_t *header; isc_result_t result; isc_boolean_t delegating; + isc_boolean_t newnsec; isc_boolean_t tree_locked = ISC_FALSE; isc_boolean_t cache_is_overmem = ISC_FALSE; REQUIRE(VALID_RBTDB(rbtdb)); if (rbtdb->common.methods == &zone_methods) - REQUIRE(((rbtnode->nsec3 && + REQUIRE(((rbtnode->nsec == DNS_RBT_NSEC_NSEC3 && (rdataset->type == dns_rdatatype_nsec3 || rdataset->covers == dns_rdatatype_nsec3)) || - (!rbtnode->nsec3 && + (rbtnode->nsec != DNS_RBT_NSEC_NSEC3 && rdataset->type != dns_rdatatype_nsec3 && rdataset->covers != dns_rdatatype_nsec3))); @@ -6101,14 +6475,23 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, delegating = ISC_FALSE; /* - * If we're adding a delegation type or the DB is a cache in an overmem - * state, hold an exclusive lock on the tree. In the latter case - * the lock does not necessarily have to be acquired but it will help - * purge stale entries more effectively. + * Add to the auxiliary NSEC tree if we're adding an NSEC record. + */ + if (rbtnode->nsec != DNS_RBT_NSEC_HAS_NSEC && + rdataset->type == dns_rdatatype_nsec) + newnsec = ISC_TRUE; + else + newnsec = ISC_FALSE; + + /* + * If we're adding a delegation type, adding to the auxiliary NSEC tree, + * or the DB is a cache in an overmem state, hold an exclusive lock on + * the tree. In the latter case the lock does not necessarily have to + * be acquired but it will help purge stale entries more effectively. */ if (IS_CACHE(rbtdb) && isc_mem_isovermem(rbtdb->common.mctx)) cache_is_overmem = ISC_TRUE; - if (delegating || cache_is_overmem) { + if (delegating || newnsec || cache_is_overmem) { tree_locked = ISC_TRUE; RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write); } @@ -6137,14 +6520,35 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, * cleaning, we can release it now. However, we still need the * node lock. */ - if (tree_locked && !delegating) { + if (tree_locked && !delegating && !newnsec) { RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write); tree_locked = ISC_FALSE; } } - result = add(rbtdb, rbtnode, rbtversion, newheader, options, ISC_FALSE, - addedrdataset, now); + result = ISC_R_SUCCESS; + if (newnsec) { + dns_fixedname_t fname; + dns_name_t *name; + dns_rbtnode_t *nsecnode; + + dns_fixedname_init(&fname); + name = dns_fixedname_name(&fname); + dns_rbt_fullnamefromnode(rbtnode, name); + nsecnode = NULL; + result = dns_rbt_addnode(rbtdb->nsec, name, &nsecnode); + if (result == ISC_R_SUCCESS) { + nsecnode->nsec = DNS_RBT_NSEC_NSEC; + rbtnode->nsec = DNS_RBT_NSEC_HAS_NSEC; + } else if (result == ISC_R_EXISTS) { + rbtnode->nsec = DNS_RBT_NSEC_HAS_NSEC; + result = ISC_R_SUCCESS; + } + } + + if (result == ISC_R_SUCCESS) + result = add(rbtdb, rbtnode, rbtversion, newheader, options, + ISC_FALSE, addedrdataset, now); if (result == ISC_R_SUCCESS && delegating) rbtnode->find_callback = 1; @@ -6181,10 +6585,10 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, REQUIRE(VALID_RBTDB(rbtdb)); if (rbtdb->common.methods == &zone_methods) - REQUIRE(((rbtnode->nsec3 && + REQUIRE(((rbtnode->nsec == DNS_RBT_NSEC_NSEC3 && (rdataset->type == dns_rdatatype_nsec3 || rdataset->covers == dns_rdatatype_nsec3)) || - (!rbtnode->nsec3 && + (rbtnode->nsec != DNS_RBT_NSEC_NSEC3 && rdataset->type != dns_rdatatype_nsec3 && rdataset->covers != dns_rdatatype_nsec3))); @@ -6403,6 +6807,78 @@ deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, return (result); } +/* + * load a non-NSEC3 node in the main tree and optionally to the auxiliary NSEC + */ +static isc_result_t +loadnode(dns_rbtdb_t *rbtdb, dns_name_t *name, dns_rbtnode_t **nodep, + isc_boolean_t hasnsec) +{ + isc_result_t noderesult, nsecresult; + dns_rbtnode_t *nsecnode; + + noderesult = dns_rbt_addnode(rbtdb->tree, name, nodep); + +#ifdef BIND9 + if (noderesult == ISC_R_SUCCESS) + dns_rpz_cidr_addip(rbtdb->rpz_cidr, name); +#endif + + if (!hasnsec) + return (noderesult); + if (noderesult == ISC_R_EXISTS) { + /* + * Add a node to the auxiliary NSEC tree for an old node + * just now getting an NSEC record. + */ + if ((*nodep)->nsec == DNS_RBT_NSEC_HAS_NSEC) + return (noderesult); + } else if (noderesult != ISC_R_SUCCESS) { + return (noderesult); + } + + /* + * Build the auxiliary tree for NSECs as we go. + * This tree speeds searches for closest NSECs that would otherwise + * need to examine many irrelevant nodes in large TLDs. + * + * Add nodes to the auxiliary tree after corresponding nodes have + * been added to the main tree. + */ + nsecnode = NULL; + nsecresult = dns_rbt_addnode(rbtdb->nsec, name, &nsecnode); + if (nsecresult == ISC_R_SUCCESS) { + nsecnode->nsec = DNS_RBT_NSEC_NSEC; + (*nodep)->nsec = DNS_RBT_NSEC_HAS_NSEC; + return (noderesult); + } + + if (nsecresult == ISC_R_EXISTS) { +#if 1 /* 0 */ + isc_log_write(dns_lctx, + DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_CACHE, + ISC_LOG_WARNING, + "addnode: NSEC node already exists"); +#endif + (*nodep)->nsec = DNS_RBT_NSEC_HAS_NSEC; + return (noderesult); + } + + nsecresult = dns_rbt_deletenode(rbtdb->tree, *nodep, ISC_FALSE); + if (nsecresult != ISC_R_SUCCESS) + isc_log_write(dns_lctx, + DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_CACHE, + ISC_LOG_WARNING, + "loading_addrdataset: " + "dns_rbt_deletenode: %s after " + "dns_rbt_addnode(NSEC): %s", + isc_result_totext(nsecresult), + isc_result_totext(noderesult)); + return (noderesult); +} + static isc_result_t loading_addrdataset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset) { rbtdb_load_t *loadctx = arg; @@ -6451,15 +6927,15 @@ loading_addrdataset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset) { rdataset->covers == dns_rdatatype_nsec3) { result = dns_rbt_addnode(rbtdb->nsec3, name, &node); if (result == ISC_R_SUCCESS) - node->nsec3 = 1; + node->nsec = DNS_RBT_NSEC_NSEC3; + } else if (rdataset->type == dns_rdatatype_nsec) { + result = loadnode(rbtdb, name, &node, ISC_TRUE); } else { - result = dns_rbt_addnode(rbtdb->tree, name, &node); - if (result == ISC_R_SUCCESS) - node->nsec3 = 0; + result = loadnode(rbtdb, name, &node, ISC_FALSE); } if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) return (result); - if (result != ISC_R_EXISTS) { + if (result == ISC_R_SUCCESS) { dns_name_t foundname; dns_name_init(&foundname, NULL); dns_rbt_namefromnode(node, &foundname); @@ -6585,9 +7061,17 @@ dump(dns_db_t *db, dns_dbversion_t *version, const char *filename, REQUIRE(VALID_RBTDB(rbtdb)); +#ifdef BIND9 return (dns_master_dump2(rbtdb->common.mctx, db, version, &dns_master_style_default, filename, masterformat)); +#else + UNUSED(version); + UNUSED(filename); + UNUSED(masterformat); + + return (ISC_R_NOTIMPLEMENTED); +#endif /* BIND9 */ } static void @@ -6768,7 +7252,7 @@ setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, isc_stdtime_t resign) { } else if (resign < oldresign) isc_heap_increased(rbtdb->heaps[header->node->locknum], header->heap_index); - else + else if (resign > oldresign) isc_heap_decreased(rbtdb->heaps[header->node->locknum], header->heap_index); } else if (resign && header->heap_index == 0) { @@ -6913,7 +7397,14 @@ static dns_dbmethods_t zone_methods = { getsigningtime, resigned, isdnssec, + NULL, +#ifdef BIND9 + get_rpz_enabled, + rpz_findips +#else + NULL, NULL +#endif }; static dns_dbmethods_t cache_methods = { @@ -6952,7 +7443,9 @@ static dns_dbmethods_t cache_methods = { NULL, NULL, isdnssec, - getrrsetstats + getrrsetstats, + NULL, + NULL }; isc_result_t @@ -7122,12 +7615,36 @@ dns_rbtdb_create return (result); } + result = dns_rbt_create(mctx, delete_callback, rbtdb, &rbtdb->nsec); + if (result != ISC_R_SUCCESS) { + free_rbtdb(rbtdb, ISC_FALSE, NULL); + return (result); + } + result = dns_rbt_create(mctx, delete_callback, rbtdb, &rbtdb->nsec3); if (result != ISC_R_SUCCESS) { free_rbtdb(rbtdb, ISC_FALSE, NULL); return (result); } +#ifdef BIND9 + /* + * Get ready for response policy IP address searching if at least one + * zone has been configured as a response policy zone and this + * is not a cache zone. + * It would be better to know that this database is for a policy + * zone named for a view, but that would require knowledge from + * above such as an argv[] set from data in the zone. + */ + if (type == dns_dbtype_zone && !dns_name_equal(origin, dns_rootname)) { + result = dns_rpz_new_cidr(mctx, origin, &rbtdb->rpz_cidr); + if (result != ISC_R_SUCCESS) { + free_rbtdb(rbtdb, ISC_FALSE, NULL); + return (result); + } + } +#endif + /* * In order to set the node callback bit correctly in zone databases, * we need to know if the node has the origin name of the zone. @@ -7152,7 +7669,7 @@ dns_rbtdb_create free_rbtdb(rbtdb, ISC_FALSE, NULL); return (result); } - rbtdb->origin_node->nsec3 = 0; + rbtdb->origin_node->nsec = DNS_RBT_NSEC_NORMAL; /* * We need to give the origin node the right locknum. */ @@ -7180,7 +7697,7 @@ dns_rbtdb_create free_rbtdb(rbtdb, ISC_FALSE, NULL); return (result); } - nsec3node->nsec3 = 1; + nsec3node->nsec = DNS_RBT_NSEC_NSEC3; /* * We need to give the nsec3 origin node the right locknum. */ @@ -8238,6 +8755,21 @@ rdataset_getadditional(dns_rdataset_t *rdataset, dns_rdatasetadditional_t type, dns_name_t *fname, dns_message_t *msg, isc_stdtime_t now) { +#ifndef BIND9 + UNUSED(rdataset); + UNUSED(type); + UNUSED(qtype); + UNUSED(acache); + UNUSED(zonep); + UNUSED(dbp); + UNUSED(versionp); + UNUSED(nodep); + UNUSED(fname); + UNUSED(msg); + UNUSED(now); + + return (ISC_R_NOTIMPLEMENTED); +#else dns_rbtdb_t *rbtdb = rdataset->private1; dns_rbtnode_t *rbtnode = rdataset->private2; unsigned char *raw = rdataset->private3; /* RDATASLAB */ @@ -8354,8 +8886,10 @@ acache_callback(dns_acacheentry_t *entry, void **arg) { dns_db_detach((dns_db_t **)(void*)&rbtdb); *arg = NULL; +#endif /* BIND9 */ } +#ifdef BIND9 static void acache_cancelentry(isc_mem_t *mctx, dns_acacheentry_t *entry, acache_cbarg_t **cbargp) @@ -8376,6 +8910,7 @@ acache_cancelentry(isc_mem_t *mctx, dns_acacheentry_t *entry, *cbargp = NULL; } +#endif /* BIND9 */ static isc_result_t rdataset_setadditional(dns_rdataset_t *rdataset, dns_rdatasetadditional_t type, @@ -8384,6 +8919,19 @@ rdataset_setadditional(dns_rdataset_t *rdataset, dns_rdatasetadditional_t type, dns_dbversion_t *version, dns_dbnode_t *node, dns_name_t *fname) { +#ifndef BIND9 + UNUSED(rdataset); + UNUSED(type); + UNUSED(qtype); + UNUSED(acache); + UNUSED(zone); + UNUSED(db); + UNUSED(version); + UNUSED(node); + UNUSED(fname); + + return (ISC_R_NOTIMPLEMENTED); +#else dns_rbtdb_t *rbtdb = rdataset->private1; dns_rbtnode_t *rbtnode = rdataset->private2; unsigned char *raw = rdataset->private3; /* RDATASLAB */ @@ -8507,12 +9055,21 @@ rdataset_setadditional(dns_rdataset_t *rdataset, dns_rdatasetadditional_t type, } return (result); +#endif } static isc_result_t rdataset_putadditional(dns_acache_t *acache, dns_rdataset_t *rdataset, dns_rdatasetadditional_t type, dns_rdatatype_t qtype) { +#ifndef BIND9 + UNUSED(acache); + UNUSED(rdataset); + UNUSED(type); + UNUSED(qtype); + + return (ISC_R_NOTIMPLEMENTED); +#else dns_rbtdb_t *rbtdb = rdataset->private1; dns_rbtnode_t *rbtnode = rdataset->private2; unsigned char *raw = rdataset->private3; /* RDATASLAB */ @@ -8577,6 +9134,7 @@ rdataset_putadditional(dns_acache_t *acache, dns_rdataset_t *rdataset, } return (ISC_R_SUCCESS); +#endif } /*% diff --git a/lib/dns/rcode.c b/lib/dns/rcode.c index 2dc0a29..18fedcd 100644 --- a/lib/dns/rcode.c +++ b/lib/dns/rcode.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rcode.c,v 1.8.48.2 2010-01-15 23:47:33 tbox Exp $ */ +/* $Id: rcode.c,v 1.16 2010-12-23 04:07:58 marka Exp $ */ #include #include @@ -79,12 +79,17 @@ { dns_tsigerror_badtrunc, "BADTRUNC", 0}, \ { 0, NULL, 0 } -/* RFC2538 section 2.1 */ +/* RFC4398 section 2.1 */ #define CERTNAMES \ { 1, "PKIX", 0}, \ { 2, "SPKI", 0}, \ { 3, "PGP", 0}, \ + { 4, "IPKIX", 0}, \ + { 5, "ISPKI", 0}, \ + { 6, "IPGP", 0}, \ + { 7, "ACPKIX", 0}, \ + { 8, "IACPKIX", 0}, \ { 253, "URI", 0}, \ { 254, "OID", 0}, \ { 0, NULL, 0} @@ -102,6 +107,7 @@ { DNS_KEYALG_NSEC3RSASHA1, "NSEC3RSASHA1", 0 }, \ { DNS_KEYALG_RSASHA256, "RSASHA256", 0 }, \ { DNS_KEYALG_RSASHA512, "RSASHA512", 0 }, \ + { DNS_KEYALG_ECCGOST, "ECCGOST", 0 }, \ { DNS_KEYALG_INDIRECT, "INDIRECT", 0 }, \ { DNS_KEYALG_PRIVATEDNS, "PRIVATEDNS", 0 }, \ { DNS_KEYALG_PRIVATEOID, "PRIVATEOID", 0 }, \ @@ -313,6 +319,21 @@ dns_secalg_totext(dns_secalg_t secalg, isc_buffer_t *target) { return (dns_mnemonic_totext(secalg, target, secalgs)); } +void +dns_secalg_format(dns_secalg_t alg, char *cp, unsigned int size) { + isc_buffer_t b; + isc_region_t r; + isc_result_t result; + + REQUIRE(cp != NULL && size > 0); + isc_buffer_init(&b, cp, size - 1); + result = dns_secalg_totext(alg, &b); + isc_buffer_usedregion(&b, &r); + r.base[r.length] = 0; + if (result != ISC_R_SUCCESS) + r.base[0] = 0; +} + isc_result_t dns_secproto_fromtext(dns_secproto_t *secprotop, isc_textregion_t *source) { unsigned int value; diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c index daaa83a..c282b03 100644 --- a/lib/dns/rdata.c +++ b/lib/dns/rdata.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2011 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdata.c,v 1.199.50.4 2011-01-13 04:48:21 tbox Exp $ */ +/* $Id: rdata.c,v 1.209 2011-01-13 04:59:25 tbox Exp $ */ /*! \file */ @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -275,23 +276,6 @@ dns_rdata_init(dns_rdata_t *rdata) { /* ISC_LIST_INIT(rdata->list); */ } -#if 1 -#define DNS_RDATA_INITIALIZED(rdata) \ - ((rdata)->data == NULL && (rdata)->length == 0 && \ - (rdata)->rdclass == 0 && (rdata)->type == 0 && (rdata)->flags == 0 && \ - !ISC_LINK_LINKED((rdata), link)) -#else -#ifdef ISC_LIST_CHECKINIT -#define DNS_RDATA_INITIALIZED(rdata) \ - (!ISC_LINK_LINKED((rdata), link)) -#else -#define DNS_RDATA_INITIALIZED(rdata) ISC_TRUE -#endif -#endif - -#define DNS_RDATA_VALIDFLAGS(rdata) \ - (((rdata)->flags & ~(DNS_RDATA_UPDATE|DNS_RDATA_OFFLINE)) == 0) - void dns_rdata_reset(dns_rdata_t *rdata) { @@ -365,6 +349,37 @@ dns_rdata_compare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2) { return (result); } +int +dns_rdata_casecompare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2) { + int result = 0; + isc_boolean_t use_default = ISC_FALSE; + + REQUIRE(rdata1 != NULL); + REQUIRE(rdata2 != NULL); + REQUIRE(rdata1->data != NULL); + REQUIRE(rdata2->data != NULL); + REQUIRE(DNS_RDATA_VALIDFLAGS(rdata1)); + REQUIRE(DNS_RDATA_VALIDFLAGS(rdata2)); + + if (rdata1->rdclass != rdata2->rdclass) + return (rdata1->rdclass < rdata2->rdclass ? -1 : 1); + + if (rdata1->type != rdata2->type) + return (rdata1->type < rdata2->type ? -1 : 1); + + CASECOMPARESWITCH + + if (use_default) { + isc_region_t r1; + isc_region_t r2; + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + result = isc_region_compare(&r1, &r2); + } + return (result); +} + /*** *** Conversions ***/ @@ -1772,3 +1787,93 @@ dns_rdatatype_isknown(dns_rdatatype_t type) { return (ISC_TRUE); return (ISC_FALSE); } + +void +dns_rdata_exists(dns_rdata_t *rdata, dns_rdatatype_t type) { + + REQUIRE(rdata != NULL); + REQUIRE(DNS_RDATA_INITIALIZED(rdata)); + + rdata->data = NULL; + rdata->length = 0; + rdata->flags = DNS_RDATA_UPDATE; + rdata->type = type; + rdata->rdclass = dns_rdataclass_any; +} + +void +dns_rdata_notexist(dns_rdata_t *rdata, dns_rdatatype_t type) { + + REQUIRE(rdata != NULL); + REQUIRE(DNS_RDATA_INITIALIZED(rdata)); + + rdata->data = NULL; + rdata->length = 0; + rdata->flags = DNS_RDATA_UPDATE; + rdata->type = type; + rdata->rdclass = dns_rdataclass_none; +} + +void +dns_rdata_deleterrset(dns_rdata_t *rdata, dns_rdatatype_t type) { + + REQUIRE(rdata != NULL); + REQUIRE(DNS_RDATA_INITIALIZED(rdata)); + + rdata->data = NULL; + rdata->length = 0; + rdata->flags = DNS_RDATA_UPDATE; + rdata->type = type; + rdata->rdclass = dns_rdataclass_any; +} + +void +dns_rdata_makedelete(dns_rdata_t *rdata) { + REQUIRE(rdata != NULL); + + rdata->rdclass = dns_rdataclass_none; +} + +const char * +dns_rdata_updateop(dns_rdata_t *rdata, dns_section_t section) { + + REQUIRE(rdata != NULL); + REQUIRE(DNS_RDATA_INITIALIZED(rdata)); + + switch (section) { + case DNS_SECTION_PREREQUISITE: + switch (rdata->rdclass) { + case dns_rdataclass_none: + switch (rdata->type) { + case dns_rdatatype_any: + return ("domain doesn't exist"); + default: + return ("rrset doesn't exist"); + } + case dns_rdataclass_any: + switch (rdata->type) { + case dns_rdatatype_any: + return ("domain exists"); + default: + return ("rrset exists (value independent)"); + } + default: + return ("rrset exists (value dependent)"); + } + case DNS_SECTION_UPDATE: + switch (rdata->rdclass) { + case dns_rdataclass_none: + return ("delete"); + case dns_rdataclass_any: + switch (rdata->type) { + case dns_rdatatype_any: + return ("delete all rrsets"); + default: + return ("delete rrset"); + } + default: + return ("add"); + } + } + return ("invalid"); +} diff --git a/lib/dns/rdata/any_255/tsig_250.c b/lib/dns/rdata/any_255/tsig_250.c index e698239..9763f6d 100644 --- a/lib/dns/rdata/any_255/tsig_250.c +++ b/lib/dns/rdata/any_255/tsig_250.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: tsig_250.c,v 1.63 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: tsig_250.c,v 1.65 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Thu Mar 16 13:39:43 PST 2000 by gson */ @@ -594,4 +594,9 @@ checknames_any_tsig(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_any_tsig(ARGS_COMPARE) { + return (compare_any_tsig(rdata1, rdata2)); +} + #endif /* RDATA_ANY_255_TSIG_250_C */ diff --git a/lib/dns/rdata/ch_3/a_1.c b/lib/dns/rdata/ch_3/a_1.c index 156caac..2623f76 100644 --- a/lib/dns/rdata/ch_3/a_1.c +++ b/lib/dns/rdata/ch_3/a_1.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: a_1.c,v 1.6 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: a_1.c,v 1.8 2009-12-04 22:06:37 tbox Exp $ */ /* by Bjorn.Victor@it.uu.se, 2005-05-07 */ /* Based on generic/soa_6.c and generic/mx_15.c */ @@ -107,7 +107,7 @@ fromwire_ch_a(ARGS_FROMWIRE) { dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); dns_name_init(&name, NULL); - + RETERR(dns_name_fromwire(&name, source, dctx, options, target)); isc_buffer_activeregion(source, &sregion); @@ -205,7 +205,7 @@ fromstruct_ch_a(ARGS_FROMSTRUCT) { dns_name_toregion(&a->ch_addr_dom, ®ion); RETERR(isc_buffer_copyregion(target, ®ion)); - + return (uint16_tobuffer(ntohs(a->ch_addr), target)); } @@ -313,4 +313,8 @@ checknames_ch_a(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_ch_a(ARGS_COMPARE) { + return (compare_ch_a(rdata1, rdata2)); +} #endif /* RDATA_CH_3_A_1_C */ diff --git a/lib/dns/rdata/generic/afsdb_18.c b/lib/dns/rdata/generic/afsdb_18.c index f82167be..bd1d1e0 100644 --- a/lib/dns/rdata/generic/afsdb_18.c +++ b/lib/dns/rdata/generic/afsdb_18.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: afsdb_18.c,v 1.47 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: afsdb_18.c,v 1.49 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Wed Mar 15 14:59:00 PST 2000 by explorer */ @@ -306,4 +306,8 @@ checknames_afsdb(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_afsdb(ARGS_COMPARE) { + return (compare_afsdb(rdata1, rdata2)); +} #endif /* RDATA_GENERIC_AFSDB_18_C */ diff --git a/lib/dns/rdata/generic/cert_37.c b/lib/dns/rdata/generic/cert_37.c index e0398d2..d06b4e6 100644 --- a/lib/dns/rdata/generic/cert_37.c +++ b/lib/dns/rdata/generic/cert_37.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: cert_37.c,v 1.50 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: cert_37.c,v 1.52 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Wed Mar 15 21:14:32 EST 2000 by tale */ @@ -276,5 +276,9 @@ checknames_cert(ARGS_CHECKNAMES) { return (ISC_TRUE); } -#endif /* RDATA_GENERIC_CERT_37_C */ +static inline int +casecompare_cert(ARGS_COMPARE) { + return (compare_cert(rdata1, rdata2)); +} +#endif /* RDATA_GENERIC_CERT_37_C */ diff --git a/lib/dns/rdata/generic/cname_5.c b/lib/dns/rdata/generic/cname_5.c index f44d8c5..508bb20 100644 --- a/lib/dns/rdata/generic/cname_5.c +++ b/lib/dns/rdata/generic/cname_5.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: cname_5.c,v 1.47 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: cname_5.c,v 1.49 2009-12-04 22:06:37 tbox Exp $ */ /* reviewed: Wed Mar 15 16:48:45 PST 2000 by brister */ @@ -229,4 +229,9 @@ checknames_cname(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_cname(ARGS_COMPARE) { + return (compare_cname(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_CNAME_5_C */ diff --git a/lib/dns/rdata/generic/dlv_32769.c b/lib/dns/rdata/generic/dlv_32769.c index 21d7abbb4..0f87433c 100644 --- a/lib/dns/rdata/generic/dlv_32769.c +++ b/lib/dns/rdata/generic/dlv_32769.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2006, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2006, 2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dlv_32769.c,v 1.6 2007-06-18 23:47:43 tbox Exp $ */ +/* $Id: dlv_32769.c,v 1.10 2010-12-23 23:47:08 tbox Exp $ */ /* draft-ietf-dnsext-delegation-signer-05.txt */ @@ -74,12 +74,20 @@ fromtext_dlv(ARGS_FROMTEXT) { /* * Digest. */ - if (c == DNS_DSDIGEST_SHA1) + switch (c) { + case DNS_DSDIGEST_SHA1: length = ISC_SHA1_DIGESTLENGTH; - else if (c == DNS_DSDIGEST_SHA256) + break; + case DNS_DSDIGEST_SHA256: length = ISC_SHA256_DIGESTLENGTH; - else + break; + case DNS_DSDIGEST_GOST: + length = ISC_GOST_DIGESTLENGTH; + break; + default: length = -1; + break; + } return (isc_hex_tobuffer(lexer, target, -1)); } @@ -144,7 +152,7 @@ fromwire_dlv(ARGS_FROMWIRE) { UNUSED(options); isc_buffer_activeregion(source, &sr); - + /* * Check digest lengths if we know them. */ @@ -152,7 +160,9 @@ fromwire_dlv(ARGS_FROMWIRE) { (sr.base[3] == DNS_DSDIGEST_SHA1 && sr.length < 4 + ISC_SHA1_DIGESTLENGTH) || (sr.base[3] == DNS_DSDIGEST_SHA256 && - sr.length < 4 + ISC_SHA256_DIGESTLENGTH)) + sr.length < 4 + ISC_SHA256_DIGESTLENGTH) || + (sr.base[3] == DNS_DSDIGEST_GOST && + sr.length < 4 + ISC_GOST_DIGESTLENGTH)) return (ISC_R_UNEXPECTEDEND); /* @@ -164,7 +174,9 @@ fromwire_dlv(ARGS_FROMWIRE) { sr.length = 4 + ISC_SHA1_DIGESTLENGTH; else if (sr.base[3] == DNS_DSDIGEST_SHA256) sr.length = 4 + ISC_SHA256_DIGESTLENGTH; - + else if (sr.base[3] == DNS_DSDIGEST_GOST) + sr.length = 4 + ISC_GOST_DIGESTLENGTH; + isc_buffer_forward(source, sr.length); return (mem_tobuffer(target, sr.base, sr.length)); } @@ -213,6 +225,9 @@ fromstruct_dlv(ARGS_FROMSTRUCT) { case DNS_DSDIGEST_SHA256: REQUIRE(dlv->length == ISC_SHA256_DIGESTLENGTH); break; + case DNS_DSDIGEST_GOST: + REQUIRE(dlv->length == ISC_GOST_DIGESTLENGTH); + break; } UNUSED(type); @@ -318,4 +333,9 @@ checknames_dlv(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_dlv(ARGS_COMPARE) { + return (compare_dlv(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_DLV_32769_C */ diff --git a/lib/dns/rdata/generic/dname_39.c b/lib/dns/rdata/generic/dname_39.c index e36702d..61356bf 100644 --- a/lib/dns/rdata/generic/dname_39.c +++ b/lib/dns/rdata/generic/dname_39.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dname_39.c,v 1.38 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: dname_39.c,v 1.40 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Wed Mar 15 16:52:38 PST 2000 by explorer */ @@ -230,4 +230,8 @@ checknames_dname(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_dname(ARGS_COMPARE) { + return (compare_dname(rdata1, rdata2)); +} #endif /* RDATA_GENERIC_DNAME_39_C */ diff --git a/lib/dns/rdata/generic/dnskey_48.c b/lib/dns/rdata/generic/dnskey_48.c index d526ca0..91fe9f8 100644 --- a/lib/dns/rdata/generic/dnskey_48.c +++ b/lib/dns/rdata/generic/dnskey_48.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnskey_48.c,v 1.8 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: dnskey_48.c,v 1.10 2009-12-04 22:06:37 tbox Exp $ */ /* * Reviewed: Wed Mar 15 16:47:10 PST 2000 by halley. @@ -76,6 +76,7 @@ totext_dnskey(ARGS_TOTEXT) { char buf[sizeof("64000")]; unsigned int flags; unsigned char algorithm; + char namebuf[DNS_NAME_FORMATSIZE]; REQUIRE(rdata->type == 48); REQUIRE(rdata->length != 0); @@ -105,6 +106,15 @@ totext_dnskey(ARGS_TOTEXT) { if ((flags & 0xc000) == 0xc000) return (ISC_R_SUCCESS); + if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0 && + algorithm == DNS_KEYALG_PRIVATEDNS) { + dns_name_t name; + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &sr); + dns_name_format(&name, namebuf, sizeof(namebuf)); + } else + namebuf[0] = 0; + /* key */ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" (", target)); @@ -127,12 +137,18 @@ totext_dnskey(ARGS_TOTEXT) { dns_rdata_toregion(rdata, &tmpr); sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm)); RETERR(str_totext(buf, target)); + if (algorithm == DNS_KEYALG_PRIVATEDNS) { + RETERR(str_totext(tctx->linebreak, target)); + RETERR(str_totext("; alg = ", target)); + RETERR(str_totext(namebuf, target)); + } } return (ISC_R_SUCCESS); } static inline isc_result_t fromwire_dnskey(ARGS_FROMWIRE) { + unsigned char algorithm; isc_region_t sr; REQUIRE(type == 48); @@ -146,6 +162,18 @@ fromwire_dnskey(ARGS_FROMWIRE) { if (sr.length < 4) return (ISC_R_UNEXPECTEDEND); + algorithm = sr.base[3]; + RETERR(mem_tobuffer(target, sr.base, 4)); + isc_region_consume(&sr, 4); + isc_buffer_forward(source, 4); + + if (algorithm == DNS_KEYALG_PRIVATEDNS) { + dns_name_t name; + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + dns_name_init(&name, NULL); + RETERR(dns_name_fromwire(&name, source, dctx, options, target)); + } + isc_buffer_activeregion(source, &sr); isc_buffer_forward(source, sr.length); return (mem_tobuffer(target, sr.base, sr.length)); } @@ -309,4 +337,13 @@ checknames_dnskey(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_dnskey(ARGS_COMPARE) { + + /* + * Treat ALG 253 (private DNS) subtype name case sensistively. + */ + return (compare_dnskey(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_DNSKEY_48_C */ diff --git a/lib/dns/rdata/generic/ds_43.c b/lib/dns/rdata/generic/ds_43.c index fcaa69b..ee74ab67 100644 --- a/lib/dns/rdata/generic/ds_43.c +++ b/lib/dns/rdata/generic/ds_43.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ds_43.c,v 1.12 2007-06-18 23:47:43 tbox Exp $ */ +/* $Id: ds_43.c,v 1.16 2010-12-23 23:47:08 tbox Exp $ */ /* draft-ietf-dnsext-delegation-signer-05.txt */ @@ -74,12 +74,20 @@ fromtext_ds(ARGS_FROMTEXT) { /* * Digest. */ - if (c == DNS_DSDIGEST_SHA1) + switch (c) { + case DNS_DSDIGEST_SHA1: length = ISC_SHA1_DIGESTLENGTH; - else if (c == DNS_DSDIGEST_SHA256) + break; + case DNS_DSDIGEST_SHA256: length = ISC_SHA256_DIGESTLENGTH; - else + break; + case DNS_DSDIGEST_GOST: + length = ISC_GOST_DIGESTLENGTH; + break; + default: length = -1; + break; + } return (isc_hex_tobuffer(lexer, target, length)); } @@ -152,7 +160,9 @@ fromwire_ds(ARGS_FROMWIRE) { (sr.base[3] == DNS_DSDIGEST_SHA1 && sr.length < 4 + ISC_SHA1_DIGESTLENGTH) || (sr.base[3] == DNS_DSDIGEST_SHA256 && - sr.length < 4 + ISC_SHA256_DIGESTLENGTH)) + sr.length < 4 + ISC_SHA256_DIGESTLENGTH) || + (sr.base[3] == DNS_DSDIGEST_GOST && + sr.length < 4 + ISC_GOST_DIGESTLENGTH)) return (ISC_R_UNEXPECTEDEND); /* @@ -164,6 +174,8 @@ fromwire_ds(ARGS_FROMWIRE) { sr.length = 4 + ISC_SHA1_DIGESTLENGTH; else if (sr.base[3] == DNS_DSDIGEST_SHA256) sr.length = 4 + ISC_SHA256_DIGESTLENGTH; + else if (sr.base[3] == DNS_DSDIGEST_GOST) + sr.length = 4 + ISC_GOST_DIGESTLENGTH; isc_buffer_forward(source, sr.length); return (mem_tobuffer(target, sr.base, sr.length)); @@ -213,6 +225,9 @@ fromstruct_ds(ARGS_FROMSTRUCT) { case DNS_DSDIGEST_SHA256: REQUIRE(ds->length == ISC_SHA256_DIGESTLENGTH); break; + case DNS_DSDIGEST_GOST: + REQUIRE(ds->length == ISC_GOST_DIGESTLENGTH); + break; } UNUSED(type); @@ -318,4 +333,9 @@ checknames_ds(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_ds(ARGS_COMPARE) { + return (compare_ds(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_DS_43_C */ diff --git a/lib/dns/rdata/generic/gpos_27.c b/lib/dns/rdata/generic/gpos_27.c index 35fcc50..7a3992a 100644 --- a/lib/dns/rdata/generic/gpos_27.c +++ b/lib/dns/rdata/generic/gpos_27.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: gpos_27.c,v 1.41 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: gpos_27.c,v 1.43 2009-12-04 22:06:37 tbox Exp $ */ /* reviewed: Wed Mar 15 16:48:45 PST 2000 by brister */ @@ -249,4 +249,9 @@ checknames_gpos(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_gpos(ARGS_COMPARE) { + return (compare_gpos(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_GPOS_27_C */ diff --git a/lib/dns/rdata/generic/hinfo_13.c b/lib/dns/rdata/generic/hinfo_13.c index 7f31ab0..6b301e6 100644 --- a/lib/dns/rdata/generic/hinfo_13.c +++ b/lib/dns/rdata/generic/hinfo_13.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: hinfo_13.c,v 1.44 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: hinfo_13.c,v 1.46 2009-12-04 22:06:37 tbox Exp $ */ /* * Reviewed: Wed Mar 15 16:47:10 PST 2000 by halley. @@ -221,4 +221,8 @@ checknames_hinfo(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_hinfo(ARGS_COMPARE) { + return (compare_hinfo(rdata1, rdata2)); +} #endif /* RDATA_GENERIC_HINFO_13_C */ diff --git a/lib/dns/rdata/generic/hip_55.c b/lib/dns/rdata/generic/hip_55.c new file mode 100644 index 0000000..4cda9c6 --- /dev/null +++ b/lib/dns/rdata/generic/hip_55.c @@ -0,0 +1,506 @@ +/* + * Copyright (C) 2009, 2011 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: hip_55.c,v 1.8 2011-01-13 04:59:26 tbox Exp $ */ + +/* reviewed: TBC */ + +/* RFC 5205 */ + +#ifndef RDATA_GENERIC_HIP_5_C +#define RDATA_GENERIC_HIP_5_C + +#define RRTYPE_HIP_ATTRIBUTES (0) + +static inline isc_result_t +fromtext_hip(ARGS_FROMTEXT) { + isc_token_t token; + dns_name_t name; + isc_buffer_t buffer; + isc_buffer_t hit_len; + isc_buffer_t key_len; + unsigned char *start; + size_t len; + + REQUIRE(type == 55); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + /* + * Dummy HIT len. + */ + hit_len = *target; + RETERR(uint8_tobuffer(0, target)); + + /* + * Algorithm. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + ISC_FALSE)); + if (token.value.as_ulong > 0xffU) + RETTOK(ISC_R_RANGE); + RETERR(uint8_tobuffer(token.value.as_ulong, target)); + + /* + * Dummy KEY len. + */ + key_len = *target; + RETERR(uint16_tobuffer(0, target)); + + /* + * HIT (base16). + */ + start = isc_buffer_used(target); + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + ISC_FALSE)); + RETTOK(isc_hex_decodestring(DNS_AS_STR(token), target)); + + /* + * Fill in HIT len. + */ + len = (unsigned char *)isc_buffer_used(target) - start; + if (len > 0xffU) + RETTOK(ISC_R_RANGE); + RETERR(uint8_tobuffer(len, &hit_len)); + + /* + * Public key (base64). + */ + start = isc_buffer_used(target); + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + ISC_FALSE)); + RETTOK(isc_base64_decodestring(DNS_AS_STR(token), target)); + + /* + * Fill in KEY len. + */ + len = (unsigned char *)isc_buffer_used(target) - start; + if (len > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(len, &key_len)); + + /* + * Rendezvous Servers. + */ + dns_name_init(&name, NULL); + do { + RETERR(isc_lex_getmastertoken(lexer, &token, + isc_tokentype_string, + ISC_TRUE)); + if (token.type != isc_tokentype_string) + break; + buffer_fromregion(&buffer, &token.value.as_region); + origin = (origin != NULL) ? origin : dns_rootname; + RETTOK(dns_name_fromtext(&name, &buffer, origin, options, + target)); + } while (1); + + /* + * Let upper layer handle eol/eof. + */ + isc_lex_ungettoken(lexer, &token); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_hip(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + size_t length, key_len, hit_len; + unsigned char algorithm; + char buf[sizeof("225 ")]; + + REQUIRE(rdata->type == 55); + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, ®ion); + + hit_len = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + + algorithm = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + + key_len = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext("( ", target)); + + /* + * Algorithm + */ + sprintf(buf, "%u ", algorithm); + RETERR(str_totext(buf, target)); + + /* + * HIT. + */ + INSIST(hit_len < region.length); + length = region.length; + region.length = hit_len; + RETERR(isc_hex_totext(®ion, 1, "", target)); + region.length = length - hit_len; + RETERR(str_totext(tctx->linebreak, target)); + + /* + * Public KEY. + */ + INSIST(key_len <= region.length); + length = region.length; + region.length = key_len; + RETERR(isc_base64_totext(®ion, 1, "", target)); + region.length = length - key_len; + RETERR(str_totext(tctx->linebreak, target)); + + /* + * Rendezvous Servers. + */ + dns_name_init(&name, NULL); + while (region.length > 0) { + dns_name_fromregion(&name, ®ion); + + RETERR(dns_name_totext(&name, ISC_FALSE, target)); + isc_region_consume(®ion, name.length); + if (region.length > 0) + RETERR(str_totext(tctx->linebreak, target)); + } + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" )", target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_hip(ARGS_FROMWIRE) { + isc_region_t region, rr; + dns_name_t name; + isc_uint8_t hit_len; + isc_uint16_t key_len; + + REQUIRE(type == 55); + + UNUSED(type); + UNUSED(rdclass); + + isc_buffer_activeregion(source, ®ion); + if (region.length < 4U) + RETERR(DNS_R_FORMERR); + + rr = region; + hit_len = uint8_fromregion(®ion); + if (hit_len == 0) + RETERR(DNS_R_FORMERR); + isc_region_consume(®ion, 2); /* hit length + algorithm */ + key_len = uint16_fromregion(®ion); + if (key_len == 0) + RETERR(DNS_R_FORMERR); + isc_region_consume(®ion, 2); + if (region.length < (unsigned) (hit_len + key_len)) + RETERR(DNS_R_FORMERR); + + RETERR(mem_tobuffer(target, rr.base, 4 + hit_len + key_len)); + isc_buffer_forward(source, 4 + hit_len + key_len); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + while (isc_buffer_activelength(source) > 0) { + dns_name_init(&name, NULL); + RETERR(dns_name_fromwire(&name, source, dctx, options, target)); + } + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +towire_hip(ARGS_TOWIRE) { + isc_region_t region; + + REQUIRE(rdata->type == 55); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, ®ion); + return (mem_tobuffer(target, region.base, region.length)); +} + +static inline int +compare_hip(ARGS_COMPARE) { + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == 55); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + return (isc_region_compare(®ion1, ®ion2)); +} + +static inline isc_result_t +fromstruct_hip(ARGS_FROMSTRUCT) { + dns_rdata_hip_t *hip = source; + dns_rdata_hip_t myhip; + isc_result_t result; + + REQUIRE(type == 55); + REQUIRE(source != NULL); + REQUIRE(hip->common.rdtype == type); + REQUIRE(hip->common.rdclass == rdclass); + REQUIRE(hip->hit_len > 0 && hip->hit != NULL); + REQUIRE(hip->key_len > 0 && hip->key != NULL); + REQUIRE((hip->servers == NULL && hip->servers_len == 0) || + (hip->servers != NULL && hip->servers_len != 0)); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint8_tobuffer(hip->hit_len, target)); + RETERR(uint8_tobuffer(hip->algorithm, target)); + RETERR(uint16_tobuffer(hip->key_len, target)); + RETERR(mem_tobuffer(target, hip->hit, hip->hit_len)); + RETERR(mem_tobuffer(target, hip->key, hip->key_len)); + + myhip = *hip; + for (result = dns_rdata_hip_first(&myhip); + result == ISC_R_SUCCESS; + result = dns_rdata_hip_next(&myhip)) + /* empty */; + + return(mem_tobuffer(target, hip->servers, hip->servers_len)); +} + +static inline isc_result_t +tostruct_hip(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_hip_t *hip = target; + + REQUIRE(rdata->type == 55); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + hip->common.rdclass = rdata->rdclass; + hip->common.rdtype = rdata->type; + ISC_LINK_INIT(&hip->common, link); + + dns_rdata_toregion(rdata, ®ion); + + hip->hit_len = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + + hip->algorithm = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + + hip->key_len = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + + hip->hit = hip->key = hip->servers = NULL; + + hip->hit = mem_maybedup(mctx, region.base, hip->hit_len); + if (hip->hit == NULL) + goto cleanup; + isc_region_consume(®ion, hip->hit_len); + + hip->key = mem_maybedup(mctx, region.base, hip->key_len); + if (hip->key == NULL) + goto cleanup; + isc_region_consume(®ion, hip->key_len); + + hip->servers_len = region.length; + if (hip->servers_len != 0) { + hip->servers = mem_maybedup(mctx, region.base, region.length); + if (hip->servers == NULL) + goto cleanup; + } + + hip->offset = hip->servers_len; + hip->mctx = mctx; + return (ISC_R_SUCCESS); + + cleanup: + if (hip->hit != NULL) + isc_mem_free(mctx, hip->hit); + if (hip->key != NULL) + isc_mem_free(mctx, hip->key); + if (hip->servers != NULL) + isc_mem_free(mctx, hip->servers); + return (ISC_R_NOMEMORY); + +} + +static inline void +freestruct_hip(ARGS_FREESTRUCT) { + dns_rdata_hip_t *hip = source; + + REQUIRE(source != NULL); + + if (hip->mctx == NULL) + return; + + isc_mem_free(hip->mctx, hip->hit); + isc_mem_free(hip->mctx, hip->key); + if (hip->servers != NULL) + isc_mem_free(hip->mctx, hip->servers); + hip->mctx = NULL; +} + +static inline isc_result_t +additionaldata_hip(ARGS_ADDLDATA) { + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + REQUIRE(rdata->type == 55); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_hip(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == 55); + + dns_rdata_toregion(rdata, &r); + return ((digest)(arg, &r)); +} + +static inline isc_boolean_t +checkowner_hip(ARGS_CHECKOWNER) { + + REQUIRE(type == 55); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (ISC_TRUE); +} + +static inline isc_boolean_t +checknames_hip(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == 55); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (ISC_TRUE); +} + +isc_result_t +dns_rdata_hip_first(dns_rdata_hip_t *hip) { + if (hip->servers_len == 0) + return (ISC_R_NOMORE); + hip->offset = 0; + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_rdata_hip_next(dns_rdata_hip_t *hip) { + isc_region_t region; + dns_name_t name; + + if (hip->offset >= hip->servers_len) + return (ISC_R_NOMORE); + + region.base = hip->servers + hip->offset; + region.length = hip->servers_len - hip->offset; + dns_name_init(&name, NULL); + dns_name_fromregion(&name, ®ion); + hip->offset += name.length; + INSIST(hip->offset <= hip->servers_len); + return (ISC_R_SUCCESS); +} + +void +dns_rdata_hip_current(dns_rdata_hip_t *hip, dns_name_t *name) { + isc_region_t region; + + REQUIRE(hip->offset < hip->servers_len); + + region.base = hip->servers + hip->offset; + region.length = hip->servers_len - hip->offset; + dns_name_fromregion(name, ®ion); + + INSIST(name->length + hip->offset <= hip->servers_len); +} + +static inline int +casecompare_hip(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + dns_name_t name1; + dns_name_t name2; + int order; + isc_uint8_t hit_len; + isc_uint16_t key_len; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == 55); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + + INSIST(r1.length > 4); + INSIST(r2.length > 4); + r1.length = 4; + r2.length = 4; + order = isc_region_compare(&r1, &r2); + if (order != 0) + return (order); + + hit_len = uint8_fromregion(&r1); + isc_region_consume(&r1, 2); /* hit length + algorithm */ + key_len = uint16_fromregion(&r1); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + isc_region_consume(&r1, 4); + isc_region_consume(&r2, 4); + INSIST(r1.length >= (unsigned) (hit_len + key_len)); + INSIST(r2.length >= (unsigned) (hit_len + key_len)); + order = isc_region_compare(&r1, &r2); + if (order != 0) + return (order); + isc_region_consume(&r1, hit_len + key_len); + isc_region_consume(&r2, hit_len + key_len); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + while (r1.length != 0 && r2.length != 0) { + dns_name_fromregion(&name1, &r1); + dns_name_fromregion(&name2, &r2); + order = dns_name_rdatacompare(&name1, &name2); + if (order != 0) + return (order); + + isc_region_consume(&r1, name_length(&name1)); + isc_region_consume(&r2, name_length(&name2)); + } + return (isc_region_compare(&r1, &r2)); +} + +#endif /* RDATA_GENERIC_HIP_5_C */ diff --git a/lib/dns/rdata/generic/hip_55.h b/lib/dns/rdata/generic/hip_55.h new file mode 100644 index 0000000..79828ad --- /dev/null +++ b/lib/dns/rdata/generic/hip_55.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: hip_55.h,v 1.2 2009-02-26 06:09:19 marka Exp $ */ + +#ifndef GENERIC_HIP_5_H +#define GENERIC_HIP_5_H 1 + +/* RFC 5205 */ + +typedef struct dns_rdata_hip { + dns_rdatacommon_t common; + isc_mem_t * mctx; + unsigned char * hit; + unsigned char * key; + unsigned char * servers; + isc_uint8_t algorithm; + isc_uint8_t hit_len; + isc_uint16_t key_len; + isc_uint16_t servers_len; + /* Private */ + isc_uint16_t offset; +} dns_rdata_hip_t; + +isc_result_t +dns_rdata_hip_first(dns_rdata_hip_t *); + +isc_result_t +dns_rdata_hip_next(dns_rdata_hip_t *); + +void +dns_rdata_hip_current(dns_rdata_hip_t *, dns_name_t *); + +#endif /* GENERIC_HIP_5_H */ diff --git a/lib/dns/rdata/generic/ipseckey_45.c b/lib/dns/rdata/generic/ipseckey_45.c index f971d49..995a135 100644 --- a/lib/dns/rdata/generic/ipseckey_45.c +++ b/lib/dns/rdata/generic/ipseckey_45.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ipseckey_45.c,v 1.4.332.5 2011-01-13 04:48:23 tbox Exp $ */ +/* $Id: ipseckey_45.c,v 1.11 2011-01-13 04:59:26 tbox Exp $ */ #ifndef RDATA_GENERIC_IPSECKEY_45_C #define RDATA_GENERIC_IPSECKEY_45_C @@ -456,4 +456,43 @@ checknames_ipseckey(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_ipseckey(ARGS_COMPARE) { + isc_region_t region1; + isc_region_t region2; + dns_name_t name1; + dns_name_t name2; + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == 45); + REQUIRE(rdata1->length >= 3); + REQUIRE(rdata2->length >= 3); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + if (memcmp(region1.base, region2.base, 3) != 0 || region1.base[1] != 3) + return (isc_region_compare(®ion1, ®ion2)); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + isc_region_consume(®ion1, 3); + isc_region_consume(®ion2, 3); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + order = dns_name_rdatacompare(&name1, &name2); + if (order != 0) + return (order); + + isc_region_consume(®ion1, name_length(&name1)); + isc_region_consume(®ion2, name_length(&name2)); + + return (isc_region_compare(®ion1, ®ion2)); +} + #endif /* RDATA_GENERIC_IPSECKEY_45_C */ diff --git a/lib/dns/rdata/generic/isdn_20.c b/lib/dns/rdata/generic/isdn_20.c index a9e03b2c..b58776c 100644 --- a/lib/dns/rdata/generic/isdn_20.c +++ b/lib/dns/rdata/generic/isdn_20.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: isdn_20.c,v 1.38 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: isdn_20.c,v 1.40 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Wed Mar 15 16:53:11 PST 2000 by bwelling */ @@ -231,4 +231,9 @@ checknames_isdn(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_isdn(ARGS_COMPARE) { + return (compare_isdn(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_ISDN_20_C */ diff --git a/lib/dns/rdata/generic/key_25.c b/lib/dns/rdata/generic/key_25.c index acd314c..6fe27cb 100644 --- a/lib/dns/rdata/generic/key_25.c +++ b/lib/dns/rdata/generic/key_25.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: key_25.c,v 1.51 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: key_25.c,v 1.53 2009-12-04 22:06:37 tbox Exp $ */ /* * Reviewed: Wed Mar 15 16:47:10 PST 2000 by halley. @@ -76,6 +76,7 @@ totext_key(ARGS_TOTEXT) { char buf[sizeof("64000")]; unsigned int flags; unsigned char algorithm; + char namebuf[DNS_NAME_FORMATSIZE]; REQUIRE(rdata->type == 25); REQUIRE(rdata->length != 0); @@ -105,6 +106,15 @@ totext_key(ARGS_TOTEXT) { if ((flags & 0xc000) == 0xc000) return (ISC_R_SUCCESS); + if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0 && + algorithm == DNS_KEYALG_PRIVATEDNS) { + dns_name_t name; + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &sr); + dns_name_format(&name, namebuf, sizeof(namebuf)); + } else + namebuf[0] = 0; + /* key */ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" (", target)); @@ -127,12 +137,18 @@ totext_key(ARGS_TOTEXT) { dns_rdata_toregion(rdata, &tmpr); sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm)); RETERR(str_totext(buf, target)); + if (algorithm == DNS_KEYALG_PRIVATEDNS) { + RETERR(str_totext(tctx->linebreak, target)); + RETERR(str_totext("; alg = ", target)); + RETERR(str_totext(namebuf, target)); + } } return (ISC_R_SUCCESS); } static inline isc_result_t fromwire_key(ARGS_FROMWIRE) { + unsigned char algorithm; isc_region_t sr; REQUIRE(type == 25); @@ -146,6 +162,18 @@ fromwire_key(ARGS_FROMWIRE) { if (sr.length < 4) return (ISC_R_UNEXPECTEDEND); + algorithm = sr.base[3]; + RETERR(mem_tobuffer(target, sr.base, 4)); + isc_region_consume(&sr, 4); + isc_buffer_forward(source, 4); + + if (algorithm == DNS_KEYALG_PRIVATEDNS) { + dns_name_t name; + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + dns_name_init(&name, NULL); + RETERR(dns_name_fromwire(&name, source, dctx, options, target)); + } + isc_buffer_activeregion(source, &sr); isc_buffer_forward(source, sr.length); return (mem_tobuffer(target, sr.base, sr.length)); } @@ -309,4 +337,9 @@ checknames_key(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_key(ARGS_COMPARE) { + return (compare_key(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_KEY_25_C */ diff --git a/lib/dns/rdata/generic/keydata_65533.c b/lib/dns/rdata/generic/keydata_65533.c new file mode 100644 index 0000000..3636209 --- /dev/null +++ b/lib/dns/rdata/generic/keydata_65533.c @@ -0,0 +1,377 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: keydata_65533.c,v 1.3 2009-12-04 21:09:33 marka Exp $ */ + +#ifndef GENERIC_KEYDATA_65533_C +#define GENERIC_KEYDATA_65533_C 1 + +#include + +#define RRTYPE_KEYDATA_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC) + +static inline isc_result_t +fromtext_keydata(ARGS_FROMTEXT) { + isc_token_t token; + dns_secalg_t alg; + dns_secproto_t proto; + dns_keyflags_t flags; + isc_uint32_t refresh, addhd, removehd; + + REQUIRE(type == 65533); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + /* refresh timer */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + ISC_FALSE)); + RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &refresh)); + RETERR(uint32_tobuffer(refresh, target)); + + /* add hold-down */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + ISC_FALSE)); + RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &addhd)); + RETERR(uint32_tobuffer(addhd, target)); + + /* remove hold-down */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + ISC_FALSE)); + RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &removehd)); + RETERR(uint32_tobuffer(removehd, target)); + + /* flags */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + ISC_FALSE)); + RETTOK(dns_keyflags_fromtext(&flags, &token.value.as_textregion)); + RETERR(uint16_tobuffer(flags, target)); + + /* protocol */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + ISC_FALSE)); + RETTOK(dns_secproto_fromtext(&proto, &token.value.as_textregion)); + RETERR(mem_tobuffer(target, &proto, 1)); + + /* algorithm */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + ISC_FALSE)); + RETTOK(dns_secalg_fromtext(&alg, &token.value.as_textregion)); + RETERR(mem_tobuffer(target, &alg, 1)); + + /* No Key? */ + if ((flags & 0xc000) == 0xc000) + return (ISC_R_SUCCESS); + + return (isc_base64_tobuffer(lexer, target, -1)); +} + +static inline isc_result_t +totext_keydata(ARGS_TOTEXT) { + isc_region_t sr; + char buf[sizeof("64000")]; + unsigned int flags; + unsigned char algorithm; + unsigned long when; + + REQUIRE(rdata->type == 65533); + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, &sr); + + /* refresh timer */ + when = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + RETERR(dns_time32_totext(when, target)); + RETERR(str_totext(" ", target)); + + /* add hold-down */ + when = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + RETERR(dns_time32_totext(when, target)); + RETERR(str_totext(" ", target)); + + /* remove hold-down */ + when = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + RETERR(dns_time32_totext(when, target)); + RETERR(str_totext(" ", target)); + + /* flags */ + flags = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + sprintf(buf, "%u", flags); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + + /* protocol */ + sprintf(buf, "%u", sr.base[0]); + isc_region_consume(&sr, 1); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + + /* algorithm */ + algorithm = sr.base[0]; + sprintf(buf, "%u", algorithm); + isc_region_consume(&sr, 1); + RETERR(str_totext(buf, target)); + + /* No Key? */ + if ((flags & 0xc000) == 0xc000) + return (ISC_R_SUCCESS); + + /* key */ + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" (", target)); + RETERR(str_totext(tctx->linebreak, target)); + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); + + if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0) + RETERR(str_totext(tctx->linebreak, target)); + else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" ", target)); + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(")", target)); + + if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0) { + isc_region_t tmpr; + + RETERR(str_totext(" ; key id = ", target)); + dns_rdata_toregion(rdata, &tmpr); + /* Skip over refresh, addhd, and removehd */ + isc_region_consume(&tmpr, 12); + sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm)); + RETERR(str_totext(buf, target)); + } + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_keydata(ARGS_FROMWIRE) { + isc_region_t sr; + + REQUIRE(type == 65533); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(dctx); + UNUSED(options); + + isc_buffer_activeregion(source, &sr); + if (sr.length < 4) + return (ISC_R_UNEXPECTEDEND); + + isc_buffer_forward(source, sr.length); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline isc_result_t +towire_keydata(ARGS_TOWIRE) { + isc_region_t sr; + + REQUIRE(rdata->type == 65533); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_keydata(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == 65533); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_keydata(ARGS_FROMSTRUCT) { + dns_rdata_keydata_t *keydata = source; + + REQUIRE(type == 65533); + REQUIRE(source != NULL); + REQUIRE(keydata->common.rdtype == type); + REQUIRE(keydata->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + /* Refresh timer */ + RETERR(uint32_tobuffer(keydata->refresh, target)); + + /* Add hold-down */ + RETERR(uint32_tobuffer(keydata->addhd, target)); + + /* Remove hold-down */ + RETERR(uint32_tobuffer(keydata->removehd, target)); + + /* Flags */ + RETERR(uint16_tobuffer(keydata->flags, target)); + + /* Protocol */ + RETERR(uint8_tobuffer(keydata->protocol, target)); + + /* Algorithm */ + RETERR(uint8_tobuffer(keydata->algorithm, target)); + + /* Data */ + return (mem_tobuffer(target, keydata->data, keydata->datalen)); +} + +static inline isc_result_t +tostruct_keydata(ARGS_TOSTRUCT) { + dns_rdata_keydata_t *keydata = target; + isc_region_t sr; + + REQUIRE(rdata->type == 65533); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + keydata->common.rdclass = rdata->rdclass; + keydata->common.rdtype = rdata->type; + ISC_LINK_INIT(&keydata->common, link); + + dns_rdata_toregion(rdata, &sr); + + /* Refresh timer */ + if (sr.length < 4) + return (ISC_R_UNEXPECTEDEND); + keydata->refresh = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + + /* Add hold-down */ + if (sr.length < 4) + return (ISC_R_UNEXPECTEDEND); + keydata->addhd = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + + /* Remove hold-down */ + if (sr.length < 4) + return (ISC_R_UNEXPECTEDEND); + keydata->removehd = uint32_fromregion(&sr); + isc_region_consume(&sr, 4); + + /* Flags */ + if (sr.length < 2) + return (ISC_R_UNEXPECTEDEND); + keydata->flags = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + + /* Protocol */ + if (sr.length < 1) + return (ISC_R_UNEXPECTEDEND); + keydata->protocol = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + + /* Algorithm */ + if (sr.length < 1) + return (ISC_R_UNEXPECTEDEND); + keydata->algorithm = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + + /* Data */ + keydata->datalen = sr.length; + keydata->data = mem_maybedup(mctx, sr.base, keydata->datalen); + if (keydata->data == NULL) + return (ISC_R_NOMEMORY); + + keydata->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_keydata(ARGS_FREESTRUCT) { + dns_rdata_keydata_t *keydata = (dns_rdata_keydata_t *) source; + + REQUIRE(source != NULL); + REQUIRE(keydata->common.rdtype == 65533); + + if (keydata->mctx == NULL) + return; + + if (keydata->data != NULL) + isc_mem_free(keydata->mctx, keydata->data); + keydata->mctx = NULL; +} + +static inline isc_result_t +additionaldata_keydata(ARGS_ADDLDATA) { + REQUIRE(rdata->type == 65533); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_keydata(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == 65533); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline isc_boolean_t +checkowner_keydata(ARGS_CHECKOWNER) { + + REQUIRE(type == 65533); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (ISC_TRUE); +} + +static inline isc_boolean_t +checknames_keydata(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == 65533); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (ISC_TRUE); +} + +static inline int +casecompare_keydata(ARGS_COMPARE) { + return (compare_keydata(rdata1, rdata2)); +} + +#endif /* GENERIC_KEYDATA_65533_C */ diff --git a/lib/dns/rdata/generic/keydata_65533.h b/lib/dns/rdata/generic/keydata_65533.h new file mode 100644 index 0000000..21cb1ba --- /dev/null +++ b/lib/dns/rdata/generic/keydata_65533.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#ifndef GENERIC_KEYDATA_65533_H +#define GENERIC_KEYDATA_65533_H 1 + +/* $Id: keydata_65533.h,v 1.2 2009-06-30 02:52:32 each Exp $ */ + +typedef struct dns_rdata_keydata { + dns_rdatacommon_t common; + isc_mem_t * mctx; + isc_uint32_t refresh; /* Timer for refreshing data */ + isc_uint32_t addhd; /* Hold-down timer for adding */ + isc_uint32_t removehd; /* Hold-down timer for removing */ + isc_uint16_t flags; /* Copy of DNSKEY_48 */ + isc_uint8_t protocol; + isc_uint8_t algorithm; + isc_uint16_t datalen; + unsigned char * data; +} dns_rdata_keydata_t; + +#endif /* GENERIC_KEYDATA_65533_H */ diff --git a/lib/dns/rdata/generic/loc_29.c b/lib/dns/rdata/generic/loc_29.c index a5efb01..62d5cd0 100644 --- a/lib/dns/rdata/generic/loc_29.c +++ b/lib/dns/rdata/generic/loc_29.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: loc_29.c,v 1.45.332.4 2009-02-17 05:54:12 marka Exp $ */ +/* $Id: loc_29.c,v 1.50 2009-12-04 21:09:33 marka Exp $ */ /* Reviewed: Wed Mar 15 18:13:09 PST 2000 by explorer */ @@ -796,4 +796,9 @@ checknames_loc(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_loc(ARGS_COMPARE) { + return (compare_loc(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_LOC_29_C */ diff --git a/lib/dns/rdata/generic/mb_7.c b/lib/dns/rdata/generic/mb_7.c index c47365a..7a4af1c 100644 --- a/lib/dns/rdata/generic/mb_7.c +++ b/lib/dns/rdata/generic/mb_7.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: mb_7.c,v 1.45 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: mb_7.c,v 1.47 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Wed Mar 15 17:31:26 PST 2000 by bwelling */ @@ -69,7 +69,7 @@ totext_mb(ARGS_TOTEXT) { static inline isc_result_t fromwire_mb(ARGS_FROMWIRE) { - dns_name_t name; + dns_name_t name; REQUIRE(type == 7); @@ -78,8 +78,8 @@ fromwire_mb(ARGS_FROMWIRE) { dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); - dns_name_init(&name, NULL); - return (dns_name_fromwire(&name, source, dctx, options, target)); + dns_name_init(&name, NULL); + return (dns_name_fromwire(&name, source, dctx, options, target)); } static inline isc_result_t @@ -231,4 +231,9 @@ checknames_mb(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_mb(ARGS_COMPARE) { + return (compare_mb(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_MB_7_C */ diff --git a/lib/dns/rdata/generic/md_3.c b/lib/dns/rdata/generic/md_3.c index 269f9be..ee06274 100644 --- a/lib/dns/rdata/generic/md_3.c +++ b/lib/dns/rdata/generic/md_3.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: md_3.c,v 1.47 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: md_3.c,v 1.49 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Wed Mar 15 17:48:20 PST 2000 by bwelling */ @@ -69,7 +69,7 @@ totext_md(ARGS_TOTEXT) { static inline isc_result_t fromwire_md(ARGS_FROMWIRE) { - dns_name_t name; + dns_name_t name; REQUIRE(type == 3); @@ -78,8 +78,8 @@ fromwire_md(ARGS_FROMWIRE) { dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); - dns_name_init(&name, NULL); - return (dns_name_fromwire(&name, source, dctx, options, target)); + dns_name_init(&name, NULL); + return (dns_name_fromwire(&name, source, dctx, options, target)); } static inline isc_result_t @@ -233,4 +233,9 @@ checknames_md(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_md(ARGS_COMPARE) { + return (compare_md(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_MD_3_C */ diff --git a/lib/dns/rdata/generic/mf_4.c b/lib/dns/rdata/generic/mf_4.c index 9223384..d14bf6c 100644 --- a/lib/dns/rdata/generic/mf_4.c +++ b/lib/dns/rdata/generic/mf_4.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: mf_4.c,v 1.45 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: mf_4.c,v 1.47 2009-12-04 22:06:37 tbox Exp $ */ /* reviewed: Wed Mar 15 17:47:33 PST 2000 by brister */ @@ -69,7 +69,7 @@ totext_mf(ARGS_TOTEXT) { static inline isc_result_t fromwire_mf(ARGS_FROMWIRE) { - dns_name_t name; + dns_name_t name; REQUIRE(type == 4); @@ -78,8 +78,8 @@ fromwire_mf(ARGS_FROMWIRE) { dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); - dns_name_init(&name, NULL); - return (dns_name_fromwire(&name, source, dctx, options, target)); + dns_name_init(&name, NULL); + return (dns_name_fromwire(&name, source, dctx, options, target)); } static inline isc_result_t @@ -232,4 +232,9 @@ checknames_mf(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_mf(ARGS_COMPARE) { + return (compare_mf(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_MF_4_C */ diff --git a/lib/dns/rdata/generic/mg_8.c b/lib/dns/rdata/generic/mg_8.c index ba7630c..c1d553a 100644 --- a/lib/dns/rdata/generic/mg_8.c +++ b/lib/dns/rdata/generic/mg_8.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: mg_8.c,v 1.43 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: mg_8.c,v 1.45 2009-12-04 22:06:37 tbox Exp $ */ /* reviewed: Wed Mar 15 17:49:21 PST 2000 by brister */ @@ -69,7 +69,7 @@ totext_mg(ARGS_TOTEXT) { static inline isc_result_t fromwire_mg(ARGS_FROMWIRE) { - dns_name_t name; + dns_name_t name; REQUIRE(type == 8); @@ -78,8 +78,8 @@ fromwire_mg(ARGS_FROMWIRE) { dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); - dns_name_init(&name, NULL); - return (dns_name_fromwire(&name, source, dctx, options, target)); + dns_name_init(&name, NULL); + return (dns_name_fromwire(&name, source, dctx, options, target)); } static inline isc_result_t @@ -227,4 +227,9 @@ checknames_mg(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_mg(ARGS_COMPARE) { + return (compare_mg(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_MG_8_C */ diff --git a/lib/dns/rdata/generic/minfo_14.c b/lib/dns/rdata/generic/minfo_14.c index 6848a4e..881e624 100644 --- a/lib/dns/rdata/generic/minfo_14.c +++ b/lib/dns/rdata/generic/minfo_14.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: minfo_14.c,v 1.45 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: minfo_14.c,v 1.47 2009-12-04 22:06:37 tbox Exp $ */ /* reviewed: Wed Mar 15 17:45:32 PST 2000 by brister */ @@ -93,8 +93,8 @@ totext_minfo(ARGS_TOTEXT) { static inline isc_result_t fromwire_minfo(ARGS_FROMWIRE) { - dns_name_t rmail; - dns_name_t email; + dns_name_t rmail; + dns_name_t email; REQUIRE(type == 14); @@ -103,11 +103,11 @@ fromwire_minfo(ARGS_FROMWIRE) { dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); - dns_name_init(&rmail, NULL); - dns_name_init(&email, NULL); + dns_name_init(&rmail, NULL); + dns_name_init(&email, NULL); - RETERR(dns_name_fromwire(&rmail, source, dctx, options, target)); - return (dns_name_fromwire(&email, source, dctx, options, target)); + RETERR(dns_name_fromwire(&rmail, source, dctx, options, target)); + return (dns_name_fromwire(&email, source, dctx, options, target)); } static inline isc_result_t @@ -321,4 +321,9 @@ checknames_minfo(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_minfo(ARGS_COMPARE) { + return (compare_minfo(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_MINFO_14_C */ diff --git a/lib/dns/rdata/generic/mr_9.c b/lib/dns/rdata/generic/mr_9.c index a480bd4..6c02108 100644 --- a/lib/dns/rdata/generic/mr_9.c +++ b/lib/dns/rdata/generic/mr_9.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: mr_9.c,v 1.42 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: mr_9.c,v 1.44 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Wed Mar 15 21:30:35 EST 2000 by tale */ @@ -69,7 +69,7 @@ totext_mr(ARGS_TOTEXT) { static inline isc_result_t fromwire_mr(ARGS_FROMWIRE) { - dns_name_t name; + dns_name_t name; REQUIRE(type == 9); @@ -78,8 +78,8 @@ fromwire_mr(ARGS_FROMWIRE) { dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); - dns_name_init(&name, NULL); - return (dns_name_fromwire(&name, source, dctx, options, target)); + dns_name_init(&name, NULL); + return (dns_name_fromwire(&name, source, dctx, options, target)); } static inline isc_result_t @@ -228,4 +228,9 @@ checknames_mr(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_mr(ARGS_COMPARE) { + return (compare_mr(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_MR_9_C */ diff --git a/lib/dns/rdata/generic/mx_15.c b/lib/dns/rdata/generic/mx_15.c index b7b43f3..0d8e6cd 100644 --- a/lib/dns/rdata/generic/mx_15.c +++ b/lib/dns/rdata/generic/mx_15.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: mx_15.c,v 1.56 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: mx_15.c,v 1.58 2009-12-04 22:06:37 tbox Exp $ */ /* reviewed: Wed Mar 15 18:05:46 PST 2000 by brister */ @@ -120,7 +120,7 @@ totext_mx(ARGS_TOTEXT) { static inline isc_result_t fromwire_mx(ARGS_FROMWIRE) { - dns_name_t name; + dns_name_t name; isc_region_t sregion; REQUIRE(type == 15); @@ -130,7 +130,7 @@ fromwire_mx(ARGS_FROMWIRE) { dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); - dns_name_init(&name, NULL); + dns_name_init(&name, NULL); isc_buffer_activeregion(source, &sregion); if (sregion.length < 2) @@ -316,4 +316,9 @@ checknames_mx(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_mx(ARGS_COMPARE) { + return (compare_mx(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_MX_15_C */ diff --git a/lib/dns/rdata/generic/ns_2.c b/lib/dns/rdata/generic/ns_2.c index 14e0c9d..f3df004 100644 --- a/lib/dns/rdata/generic/ns_2.c +++ b/lib/dns/rdata/generic/ns_2.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ns_2.c,v 1.46 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: ns_2.c,v 1.48 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Wed Mar 15 18:15:00 PST 2000 by bwelling */ @@ -77,7 +77,7 @@ totext_ns(ARGS_TOTEXT) { static inline isc_result_t fromwire_ns(ARGS_FROMWIRE) { - dns_name_t name; + dns_name_t name; REQUIRE(type == 2); @@ -86,8 +86,8 @@ fromwire_ns(ARGS_FROMWIRE) { dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); - dns_name_init(&name, NULL); - return (dns_name_fromwire(&name, source, dctx, options, target)); + dns_name_init(&name, NULL); + return (dns_name_fromwire(&name, source, dctx, options, target)); } static inline isc_result_t @@ -248,4 +248,9 @@ checknames_ns(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_ns(ARGS_COMPARE) { + return (compare_ns(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_NS_2_C */ diff --git a/lib/dns/rdata/generic/nsec3_50.c b/lib/dns/rdata/generic/nsec3_50.c index 890af1a..d21b009 100644 --- a/lib/dns/rdata/generic/nsec3_50.c +++ b/lib/dns/rdata/generic/nsec3_50.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nsec3_50.c,v 1.4.48.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: nsec3_50.c,v 1.7 2009-12-04 21:09:34 marka Exp $ */ /* * Copyright (C) 2004 Nominet, Ltd. @@ -478,4 +478,9 @@ checknames_nsec3(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_nsec3(ARGS_COMPARE) { + return (compare_nsec3(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_NSEC3_50_C */ diff --git a/lib/dns/rdata/generic/nsec3param_51.c b/lib/dns/rdata/generic/nsec3param_51.c index 1457015..01beb3c 100644 --- a/lib/dns/rdata/generic/nsec3param_51.c +++ b/lib/dns/rdata/generic/nsec3param_51.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nsec3param_51.c,v 1.4.48.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: nsec3param_51.c,v 1.7 2009-12-04 21:09:34 marka Exp $ */ /* * Copyright (C) 2004 Nominet, Ltd. @@ -311,4 +311,9 @@ checknames_nsec3param(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_nsec3param(ARGS_COMPARE) { + return (compare_nsec3param(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_NSEC3PARAM_51_C */ diff --git a/lib/dns/rdata/generic/nsec_47.c b/lib/dns/rdata/generic/nsec_47.c index ace1035..5807d5f 100644 --- a/lib/dns/rdata/generic/nsec_47.c +++ b/lib/dns/rdata/generic/nsec_47.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007, 2008, 2011 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007-2009, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nsec_47.c,v 1.11.82.2 2011-01-13 04:48:23 tbox Exp $ */ +/* $Id: nsec_47.c,v 1.15 2011-01-13 04:59:26 tbox Exp $ */ /* reviewed: Wed Mar 15 18:21:15 PST 2000 by brister */ @@ -361,4 +361,36 @@ checknames_nsec(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_nsec(ARGS_COMPARE) { + isc_region_t region1; + isc_region_t region2; + dns_name_t name1; + dns_name_t name2; + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == 47); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + + dns_name_fromregion(&name1, ®ion1); + dns_name_fromregion(&name2, ®ion2); + + order = dns_name_rdatacompare(&name1, &name2); + if (order != 0) + return (order); + + isc_region_consume(®ion1, name_length(&name1)); + isc_region_consume(®ion2, name_length(&name2)); + + return (isc_region_compare(®ion1, ®ion2)); +} #endif /* RDATA_GENERIC_NSEC_47_C */ diff --git a/lib/dns/rdata/generic/null_10.c b/lib/dns/rdata/generic/null_10.c index 06a8877..e6d9b9a 100644 --- a/lib/dns/rdata/generic/null_10.c +++ b/lib/dns/rdata/generic/null_10.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: null_10.c,v 1.42 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: null_10.c,v 1.44 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Thu Mar 16 13:57:50 PST 2000 by explorer */ @@ -189,4 +189,9 @@ checknames_null(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_null(ARGS_COMPARE) { + return (compare_null(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_NULL_10_C */ diff --git a/lib/dns/rdata/generic/nxt_30.c b/lib/dns/rdata/generic/nxt_30.c index 362e6fc..44ded55 100644 --- a/lib/dns/rdata/generic/nxt_30.c +++ b/lib/dns/rdata/generic/nxt_30.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nxt_30.c,v 1.63 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: nxt_30.c,v 1.65 2009-12-04 22:06:37 tbox Exp $ */ /* reviewed: Wed Mar 15 18:21:15 PST 2000 by brister */ @@ -326,4 +326,8 @@ checknames_nxt(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_nxt(ARGS_COMPARE) { + return (compare_nxt(rdata1, rdata2)); +} #endif /* RDATA_GENERIC_NXT_30_C */ diff --git a/lib/dns/rdata/generic/opt_41.c b/lib/dns/rdata/generic/opt_41.c index 506f4a3..695057d 100644 --- a/lib/dns/rdata/generic/opt_41.c +++ b/lib/dns/rdata/generic/opt_41.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: opt_41.c,v 1.33 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: opt_41.c,v 1.35 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Thu Mar 16 14:06:44 PST 2000 by gson */ @@ -277,4 +277,9 @@ checknames_opt(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_opt(ARGS_COMPARE) { + return (compare_opt(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_OPT_41_C */ diff --git a/lib/dns/rdata/generic/proforma.c b/lib/dns/rdata/generic/proforma.c index c3db196..0efc197 100644 --- a/lib/dns/rdata/generic/proforma.c +++ b/lib/dns/rdata/generic/proforma.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: proforma.c,v 1.36 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: proforma.c,v 1.38 2009-12-04 22:06:37 tbox Exp $ */ #ifndef RDATA_GENERIC_#_#_C #define RDATA_GENERIC_#_#_C @@ -170,4 +170,21 @@ checknames_#(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_#(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == #); + REQUIRE(rdata1->rdclass == #); + REQUIRE(rdata1->length != 0); /* XXX */ + REQUIRE(rdata2->length != 0); /* XXX */ + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + #endif /* RDATA_GENERIC_#_#_C */ diff --git a/lib/dns/rdata/generic/ptr_12.c b/lib/dns/rdata/generic/ptr_12.c index 8e718cd..0ed648f 100644 --- a/lib/dns/rdata/generic/ptr_12.c +++ b/lib/dns/rdata/generic/ptr_12.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ptr_12.c,v 1.43 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: ptr_12.c,v 1.45 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Thu Mar 16 14:05:12 PST 2000 by explorer */ @@ -79,7 +79,7 @@ totext_ptr(ARGS_TOTEXT) { static inline isc_result_t fromwire_ptr(ARGS_FROMWIRE) { - dns_name_t name; + dns_name_t name; REQUIRE(type == 12); @@ -88,8 +88,8 @@ fromwire_ptr(ARGS_FROMWIRE) { dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); - dns_name_init(&name, NULL); - return (dns_name_fromwire(&name, source, dctx, options, target)); + dns_name_init(&name, NULL); + return (dns_name_fromwire(&name, source, dctx, options, target)); } static inline isc_result_t @@ -288,4 +288,8 @@ checknames_ptr(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_ptr(ARGS_COMPARE) { + return (compare_ptr(rdata1, rdata2)); +} #endif /* RDATA_GENERIC_PTR_12_C */ diff --git a/lib/dns/rdata/generic/rp_17.c b/lib/dns/rdata/generic/rp_17.c index 19d7b35..2865e2f 100644 --- a/lib/dns/rdata/generic/rp_17.c +++ b/lib/dns/rdata/generic/rp_17.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rp_17.c,v 1.42 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: rp_17.c,v 1.44 2009-12-04 22:06:37 tbox Exp $ */ /* RFC1183 */ @@ -93,8 +93,8 @@ totext_rp(ARGS_TOTEXT) { static inline isc_result_t fromwire_rp(ARGS_FROMWIRE) { - dns_name_t rmail; - dns_name_t email; + dns_name_t rmail; + dns_name_t email; REQUIRE(type == 17); @@ -103,11 +103,11 @@ fromwire_rp(ARGS_FROMWIRE) { dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); - dns_name_init(&rmail, NULL); - dns_name_init(&email, NULL); + dns_name_init(&rmail, NULL); + dns_name_init(&email, NULL); - RETERR(dns_name_fromwire(&rmail, source, dctx, options, target)); - return (dns_name_fromwire(&email, source, dctx, options, target)); + RETERR(dns_name_fromwire(&rmail, source, dctx, options, target)); + return (dns_name_fromwire(&email, source, dctx, options, target)); } static inline isc_result_t @@ -311,4 +311,8 @@ checknames_rp(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_rp(ARGS_COMPARE) { + return (compare_rp(rdata1, rdata2)); +} #endif /* RDATA_GENERIC_RP_17_C */ diff --git a/lib/dns/rdata/generic/rrsig_46.c b/lib/dns/rdata/generic/rrsig_46.c index bcbb05b..1fa7d07 100644 --- a/lib/dns/rdata/generic/rrsig_46.c +++ b/lib/dns/rdata/generic/rrsig_46.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2011 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rrsig_46.c,v 1.10.332.2 2011-01-13 04:48:23 tbox Exp $ */ +/* $Id: rrsig_46.c,v 1.14 2011-01-13 04:59:26 tbox Exp $ */ /* Reviewed: Fri Mar 17 09:05:02 PST 2000 by gson */ @@ -544,4 +544,47 @@ checknames_rrsig(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_rrsig(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + dns_name_t name1; + dns_name_t name2; + int order; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == 46); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + + INSIST(r1.length > 18); + INSIST(r2.length > 18); + r1.length = 18; + r2.length = 18; + order = isc_region_compare(&r1, &r2); + if (order != 0) + return (order); + + dns_name_init(&name1, NULL); + dns_name_init(&name2, NULL); + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + isc_region_consume(&r1, 18); + isc_region_consume(&r2, 18); + dns_name_fromregion(&name1, &r1); + dns_name_fromregion(&name2, &r2); + order = dns_name_rdatacompare(&name1, &name2); + if (order != 0) + return (order); + + isc_region_consume(&r1, name_length(&name1)); + isc_region_consume(&r2, name_length(&name2)); + + return (isc_region_compare(&r1, &r2)); +} + #endif /* RDATA_GENERIC_RRSIG_46_C */ diff --git a/lib/dns/rdata/generic/rt_21.c b/lib/dns/rdata/generic/rt_21.c index 48323c7..efd51e2 100644 --- a/lib/dns/rdata/generic/rt_21.c +++ b/lib/dns/rdata/generic/rt_21.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rt_21.c,v 1.46 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: rt_21.c,v 1.48 2009-12-04 22:06:37 tbox Exp $ */ /* reviewed: Thu Mar 16 15:02:31 PST 2000 by brister */ @@ -90,7 +90,7 @@ totext_rt(ARGS_TOTEXT) { static inline isc_result_t fromwire_rt(ARGS_FROMWIRE) { - dns_name_t name; + dns_name_t name; isc_region_t sregion; isc_region_t tregion; @@ -101,7 +101,7 @@ fromwire_rt(ARGS_FROMWIRE) { dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); - dns_name_init(&name, NULL); + dns_name_init(&name, NULL); isc_buffer_activeregion(source, &sregion); isc_buffer_availableregion(target, &tregion); @@ -308,4 +308,9 @@ checknames_rt(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_rt(ARGS_COMPARE) { + return (compare_rt(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_RT_21_C */ diff --git a/lib/dns/rdata/generic/sig_24.c b/lib/dns/rdata/generic/sig_24.c index 3010b8e..6366309 100644 --- a/lib/dns/rdata/generic/sig_24.c +++ b/lib/dns/rdata/generic/sig_24.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sig_24.c,v 1.66 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: sig_24.c,v 1.68 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Fri Mar 17 09:05:02 PST 2000 by gson */ @@ -575,4 +575,8 @@ checknames_sig(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_sig(ARGS_COMPARE) { + return (compare_sig(rdata1, rdata2)); +} #endif /* RDATA_GENERIC_SIG_24_C */ diff --git a/lib/dns/rdata/generic/soa_6.c b/lib/dns/rdata/generic/soa_6.c index d3fdf41..34361a8 100644 --- a/lib/dns/rdata/generic/soa_6.c +++ b/lib/dns/rdata/generic/soa_6.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: soa_6.c,v 1.61.332.2 2009-02-16 23:47:15 tbox Exp $ */ +/* $Id: soa_6.c,v 1.64 2009-12-04 21:09:34 marka Exp $ */ /* Reviewed: Thu Mar 16 15:18:32 PST 2000 by explorer */ @@ -441,4 +441,9 @@ checknames_soa(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_soa(ARGS_COMPARE) { + return (compare_soa(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_SOA_6_C */ diff --git a/lib/dns/rdata/generic/spf_99.c b/lib/dns/rdata/generic/spf_99.c index b1ad062..0f8ba5f 100644 --- a/lib/dns/rdata/generic/spf_99.c +++ b/lib/dns/rdata/generic/spf_99.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: spf_99.c,v 1.4 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: spf_99.c,v 1.6 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Thu Mar 16 15:40:00 PST 2000 by bwelling */ @@ -235,4 +235,8 @@ checknames_spf(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_spf(ARGS_COMPARE) { + return (compare_spf(rdata1, rdata2)); +} #endif /* RDATA_GENERIC_SPF_99_C */ diff --git a/lib/dns/rdata/generic/sshfp_44.c b/lib/dns/rdata/generic/sshfp_44.c index 892c1ec..7b34451 100644 --- a/lib/dns/rdata/generic/sshfp_44.c +++ b/lib/dns/rdata/generic/sshfp_44.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2006, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2006, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sshfp_44.c,v 1.7 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: sshfp_44.c,v 1.9 2009-12-04 22:06:37 tbox Exp $ */ /* RFC 4255 */ @@ -259,4 +259,9 @@ checknames_sshfp(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_sshfp(ARGS_COMPARE) { + return (compare_sshfp(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_SSHFP_44_C */ diff --git a/lib/dns/rdata/generic/tkey_249.c b/lib/dns/rdata/generic/tkey_249.c index 6927c8d..64acc0f 100644 --- a/lib/dns/rdata/generic/tkey_249.c +++ b/lib/dns/rdata/generic/tkey_249.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: tkey_249.c,v 1.57 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: tkey_249.c,v 1.59 2009-12-04 22:06:37 tbox Exp $ */ /* * Reviewed: Thu Mar 16 17:35:30 PST 2000 by halley. @@ -552,4 +552,8 @@ checknames_tkey(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline isc_result_t +casecompare_tkey(ARGS_COMPARE) { + return (compare_tkey(rdata1, rdata2)); +} #endif /* RDATA_GENERIC_TKEY_249_C */ diff --git a/lib/dns/rdata/generic/txt_16.c b/lib/dns/rdata/generic/txt_16.c index fa14b86..e04e0f0 100644 --- a/lib/dns/rdata/generic/txt_16.c +++ b/lib/dns/rdata/generic/txt_16.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: txt_16.c,v 1.45 2008-02-15 23:46:51 tbox Exp $ */ +/* $Id: txt_16.c,v 1.47 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Thu Mar 16 15:40:00 PST 2000 by bwelling */ @@ -235,4 +235,9 @@ checknames_txt(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline isc_result_t +casecompare_txt(ARGS_COMPARE) { + return (compare_txt(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_TXT_16_C */ diff --git a/lib/dns/rdata/generic/unspec_103.c b/lib/dns/rdata/generic/unspec_103.c index ffd14d9..0ce9a90 100644 --- a/lib/dns/rdata/generic/unspec_103.c +++ b/lib/dns/rdata/generic/unspec_103.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: unspec_103.c,v 1.35 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: unspec_103.c,v 1.37 2009-12-04 22:06:37 tbox Exp $ */ #ifndef RDATA_GENERIC_UNSPEC_103_C #define RDATA_GENERIC_UNSPEC_103_C @@ -186,4 +186,9 @@ checknames_unspec(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_unspec(ARGS_COMPARE) { + return (compare_unspec(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_UNSPEC_103_C */ diff --git a/lib/dns/rdata/generic/x25_19.c b/lib/dns/rdata/generic/x25_19.c index 47aeb7f..f315b89 100644 --- a/lib/dns/rdata/generic/x25_19.c +++ b/lib/dns/rdata/generic/x25_19.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: x25_19.c,v 1.39 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: x25_19.c,v 1.41 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Thu Mar 16 16:15:57 PST 2000 by bwelling */ @@ -216,4 +216,9 @@ checknames_x25(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_x25(ARGS_COMPARE) { + return (compare_x25(rdata1, rdata2)); +} + #endif /* RDATA_GENERIC_X25_19_C */ diff --git a/lib/dns/rdata/hs_4/a_1.c b/lib/dns/rdata/hs_4/a_1.c index ae30719..6d02b79 100644 --- a/lib/dns/rdata/hs_4/a_1.c +++ b/lib/dns/rdata/hs_4/a_1.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: a_1.c,v 1.31 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: a_1.c,v 1.33 2009-12-04 22:06:37 tbox Exp $ */ /* reviewed: Thu Mar 16 15:58:36 PST 2000 by brister */ @@ -229,4 +229,9 @@ checknames_hs_a(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_hs_a(ARGS_COMPARE) { + return (compare_hs_a(rdata1, rdata2)); +} + #endif /* RDATA_HS_4_A_1_C */ diff --git a/lib/dns/rdata/in_1/a6_38.c b/lib/dns/rdata/in_1/a6_38.c index 450b74c..ec453b1 100644 --- a/lib/dns/rdata/in_1/a6_38.c +++ b/lib/dns/rdata/in_1/a6_38.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: a6_38.c,v 1.54 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: a6_38.c,v 1.56 2009-12-04 22:06:37 tbox Exp $ */ /* RFC2874 */ @@ -458,4 +458,9 @@ checknames_in_a6(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_in_a6(ARGS_COMPARE) { + return (compare_in_a6(rdata1, rdata2)); +} + #endif /* RDATA_IN_1_A6_38_C */ diff --git a/lib/dns/rdata/in_1/a_1.c b/lib/dns/rdata/in_1/a_1.c index 1181e44..b4c1e94 100644 --- a/lib/dns/rdata/in_1/a_1.c +++ b/lib/dns/rdata/in_1/a_1.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: a_1.c,v 1.53 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: a_1.c,v 1.55 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Thu Mar 16 16:52:50 PST 2000 by bwelling */ @@ -233,4 +233,9 @@ checknames_in_a(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_in_a(ARGS_COMPARE) { + return (compare_in_a(rdata1, rdata2)); +} + #endif /* RDATA_IN_1_A_1_C */ diff --git a/lib/dns/rdata/in_1/aaaa_28.c b/lib/dns/rdata/in_1/aaaa_28.c index 119131c..fe3954e 100644 --- a/lib/dns/rdata/in_1/aaaa_28.c +++ b/lib/dns/rdata/in_1/aaaa_28.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: aaaa_28.c,v 1.45 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: aaaa_28.c,v 1.47 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Thu Mar 16 16:52:50 PST 2000 by bwelling */ @@ -230,4 +230,8 @@ checknames_in_aaaa(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_in_aaaa(ARGS_COMPARE) { + return (compare_in_aaaa(rdata1, rdata2)); +} #endif /* RDATA_IN_1_AAAA_28_C */ diff --git a/lib/dns/rdata/in_1/apl_42.c b/lib/dns/rdata/in_1/apl_42.c index 70f6880..3f37880 100644 --- a/lib/dns/rdata/in_1/apl_42.c +++ b/lib/dns/rdata/in_1/apl_42.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: apl_42.c,v 1.14 2008-01-22 23:28:04 tbox Exp $ */ +/* $Id: apl_42.c,v 1.16 2009-12-04 22:06:37 tbox Exp $ */ /* RFC3123 */ @@ -450,4 +450,9 @@ checknames_in_apl(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_in_apl(ARGS_COMPARE) { + return (compare_in_apl(rdata1, rdata2)); +} + #endif /* RDATA_IN_1_APL_42_C */ diff --git a/lib/dns/rdata/in_1/dhcid_49.c b/lib/dns/rdata/in_1/dhcid_49.c index 5759a76d..9eca46f 100644 --- a/lib/dns/rdata/in_1/dhcid_49.c +++ b/lib/dns/rdata/in_1/dhcid_49.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2006, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dhcid_49.c,v 1.5 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: dhcid_49.c,v 1.7 2009-12-04 22:06:37 tbox Exp $ */ /* RFC 4701 */ @@ -51,7 +51,7 @@ totext_in_dhcid(ARGS_TOTEXT) { dns_rdata_toregion(rdata, &sr); if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) - RETERR(str_totext("( " /*)*/, target)); + RETERR(str_totext("( " /*)*/, target)); RETERR(isc_base64_totext(&sr, tctx->width - 2, tctx->linebreak, target)); if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { @@ -226,4 +226,9 @@ checknames_in_dhcid(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_in_dhcid(ARGS_COMPARE) { + return (compare_in_dhcid(rdata1, rdata2)); +} + #endif /* RDATA_IN_1_DHCID_49_C */ diff --git a/lib/dns/rdata/in_1/kx_36.c b/lib/dns/rdata/in_1/kx_36.c index 795844d..dfc103b 100644 --- a/lib/dns/rdata/in_1/kx_36.c +++ b/lib/dns/rdata/in_1/kx_36.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: kx_36.c,v 1.45 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: kx_36.c,v 1.47 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Thu Mar 16 17:24:54 PST 2000 by explorer */ @@ -85,7 +85,7 @@ totext_in_kx(ARGS_TOTEXT) { static inline isc_result_t fromwire_in_kx(ARGS_FROMWIRE) { - dns_name_t name; + dns_name_t name; isc_region_t sregion; REQUIRE(type == 36); @@ -96,7 +96,7 @@ fromwire_in_kx(ARGS_FROMWIRE) { dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); - dns_name_init(&name, NULL); + dns_name_init(&name, NULL); isc_buffer_activeregion(source, &sregion); if (sregion.length < 2) @@ -285,4 +285,9 @@ checknames_in_kx(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_in_kx(ARGS_COMPARE) { + return (compare_in_kx(rdata1, rdata2)); +} + #endif /* RDATA_IN_1_KX_36_C */ diff --git a/lib/dns/rdata/in_1/naptr_35.c b/lib/dns/rdata/in_1/naptr_35.c index 51aadf7..3d09757 100644 --- a/lib/dns/rdata/in_1/naptr_35.c +++ b/lib/dns/rdata/in_1/naptr_35.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: naptr_35.c,v 1.53 2008-02-15 23:46:51 tbox Exp $ */ +/* $Id: naptr_35.c,v 1.56 2009-12-04 21:09:34 marka Exp $ */ /* Reviewed: Thu Mar 16 16:52:50 PST 2000 by bwelling */ @@ -25,12 +25,134 @@ #define RDATA_IN_1_NAPTR_35_C #define RRTYPE_NAPTR_ATTRIBUTES (0) +#ifdef HAVE_REGEX_H +#include +#endif + +/* + * Check the wire format of the Regexp field. + * Don't allow embeded NUL's. + */ +static inline isc_result_t +txt_valid_regex(const unsigned char *txt) { +#ifdef HAVE_REGEX_H + regex_t preg; + unsigned int regflags = REG_EXTENDED; + unsigned int nsub = 0; + char regex[256]; + char *cp; +#endif + isc_boolean_t flags = ISC_FALSE; + isc_boolean_t replace = ISC_FALSE; + unsigned char c; + unsigned char delim; + unsigned int len; + + len = *txt++; + if (len == 0U) + return (ISC_R_SUCCESS); + + delim = *txt++; + len--; + + /* + * Digits, backslash and flags can't be delimiters. + */ + switch (delim) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case '\\': case 'i': case 0: + return (DNS_R_SYNTAX); + } + +#ifdef HAVE_REGEX_H + memset(&preg, 0, sizeof(preg)); + cp = regex; +#endif + + while (len-- > 0) { + c = *txt++; + if (c == 0) + return (DNS_R_SYNTAX); + if (c == delim && !replace) { + replace = ISC_TRUE; + continue; + } else if (c == delim && !flags) { + flags = ISC_TRUE; + continue; + } else if (c == delim) + return (DNS_R_SYNTAX); + /* + * Flags are not escaped. + */ + if (flags) { + switch (c) { + case 'i': +#ifdef HAVE_REGEX_H + regflags |= REG_ICASE; +#endif + continue; + default: + return (DNS_R_SYNTAX); + } + } +#ifdef HAVE_REGEX_H + if (!replace) + *cp++ = c; +#endif + if (c == '\\') { + if (len == 0) + return (DNS_R_SYNTAX); + c = *txt++; + if (c == 0) + return (DNS_R_SYNTAX); + len--; + if (replace) + switch (c) { + case '0': return (DNS_R_SYNTAX); +#ifdef HAVE_REGEX_H + case '1': if (nsub < 1) nsub = 1; break; + case '2': if (nsub < 2) nsub = 2; break; + case '3': if (nsub < 3) nsub = 3; break; + case '4': if (nsub < 4) nsub = 4; break; + case '5': if (nsub < 5) nsub = 5; break; + case '6': if (nsub < 6) nsub = 6; break; + case '7': if (nsub < 7) nsub = 7; break; + case '8': if (nsub < 8) nsub = 8; break; + case '9': if (nsub < 9) nsub = 9; break; +#endif + } +#ifdef HAVE_REGEX_H + if (!replace) + *cp++ = c; +#endif + } + } + if (!flags) + return (DNS_R_SYNTAX); +#ifdef HAVE_REGEX_H + *cp = '\0'; + if (regcomp(&preg, regex, regflags)) + return (DNS_R_SYNTAX); + /* + * Check that substitutions in the replacement string are consistant + * with the regular expression. + */ + if (preg.re_nsub < nsub) { + regfree(&preg); + return (DNS_R_SYNTAX); + } + regfree(&preg); +#endif + return (ISC_R_SUCCESS); +} static inline isc_result_t fromtext_in_naptr(ARGS_FROMTEXT) { isc_token_t token; dns_name_t name; isc_buffer_t buffer; + unsigned char *regex; REQUIRE(type == 35); REQUIRE(rdclass == 1); @@ -74,9 +196,11 @@ fromtext_in_naptr(ARGS_FROMTEXT) { /* * Regexp. */ + regex = isc_buffer_used(target); RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring, ISC_FALSE)); RETTOK(txt_fromtext(&token.value.as_textregion, target)); + RETTOK(txt_valid_regex(regex)); /* * Replacement. @@ -156,6 +280,7 @@ static inline isc_result_t fromwire_in_naptr(ARGS_FROMWIRE) { dns_name_t name; isc_region_t sr; + unsigned char *regex; REQUIRE(type == 35); REQUIRE(rdclass == 1); @@ -189,7 +314,9 @@ fromwire_in_naptr(ARGS_FROMWIRE) { /* * Regexp. */ + regex = isc_buffer_used(target); RETERR(txt_fromwire(source, target)); + RETERR(txt_valid_regex(regex)); /* * Replacement. @@ -575,4 +702,9 @@ checknames_in_naptr(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_in_naptr(ARGS_COMPARE) { + return (compare_in_naptr(rdata1, rdata2)); +} + #endif /* RDATA_IN_1_NAPTR_35_C */ diff --git a/lib/dns/rdata/in_1/nsap-ptr_23.c b/lib/dns/rdata/in_1/nsap-ptr_23.c index 615d24a..2554b07 100644 --- a/lib/dns/rdata/in_1/nsap-ptr_23.c +++ b/lib/dns/rdata/in_1/nsap-ptr_23.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nsap-ptr_23.c,v 1.38 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: nsap-ptr_23.c,v 1.40 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Fri Mar 17 10:16:02 PST 2000 by gson */ @@ -73,7 +73,7 @@ totext_in_nsap_ptr(ARGS_TOTEXT) { static inline isc_result_t fromwire_in_nsap_ptr(ARGS_FROMWIRE) { - dns_name_t name; + dns_name_t name; REQUIRE(type == 23); REQUIRE(rdclass == 1); @@ -83,8 +83,8 @@ fromwire_in_nsap_ptr(ARGS_FROMWIRE) { dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); - dns_name_init(&name, NULL); - return (dns_name_fromwire(&name, source, dctx, options, target)); + dns_name_init(&name, NULL); + return (dns_name_fromwire(&name, source, dctx, options, target)); } static inline isc_result_t @@ -242,4 +242,9 @@ checknames_in_nsap_ptr(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_in_nsap_ptr(ARGS_COMPARE) { + return (compare_in_nsap_ptr(rdata1, rdata2)); +} + #endif /* RDATA_IN_1_NSAP_PTR_23_C */ diff --git a/lib/dns/rdata/in_1/nsap_22.c b/lib/dns/rdata/in_1/nsap_22.c index 1aaf13f..4a56c75 100644 --- a/lib/dns/rdata/in_1/nsap_22.c +++ b/lib/dns/rdata/in_1/nsap_22.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nsap_22.c,v 1.42 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: nsap_22.c,v 1.44 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Fri Mar 17 10:41:07 PST 2000 by gson */ @@ -252,4 +252,9 @@ checknames_in_nsap(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_in_nsap(ARGS_COMPARE) { + return (compare_in_nsap(rdata1, rdata2)); +} + #endif /* RDATA_IN_1_NSAP_22_C */ diff --git a/lib/dns/rdata/in_1/px_26.c b/lib/dns/rdata/in_1/px_26.c index 517b87c..50f68cd 100644 --- a/lib/dns/rdata/in_1/px_26.c +++ b/lib/dns/rdata/in_1/px_26.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: px_26.c,v 1.43 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: px_26.c,v 1.45 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Mon Mar 20 10:44:27 PST 2000 */ @@ -115,7 +115,7 @@ totext_in_px(ARGS_TOTEXT) { static inline isc_result_t fromwire_in_px(ARGS_FROMWIRE) { - dns_name_t name; + dns_name_t name; isc_region_t sregion; REQUIRE(type == 26); @@ -126,7 +126,7 @@ fromwire_in_px(ARGS_FROMWIRE) { dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); - dns_name_init(&name, NULL); + dns_name_init(&name, NULL); /* * Preference. @@ -371,4 +371,9 @@ checknames_in_px(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_in_px(ARGS_COMPARE) { + return (compare_in_px(rdata1, rdata2)); +} + #endif /* RDATA_IN_1_PX_26_C */ diff --git a/lib/dns/rdata/in_1/srv_33.c b/lib/dns/rdata/in_1/srv_33.c index ac9e577..3dfd13e 100644 --- a/lib/dns/rdata/in_1/srv_33.c +++ b/lib/dns/rdata/in_1/srv_33.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: srv_33.c,v 1.45 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: srv_33.c,v 1.47 2009-12-04 22:06:37 tbox Exp $ */ /* Reviewed: Fri Mar 17 13:01:00 PST 2000 by bwelling */ @@ -140,7 +140,7 @@ totext_in_srv(ARGS_TOTEXT) { static inline isc_result_t fromwire_in_srv(ARGS_FROMWIRE) { - dns_name_t name; + dns_name_t name; isc_region_t sr; REQUIRE(type == 33); @@ -151,7 +151,7 @@ fromwire_in_srv(ARGS_FROMWIRE) { dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); - dns_name_init(&name, NULL); + dns_name_init(&name, NULL); /* * Priority, weight, port. @@ -370,4 +370,9 @@ checknames_in_srv(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_in_srv(ARGS_COMPARE) { + return (compare_in_srv(rdata1, rdata2)); +} + #endif /* RDATA_IN_1_SRV_33_C */ diff --git a/lib/dns/rdata/in_1/wks_11.c b/lib/dns/rdata/in_1/wks_11.c index b7d5057..29983ec 100644 --- a/lib/dns/rdata/in_1/wks_11.c +++ b/lib/dns/rdata/in_1/wks_11.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: wks_11.c,v 1.54.332.2 2009-02-16 23:47:15 tbox Exp $ */ +/* $Id: wks_11.c,v 1.57 2009-12-04 21:09:34 marka Exp $ */ /* Reviewed: Fri Mar 17 15:01:49 PST 2000 by explorer */ @@ -348,4 +348,9 @@ checknames_in_wks(ARGS_CHECKNAMES) { return (ISC_TRUE); } +static inline int +casecompare_in_wks(ARGS_COMPARE) { + return (compare_in_wks(rdata1, rdata2)); +} + #endif /* RDATA_IN_1_WKS_11_C */ diff --git a/lib/dns/rdatalist.c b/lib/dns/rdatalist.c index e8178a7..d30aff9 100644 --- a/lib/dns/rdatalist.c +++ b/lib/dns/rdatalist.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdatalist.c,v 1.36.50.2 2010-02-25 10:56:41 tbox Exp $ */ +/* $Id: rdatalist.c,v 1.40 2010-11-16 05:38:31 marka Exp $ */ /*! \file */ diff --git a/lib/dns/rdataset.c b/lib/dns/rdataset.c index 672e001..fdd7669 100644 --- a/lib/dns/rdataset.c +++ b/lib/dns/rdataset.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdataset.c,v 1.82.50.4.6.3 2011-06-21 20:13:23 each Exp $ */ +/* $Id: rdataset.c,v 1.86.220.3 2011-06-21 20:15:53 each Exp $ */ /*! \file */ diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c index d1a02a0..932f8de 100644 --- a/lib/dns/rdataslab.c +++ b/lib/dns/rdataslab.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdataslab.c,v 1.48.50.4 2010-02-25 10:56:41 tbox Exp $ */ +/* $Id: rdataslab.c,v 1.52.148.1.2.1 2011-06-02 23:47:35 tbox Exp $ */ /*! \file */ @@ -144,21 +144,25 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, nalloc = dns_rdataset_count(rdataset); nitems = nalloc; - if (nitems == 0) + if (nitems == 0 && rdataset->type != 0) return (ISC_R_FAILURE); if (nalloc > 0xffff) return (ISC_R_NOSPACE); - x = isc_mem_get(mctx, nalloc * sizeof(struct xrdata)); - if (x == NULL) - return (ISC_R_NOMEMORY); + + if (nalloc != 0) { + x = isc_mem_get(mctx, nalloc * sizeof(struct xrdata)); + if (x == NULL) + return (ISC_R_NOMEMORY); + } else + x = NULL; /* * Save all of the rdata members into an array. */ result = dns_rdataset_first(rdataset); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) goto free_rdatas; for (i = 0; i < nalloc && result == ISC_R_SUCCESS; i++) { INSIST(result == ISC_R_SUCCESS); @@ -223,11 +227,14 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, /* * Don't forget the last item! */ + if (nalloc != 0) { #if DNS_RDATASET_FIXED - buflen += (8 + x[i-1].rdata.length); + buflen += (8 + x[i-1].rdata.length); #else - buflen += (2 + x[i-1].rdata.length); + buflen += (2 + x[i-1].rdata.length); #endif + } + /* * Provide space to store the per RR meta data. */ @@ -316,7 +323,8 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, result = ISC_R_SUCCESS; free_rdatas: - isc_mem_put(mctx, x, nalloc * sizeof(struct xrdata)); + if (x != NULL) + isc_mem_put(mctx, x, nalloc * sizeof(struct xrdata)); return (result); } diff --git a/lib/dns/request.c b/lib/dns/request.c index c1cd235..b5d6248 100644 --- a/lib/dns/request.c +++ b/lib/dns/request.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: request.c,v 1.82.72.2 2009-01-18 23:47:40 tbox Exp $ */ +/* $Id: request.c,v 1.87 2010-03-04 23:50:34 tbox Exp $ */ /*! \file */ @@ -449,7 +449,8 @@ req_send(dns_request_t *request, isc_task_t *task, isc_sockaddr_t *address) { } static isc_result_t -new_request(isc_mem_t *mctx, dns_request_t **requestp) { +new_request(isc_mem_t *mctx, dns_request_t **requestp) +{ dns_request_t *request; request = isc_mem_get(mctx, sizeof(*request)); @@ -1058,6 +1059,9 @@ req_render(dns_message_t *message, isc_buffer_t **bufferp, return (result); cleanup_cctx = ISC_TRUE; + if ((options & DNS_REQUESTOPT_CASE) != 0) + dns_compress_setsensitive(&cctx, ISC_TRUE); + /* * Render message. */ diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index f60eee9..6d9ab70 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resolver.c,v 1.384.14.30.4.1 2011-06-21 20:13:23 each Exp $ */ +/* $Id: resolver.c,v 1.428.6.5.2.1 2011-06-21 20:15:53 each Exp $ */ /*! \file */ @@ -105,6 +105,14 @@ #define QTRACE(m) #endif +#ifndef DEFAULT_QUERY_TIMEOUT +#define DEFAULT_QUERY_TIMEOUT 30 /* The default time in seconds for the whole query to live. */ +#endif + +#ifndef MAXIMUM_QUERY_TIMEOUT +#define MAXIMUM_QUERY_TIMEOUT 30 /* The maximum time in seconds for the whole query to live. */ +#endif + /*% * Maximum EDNS0 input packet size. */ @@ -273,6 +281,8 @@ struct fetchctx { unsigned int findfail; unsigned int valfail; isc_boolean_t timeout; + dns_adbaddrinfo_t *addrinfo; + isc_sockaddr_t *client; }; #define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!') @@ -384,6 +394,7 @@ struct dns_resolver { unsigned int spillatmin; isc_timer_t * spillattimer; isc_boolean_t zero_no_soa_ttl; + unsigned int query_timeout; /* Locked by lock. */ unsigned int references; @@ -1035,6 +1046,7 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result, int line) { ISC_LIST_UNLINK(fctx->events, event, ev_link); task = event->ev_sender; event->ev_sender = fctx; + event->vresult = fctx->vresult; if (!HAVE_ANSWER(fctx)) event->result = result; @@ -1742,9 +1754,8 @@ resquery_send(resquery_t *query) { if ((query->options & DNS_FETCHOPT_NOVALIDATE) != 0) { fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD; } else if (res->view->enablevalidation) { - result = dns_keytable_issecuredomain(res->view->secroots, - &fctx->name, - &secure_domain); + result = dns_view_issecuredomain(res->view, &fctx->name, + &secure_domain); if (result != ISC_R_SUCCESS) secure_domain = ISC_FALSE; if (res->view->dlv != NULL) @@ -2285,7 +2296,7 @@ add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason, char code[64]; isc_buffer_t b; isc_sockaddr_t *sa; - const char *sep1, *sep2; + const char *spc = ""; isc_sockaddr_t *address = &addrinfo->sockaddr; if (reason == DNS_R_LAME) @@ -2331,18 +2342,14 @@ add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason, isc_buffer_init(&b, code, sizeof(code) - 1); dns_rcode_totext(fctx->rmessage->rcode, &b); code[isc_buffer_usedlength(&b)] = '\0'; - sep1 = "("; - sep2 = ") "; + spc = " "; } else if (reason == DNS_R_UNEXPECTEDOPCODE) { isc_buffer_init(&b, code, sizeof(code) - 1); dns_opcode_totext((dns_opcode_t)fctx->rmessage->opcode, &b); code[isc_buffer_usedlength(&b)] = '\0'; - sep1 = "("; - sep2 = ") "; + spc = " "; } else { code[0] = '\0'; - sep1 = ""; - sep2 = ""; } dns_name_format(&fctx->name, namebuf, sizeof(namebuf)); dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf)); @@ -2350,83 +2357,19 @@ add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason, isc_sockaddr_format(address, addrbuf, sizeof(addrbuf)); isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS, DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO, - "%s %s%s%sresolving '%s/%s/%s': %s", - dns_result_totext(reason), sep1, code, sep2, + "error (%s%s%s) resolving '%s/%s/%s': %s", + dns_result_totext(reason), spc, code, namebuf, typebuf, classbuf, addrbuf); } /* - * Return 'bits' bits of random entropy from fctx->rand_buf, - * refreshing it by calling isc_random_get() whenever the requested - * number of bits is greater than the number in the buffer. - */ -static inline isc_uint32_t -random_bits(fetchctx_t *fctx, isc_uint32_t bits) { - isc_uint32_t ret = 0; - - REQUIRE(VALID_FCTX(fctx)); - REQUIRE(bits <= 32); - if (bits == 0) - return (0); - - if (bits >= fctx->rand_bits) { - /* if rand_bits == 0, this is unnecessary but harmless */ - bits -= fctx->rand_bits; - ret = fctx->rand_buf << bits; - - /* refresh random buffer now */ - isc_random_get(&fctx->rand_buf); - fctx->rand_bits = sizeof(fctx->rand_buf) * CHAR_BIT; - } - - if (bits > 0) { - isc_uint32_t mask = 0xffffffff; - if (bits < 32) { - mask = (1 << bits) - 1; - } - - ret |= fctx->rand_buf & mask; - fctx->rand_buf >>= bits; - fctx->rand_bits -= bits; - } - - return (ret); -} - -/* - * Add some random jitter to a server's RTT value so that the - * order of queries will be unpredictable. - * - * RTT values of servers which have been tried are fuzzed by 128 ms. - * Servers that haven't been tried yet have their RTT set to a random - * value between 0 ms and 7 ms; they should get to go first, but in - * unpredictable order. - */ -static inline void -randomize_srtt(fetchctx_t *fctx, dns_adbaddrinfo_t *ai) { - if (TRIED(ai)) { - ai->srtt >>= 10; /* convert to milliseconds, near enough */ - ai->srtt |= (ai->srtt & 0x80) | random_bits(fctx, 7); - ai->srtt <<= 10; /* now back to microseconds */ - } else - ai->srtt = random_bits(fctx, 3) << 10; -} - -/* - * Sort addrinfo list by RTT (with random jitter) + * Sort addrinfo list by RTT. */ static void -sort_adbfind(fetchctx_t *fctx, dns_adbfind_t *find) { +sort_adbfind(dns_adbfind_t *find) { dns_adbaddrinfo_t *best, *curr; dns_adbaddrinfolist_t sorted; - /* Add jitter to SRTT values */ - curr = ISC_LIST_HEAD(find->list); - while (curr != NULL) { - randomize_srtt(fctx, curr); - curr = ISC_LIST_NEXT(curr, publink); - } - /* Lame N^2 bubble sort. */ ISC_LIST_INIT(sorted); while (!ISC_LIST_EMPTY(find->list)) { @@ -2444,19 +2387,19 @@ sort_adbfind(fetchctx_t *fctx, dns_adbfind_t *find) { } /* - * Sort a list of finds by server RTT (with random jitter) + * Sort a list of finds by server RTT. */ static void -sort_finds(fetchctx_t *fctx, dns_adbfindlist_t *findlist) { +sort_finds(dns_adbfindlist_t *findlist) { dns_adbfind_t *best, *curr; dns_adbfindlist_t sorted; dns_adbaddrinfo_t *addrinfo, *bestaddrinfo; - /* Sort each find's addrinfo list by SRTT (after adding jitter) */ + /* Sort each find's addrinfo list by SRTT. */ for (curr = ISC_LIST_HEAD(*findlist); curr != NULL; curr = ISC_LIST_NEXT(curr, publink)) - sort_adbfind(fctx, curr); + sort_adbfind(curr); /* Lame N^2 bubble sort. */ ISC_LIST_INIT(sorted); @@ -2841,8 +2784,8 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) { * We've found some addresses. We might still be looking * for more addresses. */ - sort_finds(fctx, &fctx->finds); - sort_finds(fctx, &fctx->altfinds); + sort_finds(&fctx->finds); + sort_finds(&fctx->altfinds); result = ISC_R_SUCCESS; } @@ -3471,6 +3414,7 @@ fctx_join(fetchctx_t *fctx, isc_task_t *task, isc_sockaddr_t *client, else ISC_LIST_APPEND(fctx->events, event, ev_link); fctx->references++; + fctx->client = client; fetch->magic = DNS_FETCH_MAGIC; fetch->private = fctx; @@ -3569,6 +3513,8 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, fctx->rand_buf = 0; fctx->rand_bits = 0; fctx->timeout = ISC_FALSE; + fctx->addrinfo = NULL; + fctx->client = NULL; dns_name_init(&fctx->nsname, NULL); fctx->nsfetch = NULL; @@ -3658,7 +3604,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, /* * Compute an expiration time for the entire fetch. */ - isc_interval_set(&interval, 30, 0); /* XXXRTH constant */ + isc_interval_set(&interval, res->query_timeout, 0); iresult = isc_time_nowplusinterval(&fctx->expires, &interval); if (iresult != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, @@ -3800,6 +3746,33 @@ log_lame(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo) { namebuf, domainbuf, addrbuf); } +static inline void +log_formerr(fetchctx_t *fctx, const char *format, ...) { + char nsbuf[ISC_SOCKADDR_FORMATSIZE]; + char clbuf[ISC_SOCKADDR_FORMATSIZE]; + const char *clmsg = ""; + char msgbuf[2048]; + va_list args; + + va_start(args, format); + vsnprintf(msgbuf, sizeof(msgbuf), format, args); + va_end(args); + + isc_sockaddr_format(&fctx->addrinfo->sockaddr, nsbuf, sizeof(nsbuf)); + + if (fctx->client != NULL) { + clmsg = " for client "; + isc_sockaddr_format(fctx->client, clbuf, sizeof(clbuf)); + } else { + clbuf[0] = '\0'; + } + + isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, + DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE, + "DNS format error from %s resolving %s%s%s: %s", + nsbuf, fctx->info, clmsg, clbuf, msgbuf); +} + static inline isc_result_t same_question(fetchctx_t *fctx) { isc_result_t result; @@ -3814,8 +3787,10 @@ same_question(fetchctx_t *fctx) { /* * XXXRTH Currently we support only one question. */ - if (message->counts[DNS_SECTION_QUESTION] != 1) + if (message->counts[DNS_SECTION_QUESTION] != 1) { + log_formerr(fctx, "too many questions"); return (DNS_R_FORMERR); + } result = dns_message_firstname(message, DNS_SECTION_QUESTION); if (result != ISC_R_SUCCESS) @@ -3825,10 +3800,21 @@ same_question(fetchctx_t *fctx) { rdataset = ISC_LIST_HEAD(name->list); INSIST(rdataset != NULL); INSIST(ISC_LIST_NEXT(rdataset, link) == NULL); + if (fctx->type != rdataset->type || fctx->res->rdclass != rdataset->rdclass || - !dns_name_equal(&fctx->name, name)) + !dns_name_equal(&fctx->name, name)) { + char namebuf[DNS_NAME_FORMATSIZE]; + char class[DNS_RDATACLASS_FORMATSIZE]; + char type[DNS_RDATATYPE_FORMATSIZE]; + + dns_name_format(name, namebuf, sizeof(namebuf)); + dns_rdataclass_format(rdataset->rdclass, class, sizeof(class)); + dns_rdatatype_format(rdataset->type, type, sizeof(type)); + log_formerr(fctx, "question section mismatch: got %s/%s/%s", + namebuf, class, type); return (DNS_R_FORMERR); + } return (ISC_R_SUCCESS); } @@ -3958,6 +3944,7 @@ validated(isc_task_t *task, isc_event_t *event) { REQUIRE(!ISC_LIST_EMPTY(fctx->validators)); vevent = (dns_validatorevent_t *)event; + fctx->vresult = vevent->result; FCTXTRACE("received validation completion event"); @@ -4331,8 +4318,8 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, * Is DNSSEC validation required for this name? */ if (res->view->enablevalidation) { - result = dns_keytable_issecuredomain(res->view->secroots, name, - &secure_domain); + result = dns_view_issecuredomain(res->view, name, + &secure_domain); if (result != ISC_R_SUCCESS) return (result); @@ -4804,8 +4791,8 @@ ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, * Is DNSSEC validation required for this name? */ if (fctx->res->view->enablevalidation) { - result = dns_keytable_issecuredomain(res->view->secroots, name, - &secure_domain); + result = dns_view_issecuredomain(res->view, name, + &secure_domain); if (result != ISC_R_SUCCESS) return (result); @@ -4949,7 +4936,9 @@ mark_related(dns_name_t *name, dns_rdataset_t *rdataset, } static isc_result_t -check_related(void *arg, dns_name_t *addname, dns_rdatatype_t type) { +check_section(void *arg, dns_name_t *addname, dns_rdatatype_t type, + dns_section_t section) +{ fetchctx_t *fctx = arg; isc_result_t result; dns_name_t *name; @@ -4960,15 +4949,19 @@ check_related(void *arg, dns_name_t *addname, dns_rdatatype_t type) { REQUIRE(VALID_FCTX(fctx)); +#if CHECK_FOR_GLUE_IN_ANSWER + if (section == DNS_SECTION_ANSWER && type != dns_rdatatype_a) + return (ISC_R_SUCCESS); +#endif + if (GLUING(fctx)) gluing = ISC_TRUE; else gluing = ISC_FALSE; name = NULL; rdataset = NULL; - result = dns_message_findname(fctx->rmessage, DNS_SECTION_ADDITIONAL, - addname, dns_rdatatype_any, 0, &name, - NULL); + result = dns_message_findname(fctx->rmessage, section, addname, + dns_rdatatype_any, 0, &name, NULL); if (result == ISC_R_SUCCESS) { external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain)); if (type == dns_rdatatype_a) { @@ -5006,6 +4999,21 @@ check_related(void *arg, dns_name_t *addname, dns_rdatatype_t type) { return (ISC_R_SUCCESS); } +static isc_result_t +check_related(void *arg, dns_name_t *addname, dns_rdatatype_t type) { + return (check_section(arg, addname, type, DNS_SECTION_ADDITIONAL)); +} + +#ifndef CHECK_FOR_GLUE_IN_ANSWER +#define CHECK_FOR_GLUE_IN_ANSWER 0 +#endif +#if CHECK_FOR_GLUE_IN_ANSWER +static isc_result_t +check_answer(void *arg, dns_name_t *addname, dns_rdatatype_t type) { + return (check_section(arg, addname, type, DNS_SECTION_ANSWER)); +} +#endif + static void chase_additional(fetchctx_t *fctx) { isc_boolean_t rescan; @@ -5062,8 +5070,8 @@ cname_target(dns_rdataset_t *rdataset, dns_name_t *tname) { } static inline isc_result_t -dname_target(dns_rdataset_t *rdataset, dns_name_t *qname, dns_name_t *oname, - dns_fixedname_t *fixeddname) +dname_target(fetchctx_t *fctx, dns_rdataset_t *rdataset, dns_name_t *qname, + dns_name_t *oname, dns_fixedname_t *fixeddname) { isc_result_t result; dns_rdata_t rdata = DNS_RDATA_INIT; @@ -5076,7 +5084,6 @@ dname_target(dns_rdataset_t *rdataset, dns_name_t *qname, dns_name_t *oname, /* * Get the target name of the DNAME. */ - result = dns_rdataset_first(rdataset); if (result != ISC_R_SUCCESS) return (result); @@ -5090,7 +5097,14 @@ dname_target(dns_rdataset_t *rdataset, dns_name_t *qname, dns_name_t *oname, */ namereln = dns_name_fullcompare(qname, oname, &order, &nlabels); if (namereln != dns_namereln_subdomain) { + char qbuf[DNS_NAME_FORMATSIZE]; + char obuf[DNS_NAME_FORMATSIZE]; + dns_rdata_freestruct(&dname); + dns_name_format(qname, qbuf, sizeof(qbuf)); + dns_name_format(oname, obuf, sizeof(obuf)); + log_formerr(fctx, "unrelated DNAME in answer: " + "%s is not in %s", qbuf, obuf); return (DNS_R_FORMERR); } dns_fixedname_init(&prefix); @@ -5103,16 +5117,147 @@ dname_target(dns_rdataset_t *rdataset, dns_name_t *qname, dns_name_t *oname, return (result); } +static isc_boolean_t +is_answeraddress_allowed(dns_view_t *view, dns_name_t *name, + dns_rdataset_t *rdataset) +{ + isc_result_t result; + dns_rdata_t rdata = DNS_RDATA_INIT; + struct in_addr ina; + struct in6_addr in6a; + isc_netaddr_t netaddr; + char addrbuf[ISC_NETADDR_FORMATSIZE]; + char namebuf[DNS_NAME_FORMATSIZE]; + char classbuf[64]; + char typebuf[64]; + int match; + + /* By default, we allow any addresses. */ + if (view->denyansweracl == NULL) + return (ISC_TRUE); + + /* + * If the owner name matches one in the exclusion list, either exactly + * or partially, allow it. + */ + if (view->answeracl_exclude != NULL) { + dns_rbtnode_t *node = NULL; + + result = dns_rbt_findnode(view->answeracl_exclude, name, NULL, + &node, NULL, 0, NULL, NULL); + + if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) + return (ISC_TRUE); + } + + /* + * Otherwise, search the filter list for a match for each address + * record. If a match is found, the address should be filtered, + * so should the entire answer. + */ + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + dns_rdata_reset(&rdata); + dns_rdataset_current(rdataset, &rdata); + if (rdataset->type == dns_rdatatype_a) { + INSIST(rdata.length == sizeof(ina.s_addr)); + memcpy(&ina.s_addr, rdata.data, sizeof(ina.s_addr)); + isc_netaddr_fromin(&netaddr, &ina); + } else { + INSIST(rdata.length == sizeof(in6a.s6_addr)); + memcpy(in6a.s6_addr, rdata.data, sizeof(in6a.s6_addr)); + isc_netaddr_fromin6(&netaddr, &in6a); + } + + result = dns_acl_match(&netaddr, NULL, view->denyansweracl, + &view->aclenv, &match, NULL); + + if (result == ISC_R_SUCCESS && match > 0) { + isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf)); + dns_name_format(name, namebuf, sizeof(namebuf)); + dns_rdatatype_format(rdataset->type, typebuf, + sizeof(typebuf)); + dns_rdataclass_format(rdataset->rdclass, classbuf, + sizeof(classbuf)); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, + DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE, + "answer address %s denied for %s/%s/%s", + addrbuf, namebuf, typebuf, classbuf); + return (ISC_FALSE); + } + } + + return (ISC_TRUE); +} + +static isc_boolean_t +is_answertarget_allowed(dns_view_t *view, dns_name_t *name, + dns_rdatatype_t type, dns_name_t *tname, + dns_name_t *domain) +{ + isc_result_t result; + dns_rbtnode_t *node = NULL; + char qnamebuf[DNS_NAME_FORMATSIZE]; + char tnamebuf[DNS_NAME_FORMATSIZE]; + char classbuf[64]; + char typebuf[64]; + + /* By default, we allow any target name. */ + if (view->denyanswernames == NULL) + return (ISC_TRUE); + + /* + * If the owner name matches one in the exclusion list, either exactly + * or partially, allow it. + */ + if (view->answernames_exclude != NULL) { + result = dns_rbt_findnode(view->answernames_exclude, name, NULL, + &node, NULL, 0, NULL, NULL); + if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) + return (ISC_TRUE); + } + + /* + * If the target name is a subdomain of the search domain, allow it. + */ + if (dns_name_issubdomain(tname, domain)) + return (ISC_TRUE); + + /* + * Otherwise, apply filters. + */ + result = dns_rbt_findnode(view->denyanswernames, tname, NULL, &node, + NULL, 0, NULL, NULL); + if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { + dns_name_format(name, qnamebuf, sizeof(qnamebuf)); + dns_name_format(tname, tnamebuf, sizeof(tnamebuf)); + dns_rdatatype_format(type, typebuf, sizeof(typebuf)); + dns_rdataclass_format(view->rdclass, classbuf, + sizeof(classbuf)); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, + DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE, + "%s target %s denied for %s/%s", + typebuf, tnamebuf, qnamebuf, classbuf); + return (ISC_FALSE); + } + + return (ISC_TRUE); +} + /* * Handle a no-answer response (NXDOMAIN, NXRRSET, or referral). - * If bind8_ns_resp is ISC_TRUE, this is a suspected BIND 8 - * response to an NS query that should be treated as a referral - * even though the NS records occur in the answer section - * rather than the authority section. + * If look_in_options has LOOK_FOR_NS_IN_ANSWER then we look in the answer + * section for the NS RRset if the query type is NS; if it has + * LOOK_FOR_GLUE_IN_ANSWER we look for glue incorrectly returned in the answer + * section for A and AAAA queries. */ +#define LOOK_FOR_NS_IN_ANSWER 0x1 +#define LOOK_FOR_GLUE_IN_ANSWER 0x2 + static isc_result_t noanswer_response(fetchctx_t *fctx, dns_name_t *oqname, - isc_boolean_t bind8_ns_resp) + unsigned int look_in_options) { isc_result_t result; dns_message_t *message; @@ -5120,11 +5265,16 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname, dns_rdataset_t *rdataset, *ns_rdataset; isc_boolean_t aa, negative_response; dns_rdatatype_t type; - dns_section_t section = - bind8_ns_resp ? DNS_SECTION_ANSWER : DNS_SECTION_AUTHORITY; + dns_section_t section; FCTXTRACE("noanswer_response"); + if ((look_in_options & LOOK_FOR_NS_IN_ANSWER) != 0) { + INSIST(fctx->type == dns_rdatatype_ns); + section = DNS_SECTION_ANSWER; + } else + section = DNS_SECTION_AUTHORITY; + message = fctx->rmessage; /* @@ -5197,8 +5347,22 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname, type = rdataset->covers; if (((type == dns_rdatatype_ns || type == dns_rdatatype_soa) && - !dns_name_issubdomain(qname, name))) + !dns_name_issubdomain(qname, name))) { + char qbuf[DNS_NAME_FORMATSIZE]; + char nbuf[DNS_NAME_FORMATSIZE]; + char tbuf[DNS_RDATATYPE_FORMATSIZE]; + dns_rdatatype_format(fctx->type, tbuf, + sizeof(tbuf)); + dns_name_format(name, nbuf, + sizeof(nbuf)); + dns_name_format(qname, qbuf, + sizeof(qbuf)); + log_formerr(fctx, + "unrelated %s %s in " + "%s authority section", + tbuf, qbuf, nbuf); return (DNS_R_FORMERR); + } if (type == dns_rdatatype_ns) { /* * NS or RRSIG NS. @@ -5208,8 +5372,14 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname, if (rdataset->type == dns_rdatatype_ns) { if (ns_name != NULL && - name != ns_name) + name != ns_name) { + log_formerr(fctx, + "multiple NS " + "RRsets in " + "authority " + "section"); return (DNS_R_FORMERR); + } ns_name = name; ns_rdataset = rdataset; } @@ -5228,8 +5398,14 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname, if (rdataset->type == dns_rdatatype_soa) { if (soa_name != NULL && - name != soa_name) + name != soa_name) { + log_formerr(fctx, + "multiple SOA " + "RRs in " + "authority " + "section"); return (DNS_R_FORMERR); + } soa_name = name; } name->attributes |= @@ -5305,15 +5481,25 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname, * * These should only be here if * this is a referral, and there - * should only be one DS. + * should only be one DS RRset. */ - if (ns_name == NULL) + if (ns_name == NULL) { + log_formerr(fctx, + "DS with no " + "referral"); return (DNS_R_FORMERR); + } if (rdataset->type == dns_rdatatype_ds) { if (ds_name != NULL && - name != ds_name) + name != ds_name) { + log_formerr(fctx, + "DS doesn't " + "match " + "referral " + "(NS)"); return (DNS_R_FORMERR); + } ds_name = name; } name->attributes |= @@ -5363,6 +5549,7 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname, /* * The responder is insane. */ + log_formerr(fctx, "invalid response"); return (DNS_R_FORMERR); } } @@ -5370,8 +5557,10 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname, /* * If we found both NS and SOA, they should be the same name. */ - if (ns_name != NULL && soa_name != NULL && ns_name != soa_name) + if (ns_name != NULL && soa_name != NULL && ns_name != soa_name) { + log_formerr(fctx, "NS/SOA mismatch"); return (DNS_R_FORMERR); + } /* * Do we have a referral? (We only want to follow a referral if @@ -5384,14 +5573,18 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname, * progress. We return DNS_R_FORMERR so that we'll keep * trying other servers. */ - if (dns_name_equal(ns_name, &fctx->domain)) + if (dns_name_equal(ns_name, &fctx->domain)) { + log_formerr(fctx, "non-improving referral"); return (DNS_R_FORMERR); + } /* * If the referral name is not a parent of the query * name, consider the responder insane. */ if (! dns_name_issubdomain(&fctx->name, ns_name)) { + /* Logged twice */ + log_formerr(fctx, "referral to non-parent"); FCTXTRACE("referral to non-parent"); return (DNS_R_FORMERR); } @@ -5405,6 +5598,20 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname, fctx->attributes |= FCTX_ATTR_GLUING; (void)dns_rdataset_additionaldata(ns_rdataset, check_related, fctx); +#if CHECK_FOR_GLUE_IN_ANSWER + /* + * Look in the answer section for "glue" that is incorrectly + * returned as a answer. This is needed if the server also + * minimizes the response size by not adding records to the + * additional section that are in the answer section or if + * the record gets dropped due to message size constraints. + */ + if ((look_in_options & LOOK_FOR_GLUE_IN_ANSWER) != 0 && + (fctx->type == dns_rdatatype_aaaa || + fctx->type == dns_rdatatype_a)) + (void)dns_rdataset_additionaldata(ns_rdataset, + check_answer, fctx); +#endif fctx->attributes &= ~FCTX_ATTR_GLUING; /* * NS rdatasets with 0 TTL cause problems. @@ -5460,6 +5667,7 @@ answer_response(fetchctx_t *fctx) { unsigned int aflag; dns_rdatatype_t type; dns_fixedname_t dname, fqname; + dns_view_t *view; FCTXTRACE("answer_response"); @@ -5482,6 +5690,7 @@ answer_response(fetchctx_t *fctx) { aa = ISC_FALSE; qname = &fctx->name; type = fctx->type; + view = fctx->res->view; result = dns_message_firstname(message, DNS_SECTION_ANSWER); while (!done && result == ISC_R_SUCCESS) { name = NULL; @@ -5500,8 +5709,21 @@ answer_response(fetchctx_t *fctx) { * NSEC3 records are not allowed to * appear in the answer section. */ + log_formerr(fctx, "NSEC3 in answer"); return (DNS_R_FORMERR); } + + /* + * Apply filters, if given, on answers to reject + * a malicious attempt of rebinding. + */ + if ((rdataset->type == dns_rdatatype_a || + rdataset->type == dns_rdatatype_aaaa) && + !is_answeraddress_allowed(view, name, + rdataset)) { + return (DNS_R_SERVFAIL); + } + if (rdataset->type == type && !found_cname) { /* * We've found an ordinary answer. @@ -5540,8 +5762,16 @@ answer_response(fetchctx_t *fctx) { */ if (type == dns_rdatatype_rrsig || type == dns_rdatatype_dnskey || - type == dns_rdatatype_nsec) + type == dns_rdatatype_nsec || + type == dns_rdatatype_nsec3) { + char buf[DNS_RDATATYPE_FORMATSIZE]; + dns_rdatatype_format(fctx->type, + buf, sizeof(buf)); + log_formerr(fctx, + "CNAME response " + "for %s RR", buf); return (DNS_R_FORMERR); + } found = ISC_TRUE; found_cname = ISC_TRUE; want_chaining = ISC_TRUE; @@ -5550,6 +5780,14 @@ answer_response(fetchctx_t *fctx) { &tname); if (result != ISC_R_SUCCESS) return (result); + /* Apply filters on the target name. */ + if (!is_answertarget_allowed(view, + name, + rdataset->type, + &tname, + &fctx->domain)) { + return (DNS_R_SERVFAIL); + } } else if (rdataset->type == dns_rdatatype_rrsig && rdataset->covers == dns_rdatatype_cname @@ -5650,6 +5888,8 @@ answer_response(fetchctx_t *fctx) { rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { isc_boolean_t found_dname = ISC_FALSE; + dns_name_t *dname_name; + found = ISC_FALSE; aflag = 0; if (rdataset->type == dns_rdatatype_dname) { @@ -5660,12 +5900,15 @@ answer_response(fetchctx_t *fctx) { * If we're not chaining, then the * DNAME should not be external. */ - if (!chaining && external) + if (!chaining && external) { + log_formerr(fctx, + "external DNAME"); return (DNS_R_FORMERR); + } found = ISC_TRUE; want_chaining = ISC_TRUE; aflag = DNS_RDATASETATTR_ANSWER; - result = dname_target(rdataset, + result = dname_target(fctx, rdataset, qname, name, &dname); if (result == ISC_R_NOSPACE) { @@ -5679,6 +5922,15 @@ answer_response(fetchctx_t *fctx) { return (result); else found_dname = ISC_TRUE; + + dname_name = dns_fixedname_name(&dname); + if (!is_answertarget_allowed(view, + qname, + rdataset->type, + dname_name, + &fctx->domain)) { + return (DNS_R_SERVFAIL); + } } else if (rdataset->type == dns_rdatatype_rrsig && rdataset->covers == dns_rdatatype_dname) { @@ -5766,8 +6018,10 @@ answer_response(fetchctx_t *fctx) { /* * We should have found an answer. */ - if (!have_answer) + if (!have_answer) { + log_formerr(fctx, "reply has no answer"); return (DNS_R_FORMERR); + } /* * This response is now potentially cacheable. @@ -5784,15 +6038,18 @@ answer_response(fetchctx_t *fctx) { * If it isn't a noanswer response, no harm will be * done. */ - return (noanswer_response(fctx, qname, ISC_FALSE)); + return (noanswer_response(fctx, qname, 0)); } /* * We didn't end with an incomplete chain, so the rcode should be * "no error". */ - if (message->rcode != dns_rcode_noerror) + if (message->rcode != dns_rcode_noerror) { + log_formerr(fctx, "CNAME/DNAME chain complete, but RCODE " + "indicates error"); return (DNS_R_FORMERR); + } /* * Examine the authority section (if there is one). @@ -6129,6 +6386,39 @@ log_packet(dns_message_t *message, int level, isc_mem_t *mctx) { isc_mem_put(mctx, buf, len); } +static isc_boolean_t +iscname(fetchctx_t *fctx) { + isc_result_t result; + + result = dns_message_findname(fctx->rmessage, DNS_SECTION_ANSWER, + &fctx->name, dns_rdatatype_cname, 0, + NULL, NULL); + return (result == ISC_R_SUCCESS ? ISC_TRUE : ISC_FALSE); +} + +static isc_boolean_t +betterreferral(fetchctx_t *fctx) { + isc_result_t result; + dns_name_t *name; + dns_rdataset_t *rdataset; + dns_message_t *message = fctx->rmessage; + + for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY); + result == ISC_R_SUCCESS; + result = dns_message_nextname(message, DNS_SECTION_AUTHORITY)) { + name = NULL; + dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name); + if (!isstrictsubdomain(name, &fctx->domain)) + continue; + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) + if (rdataset->type == dns_rdatatype_ns) + return (ISC_TRUE); + } + return (ISC_FALSE); +} + static void resquery_response(isc_task_t *task, isc_event_t *event) { isc_result_t result = ISC_R_SUCCESS; @@ -6180,6 +6470,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) { fctx->timeouts = 0; fctx->timeout = ISC_FALSE; + fctx->addrinfo = query->addrinfo; /* * XXXRTH We should really get the current time just once. We @@ -6476,6 +6767,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) { * cannot make any more progress with this * fetch. */ + log_formerr(fctx, "server sent FORMERR"); result = DNS_R_FORMERR; } } else if (message->rcode == dns_rcode_yxdomain) { @@ -6590,27 +6882,62 @@ resquery_response(isc_task_t *task, isc_event_t *event) { (message->rcode == dns_rcode_noerror || message->rcode == dns_rcode_nxdomain)) { /* - * We've got answers. However, if we sent - * a BIND 8 server an NS query, it may have - * incorrectly responded with a non-authoritative - * answer instead of a referral. Since this - * answer lacks the SIGs necessary to do DNSSEC - * validation, we must invoke the following special - * kludge to treat it as a referral. + * [normal case] + * We've got answers. If it has an authoritative answer or an + * answer from a forwarder, we're done. */ - if (fctx->type == dns_rdatatype_ns && - (message->flags & DNS_MESSAGEFLAG_AA) == 0 && - !ISFORWARDER(query->addrinfo)) - { - result = noanswer_response(fctx, NULL, ISC_TRUE); + if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 || + ISFORWARDER(query->addrinfo)) + result = answer_response(fctx); + else if (iscname(fctx) && + fctx->type != dns_rdatatype_any && + fctx->type != dns_rdatatype_cname) { + /* + * A BIND8 server could return a non-authoritative + * answer when a CNAME is followed. We should treat + * it as a valid answer. + */ + result = answer_response(fctx); + } else if (fctx->type != dns_rdatatype_ns && + !betterreferral(fctx)) { + /* + * Lame response !!!. + */ + result = answer_response(fctx); + } else { + if (fctx->type == dns_rdatatype_ns) { + /* + * A BIND 8 server could incorrectly return a + * non-authoritative answer to an NS query + * instead of a referral. Since this answer + * lacks the SIGs necessary to do DNSSEC + * validation, we must invoke the following + * special kludge to treat it as a referral. + */ + result = noanswer_response(fctx, NULL, + LOOK_FOR_NS_IN_ANSWER); + } else { + /* + * Some other servers may still somehow include + * an answer when it should return a referral + * with an empty answer. Check to see if we can + * treat this as a referral by ignoring the + * answer. Further more, there may be an + * implementation that moves A/AAAA glue records + * to the answer section for that type of + * delegation when the query is for that glue + * record. LOOK_FOR_GLUE_IN_ANSWER will handle + * such a corner case. + */ + result = noanswer_response(fctx, NULL, + LOOK_FOR_GLUE_IN_ANSWER); + } if (result != DNS_R_DELEGATION) { /* - * The answer section must have contained - * something other than the NS records - * we asked for. Since AA is not set - * and the server is not a forwarder, - * it is technically lame and it's easier - * to treat it as such than to figure out + * At this point, AA is not set, the response + * is not a referral, and the server is not a + * forwarder. It is technically lame and it's + * easier to treat it as such than to figure out * some more elaborate course of action. */ broken_server = DNS_R_LAME; @@ -6619,7 +6946,6 @@ resquery_response(isc_task_t *task, isc_event_t *event) { } goto force_referral; } - result = answer_response(fctx); if (result != ISC_R_SUCCESS) { if (result == DNS_R_FORMERR) keep_trying = ISC_TRUE; @@ -6631,7 +6957,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) { /* * NXDOMAIN, NXRDATASET, or referral. */ - result = noanswer_response(fctx, NULL, ISC_FALSE); + result = noanswer_response(fctx, NULL, 0); if (result == DNS_R_CHASEDSSERVERS) { } else if (result == DNS_R_DELEGATION) { force_referral: @@ -7043,6 +7369,7 @@ dns_resolver_create(dns_view_t *view, res->spillatmax = 100; res->spillattimer = NULL; res->zero_no_soa_ttl = ISC_FALSE; + res->query_timeout = DEFAULT_QUERY_TIMEOUT; res->ndisps = 0; res->nextdisp = 0; /* meaningless at this point, but init it */ res->nbuckets = ntasks; @@ -7194,6 +7521,7 @@ dns_resolver_create(dns_view_t *view, return (result); } +#ifdef BIND9 static void prime_done(isc_task_t *task, isc_event_t *event) { dns_resolver_t *res; @@ -7299,16 +7627,15 @@ dns_resolver_prime(dns_resolver_t *res) { } } } +#endif /* BIND9 */ void dns_resolver_freeze(dns_resolver_t *res) { - /* * Freeze resolver. */ REQUIRE(VALID_RESOLVER(res)); - REQUIRE(!res->frozen); res->frozen = ISC_TRUE; } @@ -8341,3 +8668,22 @@ dns_resolver_getoptions(dns_resolver_t *resolver) { return (resolver->options); } + +unsigned int +dns_resolver_gettimeout(dns_resolver_t *resolver) { + REQUIRE(VALID_RESOLVER(resolver)); + + return (resolver->query_timeout); +} + +void +dns_resolver_settimeout(dns_resolver_t *resolver, unsigned int seconds) { + REQUIRE(VALID_RESOLVER(resolver)); + + if (seconds == 0) + seconds = DEFAULT_QUERY_TIMEOUT; + if (seconds > MAXIMUM_QUERY_TIMEOUT) + seconds = MAXIMUM_QUERY_TIMEOUT; + + resolver->query_timeout = seconds; +} diff --git a/lib/dns/result.c b/lib/dns/result.c index 2b0457c..4cc194d 100644 --- a/lib/dns/result.c +++ b/lib/dns/result.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2008, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: result.c,v 1.125.48.2 2010-02-25 10:56:41 tbox Exp $ */ +/* $Id: result.c,v 1.132 2011-01-11 23:47:13 tbox Exp $ */ /*! \file */ @@ -105,7 +105,7 @@ static const char *text[DNS_R_NRESULTS] = { "no valid RRSIG", /*%< 59 DNS_R_NOVALIDSIG */ "no valid NSEC", /*%< 60 DNS_R_NOVALIDNSEC */ - "not insecure", /*%< 61 DNS_R_NOTINSECURE */ + "insecurity proof failed", /*%< 61 DNS_R_NOTINSECURE */ "unknown service", /*%< 62 DNS_R_UNKNOWNSERVICE */ "recoverable error occurred", /*%< 63 DNS_R_RECOVERABLE */ "unknown opt attribute record", /*%< 64 DNS_R_UNKNOWNOPT */ @@ -160,6 +160,7 @@ static const char *text[DNS_R_NRESULTS] = { "not master", /*%< 105 DNS_R_NOTMASTER */ "broken trust chain", /*%< 106 DNS_R_BROKENCHAIN */ + "expired", /*%< 106 DNS_R_EXPIRED */ }; static const char *rcode_text[DNS_R_NRCODERESULTS] = { diff --git a/lib/dns/rootns.c b/lib/dns/rootns.c index d51a0d6..40e2244 100644 --- a/lib/dns/rootns.c +++ b/lib/dns/rootns.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rootns.c,v 1.36.50.4 2010-06-18 05:37:50 marka Exp $ */ +/* $Id: rootns.c,v 1.40 2010-06-18 05:36:24 marka Exp $ */ /*! \file */ diff --git a/lib/dns/rpz.c b/lib/dns/rpz.c new file mode 100644 index 0000000..f809e7b --- /dev/null +++ b/lib/dns/rpz.c @@ -0,0 +1,1168 @@ +/* + * Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: rpz.c,v 1.7 2011-01-17 04:27:23 marka Exp $ */ + +/*! \file */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * Parallel radix trees for databases of response policy IP addresses + * + * The radix or Patricia trees are somewhat specialized to handle response + * policy addresses by representing the two test of IP IP addresses and name + * server IP addresses in a single tree. + * + * Each leaf indicates that an IP address is listed in the IP address or the + * name server IP address policy sub-zone (or both) of the corresponding + * response response zone. The policy data such as a CNAME or an A record + * is kept in the policy zone. After an IP address has been found in a radix + * tree, the node in the policy zone's database is found by converting + * the IP address to a domain name in a canonical form. + * + * The response policy zone canonical form of IPv6 addresses is one of: + * prefix.W.W.W.W.W.W.W.W + * prefix.WORDS.zz + * prefix.WORDS.zz.WORDS + * prefix.zz.WORDS + * where + * prefix is the prefix length of the IPv6 address between 1 and 128 + * W is a number between 0 and 65535 + * WORDS is one or more numbers W separated with "." + * zz corresponds to :: in the standard IPv6 text representation + * + * The canonical form of IPv4 addresses is: + * prefix.B.B.B.B + * where + * prefix is the prefix length of the address between 1 and 32 + * B is a number between 0 and 255 + * + * IPv4 addresses are distinguished from IPv6 addresses by having + * 5 labels all of which are numbers, and a prefix between 1 and 32. + */ + + +/* + * Use a private definition of IPv6 addresses because s6_addr32 is not + * always defined and our IPv6 addresses are in non-standard byte order + */ +typedef isc_uint32_t dns_rpz_cidr_word_t; +#define DNS_RPZ_CIDR_WORD_BITS ((int)sizeof(dns_rpz_cidr_word_t)*8) +#define DNS_RPZ_CIDR_KEY_BITS ((int)sizeof(dns_rpz_cidr_key_t)*8) +#define DNS_RPZ_CIDR_WORDS (128/DNS_RPZ_CIDR_WORD_BITS) +typedef struct { + dns_rpz_cidr_word_t w[DNS_RPZ_CIDR_WORDS]; +} dns_rpz_cidr_key_t; + +#define ADDR_V4MAPPED 0xffff + +#define DNS_RPZ_WORD_MASK(b) \ + ((b) == 0 ? (dns_rpz_cidr_word_t)(-1) \ + : ((dns_rpz_cidr_word_t)(-1) \ + << (DNS_RPZ_CIDR_WORD_BITS - (b)))) + +#define DNS_RPZ_IP_BIT(ip, bitno) \ + (1 & ((ip)->w[(bitno)/DNS_RPZ_CIDR_WORD_BITS] >> \ + (DNS_RPZ_CIDR_WORD_BITS - 1 - ((bitno) % DNS_RPZ_CIDR_WORD_BITS)))) + +typedef struct dns_rpz_cidr_node dns_rpz_cidr_node_t; +typedef isc_uint8_t dns_rpz_cidr_flags_t; +struct dns_rpz_cidr_node { + dns_rpz_cidr_node_t *parent; + dns_rpz_cidr_node_t *child[2]; + dns_rpz_cidr_key_t ip; + dns_rpz_cidr_bits_t bits; + dns_rpz_cidr_flags_t flags; +#define DNS_RPZ_CIDR_FG_IP 0x01 /* has IP data or is parent of IP */ +#define DNS_RPZ_CIDR_FG_IP_DATA 0x02 /* has IP data */ +#define DNS_RPZ_CIDR_FG_NSIPv4 0x04 /* has or is parent of NSIPv4 data */ +#define DNS_RPZ_CIDR_FG_NSIPv6 0x08 /* has or is parent of NSIPv6 data */ +#define DNS_RPZ_CIDR_FG_NSIP_DATA 0x10 /* has NSIP data */ +}; + +struct dns_rpz_cidr { + isc_mem_t *mctx; + isc_boolean_t had_nsdname; + dns_rpz_cidr_node_t *root; + dns_name_t ip_name; /* RPZ_IP_ZONE.LOCALHOST. */ + dns_name_t nsip_name; /* RPZ_NSIP_ZONE.LOCALHOST. */ + dns_name_t nsdname_name; /* RPZ_NSDNAME_ZONE.LOCALHOST */ +}; + + +static isc_boolean_t have_rpz_zones = ISC_FALSE; + + +const char * +dns_rpz_type2str(dns_rpz_type_t type) +{ + switch (type) { + case DNS_RPZ_TYPE_QNAME: + return ("QNAME"); + case DNS_RPZ_TYPE_IP: + return ("IP"); + case DNS_RPZ_TYPE_NSIP: + return ("NSIP"); + case DNS_RPZ_TYPE_NSDNAME: + return ("NSDNAME"); + case DNS_RPZ_TYPE_BAD: + break; + } + FATAL_ERROR(__FILE__, __LINE__, + "impossible response policy zone type %d", type); + return ("impossible"); +} + + + +dns_rpz_policy_t +dns_rpz_str2policy(const char *str) +{ + if (str == NULL) + return (DNS_RPZ_POLICY_ERROR); + if (!strcasecmp(str, "given")) + return (DNS_RPZ_POLICY_GIVEN); + if (!strcasecmp(str, "no-op")) + return (DNS_RPZ_POLICY_NO_OP); + if (!strcasecmp(str, "nxdomain")) + return (DNS_RPZ_POLICY_NXDOMAIN); + if (!strcasecmp(str, "nodata")) + return (DNS_RPZ_POLICY_NODATA); + if (!strcasecmp(str, "cname")) + return (DNS_RPZ_POLICY_CNAME); + return (DNS_RPZ_POLICY_ERROR); +} + + + +/* + * Free the radix tree of a response policy database. + */ +void +dns_rpz_cidr_free(dns_rpz_cidr_t **cidrp) { + dns_rpz_cidr_node_t *cur, *child, *parent; + dns_rpz_cidr_t *cidr; + + REQUIRE(cidrp != NULL); + + cidr = *cidrp; + if (cidr == NULL) + return; + + cur = cidr->root; + while (cur != NULL) { + /* Depth first. */ + child = cur->child[0]; + if (child != NULL) { + cur = child; + continue; + } + child = cur->child[1]; + if (child != NULL) { + cur = child; + continue; + } + + /* Delete this leaf and go up. */ + parent = cur->parent; + if (parent == NULL) + cidr->root = NULL; + else + parent->child[parent->child[1] == cur] = NULL; + isc_mem_put(cidr->mctx, cur, sizeof(*cur)); + cur = parent; + } + + dns_name_free(&cidr->ip_name, cidr->mctx); + dns_name_free(&cidr->nsip_name, cidr->mctx); + dns_name_free(&cidr->nsdname_name, cidr->mctx); + isc_mem_put(cidr->mctx, cidr, sizeof(*cidr)); + *cidrp = NULL; +} + + + +/* + * Forget a view's list of policy zones. + */ +void +dns_rpz_view_destroy(dns_view_t *view) { + dns_rpz_zone_t *zone; + + REQUIRE(view != NULL); + + while (!ISC_LIST_EMPTY(view->rpz_zones)) { + zone = ISC_LIST_HEAD(view->rpz_zones); + ISC_LIST_UNLINK(view->rpz_zones, zone, link); + if (dns_name_dynamic(&zone->origin)) + dns_name_free(&zone->origin, view->mctx); + if (dns_name_dynamic(&zone->nsdname)) + dns_name_free(&zone->nsdname, view->mctx); + if (dns_name_dynamic(&zone->cname)) + dns_name_free(&zone->cname, view->mctx); + isc_mem_put(view->mctx, zone, sizeof(*zone)); + } +} + +/* + * Note that we have at least one response policy zone. + * It would be better for something to tell the rbtdb code that the + * zone is in at least one view's list of policy zones. + */ +void +dns_rpz_set_need(isc_boolean_t need) +{ + have_rpz_zones = need; +} + + +isc_boolean_t +dns_rpz_needed(void) +{ + return (have_rpz_zones); +} + + + +/* + * Start a new radix tree for a response policy zone. + */ +isc_result_t +dns_rpz_new_cidr(isc_mem_t *mctx, dns_name_t *origin, + dns_rpz_cidr_t **rbtdb_cidr) +{ + isc_result_t result; + dns_rpz_cidr_t *cidr; + + REQUIRE(rbtdb_cidr != NULL && *rbtdb_cidr == NULL); + + /* + * Only if there is at least one response policy zone. + */ + if (!have_rpz_zones) + return (ISC_R_SUCCESS); + + cidr = isc_mem_get(mctx, sizeof(*cidr)); + if (cidr == NULL) + return (ISC_R_NOMEMORY); + memset(cidr, 0, sizeof(*cidr)); + cidr->mctx = mctx; + + dns_name_init(&cidr->ip_name, NULL); + result = dns_name_fromstring2(&cidr->ip_name, DNS_RPZ_IP_ZONE, origin, + DNS_NAME_DOWNCASE, mctx); + if (result != ISC_R_SUCCESS) { + isc_mem_put(mctx, cidr, sizeof(*cidr)); + return (result); + } + + dns_name_init(&cidr->nsip_name, NULL); + result = dns_name_fromstring2(&cidr->nsip_name, DNS_RPZ_NSIP_ZONE, + origin, DNS_NAME_DOWNCASE, mctx); + if (result != ISC_R_SUCCESS) { + dns_name_free(&cidr->ip_name, mctx); + isc_mem_put(mctx, cidr, sizeof(*cidr)); + return (result); + } + + dns_name_init(&cidr->nsdname_name, NULL); + result = dns_name_fromstring2(&cidr->nsdname_name, DNS_RPZ_NSDNAME_ZONE, + origin, DNS_NAME_DOWNCASE, mctx); + if (result != ISC_R_SUCCESS) { + dns_name_free(&cidr->nsip_name, mctx); + dns_name_free(&cidr->ip_name, mctx); + isc_mem_put(mctx, cidr, sizeof(*cidr)); + return (result); + } + + *rbtdb_cidr = cidr; + return (ISC_R_SUCCESS); +} + + +/* + * See if a policy zone has IP, NSIP, or NSDNAME rules or records. + */ +void +dns_rpz_enabled(dns_rpz_cidr_t *cidr, dns_rpz_st_t *st) { + if (cidr->root != NULL && + (cidr->root->flags & DNS_RPZ_CIDR_FG_IP) != 0) + st->state |= DNS_RPZ_HAVE_IP; + if (cidr->root != NULL && + (cidr->root->flags & DNS_RPZ_CIDR_FG_NSIPv4) != 0) + st->state |= DNS_RPZ_HAVE_NSIPv4; + if (cidr->root != NULL && + (cidr->root->flags & DNS_RPZ_CIDR_FG_NSIPv6) != 0) + st->state |= DNS_RPZ_HAVE_NSIPv6; + if (cidr->had_nsdname) + st->state |= DNS_RPZ_HAD_NSDNAME; +} + +static inline dns_rpz_cidr_flags_t +get_flags(const dns_rpz_cidr_key_t *ip, dns_rpz_cidr_bits_t prefix, + dns_rpz_type_t rpz_type) +{ + if (rpz_type == DNS_RPZ_TYPE_NSIP) { + if (prefix >= 96 && + ip->w[0] == 0 && ip->w[1] == 0 && + ip->w[2] == ADDR_V4MAPPED) + return (DNS_RPZ_CIDR_FG_NSIP_DATA | + DNS_RPZ_CIDR_FG_NSIPv4); + else + return (DNS_RPZ_CIDR_FG_NSIP_DATA | + DNS_RPZ_CIDR_FG_NSIPv6); + } else { + return (DNS_RPZ_CIDR_FG_IP | DNS_RPZ_CIDR_FG_IP_DATA); + } +} + + + +/* + * Mark a node as having IP or NSIP data and all of its parents + * as members of the IP or NSIP tree. + */ +static void +set_node_flags(dns_rpz_cidr_node_t *node, dns_rpz_type_t rpz_type) { + dns_rpz_cidr_flags_t flags; + + flags = get_flags(&node->ip, node->bits, rpz_type); + node->flags |= flags; + flags &= ~(DNS_RPZ_CIDR_FG_NSIP_DATA | DNS_RPZ_CIDR_FG_IP_DATA); + for (;;) { + node = node->parent; + if (node == NULL) + return; + node->flags |= flags; + } +} + + + +/* + * Make a radix tree node. + */ +static dns_rpz_cidr_node_t * +new_node(dns_rpz_cidr_t *cidr, const dns_rpz_cidr_key_t *ip, + dns_rpz_cidr_bits_t bits, dns_rpz_cidr_flags_t flags) +{ + dns_rpz_cidr_node_t *node; + int i, words, wlen; + + node = isc_mem_get(cidr->mctx, sizeof(*node)); + if (node == NULL) + return (NULL); + memset(node, 0, sizeof(*node)); + + node->flags = flags & ~(DNS_RPZ_CIDR_FG_IP_DATA | + DNS_RPZ_CIDR_FG_NSIP_DATA); + + node->bits = bits; + words = bits / DNS_RPZ_CIDR_WORD_BITS; + wlen = bits % DNS_RPZ_CIDR_WORD_BITS; + i = 0; + while (i < words) { + node->ip.w[i] = ip->w[i]; + ++i; + } + if (wlen != 0) { + node->ip.w[i] = ip->w[i] & DNS_RPZ_WORD_MASK(wlen); + ++i; + } + while (i < DNS_RPZ_CIDR_WORDS) + node->ip.w[i++] = 0; + + return (node); +} + + + +static void +badname(int level, dns_name_t *name, const char *comment) +{ + char printname[DNS_NAME_FORMATSIZE]; + + if (isc_log_wouldlog(dns_lctx, level)) { + dns_name_format(name, printname, sizeof(printname)); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_RBTDB, level, + "invalid response policy name \"%s\"%s", + printname, comment); + } +} + + + +/* + * Convert an IP address from radix tree binary (host byte order) to + * to its canonical response policy domain name and its name in the + * policy zone. + */ +static isc_result_t +ip2name(dns_rpz_cidr_t *cidr, const dns_rpz_cidr_key_t *tgt_ip, + dns_rpz_cidr_bits_t tgt_prefix, dns_rpz_type_t type, + dns_name_t *canon_name, dns_name_t *search_name) +{ +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 46 +#endif + int w[DNS_RPZ_CIDR_WORDS*2]; + char str[1+8+1+INET6_ADDRSTRLEN+1]; + isc_buffer_t buffer; + dns_name_t *name; + isc_result_t result; + isc_boolean_t zeros; + int i, n, len; + + if (tgt_prefix > 96 && + tgt_ip->w[0] == 0 && + tgt_ip->w[1] == 0 && + tgt_ip->w[2] == ADDR_V4MAPPED) { + len = snprintf(str, sizeof(str), "%d.%d.%d.%d.%d", + tgt_prefix - 96, + tgt_ip->w[3] & 0xff, + (tgt_ip->w[3]>>8) & 0xff, + (tgt_ip->w[3]>>16) & 0xff, + (tgt_ip->w[3]>>24) & 0xff); + if (len == -1 || len > (int)sizeof(str)) + return (ISC_R_FAILURE); + } else { + for (i = 0; i < DNS_RPZ_CIDR_WORDS; i++) { + w[i*2+1] = ((tgt_ip->w[DNS_RPZ_CIDR_WORDS-1-i] >> 16) + & 0xffff); + w[i*2] = tgt_ip->w[DNS_RPZ_CIDR_WORDS-1-i] & 0xffff; + } + zeros = ISC_FALSE; + len = snprintf(str, sizeof(str), "%d", tgt_prefix); + if (len == -1) + return (ISC_R_FAILURE); + i = 0; + while (i < DNS_RPZ_CIDR_WORDS * 2) { + if (w[i] != 0 || zeros + || i >= DNS_RPZ_CIDR_WORDS * 2 - 1 + || w[i+1] != 0) { + INSIST((size_t)len <= sizeof(str)); + n = snprintf(&str[len], sizeof(str) - len, + ".%x", w[i++]); + if (n < 0) + return (ISC_R_FAILURE); + len += n; + } else { + zeros = ISC_TRUE; + INSIST((size_t)len <= sizeof(str)); + n = snprintf(&str[len], sizeof(str) - len, + ".zz"); + if (n < 0) + return (ISC_R_FAILURE); + len += n; + i += 2; + while (i < DNS_RPZ_CIDR_WORDS * 2 && w[i] == 0) + ++i; + } + if (len > (int)sizeof(str)) + return (ISC_R_FAILURE); + } + } + + if (canon_name != NULL) { + isc__buffer_init(&buffer, str, sizeof(str)); + isc__buffer_add(&buffer, len); + result = dns_name_fromtext(canon_name, &buffer, + dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) + return (result); + } + if (search_name != NULL) { + isc__buffer_init(&buffer, str, sizeof(str)); + isc__buffer_add(&buffer, len); + if (type == DNS_RPZ_TYPE_NSIP) + name = &cidr->nsip_name; + else + name = &cidr->ip_name; + result = dns_name_fromtext(search_name, &buffer, name, 0, NULL); + if (result != ISC_R_SUCCESS) + return (result); + } + return (ISC_R_SUCCESS); +} + + + +/* + * Decide which kind of IP address response policy zone a name is in. + */ +static dns_rpz_type_t +set_type(dns_rpz_cidr_t *cidr, dns_name_t *name) { + + if (dns_name_issubdomain(name, &cidr->ip_name)) + return (DNS_RPZ_TYPE_IP); + + /* + * Require `./configure --enable-rpz-nsip` and nsdname + * until consistency problems are resolved. + */ +#ifdef ENABLE_RPZ_NSIP + if (dns_name_issubdomain(name, &cidr->nsip_name)) + return (DNS_RPZ_TYPE_NSIP); +#endif + +#ifdef ENABLE_RPZ_NSDNAME + if (dns_name_issubdomain(name, &cidr->nsdname_name)) + return (DNS_RPZ_TYPE_NSDNAME); +#endif + + return (DNS_RPZ_TYPE_QNAME); +} + + + +/* + * Convert an IP address from canonical response policy domain name form + * to radix tree binary (host byte order). + */ +static isc_result_t +name2ipkey(dns_rpz_cidr_t *cidr, int level, dns_name_t *src_name, + dns_rpz_type_t type, dns_rpz_cidr_key_t *tgt_ip, + dns_rpz_cidr_bits_t *tgt_prefix) +{ + isc_buffer_t buffer; + unsigned char data[DNS_NAME_MAXWIRE+1]; + dns_fixedname_t fname; + dns_name_t *name; + const char *cp, *end; + char *cp2; + int ip_labels; + dns_rpz_cidr_bits_t bits; + unsigned long prefix, l; + int i; + + /* + * Need at least enough labels for the shortest name, + * :: or 128.*.RPZ_x_ZONE.rpz.LOCALHOST. + */ + ip_labels = dns_name_countlabels(src_name); + ip_labels -= dns_name_countlabels(&cidr->ip_name); + ip_labels--; + if (ip_labels < 1) { + badname(level, src_name, ", too short"); + return (ISC_R_FAILURE); + } + + /* + * Get text for the IP address without RPZ_x_ZONE.rpz.LOCALHOST. + */ + dns_fixedname_init(&fname); + name = dns_fixedname_name(&fname); + dns_name_split(src_name, dns_name_countlabels(&cidr->ip_name), + name, NULL); + isc_buffer_init(&buffer, data, sizeof(data)); + dns_name_totext(name, ISC_TRUE, &buffer); + isc_buffer_putuint8(&buffer, '\0'); + cp = isc_buffer_base(&buffer); + + prefix = strtoul(cp, &cp2, 10); + if (prefix < 1U || prefix > 128U || *cp2 != '.') { + badname(level, src_name, ", bad prefix length"); + return (ISC_R_FAILURE); + } + cp = cp2+1; + + end = isc_buffer_used(&buffer); + if (ip_labels == 4 && !strchr(cp, 'z')) { + /* + * Convert an IPv4 address + * from the form "prefix.w.z.y.x" + */ + if (prefix > 32U) { + badname(level, src_name, "; bad IPv4 prefix length"); + return (ISC_R_FAILURE); + } + prefix += 96; + *tgt_prefix = (dns_rpz_cidr_bits_t)prefix; + tgt_ip->w[0] = 0; + tgt_ip->w[1] = 0; + tgt_ip->w[2] = ADDR_V4MAPPED; + tgt_ip->w[3] = 0; + for (i = 0; i < 32; i += 8) { + l = strtoul(cp, &cp2, 10); + if (l > 255U || (*cp2 != '.' && *cp2 != '\0')) { + badname(level, src_name, "; bad IPv4 address"); + return (ISC_R_FAILURE); + } + tgt_ip->w[3] |= l << i; + cp = cp2 + 1; + } + } else { + /* + * Convert a text IPv6 address. + */ + *tgt_prefix = (dns_rpz_cidr_bits_t)prefix; + for (i = 0; + ip_labels > 0 && i < DNS_RPZ_CIDR_WORDS * 2; + ip_labels--) { + if (cp[0] == 'z' && cp[1] == 'z' && + (cp[2] == '.' || cp[2] == '\0') && + i <= 6) { + do { + if ((i & 1) == 0) + tgt_ip->w[3-i/2] = 0; + ++i; + } while (ip_labels + i <= 8); + cp += 3; + } else { + l = strtoul(cp, &cp2, 16); + if (l > 0xffffu || + (*cp2 != '.' && *cp2 != '\0')) { + badname(level, src_name, ""); + return (ISC_R_FAILURE); + } + if ((i & 1) == 0) + tgt_ip->w[3-i/2] = l; + else + tgt_ip->w[3-i/2] |= l << 16; + i++; + cp = cp2 + 1; + } + } + } + if (cp != end) { + badname(level, src_name, ""); + return (ISC_R_FAILURE); + } + + /* + * Check for 1s after the prefix length. + */ + bits = (dns_rpz_cidr_bits_t)prefix; + while (bits < DNS_RPZ_CIDR_KEY_BITS) { + dns_rpz_cidr_word_t aword; + + i = bits % DNS_RPZ_CIDR_WORD_BITS; + aword = tgt_ip->w[bits / DNS_RPZ_CIDR_WORD_BITS]; + if ((aword & ~DNS_RPZ_WORD_MASK(i)) != 0) { + badname(level, src_name, "; wrong prefix length"); + return (ISC_R_FAILURE); + } + bits -= i; + bits += DNS_RPZ_CIDR_WORD_BITS; + } + + /* + * Convert the IPv6 address back to a canonical policy domain name + * to ensure that it is in canonical form. + */ + if (ISC_R_SUCCESS != ip2name(cidr, tgt_ip, (dns_rpz_cidr_bits_t)prefix, + type, NULL, name) || + !dns_name_equal(src_name, name)) { + badname(level, src_name, "; not canonical"); + return (ISC_R_FAILURE); + } + + return (ISC_R_SUCCESS); +} + + + +/* + * find first differing bit + */ +static int +ffbit(dns_rpz_cidr_word_t w) { + int bit; + + if (w == 0) + return (DNS_RPZ_CIDR_WORD_BITS); + for (bit = 0; (w & (1U << (DNS_RPZ_CIDR_WORD_BITS-1))) == 0; bit++) + w <<= 1; + return (bit); +} + + + +/* + * find the first differing bit in two keys + */ +static int +diff_keys(const dns_rpz_cidr_key_t *key1, dns_rpz_cidr_bits_t bits1, + const dns_rpz_cidr_key_t *key2, dns_rpz_cidr_bits_t bits2) +{ + dns_rpz_cidr_word_t delta; + dns_rpz_cidr_bits_t maxbit, bit; + int i; + + maxbit = ISC_MIN(bits1, bits2); + + /* + * find the first differing words + */ + for (i = 0, bit = 0; + bit <= maxbit; + i++, bit += DNS_RPZ_CIDR_WORD_BITS) { + delta = key1->w[i] ^ key2->w[i]; + if (delta != 0) { + bit += ffbit(delta); + break; + } + } + return (ISC_MIN(bit, maxbit)); +} + + + +/* + * Search a radix tree for an IP address for ordinary lookup + * or for a CIDR block adding or deleting an entry + * The tree read (for simple search) or write lock must be held by the caller. + * + * return ISC_R_SUCCESS, ISC_R_NOTFOUND, DNS_R_PARTIALMATCH, ISC_R_EXISTS, + * ISC_R_NOMEMORY + */ +static isc_result_t +search(dns_rpz_cidr_t *cidr, const dns_rpz_cidr_key_t *tgt_ip, + dns_rpz_cidr_bits_t tgt_prefix, dns_rpz_type_t type, + isc_boolean_t create, + dns_rpz_cidr_node_t **found) /* NULL or longest match node */ +{ + dns_rpz_cidr_node_t *cur, *parent, *child, *new_parent, *sibling; + int cur_num, child_num; + dns_rpz_cidr_bits_t dbit; + dns_rpz_cidr_flags_t flags, data_flag; + isc_result_t find_result; + + flags = get_flags(tgt_ip, tgt_prefix, type); + data_flag = flags & (DNS_RPZ_CIDR_FG_IP_DATA | + DNS_RPZ_CIDR_FG_NSIP_DATA); + + find_result = ISC_R_NOTFOUND; + if (found != NULL) + *found = NULL; + cur = cidr->root; + parent = NULL; + cur_num = 0; + for (;;) { + if (cur == NULL) { + /* + * No child so we cannot go down. Fail or + * add the target as a child of the current parent. + */ + if (!create) + return (find_result); + child = new_node(cidr, tgt_ip, tgt_prefix, 0); + if (child == NULL) + return (ISC_R_NOMEMORY); + if (parent == NULL) + cidr->root = child; + else + parent->child[cur_num] = child; + child->parent = parent; + set_node_flags(child, type); + if (found != NULL) + *found = cur; + return (ISC_R_SUCCESS); + } + + /* + * Pretend a node not in the correct tree does not exist + * if we are not adding to the tree, + * If we are adding, then continue down to eventually + * add a node and mark/put this node in the correct tree. + */ + if ((cur->flags & flags) == 0 && !create) + return (find_result); + + dbit = diff_keys(tgt_ip, tgt_prefix, &cur->ip, cur->bits); + /* + * dbit <= tgt_prefix and dbit <= cur->bits always. + * We are finished searching if we matched all of the target. + */ + if (dbit == tgt_prefix) { + if (tgt_prefix == cur->bits) { + /* + * The current node matches the target exactly. + * It is the answer if it has data. + */ + if ((cur->flags & data_flag) != 0) { + if (create) + return (ISC_R_EXISTS); + if (found != NULL) + *found = cur; + return (ISC_R_SUCCESS); + } else if (create) { + /* + * The node had no data but does now. + */ + set_node_flags(cur, type); + if (found != NULL) + *found = cur; + return (ISC_R_SUCCESS); + } + return (find_result); + } + + /* + * We know tgt_prefix < cur_bits which means that + * the target is shorter than the current node. + * Add the target as the current node's parent. + */ + if (!create) + return (find_result); + + new_parent = new_node(cidr, tgt_ip, tgt_prefix, + cur->flags); + if (new_parent == NULL) + return (ISC_R_NOMEMORY); + new_parent->parent = parent; + if (parent == NULL) + cidr->root = new_parent; + else + parent->child[cur_num] = new_parent; + child_num = DNS_RPZ_IP_BIT(&cur->ip, tgt_prefix+1); + new_parent->child[child_num] = cur; + cur->parent = new_parent; + set_node_flags(new_parent, type); + if (found != NULL) + *found = new_parent; + return (ISC_R_SUCCESS); + } + + if (dbit == cur->bits) { + /* + * We have a partial match by matching of all of the + * current node but only part of the target. + * Try to go down. + */ + if ((cur->flags & data_flag) != 0) { + find_result = DNS_R_PARTIALMATCH; + if (found != NULL) + *found = cur; + } + + parent = cur; + cur_num = DNS_RPZ_IP_BIT(tgt_ip, dbit); + cur = cur->child[cur_num]; + continue; + } + + + /* + * dbit < tgt_prefix and dbit < cur->bits, + * so we failed to match both the target and the current node. + * Insert a fork of a parent above the current node and + * add the target as a sibling of the current node + */ + if (!create) + return (find_result); + + sibling = new_node(cidr, tgt_ip, tgt_prefix, 0); + if (sibling == NULL) + return (ISC_R_NOMEMORY); + new_parent = new_node(cidr, tgt_ip, dbit, cur->flags); + if (new_parent == NULL) { + isc_mem_put(cidr->mctx, sibling, sizeof(*sibling)); + return (ISC_R_NOMEMORY); + } + new_parent->parent = parent; + if (parent == NULL) + cidr->root = new_parent; + else + parent->child[cur_num] = new_parent; + child_num = DNS_RPZ_IP_BIT(tgt_ip, dbit); + new_parent->child[child_num] = sibling; + new_parent->child[1-child_num] = cur; + cur->parent = new_parent; + sibling->parent = new_parent; + set_node_flags(sibling, type); + if (found != NULL) + *found = sibling; + return (ISC_R_SUCCESS); + } +} + + + +/* + * Add an IP address to the radix tree of a response policy database. + * The tree write lock must be held by the caller. + */ +void +dns_rpz_cidr_addip(dns_rpz_cidr_t *cidr, dns_name_t *name) +{ + dns_rpz_cidr_key_t tgt_ip; + dns_rpz_cidr_bits_t tgt_prefix; + dns_rpz_type_t type; + + if (cidr == NULL) + return; + + /* + * no worries if the new name is not an IP address + */ + type = set_type(cidr, name); + switch (type) { + case DNS_RPZ_TYPE_IP: + case DNS_RPZ_TYPE_NSIP: + break; + case DNS_RPZ_TYPE_NSDNAME: + cidr->had_nsdname = ISC_TRUE; + return; + case DNS_RPZ_TYPE_QNAME: + case DNS_RPZ_TYPE_BAD: + return; + } + if (ISC_R_SUCCESS != name2ipkey(cidr, DNS_RPZ_ERROR_LEVEL, name, + type, &tgt_ip, &tgt_prefix)) + return; + + if (ISC_R_EXISTS == search(cidr, &tgt_ip, tgt_prefix, type, + ISC_TRUE, NULL) && + isc_log_wouldlog(dns_lctx, DNS_RPZ_ERROR_LEVEL)) { + char printname[DNS_NAME_FORMATSIZE]; + + dns_name_format(name, printname, sizeof(printname)); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL, + "duplicate response policy name \"%s\"", + printname); + } +} + + + +/* + * Delete an IP address from the radix tree of a response policy database. + * The tree write lock must be held by the caller. + */ +void +dns_rpz_cidr_deleteip(dns_rpz_cidr_t *cidr, dns_name_t *name) { + dns_rpz_cidr_key_t tgt_ip; + dns_rpz_cidr_bits_t tgt_prefix; + dns_rpz_type_t type; + dns_rpz_cidr_node_t *tgt = NULL, *parent, *child; + dns_rpz_cidr_flags_t flags, data_flag; + + if (cidr == NULL) + return; + + /* + * Decide which kind of policy zone IP address it is, if either + * and then find its node. + */ + type = set_type(cidr, name); + switch (type) { + case DNS_RPZ_TYPE_IP: + case DNS_RPZ_TYPE_NSIP: + break; + case DNS_RPZ_TYPE_NSDNAME: + /* + * We cannot easily count nsdnames because + * internal rbt nodes get deleted. + */ + return; + case DNS_RPZ_TYPE_QNAME: + case DNS_RPZ_TYPE_BAD: + return; + } + + /* + * Do not get excited about the deletion of interior rbt nodes. + */ + if (ISC_R_SUCCESS != name2ipkey(cidr, DNS_RPZ_DEBUG_LEVEL2, name, + type, &tgt_ip, &tgt_prefix)) + return; + if (ISC_R_SUCCESS != search(cidr, &tgt_ip, tgt_prefix, type, + ISC_FALSE, &tgt)) { + if (isc_log_wouldlog(dns_lctx, DNS_RPZ_ERROR_LEVEL)) { + char printname[DNS_NAME_FORMATSIZE]; + + dns_name_format(name, printname, sizeof(printname)); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL, + "missing response policy node \"%s\"", + printname); + } + return; + } + + /* + * Mark the node and its parents to reflect the deleted IP address. + */ + flags = get_flags(&tgt_ip, tgt_prefix, type); + data_flag = flags & (DNS_RPZ_CIDR_FG_IP_DATA | + DNS_RPZ_CIDR_FG_NSIP_DATA); + tgt->flags &= ~data_flag; + for (parent = tgt; parent != NULL; parent = parent->parent) { + if ((parent->flags & data_flag) != 0 || + (parent->child[0] != NULL && + (parent->child[0]->flags & flags) != 0) || + (parent->child[1] != NULL && + (parent->child[1]->flags & flags) != 0)) + break; + parent->flags &= ~flags; + } + + /* + * We might need to delete 2 nodes. + */ + do { + /* + * The node is now useless if it has no data of its own + * and 0 or 1 children. We are finished if it is not useless. + */ + if ((child = tgt->child[0]) != NULL) { + if (tgt->child[1] != NULL) + return; + } else { + child = tgt->child[1]; + } + if ((tgt->flags & (DNS_RPZ_CIDR_FG_IP_DATA | + DNS_RPZ_CIDR_FG_NSIP_DATA)) != 0) + return; + + /* + * Replace the pointer to this node in the parent with + * the remaining child or NULL. + */ + parent = tgt->parent; + if (parent == NULL) { + cidr->root = child; + } else { + parent->child[parent->child[1] == tgt] = child; + } + /* + * If the child exists fix up its parent pointer. + */ + if (child != NULL) + child->parent = parent; + isc_mem_put(cidr->mctx, tgt, sizeof(*tgt)); + + tgt = parent; + } while (tgt != NULL); +} + + + +/* + * Caller must hold tree lock. + * Return ISC_R_NOTFOUND + * or ISC_R_SUCCESS and the found entry's canonical and search names + * and its prefix length + */ +isc_result_t +dns_rpz_cidr_find(dns_rpz_cidr_t *cidr, const isc_netaddr_t *netaddr, + dns_rpz_type_t type, dns_name_t *canon_name, + dns_name_t *search_name, dns_rpz_cidr_bits_t *prefix) +{ + dns_rpz_cidr_key_t tgt_ip; + isc_result_t result; + dns_rpz_cidr_node_t *found; + int i; + + /* + * Convert IP address to CIDR tree key. + */ + if (netaddr->family == AF_INET) { + tgt_ip.w[0] = 0; + tgt_ip.w[1] = 0; + tgt_ip.w[2] = ADDR_V4MAPPED; + tgt_ip.w[3] = ntohl(netaddr->type.in.s_addr); + } else if (netaddr->family == AF_INET6) { + dns_rpz_cidr_key_t src_ip6; + + /* + * Given the int aligned struct in_addr member of netaddr->type + * one could cast netaddr->type.in6 to dns_rpz_cidr_key_t *, + * but there are objections. + */ + memcpy(src_ip6.w, &netaddr->type.in6, sizeof(src_ip6.w)); + for (i = 0; i < 4; i++) { + tgt_ip.w[i] = ntohl(src_ip6.w[i]); + } + } else { + return (ISC_R_NOTFOUND); + } + + result = search(cidr, &tgt_ip, 128, type, ISC_FALSE, &found); + if (result != ISC_R_SUCCESS && result != DNS_R_PARTIALMATCH) + return (result); + + *prefix = found->bits; + return (ip2name(cidr, &found->ip, found->bits, type, + canon_name, search_name)); +} + + + +/* + * Translate CNAME rdata to a QNAME response policy action. + */ +dns_rpz_policy_t +dns_rpz_decode_cname(dns_rdataset_t *rdataset, dns_name_t *selfname) { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_cname_t cname; + isc_result_t result; + + result = dns_rdataset_first(rdataset); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + dns_rdataset_current(rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &cname, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + dns_rdata_reset(&rdata); + + /* + * CNAME . means NXDOMAIN + */ + if (dns_name_equal(&cname.cname, dns_rootname)) + return (DNS_RPZ_POLICY_NXDOMAIN); + + /* + * CNAME *. means NODATA + */ + if (dns_name_countlabels(&cname.cname) == 2 + && dns_name_iswildcard(&cname.cname)) + return (DNS_RPZ_POLICY_NODATA); + + /* + * 128.1.0.127.rpz-ip CNAME 128.1.0.0.127. means "do not rewrite" + */ + if (selfname != NULL && dns_name_equal(&cname.cname, selfname)) + return (DNS_RPZ_POLICY_NO_OP); + + /* + * evil.com CNAME garden.net rewrites www.evil.com to www.garden.net. + */ + return (DNS_RPZ_POLICY_RECORD); +} diff --git a/lib/dns/rriterator.c b/lib/dns/rriterator.c new file mode 100644 index 0000000..31d67af --- /dev/null +++ b/lib/dns/rriterator.c @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: rriterator.c,v 1.2 2009-06-30 02:52:32 each Exp $ */ + +/*! \file */ + +/*** + *** Imports + ***/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/*** + *** RRiterator methods + ***/ + +isc_result_t +dns_rriterator_init(dns_rriterator_t *it, dns_db_t *db, dns_dbversion_t *ver, + isc_stdtime_t now) +{ + isc_result_t result; + it->magic = RRITERATOR_MAGIC; + it->db = db; + it->dbit = NULL; + it->ver = ver; + it->now = now; + it->node = NULL; + result = dns_db_createiterator(it->db, 0, &it->dbit); + if (result != ISC_R_SUCCESS) + return (result); + it->rdatasetit = NULL; + dns_rdata_init(&it->rdata); + dns_rdataset_init(&it->rdataset); + dns_fixedname_init(&it->fixedname); + INSIST(! dns_rdataset_isassociated(&it->rdataset)); + it->result = ISC_R_SUCCESS; + return (it->result); +} + +isc_result_t +dns_rriterator_first(dns_rriterator_t *it) { + REQUIRE(VALID_RRITERATOR(it)); + /* Reset state */ + if (dns_rdataset_isassociated(&it->rdataset)) + dns_rdataset_disassociate(&it->rdataset); + if (it->rdatasetit != NULL) + dns_rdatasetiter_destroy(&it->rdatasetit); + if (it->node != NULL) + dns_db_detachnode(it->db, &it->node); + it->result = dns_dbiterator_first(it->dbit); + + /* + * The top node may be empty when out of zone glue exists. + * Walk the tree to find the first node with data. + */ + while (it->result == ISC_R_SUCCESS) { + it->result = dns_dbiterator_current(it->dbit, &it->node, + dns_fixedname_name(&it->fixedname)); + if (it->result != ISC_R_SUCCESS) + return (it->result); + + it->result = dns_db_allrdatasets(it->db, it->node, it->ver, + it->now, &it->rdatasetit); + if (it->result != ISC_R_SUCCESS) + return (it->result); + + it->result = dns_rdatasetiter_first(it->rdatasetit); + if (it->result != ISC_R_SUCCESS) { + /* + * This node is empty. Try next node. + */ + dns_rdatasetiter_destroy(&it->rdatasetit); + dns_db_detachnode(it->db, &it->node); + it->result = dns_dbiterator_next(it->dbit); + continue; + } + dns_rdatasetiter_current(it->rdatasetit, &it->rdataset); + it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER; + it->result = dns_rdataset_first(&it->rdataset); + return (it->result); + } + return (it->result); +} + +isc_result_t +dns_rriterator_nextrrset(dns_rriterator_t *it) { + REQUIRE(VALID_RRITERATOR(it)); + if (dns_rdataset_isassociated(&it->rdataset)) + dns_rdataset_disassociate(&it->rdataset); + it->result = dns_rdatasetiter_next(it->rdatasetit); + /* + * The while loop body is executed more than once + * only when an empty dbnode needs to be skipped. + */ + while (it->result == ISC_R_NOMORE) { + dns_rdatasetiter_destroy(&it->rdatasetit); + dns_db_detachnode(it->db, &it->node); + it->result = dns_dbiterator_next(it->dbit); + if (it->result == ISC_R_NOMORE) { + /* We are at the end of the entire database. */ + return (it->result); + } + if (it->result != ISC_R_SUCCESS) + return (it->result); + it->result = dns_dbiterator_current(it->dbit, &it->node, + dns_fixedname_name(&it->fixedname)); + if (it->result != ISC_R_SUCCESS) + return (it->result); + it->result = dns_db_allrdatasets(it->db, it->node, it->ver, + it->now, &it->rdatasetit); + if (it->result != ISC_R_SUCCESS) + return (it->result); + it->result = dns_rdatasetiter_first(it->rdatasetit); + } + if (it->result != ISC_R_SUCCESS) + return (it->result); + dns_rdatasetiter_current(it->rdatasetit, &it->rdataset); + it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER; + it->result = dns_rdataset_first(&it->rdataset); + return (it->result); +} + +isc_result_t +dns_rriterator_next(dns_rriterator_t *it) { + REQUIRE(VALID_RRITERATOR(it)); + if (it->result != ISC_R_SUCCESS) + return (it->result); + + INSIST(it->dbit != NULL); + INSIST(it->node != NULL); + INSIST(it->rdatasetit != NULL); + + it->result = dns_rdataset_next(&it->rdataset); + if (it->result == ISC_R_NOMORE) + return (dns_rriterator_nextrrset(it)); + return (it->result); +} + +void +dns_rriterator_pause(dns_rriterator_t *it) { + REQUIRE(VALID_RRITERATOR(it)); + RUNTIME_CHECK(dns_dbiterator_pause(it->dbit) == ISC_R_SUCCESS); +} + +void +dns_rriterator_destroy(dns_rriterator_t *it) { + REQUIRE(VALID_RRITERATOR(it)); + if (dns_rdataset_isassociated(&it->rdataset)) + dns_rdataset_disassociate(&it->rdataset); + if (it->rdatasetit != NULL) + dns_rdatasetiter_destroy(&it->rdatasetit); + if (it->node != NULL) + dns_db_detachnode(it->db, &it->node); + dns_dbiterator_destroy(&it->dbit); +} + +void +dns_rriterator_current(dns_rriterator_t *it, dns_name_t **name, + isc_uint32_t *ttl, dns_rdataset_t **rdataset, + dns_rdata_t **rdata) +{ + REQUIRE(name != NULL && *name == NULL); + REQUIRE(VALID_RRITERATOR(it)); + REQUIRE(it->result == ISC_R_SUCCESS); + + *name = dns_fixedname_name(&it->fixedname); + *ttl = it->rdataset.ttl; + + dns_rdata_reset(&it->rdata); + dns_rdataset_current(&it->rdataset, &it->rdata); + + if (rdataset) + *rdataset = &it->rdataset; + + if (rdata) + *rdata = &it->rdata; +} diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c index 49c6430..d27007d 100644 --- a/lib/dns/sdb.c +++ b/lib/dns/sdb.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sdb.c,v 1.66.48.6 2010-08-16 05:21:42 marka Exp $ */ +/* $Id: sdb.c,v 1.76 2011-01-13 04:59:25 tbox Exp $ */ /*! \file */ @@ -450,7 +450,7 @@ getnode(dns_sdballnodes_t *allnodes, const char *name, dns_sdbnode_t **nodep) { isc_buffer_init(&b, name, strlen(name)); isc_buffer_add(&b, strlen(name)); - result = dns_name_fromtext(newname, &b, origin, ISC_FALSE, NULL); + result = dns_name_fromtext(newname, &b, origin, 0, NULL); if (result != ISC_R_SUCCESS) return (result); @@ -1253,6 +1253,8 @@ static dns_dbmethods_t sdb_methods = { NULL, NULL, NULL, + NULL, + NULL, NULL }; diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c index 6be315a..e684e1d 100644 --- a/lib/dns/sdlz.c +++ b/lib/dns/sdlz.c @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2005-2010 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2005-2011 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -50,7 +50,7 @@ * USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sdlz.c,v 1.18.50.6 2010-08-16 05:21:42 marka Exp $ */ +/* $Id: sdlz.c,v 1.31 2011-01-13 06:29:16 marka Exp $ */ /*! \file */ @@ -108,6 +108,8 @@ struct dns_sdlz_db { isc_mutex_t refcnt_lock; /* Locked */ unsigned int references; + dns_dbversion_t *future_version; + int dummy_version; }; struct dns_sdlzlookup { @@ -164,8 +166,6 @@ typedef struct sdlz_rdatasetiter { /* This is a reasonable value */ #define SDLZ_DEFAULT_TTL (60 * 60 * 24) -static int dummy; - #ifdef __COVERITY__ #define MAYBE_LOCK(imp) LOCK(&imp->driverlock) #define MAYBE_UNLOCK(imp) UNLOCK(&imp->driverlock) @@ -225,11 +225,22 @@ static dns_dbiteratormethods_t dbiterator_methods = { * Utility functions */ -/*% Converts the input string to lowercase, in place. */ +/* + * Log a message at the given level + */ +static void +sdlz_log(int level, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(level), + fmt, ap); + va_end(ap); +} +/*% Converts the input string to lowercase, in place. */ static void dns_sdlz_tolower(char *str) { - unsigned int len = strlen(str); unsigned int i; @@ -237,7 +248,6 @@ dns_sdlz_tolower(char *str) { if (str[i] >= 'A' && str[i] <= 'Z') str[i] += 32; } - } static inline unsigned int @@ -381,43 +391,79 @@ dump(dns_db_t *db, dns_dbversion_t *version, const char *filename, static void currentversion(dns_db_t *db, dns_dbversion_t **versionp) { + dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; + REQUIRE(VALID_SDLZDB(sdlz)); REQUIRE(versionp != NULL && *versionp == NULL); - UNUSED(db); - - *versionp = (void *) &dummy; + *versionp = (void *) &sdlz->dummy_version; return; } static isc_result_t newversion(dns_db_t *db, dns_dbversion_t **versionp) { - UNUSED(db); - UNUSED(versionp); + dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; + char origin[DNS_NAME_MAXTEXT + 1]; + isc_result_t result; - return (ISC_R_NOTIMPLEMENTED); + REQUIRE(VALID_SDLZDB(sdlz)); + + if (sdlz->dlzimp->methods->newversion == NULL) + return (ISC_R_NOTIMPLEMENTED); + + dns_name_format(&sdlz->common.origin, origin, sizeof(origin)); + + result = sdlz->dlzimp->methods->newversion(origin, + sdlz->dlzimp->driverarg, + sdlz->dbdata, versionp); + if (result != ISC_R_SUCCESS) { + sdlz_log(ISC_LOG_ERROR, + "sdlz newversion on origin %s failed : %s", + origin, isc_result_totext(result)); + return (result); + } + + sdlz->future_version = *versionp; + return (ISC_R_SUCCESS); } static void attachversion(dns_db_t *db, dns_dbversion_t *source, dns_dbversion_t **targetp) { - REQUIRE(source != NULL && source == (void *) &dummy); + dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; + + REQUIRE(VALID_SDLZDB(sdlz)); + REQUIRE(source != NULL && source == (void *)&sdlz->dummy_version); - UNUSED(db); - UNUSED(source); - UNUSED(targetp); *targetp = source; } static void closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { - REQUIRE(versionp != NULL && *versionp == (void *) &dummy); - REQUIRE(commit == ISC_FALSE); + dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; + char origin[DNS_NAME_MAXTEXT + 1]; - UNUSED(db); - UNUSED(commit); + REQUIRE(VALID_SDLZDB(sdlz)); + REQUIRE(versionp != NULL); + + if (*versionp == (void *)&sdlz->dummy_version) { + *versionp = NULL; + return; + } + + REQUIRE(*versionp == sdlz->future_version); + REQUIRE(sdlz->dlzimp->methods->closeversion != NULL); + + dns_name_format(&sdlz->common.origin, origin, sizeof(origin)); - *versionp = NULL; + sdlz->dlzimp->methods->closeversion(origin, commit, + sdlz->dlzimp->driverarg, + sdlz->dbdata, versionp); + if (*versionp != NULL) + sdlz_log(ISC_LOG_ERROR, + "sdlz closeversion on origin %s failed", origin); + + sdlz->future_version = NULL; } static isc_result_t @@ -506,11 +552,11 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, dns_sdlzauthorityfunc_t authority; REQUIRE(VALID_SDLZDB(sdlz)); - REQUIRE(create == ISC_FALSE); REQUIRE(nodep != NULL && *nodep == NULL); - UNUSED(name); - UNUSED(create); + if (sdlz->dlzimp->methods->newversion == NULL) { + REQUIRE(create == ISC_FALSE); + } isc_buffer_init(&b, namestr, sizeof(namestr)); if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVEOWNER) != 0) { @@ -558,7 +604,7 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, * if the host (namestr) was not found, try to lookup a * "wildcard" host. */ - if (result != ISC_R_SUCCESS) { + if (result != ISC_R_SUCCESS && !create) { result = sdlz->dlzimp->methods->lookup(zonestr, "*", sdlz->dlzimp->driverarg, sdlz->dbdata, node); @@ -566,7 +612,7 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, MAYBE_UNLOCK(sdlz->dlzimp); - if (result != ISC_R_SUCCESS && !isorigin) { + if (result != ISC_R_SUCCESS && !isorigin && !create) { destroynode(node); return (result); } @@ -584,6 +630,23 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, } } + if (node->name == NULL) { + node->name = isc_mem_get(sdlz->common.mctx, + sizeof(dns_name_t)); + if (node->name == NULL) { + destroynode(node); + return (ISC_R_NOMEMORY); + } + dns_name_init(node->name, NULL); + result = dns_name_dup(name, sdlz->common.mctx, node->name); + if (result != ISC_R_SUCCESS) { + isc_mem_put(sdlz->common.mctx, node->name, + sizeof(dns_name_t)); + destroynode(node); + return (result); + } + } + *nodep = node; return (ISC_R_SUCCESS); } @@ -778,7 +841,7 @@ find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, REQUIRE(VALID_SDLZDB(sdlz)); REQUIRE(nodep == NULL || *nodep == NULL); - REQUIRE(version == NULL || version == (void *) &dummy); + REQUIRE(version == NULL || version == (void*)&sdlz->dummy_version); UNUSED(options); UNUSED(sdlz); @@ -920,9 +983,14 @@ static isc_result_t allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) { + dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *) db; sdlz_rdatasetiter_t *iterator; - REQUIRE(version == NULL || version == &dummy); + REQUIRE(VALID_SDLZDB(sdlz)); + + REQUIRE(version == NULL || + version == (void*)&sdlz->dummy_version || + version == sdlz->future_version); UNUSED(version); UNUSED(now); @@ -945,47 +1013,139 @@ allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, } static isc_result_t +modrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, + dns_rdataset_t *rdataset, unsigned int options, + dns_sdlzmodrdataset_t mod_function) +{ + dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; + dns_master_style_t *style = NULL; + isc_result_t result; + isc_buffer_t *buffer = NULL; + isc_mem_t *mctx; + dns_sdlznode_t *sdlznode; + char *rdatastr = NULL; + char name[DNS_NAME_MAXTEXT + 1]; + + REQUIRE(VALID_SDLZDB(sdlz)); + + if (mod_function == NULL) + return (ISC_R_NOTIMPLEMENTED); + + sdlznode = (dns_sdlznode_t *)node; + + UNUSED(options); + + dns_name_format(sdlznode->name, name, sizeof(name)); + + mctx = sdlz->common.mctx; + + result = isc_buffer_allocate(mctx, &buffer, 1024); + if (result != ISC_R_SUCCESS) + return (result); + + result = dns_master_stylecreate(&style, 0, 0, 0, 0, 0, 0, 1, mctx); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = dns_master_rdatasettotext(sdlznode->name, rdataset, + style, buffer); + if (result != ISC_R_SUCCESS) + goto cleanup; + + if (isc_buffer_usedlength(buffer) < 1) { + result = ISC_R_BADADDRESSFORM; + goto cleanup; + } + + rdatastr = isc_buffer_base(buffer); + if (rdatastr == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + rdatastr[isc_buffer_usedlength(buffer) - 1] = 0; + + MAYBE_LOCK(sdlz->dlzimp); + result = mod_function(name, rdatastr, sdlz->dlzimp->driverarg, + sdlz->dbdata, version); + MAYBE_UNLOCK(sdlz->dlzimp); + +cleanup: + isc_buffer_free(&buffer); + if (style != NULL) + dns_master_styledestroy(&style, mctx); + + return (result); +} + +static isc_result_t addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options, dns_rdataset_t *addedrdataset) { - UNUSED(db); - UNUSED(node); - UNUSED(version); + dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; + isc_result_t result; + UNUSED(now); - UNUSED(rdataset); - UNUSED(options); UNUSED(addedrdataset); + REQUIRE(VALID_SDLZDB(sdlz)); - return (ISC_R_NOTIMPLEMENTED); + if (sdlz->dlzimp->methods->addrdataset == NULL) + return (ISC_R_NOTIMPLEMENTED); + + result = modrdataset(db, node, version, rdataset, options, + sdlz->dlzimp->methods->addrdataset); + return (result); } + static isc_result_t subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, dns_rdataset_t *rdataset, unsigned int options, dns_rdataset_t *newrdataset) { - UNUSED(db); - UNUSED(node); - UNUSED(version); - UNUSED(rdataset); - UNUSED(options); + dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; + isc_result_t result; + UNUSED(newrdataset); + REQUIRE(VALID_SDLZDB(sdlz)); - return (ISC_R_NOTIMPLEMENTED); + if (sdlz->dlzimp->methods->subtractrdataset == NULL) { + return (ISC_R_NOTIMPLEMENTED); + } + + result = modrdataset(db, node, version, rdataset, options, + sdlz->dlzimp->methods->subtractrdataset); + return (result); } static isc_result_t deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, dns_rdatatype_t type, dns_rdatatype_t covers) { - UNUSED(db); - UNUSED(node); - UNUSED(version); - UNUSED(type); + dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; + char name[DNS_NAME_MAXTEXT + 1]; + char b_type[DNS_RDATATYPE_FORMATSIZE]; + dns_sdlznode_t *sdlznode; + isc_result_t result; + UNUSED(covers); - return (ISC_R_NOTIMPLEMENTED); + REQUIRE(VALID_SDLZDB(sdlz)); + + if (sdlz->dlzimp->methods->delrdataset == NULL) + return (ISC_R_NOTIMPLEMENTED); + + sdlznode = (dns_sdlznode_t *)node; + dns_name_format(sdlznode->name, name, sizeof(name)); + dns_rdatatype_format(type, b_type, sizeof(b_type)); + + MAYBE_LOCK(sdlz->dlzimp); + result = sdlz->dlzimp->methods->delrdataset(name, b_type, + sdlz->dlzimp->driverarg, + sdlz->dbdata, version); + MAYBE_UNLOCK(sdlz->dlzimp); + + return (result); } static isc_boolean_t @@ -1021,6 +1181,26 @@ settask(dns_db_t *db, isc_task_t *task) { } +/* + * getoriginnode() is used by the update code to find the + * dns_rdatatype_dnskey record for a zone + */ +static isc_result_t +getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) { + dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; + isc_result_t result; + + REQUIRE(VALID_SDLZDB(sdlz)); + if (sdlz->dlzimp->methods->newversion == NULL) + return (ISC_R_NOTIMPLEMENTED); + + result = findnode(db, &sdlz->common.origin, ISC_FALSE, nodep); + if (result != ISC_R_SUCCESS) + sdlz_log(ISC_LOG_ERROR, "sdlz getoriginnode failed : %s", + isc_result_totext(result)); + return (result); +} + static dns_dbmethods_t sdlzdb_methods = { attach, detach, @@ -1049,6 +1229,8 @@ static dns_dbmethods_t sdlzdb_methods = { ispersistent, overmem, settask, + getoriginnode, + NULL, NULL, NULL, NULL, @@ -1371,9 +1553,7 @@ dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc, isc_result_t result = ISC_R_NOTFOUND; /* Write debugging message to log */ - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), - "Loading SDLZ driver."); + sdlz_log(ISC_LOG_DEBUG(2), "Loading SDLZ driver."); /* * Performs checks to make sure data is as we expect it to be. @@ -1395,13 +1575,9 @@ dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc, /* Write debugging message to log */ if (result == ISC_R_SUCCESS) { - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), - "SDLZ driver loaded successfully."); + sdlz_log(ISC_LOG_DEBUG(2), "SDLZ driver loaded successfully."); } else { - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, - "SDLZ driver failed to load."); + sdlz_log(ISC_LOG_ERROR, "SDLZ driver failed to load."); } return (result); @@ -1414,9 +1590,7 @@ dns_sdlzdestroy(void *driverdata, void **dbdata) dns_sdlzimplementation_t *imp; /* Write debugging message to log */ - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), - "Unloading SDLZ driver."); + sdlz_log(ISC_LOG_DEBUG(2), "Unloading SDLZ driver."); imp = driverdata; @@ -1472,11 +1646,97 @@ dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx, return (result); } + +static isc_result_t +dns_sdlzconfigure(void *driverarg, void *dbdata, dns_view_t *view) +{ + isc_result_t result; + dns_sdlzimplementation_t *imp; + + REQUIRE(driverarg != NULL); + + imp = (dns_sdlzimplementation_t *) driverarg; + + /* Call SDLZ driver's configure method */ + if (imp->methods->configure != NULL) { + MAYBE_LOCK(imp); + result = imp->methods->configure(view, imp->driverarg, dbdata); + MAYBE_UNLOCK(imp); + } else { + result = ISC_R_SUCCESS; + } + + return (result); +} + +static isc_boolean_t +dns_sdlzssumatch(dns_name_t *signer, dns_name_t *name, isc_netaddr_t *tcpaddr, + dns_rdatatype_t type, const dst_key_t *key, void *driverarg, + void *dbdata) +{ + dns_sdlzimplementation_t *imp; + char b_signer[DNS_NAME_FORMATSIZE]; + char b_name[DNS_NAME_FORMATSIZE]; + char b_addr[ISC_NETADDR_FORMATSIZE]; + char b_type[DNS_RDATATYPE_FORMATSIZE]; + char b_key[DST_KEY_FORMATSIZE]; + isc_buffer_t *tkey_token; + isc_region_t token_region; + isc_uint32_t token_len = 0; + isc_boolean_t ret; + + REQUIRE(driverarg != NULL); + + imp = (dns_sdlzimplementation_t *) driverarg; + if (imp->methods->ssumatch == NULL) + return (ISC_FALSE); + + /* + * Format the request elements. sdlz operates on strings, not + * structures + */ + if (signer) + dns_name_format(signer, b_signer, sizeof(b_signer)); + else + b_signer[0] = 0; + + dns_name_format(name, b_name, sizeof(b_name)); + + if (tcpaddr) + isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr)); + else + b_addr[0] = 0; + + dns_rdatatype_format(type, b_type, sizeof(b_type)); + + if (key) + dst_key_format(key, b_key, sizeof(b_key)); + else + b_key[0] = 0; + + tkey_token = dst_key_tkeytoken(key); + + if (tkey_token) { + isc_buffer_region(tkey_token, &token_region); + token_len = token_region.length; + } + + MAYBE_LOCK(imp); + ret = imp->methods->ssumatch(b_signer, b_name, b_addr, b_type, b_key, + token_len, + token_len ? token_region.base : NULL, + imp->driverarg, dbdata); + MAYBE_UNLOCK(imp); + return (ret); +} + static dns_dlzmethods_t sdlzmethods = { dns_sdlzcreate, dns_sdlzdestroy, dns_sdlzfindzone, - dns_sdlzallowzonexfr + dns_sdlzallowzonexfr, + dns_sdlzconfigure, + dns_sdlzssumatch }; /* @@ -1530,8 +1790,16 @@ dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl, ISC_LINK_INIT(rdatalist, link); ISC_LIST_APPEND(lookup->lists, rdatalist, link); } else - if (rdatalist->ttl != ttl) - return (DNS_R_BADTTL); + if (rdatalist->ttl > ttl) { + /* + * BIND9 doesn't enforce all RRs in an RRset + * having the same TTL, as per RFC 2136, + * section 7.12. If a DLZ backend has + * different TTLs, then the best + * we can do is return the lowest. + */ + rdatalist->ttl = ttl; + } rdata = isc_mem_get(mctx, sizeof(dns_rdata_t)); if (rdata == NULL) @@ -1615,7 +1883,7 @@ dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name, isc_buffer_init(&b, name, strlen(name)); isc_buffer_add(&b, strlen(name)); - result = dns_name_fromtext(newname, &b, origin, ISC_FALSE, NULL); + result = dns_name_fromtext(newname, &b, origin, 0, NULL); if (result != ISC_R_SUCCESS) return (result); @@ -1694,9 +1962,7 @@ dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods, DNS_SDLZFLAG_THREADSAFE)) == 0); /* Write debugging message to log */ - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), - "Registering SDLZ driver '%s'", drivername); + sdlz_log(ISC_LOG_DEBUG(2), "Registering SDLZ driver '%s'", drivername); /* * Allocate memory for a sdlz_implementation object. Error if @@ -1769,9 +2035,7 @@ dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) { isc_mem_t *mctx; /* Write debugging message to log */ - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), - "Unregistering SDLZ driver."); + sdlz_log(ISC_LOG_DEBUG(2), "Unregistering SDLZ driver."); /* * Performs checks to make sure data is as we expect it to be. @@ -1797,3 +2061,16 @@ dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) { *sdlzimp = NULL; } + + +isc_result_t +dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass, + dns_name_t *name, dns_db_t **dbp) +{ + isc_result_t result; + + result = dns_sdlzcreateDBP(dlzdatabase->mctx, + dlzdatabase->implementation->driverarg, + dlzdatabase->dbdata, name, rdclass, dbp); + return (result); +} diff --git a/lib/dns/soa.c b/lib/dns/soa.c index f338586..bd0d185 100644 --- a/lib/dns/soa.c +++ b/lib/dns/soa.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,15 +15,18 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: soa.c,v 1.8 2007-06-19 23:47:16 tbox Exp $ */ +/* $Id: soa.c,v 1.12 2009-09-10 02:18:40 each Exp $ */ /*! \file */ #include +#include +#include #include #include +#include #include static inline isc_uint32_t @@ -60,6 +63,39 @@ soa_get(dns_rdata_t *rdata, int offset) { return (decode_uint32(rdata->data + rdata->length - 20 + offset)); } +isc_result_t +dns_soa_buildrdata(dns_name_t *origin, dns_name_t *contact, + dns_rdataclass_t rdclass, + isc_uint32_t serial, isc_uint32_t refresh, + isc_uint32_t retry, isc_uint32_t expire, + isc_uint32_t minimum, unsigned char *buffer, + dns_rdata_t *rdata) { + dns_rdata_soa_t soa; + isc_buffer_t rdatabuf; + + REQUIRE(origin != NULL); + REQUIRE(contact != NULL); + + memset(buffer, 0, DNS_SOA_BUFFERSIZE); + isc_buffer_init(&rdatabuf, buffer, DNS_SOA_BUFFERSIZE); + + soa.common.rdtype = dns_rdatatype_soa; + soa.common.rdclass = rdclass; + soa.mctx = NULL; + soa.serial = serial; + soa.refresh = refresh; + soa.retry = retry; + soa.expire = expire; + soa.minimum = minimum; + dns_name_init(&soa.origin, NULL); + dns_name_clone(origin, &soa.origin); + dns_name_init(&soa.contact, NULL); + dns_name_clone(contact, &soa.contact); + + return (dns_rdata_fromstruct(rdata, rdclass, dns_rdatatype_soa, + &soa, &rdatabuf)); +} + isc_uint32_t dns_soa_getserial(dns_rdata_t *rdata) { return soa_get(rdata, 0); diff --git a/lib/dns/spnego.c b/lib/dns/spnego.c index ad15331..5ad492c 100644 --- a/lib/dns/spnego.c +++ b/lib/dns/spnego.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2006-2011 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: spnego.c,v 1.8.118.4 2009-07-21 07:27:13 marka Exp $ */ +/* $Id: spnego.c,v 1.16 2011-01-11 23:47:13 tbox Exp $ */ /*! \file * \brief @@ -172,6 +172,8 @@ /* asn1_err.h */ /* Generated from ../../../lib/asn1/asn1_err.et */ +#ifndef ERROR_TABLE_BASE_asn1 +/* these may be brought in already via gssapi_krb5.h */ typedef enum asn1_error_number { ASN1_BAD_TIMEFORMAT = 1859794432, ASN1_MISSING_FIELD = 1859794433, @@ -186,6 +188,7 @@ typedef enum asn1_error_number { } asn1_error_number; #define ERROR_TABLE_BASE_asn1 1859794432 +#endif #define __asn1_common_definitions__ @@ -409,7 +412,7 @@ code_NegTokenArg(OM_uint32 * minor_status, { OM_uint32 ret; u_char *buf; - size_t buf_size, buf_len; + size_t buf_size, buf_len = 0; buf_size = 1024; buf = malloc(buf_size); diff --git a/lib/dns/ssu.c b/lib/dns/ssu.c index 128071c..eb13551 100644 --- a/lib/dns/ssu.c +++ b/lib/dns/ssu.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2008, 2010, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -17,7 +17,7 @@ /*! \file */ /* - * $Id: ssu.c,v 1.34 2008-01-18 23:46:58 tbox Exp $ + * $Id: ssu.c,v 1.38 2011-01-06 23:47:00 tbox Exp $ * Principal Author: Brian Wellington */ @@ -30,11 +30,13 @@ #include #include +#include #include #include #include #include +#include #define SSUTABLEMAGIC ISC_MAGIC('S', 'S', 'U', 'T') #define VALID_SSUTABLE(table) ISC_MAGIC_VALID(table, SSUTABLEMAGIC) @@ -59,6 +61,7 @@ struct dns_ssutable { isc_mem_t *mctx; unsigned int references; isc_mutex_t lock; + dns_dlzdb_t *dlzdatabase; ISC_LIST(dns_ssurule_t) rules; }; @@ -345,7 +348,8 @@ stf_from_address(dns_name_t *stfself, isc_netaddr_t *tcpaddr) { isc_boolean_t dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer, dns_name_t *name, isc_netaddr_t *tcpaddr, - dns_rdatatype_t type) + dns_rdatatype_t type, + const dst_key_t *key) { dns_ssurule_t *rule; unsigned int i; @@ -483,10 +487,27 @@ dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer, if (!dns_name_equal(stfself, name)) continue; break; + case DNS_SSUMATCHTYPE_EXTERNAL: + if (!dns_ssu_external_match(rule->identity, signer, + name, tcpaddr, type, key, + table->mctx)) + continue; + break; + case DNS_SSUMATCHTYPE_DLZ: + if (!dns_dlz_ssumatch(table->dlzdatabase, signer, + name, tcpaddr, type, key)) + continue; + break; } if (rule->ntypes == 0) { - if (!isusertype(type)) + /* + * If this is a DLZ rule, then the DLZ ssu + * checks will have already checked + * the type. + */ + if (rule->matchtype != DNS_SSUMATCHTYPE_DLZ && + !isusertype(type)) continue; } else { for (i = 0; i < rule->ntypes; i++) { @@ -550,3 +571,42 @@ dns_ssutable_nextrule(dns_ssurule_t *rule, dns_ssurule_t **nextrule) { *nextrule = ISC_LIST_NEXT(rule, link); return (*nextrule != NULL ? ISC_R_SUCCESS : ISC_R_NOMORE); } + +/* + * Create a specialised SSU table that points at an external DLZ database + */ +isc_result_t +dns_ssutable_createdlz(isc_mem_t *mctx, dns_ssutable_t **tablep, + dns_dlzdb_t *dlzdatabase) +{ + isc_result_t result; + dns_ssurule_t *rule; + dns_ssutable_t *table = NULL; + + REQUIRE(tablep != NULL && *tablep == NULL); + + result = dns_ssutable_create(mctx, &table); + if (result != ISC_R_SUCCESS) + return (result); + + table->dlzdatabase = dlzdatabase; + + rule = isc_mem_get(table->mctx, sizeof(dns_ssurule_t)); + if (rule == NULL) { + dns_ssutable_detach(&table); + return (ISC_R_NOMEMORY); + } + + rule->identity = NULL; + rule->name = NULL; + rule->types = NULL; + rule->grant = ISC_TRUE; + rule->matchtype = DNS_SSUMATCHTYPE_DLZ; + rule->ntypes = 0; + rule->types = NULL; + rule->magic = SSURULEMAGIC; + + ISC_LIST_INITANDAPPEND(table->rules, rule, link); + *tablep = table; + return (ISC_R_SUCCESS); +} diff --git a/lib/dns/ssu_external.c b/lib/dns/ssu_external.c new file mode 100644 index 0000000..ac72a1f --- /dev/null +++ b/lib/dns/ssu_external.c @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: ssu_external.c,v 1.7 2011-01-13 07:05:57 marka Exp $ */ + +/* + * This implements external update-policy rules. This allows permission + * to update a zone to be checked by consulting an external daemon (e.g., + * kerberos). + */ + +#include +#include +#include + +#ifdef ISC_PLATFORM_HAVESYSUNH +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + + +static void +ssu_e_log(int level, const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_SECURITY, + DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(level), fmt, ap); + va_end(ap); +} + + +/* + * Connect to a UNIX domain socket. + */ +static int +ux_socket_connect(const char *path) { + int fd = -1; +#ifdef ISC_PLATFORM_HAVESYSUNH + struct sockaddr_un addr; + + REQUIRE(path != NULL); + + if (strlen(path) > sizeof(addr.sun_path)) { + ssu_e_log(3, "ssu_external: socket path '%s' " + "longer than system maximum %u", + path, sizeof(addr.sun_path)); + return (-1); + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, path, sizeof(addr.sun_path)); + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) { + char strbuf[ISC_STRERRORSIZE]; + isc__strerror(errno, strbuf, sizeof(strbuf)); + ssu_e_log(3, "ssu_external: unable to create socket - %s", + strbuf); + return (-1); + } + + if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { + char strbuf[ISC_STRERRORSIZE]; + isc__strerror(errno, strbuf, sizeof(strbuf)); + ssu_e_log(3, "ssu_external: unable to connect to " + "socket '%s' - %s", + path, strbuf); + close(fd); + return (-1); + } +#endif + return (fd); +} + +/* Change this version if you update the format of the request */ +#define SSU_EXTERNAL_VERSION 1 + +/* + * Perform an update-policy rule check against an external application + * over a socket. + * + * This currently only supports local: for unix domain datagram sockets. + * + * Note that by using a datagram socket and creating a new socket each + * time we avoid the need for locking and allow for parallel access to + * the authorization server. + */ +isc_boolean_t +dns_ssu_external_match(dns_name_t *identity, + dns_name_t *signer, dns_name_t *name, + isc_netaddr_t *tcpaddr, dns_rdatatype_t type, + const dst_key_t *key, isc_mem_t *mctx) +{ + char b_identity[DNS_NAME_FORMATSIZE]; + char b_signer[DNS_NAME_FORMATSIZE]; + char b_name[DNS_NAME_FORMATSIZE]; + char b_addr[ISC_NETADDR_FORMATSIZE]; + char b_type[DNS_RDATATYPE_FORMATSIZE]; + char b_key[DST_KEY_FORMATSIZE]; + isc_buffer_t *tkey_token; + int fd; + const char *sock_path; + size_t req_len; + isc_region_t token_region; + unsigned char *data; + isc_buffer_t buf; + isc_uint32_t token_len = 0; + isc_uint32_t reply; + ssize_t ret; + + /* The identity contains local:/path/to/socket */ + dns_name_format(identity, b_identity, sizeof(b_identity)); + + /* For now only local: is supported */ + if (strncmp(b_identity, "local:", 6) != 0) { + ssu_e_log(3, "ssu_external: invalid socket path '%s'", + b_identity); + return (ISC_FALSE); + } + sock_path = &b_identity[6]; + + fd = ux_socket_connect(sock_path); + if (fd == -1) + return (ISC_FALSE); + + tkey_token = dst_key_tkeytoken(key); + + /* Format the request elements */ + if (signer) + dns_name_format(signer, b_signer, sizeof(b_signer)); + else + b_signer[0] = 0; + + dns_name_format(name, b_name, sizeof(b_name)); + + if (tcpaddr) + isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr)); + else + b_addr[0] = 0; + + dns_rdatatype_format(type, b_type, sizeof(b_type)); + + if (key) + dst_key_format(key, b_key, sizeof(b_key)); + else + b_key[0] = 0; + + if (tkey_token) { + isc_buffer_region(tkey_token, &token_region); + token_len = token_region.length; + } + + /* Work out how big the request will be */ + req_len = sizeof(isc_uint32_t) + /* Format version */ + sizeof(isc_uint32_t) + /* Length */ + strlen(b_signer) + 1 + /* Signer */ + strlen(b_name) + 1 + /* Name */ + strlen(b_addr) + 1 + /* Address */ + strlen(b_type) + 1 + /* Type */ + strlen(b_key) + 1 + /* Key */ + sizeof(isc_uint32_t) + /* tkey_token length */ + token_len; /* tkey_token */ + + + /* format the buffer */ + data = isc_mem_allocate(mctx, req_len); + if (data == NULL) { + close(fd); + return (ISC_FALSE); + } + + isc_buffer_init(&buf, data, req_len); + isc_buffer_putuint32(&buf, SSU_EXTERNAL_VERSION); + isc_buffer_putuint32(&buf, req_len); + + /* Strings must be null-terminated */ + isc_buffer_putstr(&buf, b_signer); + isc_buffer_putuint8(&buf, 0); + isc_buffer_putstr(&buf, b_name); + isc_buffer_putuint8(&buf, 0); + isc_buffer_putstr(&buf, b_addr); + isc_buffer_putuint8(&buf, 0); + isc_buffer_putstr(&buf, b_type); + isc_buffer_putuint8(&buf, 0); + isc_buffer_putstr(&buf, b_key); + isc_buffer_putuint8(&buf, 0); + + isc_buffer_putuint32(&buf, token_len); + if (tkey_token && token_len != 0) + isc_buffer_putmem(&buf, token_region.base, token_len); + + ENSURE(isc_buffer_availablelength(&buf) == 0); + + /* Send the request */ + ret = write(fd, data, req_len); + isc_mem_free(mctx, data); + if (ret != (ssize_t) req_len) { + char strbuf[ISC_STRERRORSIZE]; + isc__strerror(errno, strbuf, sizeof(strbuf)); + ssu_e_log(3, "ssu_external: unable to send request - %s", + strbuf); + close(fd); + return (ISC_FALSE); + } + + /* Receive the reply */ + ret = read(fd, &reply, sizeof(isc_uint32_t)); + if (ret != (ssize_t) sizeof(isc_uint32_t)) { + char strbuf[ISC_STRERRORSIZE]; + isc__strerror(errno, strbuf, sizeof(strbuf)); + ssu_e_log(3, "ssu_external: unable to receive reply - %s", + strbuf); + close(fd); + return (ISC_FALSE); + } + + close(fd); + + reply = ntohl(reply); + + if (reply == 0) { + ssu_e_log(3, "ssu_external: denied external auth for '%s'", + b_name); + return (ISC_FALSE); + } else if (reply == 1) { + ssu_e_log(3, "ssu_external: allowed external auth for '%s'", + b_name); + return (ISC_TRUE); + } + + ssu_e_log(3, "ssu_external: invalid reply 0x%08x", reply); + + return (ISC_FALSE); +} diff --git a/lib/dns/stats.c b/lib/dns/stats.c index b73a3b3..cb46bf5 100644 --- a/lib/dns/stats.c +++ b/lib/dns/stats.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: stats.c,v 1.16.118.2 2009-01-29 23:47:44 tbox Exp $ */ +/* $Id: stats.c,v 1.18 2009-01-27 23:47:54 tbox Exp $ */ /*! \file */ diff --git a/lib/dns/time.c b/lib/dns/time.c index bd8cdc3..3f55f19 100644 --- a/lib/dns/time.c +++ b/lib/dns/time.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: time.c,v 1.31.332.4 2010-04-21 23:48:05 tbox Exp $ */ +/* $Id: time.c,v 1.35 2010-04-21 23:51:22 tbox Exp $ */ /*! \file */ diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c index 7107dd5..a861ee3 100644 --- a/lib/dns/tkey.c +++ b/lib/dns/tkey.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -16,7 +16,7 @@ */ /* - * $Id: tkey.c,v 1.90.118.4 2010-12-09 01:12:55 marka Exp $ + * $Id: tkey.c,v 1.100 2011-01-08 23:47:01 tbox Exp $ */ /*! \file */ #include @@ -99,6 +99,7 @@ dns_tkeyctx_create(isc_mem_t *mctx, isc_entropy_t *ectx, dns_tkeyctx_t **tctxp) tctx->dhkey = NULL; tctx->domain = NULL; tctx->gsscred = NULL; + tctx->gssapi_keytab = NULL; *tctxp = tctx; return (ISC_R_SUCCESS); @@ -121,6 +122,9 @@ dns_tkeyctx_destroy(dns_tkeyctx_t **tctxp) { dns_name_free(tctx->domain, mctx); isc_mem_put(mctx, tctx->domain, sizeof(dns_name_t)); } + if (tctx->gssapi_keytab != NULL) { + isc_mem_free(mctx, tctx->gssapi_keytab); + } if (tctx->gsscred != NULL) dst_gssapi_releasecred(&tctx->gsscred); isc_entropy_detach(&tctx->ectx); @@ -430,8 +434,17 @@ process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin, isc_buffer_t *outtoken = NULL; gss_ctx_id_t gss_ctx = NULL; - if (tctx->gsscred == NULL) + /* + * You have to define either a gss credential (principal) to + * accept with tkey-gssapi-credential, or you have to + * configure a specific keytab (with tkey-gssapi-keytab) in + * order to use gsstkey + */ + if (tctx->gsscred == NULL && tctx->gssapi_keytab == NULL) { + tkey_log("process_gsstkey(): no tkey-gssapi-credential " + "or tkey-gssapi-keytab configured"); return (ISC_R_NOPERM); + } if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPI_NAME) && !dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPIMS_NAME)) { @@ -454,7 +467,11 @@ process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin, dns_fixedname_init(&principal); - result = dst_gssapi_acceptctx(tctx->gsscred, &intoken, + /* + * Note that tctx->gsscred may be NULL if tctx->gssapi_keytab is set + */ + result = dst_gssapi_acceptctx(tctx->gsscred, tctx->gssapi_keytab, + &intoken, &outtoken, &gss_ctx, dns_fixedname_name(&principal), tctx->mctx); @@ -479,7 +496,8 @@ process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin, #endif isc_uint32_t expire; - RETERR(dst_key_fromgssapi(name, gss_ctx, ring->mctx, &dstkey)); + RETERR(dst_key_fromgssapi(name, gss_ctx, ring->mctx, + &dstkey, &intoken)); /* * Limit keys to 1 hour or the context's lifetime whichever * is smaller. @@ -734,8 +752,7 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx, } isc_buffer_init(&b, randomtext, sizeof(randomtext)); isc_buffer_add(&b, sizeof(randomtext)); - result = dns_name_fromtext(keyname, &b, NULL, - ISC_FALSE, NULL); + result = dns_name_fromtext(keyname, &b, NULL, 0, NULL); if (result != ISC_R_SUCCESS) goto failure; } @@ -985,7 +1002,8 @@ dns_tkey_builddhquery(dns_message_t *msg, dst_key_t *key, dns_name_t *name, isc_result_t dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname, isc_buffer_t *intoken, isc_uint32_t lifetime, - gss_ctx_id_t *context, isc_boolean_t win2k) + gss_ctx_id_t *context, isc_boolean_t win2k, + isc_mem_t *mctx, char **err_message) { dns_rdata_tkey_t tkey; isc_result_t result; @@ -999,9 +1017,11 @@ dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname, REQUIRE(name != NULL); REQUIRE(gname != NULL); REQUIRE(context != NULL); + REQUIRE(mctx != NULL); isc_buffer_init(&token, array, sizeof(array)); - result = dst_gssapi_initctx(gname, NULL, &token, context); + result = dst_gssapi_initctx(gname, NULL, &token, context, + mctx, err_message); if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS) return (result); @@ -1218,7 +1238,7 @@ isc_result_t dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg, dns_name_t *gname, gss_ctx_id_t *context, isc_buffer_t *outtoken, dns_tsigkey_t **outkey, - dns_tsig_keyring_t *ring) + dns_tsig_keyring_t *ring, char **err_message) { dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT; dns_name_t *tkeyname; @@ -1232,6 +1252,7 @@ dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg, REQUIRE(qmsg != NULL); REQUIRE(rmsg != NULL); REQUIRE(gname != NULL); + REQUIRE(ring != NULL); if (outkey != NULL) REQUIRE(*outkey == NULL); @@ -1268,10 +1289,11 @@ dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg, isc_buffer_init(outtoken, array, sizeof(array)); isc_buffer_init(&intoken, rtkey.key, rtkey.keylen); - RETERR(dst_gssapi_initctx(gname, &intoken, outtoken, context)); + RETERR(dst_gssapi_initctx(gname, &intoken, outtoken, context, + ring->mctx, err_message)); RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx, - &dstkey)); + &dstkey, NULL)); RETERR(dns_tsigkey_createfromkey(tkeyname, DNS_TSIG_GSSAPI_NAME, dstkey, ISC_FALSE, NULL, @@ -1349,7 +1371,7 @@ isc_result_t dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg, dns_name_t *server, gss_ctx_id_t *context, dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring, - isc_boolean_t win2k) + isc_boolean_t win2k, char **err_message) { dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT; dns_name_t *tkeyname; @@ -1393,12 +1415,13 @@ dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg, isc_buffer_init(&intoken, rtkey.key, rtkey.keylen); isc_buffer_init(&outtoken, array, sizeof(array)); - result = dst_gssapi_initctx(server, &intoken, &outtoken, context); + result = dst_gssapi_initctx(server, &intoken, &outtoken, context, + ring->mctx, err_message); if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS) return (result); RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx, - &dstkey)); + &dstkey, NULL)); /* * XXXSRA This seems confused. If we got CONTINUE from initctx, diff --git a/lib/dns/tsec.c b/lib/dns/tsec.c new file mode 100644 index 0000000..b7ed777 --- /dev/null +++ b/lib/dns/tsec.c @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: tsec.c,v 1.7 2010-12-09 00:54:34 marka Exp $ */ + +#include + +#include + +#include +#include +#include + +#include + +#define DNS_TSEC_MAGIC ISC_MAGIC('T', 's', 'e', 'c') +#define DNS_TSEC_VALID(t) ISC_MAGIC_VALID(t, DNS_TSEC_MAGIC) + +/*% + * DNS Transaction Security object. We assume this is not shared by + * multiple threads, and so the structure does not contain a lock. + */ +struct dns_tsec { + unsigned int magic; + dns_tsectype_t type; + isc_mem_t *mctx; + union { + dns_tsigkey_t *tsigkey; + dst_key_t *key; + } ukey; +}; + +isc_result_t +dns_tsec_create(isc_mem_t *mctx, dns_tsectype_t type, dst_key_t *key, + dns_tsec_t **tsecp) +{ + isc_result_t result; + dns_tsec_t *tsec; + dns_tsigkey_t *tsigkey = NULL; + dns_name_t *algname; + + REQUIRE(mctx != NULL); + REQUIRE(tsecp != NULL && *tsecp == NULL); + + tsec = isc_mem_get(mctx, sizeof(*tsec)); + if (tsec == NULL) + return (ISC_R_NOMEMORY); + + tsec->type = type; + tsec->mctx = mctx; + + switch (type) { + case dns_tsectype_tsig: + switch (dst_key_alg(key)) { + case DST_ALG_HMACMD5: + algname = dns_tsig_hmacmd5_name; + break; + case DST_ALG_HMACSHA1: + algname = dns_tsig_hmacsha1_name; + break; + case DST_ALG_HMACSHA224: + algname = dns_tsig_hmacsha224_name; + break; + case DST_ALG_HMACSHA256: + algname = dns_tsig_hmacsha256_name; + break; + case DST_ALG_HMACSHA384: + algname = dns_tsig_hmacsha384_name; + break; + case DST_ALG_HMACSHA512: + algname = dns_tsig_hmacsha512_name; + break; + default: + isc_mem_put(mctx, tsec, sizeof(*tsec)); + return (DNS_R_BADALG); + } + result = dns_tsigkey_createfromkey(dst_key_name(key), + algname, key, ISC_FALSE, + NULL, 0, 0, mctx, NULL, + &tsigkey); + if (result != ISC_R_SUCCESS) { + isc_mem_put(mctx, tsec, sizeof(*tsec)); + return (result); + } + tsec->ukey.tsigkey = tsigkey; + break; + case dns_tsectype_sig0: + tsec->ukey.key = key; + break; + default: + INSIST(0); + } + + tsec->magic = DNS_TSEC_MAGIC; + + *tsecp = tsec; + return (ISC_R_SUCCESS); +} + +void +dns_tsec_destroy(dns_tsec_t **tsecp) { + dns_tsec_t *tsec; + + REQUIRE(tsecp != NULL && *tsecp != NULL); + tsec = *tsecp; + REQUIRE(DNS_TSEC_VALID(tsec)); + + switch (tsec->type) { + case dns_tsectype_tsig: + dns_tsigkey_detach(&tsec->ukey.tsigkey); + break; + case dns_tsectype_sig0: + dst_key_free(&tsec->ukey.key); + break; + default: + INSIST(0); + } + + tsec->magic = 0; + isc_mem_put(tsec->mctx, tsec, sizeof(*tsec)); + + *tsecp = NULL; +} + +dns_tsectype_t +dns_tsec_gettype(dns_tsec_t *tsec) { + REQUIRE(DNS_TSEC_VALID(tsec)); + + return (tsec->type); +} + +void +dns_tsec_getkey(dns_tsec_t *tsec, void *keyp) { + REQUIRE(DNS_TSEC_VALID(tsec)); + REQUIRE(keyp != NULL); + + switch (tsec->type) { + case dns_tsectype_tsig: + dns_tsigkey_attach(tsec->ukey.tsigkey, (dns_tsigkey_t **)keyp); + break; + case dns_tsectype_sig0: + *(dst_key_t **)keyp = tsec->ukey.key; + break; + default: + INSIST(0); + } +} diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c index 65d32dc..cec5222 100644 --- a/lib/dns/tsig.c +++ b/lib/dns/tsig.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -16,7 +16,7 @@ */ /* - * $Id: tsig.c,v 1.136.18.5 2010-12-09 01:12:55 marka Exp $ + * $Id: tsig.c,v 1.147 2011-01-11 23:47:13 tbox Exp $ */ /*! \file */ #include @@ -91,31 +91,6 @@ static dns_name_t gsstsig = { }; LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapi_name = &gsstsig; -static void -remove_fromring(dns_tsigkey_t *tkey) { - if (tkey->generated) { - ISC_LIST_UNLINK(tkey->ring->lru, tkey, link); - tkey->ring->generated--; - } - (void)dns_rbt_deletename(tkey->ring->keys, &tkey->name, ISC_FALSE); -} - -static void -adjust_lru(dns_tsigkey_t *tkey) { - if (tkey->generated) { - RWLOCK(&tkey->ring->lock, isc_rwlocktype_write); - /* - * We may have been removed from the LRU list between - * removing the read lock and aquiring the write lock. - */ - if (ISC_LINK_LINKED(tkey, link)) { - ISC_LIST_UNLINK(tkey->ring->lru, tkey, link); - ISC_LIST_APPEND(tkey->ring->lru, tkey, link); - } - RWUNLOCK(&tkey->ring->lock, isc_rwlocktype_write); - } -} - /* * Since Microsoft doesn't follow its own standard, we will use this * alternate name as a second guess. @@ -228,8 +203,10 @@ tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) { else strcpy(namestr, ""); - if (key != NULL && key->generated) + if (key != NULL && key->generated && key->creator) dns_name_format(key->creator, creatorstr, sizeof(creatorstr)); + else + strcpy(creatorstr, ""); va_start(ap, fmt); vsnprintf(message, sizeof(message), fmt, ap); @@ -245,6 +222,71 @@ tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) { level, "tsig key '%s': %s", namestr, message); } +static void +remove_fromring(dns_tsigkey_t *tkey) { + if (tkey->generated) { + ISC_LIST_UNLINK(tkey->ring->lru, tkey, link); + tkey->ring->generated--; + } + (void)dns_rbt_deletename(tkey->ring->keys, &tkey->name, ISC_FALSE); +} + +static void +adjust_lru(dns_tsigkey_t *tkey) { + if (tkey->generated) { + RWLOCK(&tkey->ring->lock, isc_rwlocktype_write); + /* + * We may have been removed from the LRU list between + * removing the read lock and aquiring the write lock. + */ + if (ISC_LINK_LINKED(tkey, link)) { + ISC_LIST_UNLINK(tkey->ring->lru, tkey, link); + ISC_LIST_APPEND(tkey->ring->lru, tkey, link); + } + RWUNLOCK(&tkey->ring->lock, isc_rwlocktype_write); + } +} + +/* + * A supplemental routine just to add a key to ring. Note that reference + * counter should be counted separately because we may be adding the key + * as part of creation of the key, in which case the reference counter was + * already initialized. Also note we don't need RWLOCK for the reference + * counter: it's protected by a separate lock. + */ +static isc_result_t +keyring_add(dns_tsig_keyring_t *ring, dns_name_t *name, + dns_tsigkey_t *tkey) +{ + isc_result_t result; + + RWLOCK(&ring->lock, isc_rwlocktype_write); + ring->writecount++; + + /* + * Do on the fly cleaning. Find some nodes we might not + * want around any more. + */ + if (ring->writecount > 10) { + cleanup_ring(ring); + ring->writecount = 0; + } + + result = dns_rbt_addname(ring->keys, name, tkey); + if (tkey->generated) { + /* + * Add the new key to the LRU list and remove the least + * recently used key if there are too many keys on the list. + */ + ISC_LIST_INITANDAPPEND(ring->lru, tkey, link); + if (ring->generated++ > ring->maxgenerated) + remove_fromring(ISC_LIST_HEAD(ring->lru)); + } + RWUNLOCK(&ring->lock, isc_rwlocktype_write); + + return (result); +} + isc_result_t dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm, dst_key_t *dstkey, isc_boolean_t generated, @@ -363,7 +405,7 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm, tkey->ring = ring; if (key != NULL) - refs++; + refs = 1; if (ring != NULL) refs++; ret = isc_refcount_init(&tkey->refs, refs); @@ -379,36 +421,9 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm, tkey->magic = TSIG_MAGIC; if (ring != NULL) { - RWLOCK(&ring->lock, isc_rwlocktype_write); - ring->writecount++; - - /* - * Do on the fly cleaning. Find some nodes we might not - * want around any more. - */ - if (ring->writecount > 10) { - cleanup_ring(ring); - ring->writecount = 0; - } - - ret = dns_rbt_addname(ring->keys, name, tkey); - if (ret != ISC_R_SUCCESS) { - RWUNLOCK(&ring->lock, isc_rwlocktype_write); + ret = keyring_add(ring, name, tkey); + if (ret != ISC_R_SUCCESS) goto cleanup_refs; - } - - if (tkey->generated) { - /* - * Add the new key to the LRU list and remove the - * least recently used key if there are too many - * keys on the list. - */ - ISC_LIST_INITANDAPPEND(ring->lru, tkey, link); - if (ring->generated++ > ring->maxgenerated) - remove_fromring(ISC_LIST_HEAD(ring->lru)); - } - - RWUNLOCK(&ring->lock, isc_rwlocktype_write); } /* @@ -424,6 +439,7 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm, "the key '%s' is too short to be secure", namestr); } + if (key != NULL) *key = tkey; @@ -512,6 +528,184 @@ cleanup_ring(dns_tsig_keyring_t *ring) } } +static void +destroyring(dns_tsig_keyring_t *ring) { + dns_rbt_destroy(&ring->keys); + isc_rwlock_destroy(&ring->lock); + isc_mem_putanddetach(&ring->mctx, ring, sizeof(dns_tsig_keyring_t)); +} + +static unsigned int +dst_alg_fromname(dns_name_t *algorithm) { + if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) { + return (DST_ALG_HMACMD5); + } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) { + return (DST_ALG_HMACSHA1); + } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) { + return (DST_ALG_HMACSHA224); + } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) { + return (DST_ALG_HMACSHA256); + } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) { + return (DST_ALG_HMACSHA384); + } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) { + return (DST_ALG_HMACSHA512); + } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) { + return (DST_ALG_GSSAPI); + } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) { + return (DST_ALG_GSSAPI); + } else + return (0); +} + +static isc_result_t +restore_key(dns_tsig_keyring_t *ring, isc_stdtime_t now, FILE *fp) { + dst_key_t *dstkey = NULL; + char namestr[1024]; + char creatorstr[1024]; + char algorithmstr[1024]; + char keystr[4096]; + unsigned int inception, expire; + int n; + isc_buffer_t b; + dns_name_t *name, *creator, *algorithm; + dns_fixedname_t fname, fcreator, falgorithm; + isc_result_t result; + unsigned int dstalg; + + n = fscanf(fp, "%1023s %1023s %u %u %1023s %4095s\n", namestr, + creatorstr, &inception, &expire, algorithmstr, keystr); + if (n == EOF) + return (ISC_R_NOMORE); + if (n != 6) + return (ISC_R_FAILURE); + + if (isc_serial_lt(expire, now)) + return (DNS_R_EXPIRED); + + dns_fixedname_init(&fname); + name = dns_fixedname_name(&fname); + isc_buffer_init(&b, namestr, strlen(namestr)); + isc_buffer_add(&b, strlen(namestr)); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) + return (result); + + dns_fixedname_init(&fcreator); + creator = dns_fixedname_name(&fcreator); + isc_buffer_init(&b, creatorstr, strlen(creatorstr)); + isc_buffer_add(&b, strlen(creatorstr)); + result = dns_name_fromtext(creator, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) + return (result); + + dns_fixedname_init(&falgorithm); + algorithm = dns_fixedname_name(&falgorithm); + isc_buffer_init(&b, algorithmstr, strlen(algorithmstr)); + isc_buffer_add(&b, strlen(algorithmstr)); + result = dns_name_fromtext(algorithm, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) + return (result); + + dstalg = dst_alg_fromname(algorithm); + if (dstalg == 0) + return (DNS_R_BADALG); + + result = dst_key_restore(name, dstalg, DNS_KEYOWNER_ENTITY, + DNS_KEYPROTO_DNSSEC, dns_rdataclass_in, + ring->mctx, keystr, &dstkey); + if (result != ISC_R_SUCCESS) + return (result); + + result = dns_tsigkey_createfromkey(name, algorithm, dstkey, + ISC_TRUE, creator, inception, + expire, ring->mctx, ring, NULL); + if (result != ISC_R_SUCCESS && dstkey != NULL) + dst_key_free(&dstkey); + return (result); +} + +static void +dump_key(dns_tsigkey_t *tkey, FILE *fp) +{ + char *buffer = NULL; + int length = 0; + char namestr[DNS_NAME_FORMATSIZE]; + char creatorstr[DNS_NAME_FORMATSIZE]; + char algorithmstr[DNS_NAME_FORMATSIZE]; + isc_result_t result; + + dns_name_format(&tkey->name, namestr, sizeof(namestr)); + dns_name_format(tkey->creator, creatorstr, sizeof(creatorstr)); + dns_name_format(tkey->algorithm, algorithmstr, sizeof(algorithmstr)); + result = dst_key_dump(tkey->key, tkey->mctx, &buffer, &length); + if (result == ISC_R_SUCCESS) + fprintf(fp, "%s %s %u %u %s %.*s\n", namestr, creatorstr, + tkey->inception, tkey->expire, algorithmstr, + length, buffer); + if (buffer != NULL) + isc_mem_put(tkey->mctx, buffer, length); +} + +isc_result_t +dns_tsigkeyring_dumpanddetach(dns_tsig_keyring_t **ringp, FILE *fp) { + isc_result_t result; + dns_rbtnodechain_t chain; + dns_name_t foundname; + dns_fixedname_t fixedorigin; + dns_name_t *origin; + isc_stdtime_t now; + dns_rbtnode_t *node; + dns_tsigkey_t *tkey; + dns_tsig_keyring_t *ring; + unsigned int references; + + REQUIRE(ringp != NULL && *ringp != NULL); + + ring = *ringp; + *ringp = NULL; + + RWLOCK(&ring->lock, isc_rwlocktype_write); + INSIST(ring->references > 0); + ring->references--; + references = ring->references; + RWUNLOCK(&ring->lock, isc_rwlocktype_write); + + if (references != 0) + return (DNS_R_CONTINUE); + + isc_stdtime_get(&now); + dns_name_init(&foundname, NULL); + dns_fixedname_init(&fixedorigin); + origin = dns_fixedname_name(&fixedorigin); + dns_rbtnodechain_init(&chain, ring->mctx); + result = dns_rbtnodechain_first(&chain, ring->keys, &foundname, + origin); + if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { + dns_rbtnodechain_invalidate(&chain); + goto destroy; + } + + for (;;) { + node = NULL; + dns_rbtnodechain_current(&chain, &foundname, origin, &node); + tkey = node->data; + if (tkey != NULL && tkey->generated && tkey->expire >= now) + dump_key(tkey, fp); + result = dns_rbtnodechain_next(&chain, &foundname, + origin); + if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { + dns_rbtnodechain_invalidate(&chain); + if (result == ISC_R_NOMORE) + result = ISC_R_SUCCESS; + goto destroy; + } + } + + destroy: + destroyring(ring); + return (result); +} + isc_result_t dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm, unsigned char *secret, int length, isc_boolean_t generated, @@ -1589,14 +1783,43 @@ dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) { ring->maxgenerated = DNS_TSIG_MAXGENERATEDKEYS; ISC_LIST_INIT(ring->lru); isc_mem_attach(mctx, &ring->mctx); + ring->references = 1; *ringp = ring; return (ISC_R_SUCCESS); } +isc_result_t +dns_tsigkeyring_add(dns_tsig_keyring_t *ring, dns_name_t *name, + dns_tsigkey_t *tkey) +{ + isc_result_t result; + + result = keyring_add(ring, name, tkey); + if (result == ISC_R_SUCCESS) + isc_refcount_increment(&tkey->refs, NULL); + + return (result); +} + void -dns_tsigkeyring_destroy(dns_tsig_keyring_t **ringp) { +dns_tsigkeyring_attach(dns_tsig_keyring_t *source, dns_tsig_keyring_t **target) +{ + REQUIRE(source != NULL); + REQUIRE(target != NULL && *target == NULL); + + RWLOCK(&source->lock, isc_rwlocktype_write); + INSIST(source->references > 0); + source->references++; + INSIST(source->references > 0); + *target = source; + RWUNLOCK(&source->lock, isc_rwlocktype_write); +} + +void +dns_tsigkeyring_detach(dns_tsig_keyring_t **ringp) { dns_tsig_keyring_t *ring; + unsigned int references; REQUIRE(ringp != NULL); REQUIRE(*ringp != NULL); @@ -1604,7 +1827,27 @@ dns_tsigkeyring_destroy(dns_tsig_keyring_t **ringp) { ring = *ringp; *ringp = NULL; - dns_rbt_destroy(&ring->keys); - isc_rwlock_destroy(&ring->lock); - isc_mem_putanddetach(&ring->mctx, ring, sizeof(dns_tsig_keyring_t)); + RWLOCK(&ring->lock, isc_rwlocktype_write); + INSIST(ring->references > 0); + ring->references--; + references = ring->references; + RWUNLOCK(&ring->lock, isc_rwlocktype_write); + + if (references == 0) + destroyring(ring); +} + +void +dns_keyring_restore(dns_tsig_keyring_t *ring, FILE *fp) { + isc_stdtime_t now; + isc_result_t result; + + isc_stdtime_get(&now); + do { + result = restore_key(ring, now, fp); + if (result == ISC_R_NOMORE) + return; + if (result == DNS_R_BADALG || result == DNS_R_EXPIRED) + result = ISC_R_SUCCESS; + } while (result == ISC_R_SUCCESS); } diff --git a/lib/dns/validator.c b/lib/dns/validator.c index 79c8798..6c0d38d 100644 --- a/lib/dns/validator.c +++ b/lib/dns/validator.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: validator.c,v 1.164.12.23.4.3 2011-06-21 20:13:23 each Exp $ */ +/* $Id: validator.c,v 1.197.40.3 2011-06-21 20:15:54 each Exp $ */ #include @@ -28,17 +28,17 @@ #include #include -#include #include +#include #include #include +#include #include #include #include #include #include #include -#include #include #include #include @@ -255,9 +255,17 @@ dlv_algorithm_supported(dns_validator_t *val) { dlv.algorithm)) continue; +#ifdef HAVE_OPENSSL_GOST + if (dlv.digest_type != DNS_DSDIGEST_SHA256 && + dlv.digest_type != DNS_DSDIGEST_SHA1 && + dlv.digest_type != DNS_DSDIGEST_GOST) + continue; +#else if (dlv.digest_type != DNS_DSDIGEST_SHA256 && dlv.digest_type != DNS_DSDIGEST_SHA1) continue; +#endif + return (ISC_TRUE); } @@ -383,7 +391,7 @@ isdelegation(dns_name_t *name, dns_rdataset_t *rdataset, } /*% - * We have been asked to to look for a key. + * We have been asked to look for a key. * If found resume the validation process. * If not found fail the validation process. */ @@ -582,7 +590,8 @@ dsfetched2(isc_task_t *task, isc_event_t *event) { if (isdelegation(tname, &val->frdataset, eresult)) { if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, - "must be secure failure"); + "must be secure failure, no DS" + " and this is a delegation"); validator_done(val, DNS_R_MUSTBESECURE); } else if (val->view->dlv == NULL || DLVTRIED(val)) { markanswer(val, "dsfetched2"); @@ -1089,7 +1098,7 @@ nsec3noexistnodata(dns_validator_t *val, dns_name_t* name, if (ns && !soa) { if (!atparent) { /* - * This NSEC record is from somewhere + * This NSEC3 record is from somewhere * higher in the DNS, and at the * parent of a delegation. It can not * be legitimately used here. @@ -1100,7 +1109,7 @@ nsec3noexistnodata(dns_validator_t *val, dns_name_t* name, } } else if (atparent && ns && soa) { /* - * This NSEC record is from the child. + * This NSEC3 record is from the child. * It can not be legitimately used here. */ validator_log(val, ISC_LOG_DEBUG(3), @@ -1505,8 +1514,11 @@ create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type, if (dns_rdataset_isassociated(&val->fsigrdataset)) dns_rdataset_disassociate(&val->fsigrdataset); - if (check_deadlock(val, name, type, NULL, NULL)) + if (check_deadlock(val, name, type, NULL, NULL)) { + validator_log(val, ISC_LOG_DEBUG(3), + "deadlock found (create_fetch)"); return (DNS_R_NOVALIDSIG); + } validator_logcreate(val, name, type, caller, "fetch"); return (dns_resolver_createfetch(val->view->resolver, name, type, @@ -1528,8 +1540,11 @@ create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type, { isc_result_t result; - if (check_deadlock(val, name, type, rdataset, sigrdataset)) + if (check_deadlock(val, name, type, rdataset, sigrdataset)) { + validator_log(val, ISC_LOG_DEBUG(3), + "deadlock found (create_validator)"); return (DNS_R_NOVALIDSIG); + } validator_logcreate(val, name, type, caller, "validator"); result = dns_validator_create(val->view, name, type, @@ -1768,16 +1783,23 @@ compute_keytag(dns_rdata_t *rdata, dns_rdata_dnskey_t *key) { */ static isc_boolean_t isselfsigned(dns_validator_t *val) { + dns_fixedname_t fixed; dns_rdataset_t *rdataset, *sigrdataset; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_t sigrdata = DNS_RDATA_INIT; dns_rdata_dnskey_t key; dns_rdata_rrsig_t sig; dns_keytag_t keytag; + dns_name_t *name; isc_result_t result; + dst_key_t *dstkey; + isc_mem_t *mctx; + isc_boolean_t answer = ISC_FALSE; rdataset = val->event->rdataset; sigrdataset = val->event->sigrdataset; + name = val->event->name; + mctx = val->view->mctx; INSIST(rdataset->type == dns_rdatatype_dnskey); @@ -1799,12 +1821,31 @@ isselfsigned(dns_validator_t *val) { result = dns_rdata_tostruct(&sigrdata, &sig, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); - if (sig.algorithm == key.algorithm && - sig.keyid == keytag) - return (ISC_TRUE); + if (sig.algorithm != key.algorithm || + sig.keyid != keytag || + !dns_name_equal(name, &sig.signer)) + continue; + + dstkey = NULL; + result = dns_dnssec_keyfromrdata(name, &rdata, mctx, + &dstkey); + if (result != ISC_R_SUCCESS) + continue; + + result = dns_dnssec_verify2(name, rdataset, dstkey, + ISC_TRUE, mctx, &sigrdata, + dns_fixedname_name(&fixed)); + dst_key_free(&dstkey); + if (result != ISC_R_SUCCESS) + continue; + if ((key.flags & DNS_KEYFLAG_REVOKE) == 0) { + answer = ISC_TRUE; + continue; + } + dns_view_untrust(val->view, name, &key, mctx); } } - return (ISC_FALSE); + return (answer); } /*% @@ -1946,6 +1987,8 @@ validate(dns_validator_t *val, isc_boolean_t resume) { break; } val->key = dns_keynode_key(val->keynode); + if (val->key == NULL) + break; } else { if (get_dst_key(val, val->siginfo, val->keyset) != ISC_R_SUCCESS) @@ -1962,8 +2005,6 @@ validate(dns_validator_t *val, isc_boolean_t resume) { isc_stdtime_get(&now); ttl = ISC_MIN(event->rdataset->ttl, val->siginfo->timeexpire - now); - if (val->keyset != NULL) - ttl = ISC_MIN(ttl, val->keyset->ttl); event->rdataset->ttl = ttl; event->sigrdataset->ttl = ttl; } @@ -1992,7 +2033,8 @@ validate(dns_validator_t *val, isc_boolean_t resume) { } else if (result == ISC_R_SUCCESS) { marksecure(event); validator_log(val, ISC_LOG_DEBUG(3), - "marking as secure"); + "marking as secure, " + "noqname proof not needed"); return (result); } else { validator_log(val, ISC_LOG_DEBUG(3), @@ -2013,25 +2055,102 @@ validate(dns_validator_t *val, isc_boolean_t resume) { } /*% + * Check whether this DNSKEY (keyrdata) signed the DNSKEY RRset + * (val->event->rdataset). + */ +static isc_result_t +checkkey(dns_validator_t *val, dns_rdata_t *keyrdata, isc_uint16_t keyid, + dns_secalg_t algorithm) +{ + dns_rdata_rrsig_t sig; + dst_key_t *dstkey = NULL; + isc_result_t result; + + for (result = dns_rdataset_first(val->event->sigrdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(val->event->sigrdataset)) + { + dns_rdata_t rdata = DNS_RDATA_INIT; + + dns_rdataset_current(val->event->sigrdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &sig, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + if (keyid != sig.keyid || algorithm != sig.algorithm) + continue; + if (dstkey == NULL) { + result = dns_dnssec_keyfromrdata(val->event->name, + keyrdata, + val->view->mctx, + &dstkey); + if (result != ISC_R_SUCCESS) + /* + * This really shouldn't happen, but... + */ + continue; + } + result = verify(val, dstkey, &rdata, sig.keyid); + if (result == ISC_R_SUCCESS) + break; + } + if (dstkey != NULL) + dst_key_free(&dstkey); + return (result); +} + +/*% + * Find the DNSKEY that corresponds to the DS. + */ +static isc_result_t +keyfromds(dns_validator_t *val, dns_rdataset_t *rdataset, dns_rdata_t *dsrdata, + isc_uint8_t digest, isc_uint16_t keyid, dns_secalg_t algorithm, + dns_rdata_t *keyrdata) +{ + dns_keytag_t keytag; + dns_rdata_dnskey_t key; + isc_result_t result; + unsigned char dsbuf[DNS_DS_BUFFERSIZE]; + + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) + { + dns_rdata_t newdsrdata = DNS_RDATA_INIT; + + dns_rdata_reset(keyrdata); + dns_rdataset_current(rdataset, keyrdata); + result = dns_rdata_tostruct(keyrdata, &key, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + keytag = compute_keytag(keyrdata, &key); + if (keyid != keytag || algorithm != key.algorithm) + continue; + dns_rdata_reset(&newdsrdata); + result = dns_ds_buildrdata(val->event->name, keyrdata, digest, + dsbuf, &newdsrdata); + if (result != ISC_R_SUCCESS) { + validator_log(val, ISC_LOG_DEBUG(3), + "dns_ds_buildrdata() -> %s", + dns_result_totext(result)); + continue; + } + if (dns_rdata_compare(dsrdata, &newdsrdata) == 0) + break; + } + return (result); +} + +/*% * Validate the DNSKEY RRset by looking for a DNSKEY that matches a * DLV record and that also verifies the DNSKEY RRset. */ static isc_result_t dlv_validatezonekey(dns_validator_t *val) { - dns_keytag_t keytag; dns_rdata_dlv_t dlv; - dns_rdata_dnskey_t key; - dns_rdata_rrsig_t sig; dns_rdata_t dlvrdata = DNS_RDATA_INIT; dns_rdata_t keyrdata = DNS_RDATA_INIT; - dns_rdata_t newdsrdata = DNS_RDATA_INIT; - dns_rdata_t sigrdata = DNS_RDATA_INIT; dns_rdataset_t trdataset; - dst_key_t *dstkey; isc_boolean_t supported_algorithm; isc_result_t result; - unsigned char dsbuf[DNS_DS_BUFFERSIZE]; - isc_uint8_t digest_type; + char digest_types[256]; validator_log(val, ISC_LOG_DEBUG(3), "dlv_validatezonekey"); @@ -2048,7 +2167,7 @@ dlv_validatezonekey(dns_validator_t *val) { * need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256 * is present. */ - digest_type = DNS_DSDIGEST_SHA1; + memset(digest_types, 1, sizeof(digest_types)); for (result = dns_rdataset_first(&val->dlv); result == ISC_R_SUCCESS; result = dns_rdataset_next(&val->dlv)) { @@ -2064,7 +2183,7 @@ dlv_validatezonekey(dns_validator_t *val) { if (dlv.digest_type == DNS_DSDIGEST_SHA256 && dlv.length == ISC_SHA256_DIGESTLENGTH) { - digest_type = DNS_DSDIGEST_SHA256; + digest_types[DNS_DSDIGEST_SHA1] = 0; break; } } @@ -2082,7 +2201,7 @@ dlv_validatezonekey(dns_validator_t *val) { dlv.digest_type)) continue; - if (dlv.digest_type != digest_type) + if (digest_types[dlv.digest_type] == 0) continue; if (!dns_resolver_algorithm_supported(val->view->resolver, @@ -2095,70 +2214,27 @@ dlv_validatezonekey(dns_validator_t *val) { dns_rdataset_init(&trdataset); dns_rdataset_clone(val->event->rdataset, &trdataset); - for (result = dns_rdataset_first(&trdataset); - result == ISC_R_SUCCESS; - result = dns_rdataset_next(&trdataset)) - { - dns_rdata_reset(&keyrdata); - dns_rdataset_current(&trdataset, &keyrdata); - result = dns_rdata_tostruct(&keyrdata, &key, NULL); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - keytag = compute_keytag(&keyrdata, &key); - if (dlv.key_tag != keytag || - dlv.algorithm != key.algorithm) - continue; - dns_rdata_reset(&newdsrdata); - result = dns_ds_buildrdata(val->event->name, - &keyrdata, dlv.digest_type, - dsbuf, &newdsrdata); - if (result != ISC_R_SUCCESS) { - validator_log(val, ISC_LOG_DEBUG(3), - "dns_ds_buildrdata() -> %s", - dns_result_totext(result)); - continue; - } - /* Covert to DLV */ - newdsrdata.type = dns_rdatatype_dlv; - if (dns_rdata_compare(&dlvrdata, &newdsrdata) == 0) - break; - } + /* + * Convert to DLV to DS and find matching DNSKEY. + */ + dlvrdata.type = dns_rdatatype_ds; + result = keyfromds(val, &trdataset, &dlvrdata, + dlv.digest_type, dlv.key_tag, + dlv.algorithm, &keyrdata); if (result != ISC_R_SUCCESS) { dns_rdataset_disassociate(&trdataset); validator_log(val, ISC_LOG_DEBUG(3), "no DNSKEY matching DLV"); continue; } + validator_log(val, ISC_LOG_DEBUG(3), "Found matching DLV record: checking for signature"); + /* + * Check that this DNSKEY signed the DNSKEY rrset. + */ + result = checkkey(val, &keyrdata, dlv.key_tag, dlv.algorithm); - for (result = dns_rdataset_first(val->event->sigrdataset); - result == ISC_R_SUCCESS; - result = dns_rdataset_next(val->event->sigrdataset)) - { - dns_rdata_reset(&sigrdata); - dns_rdataset_current(val->event->sigrdataset, - &sigrdata); - result = dns_rdata_tostruct(&sigrdata, &sig, NULL); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - if (dlv.key_tag != sig.keyid || - dlv.algorithm != sig.algorithm) - continue; - dstkey = NULL; - result = dns_dnssec_keyfromrdata(val->event->name, - &keyrdata, - val->view->mctx, - &dstkey); - if (result != ISC_R_SUCCESS) - /* - * This really shouldn't happen, but... - */ - continue; - - result = verify(val, dstkey, &sigrdata, sig.keyid); - dst_key_free(&dstkey); - if (result == ISC_R_SUCCESS) - break; - } dns_rdataset_disassociate(&trdataset); if (result == ISC_R_SUCCESS) break; @@ -2167,12 +2243,13 @@ dlv_validatezonekey(dns_validator_t *val) { } if (result == ISC_R_SUCCESS) { marksecure(val->event); - validator_log(val, ISC_LOG_DEBUG(3), "marking as secure"); + validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (dlv)"); return (result); } else if (result == ISC_R_NOMORE && !supported_algorithm) { if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, - "must be secure failure"); + "must be secure failure," + "no supported algorithm/digest (dlv)"); return (DNS_R_MUSTBESECURE); } validator_log(val, ISC_LOG_DEBUG(3), @@ -2184,7 +2261,8 @@ dlv_validatezonekey(dns_validator_t *val) { } /*% - * Attempts positive response validation of an RRset containing zone keys. + * Attempts positive response validation of an RRset containing zone keys + * (i.e. a DNSKEY rrset). * * Returns: * \li ISC_R_SUCCESS Validation completed successfully @@ -2198,19 +2276,15 @@ validatezonekey(dns_validator_t *val) { dns_validatorevent_t *event; dns_rdataset_t trdataset; dns_rdata_t dsrdata = DNS_RDATA_INIT; - dns_rdata_t newdsrdata = DNS_RDATA_INIT; dns_rdata_t keyrdata = DNS_RDATA_INIT; dns_rdata_t sigrdata = DNS_RDATA_INIT; - unsigned char dsbuf[DNS_DS_BUFFERSIZE]; char namebuf[DNS_NAME_FORMATSIZE]; - dns_keytag_t keytag; dns_rdata_ds_t ds; - dns_rdata_dnskey_t key; dns_rdata_rrsig_t sig; dst_key_t *dstkey; isc_boolean_t supported_algorithm; isc_boolean_t atsep = ISC_FALSE; - isc_uint8_t digest_type; + char digest_types[256]; /* * Caller must be holding the validator lock. @@ -2259,8 +2333,7 @@ validatezonekey(dns_validator_t *val) { result = dns_keytable_findkeynode(val->keytable, val->event->name, sig.algorithm, - sig.keyid, - &keynode); + sig.keyid, &keynode); if (result == ISC_R_NOTFOUND && dns_keytable_finddeepestmatch(val->keytable, val->event->name, found) != ISC_R_SUCCESS) { @@ -2284,11 +2357,18 @@ validatezonekey(dns_validator_t *val) { while (result == ISC_R_SUCCESS) { dns_keynode_t *nextnode = NULL; dstkey = dns_keynode_key(keynode); + if (dstkey == NULL) { + dns_keytable_detachkeynode( + val->keytable, + &keynode); + break; + } result = verify(val, dstkey, &sigrdata, sig.keyid); if (result == ISC_R_SUCCESS) { - dns_keytable_detachkeynode(val->keytable, - &keynode); + dns_keytable_detachkeynode( + val->keytable, + &keynode); break; } result = dns_keytable_findnextkeynode( @@ -2318,8 +2398,8 @@ validatezonekey(dns_validator_t *val) { sizeof(namebuf)); validator_log(val, ISC_LOG_NOTICE, "unable to find a DNSKEY which verifies " - "the DNSKEY RRset and also matches one " - "of specified trusted-keys for '%s'", + "the DNSKEY RRset and also matches a " + "trusted key for '%s'", namebuf); validator_log(val, ISC_LOG_NOTICE, "please check the 'trusted-keys' for " @@ -2413,7 +2493,8 @@ validatezonekey(dns_validator_t *val) { if (val->dsset->trust < dns_trust_secure) { if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, - "must be secure failure"); + "must be secure failure," + " insecure DS"); return (DNS_R_MUSTBESECURE); } if (val->view->dlv == NULL || DLVTRIED(val)) { @@ -2437,7 +2518,7 @@ validatezonekey(dns_validator_t *val) { * need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256 * is present. */ - digest_type = DNS_DSDIGEST_SHA1; + memset(digest_types, 1, sizeof(digest_types)); for (result = dns_rdataset_first(val->dsset); result == ISC_R_SUCCESS; result = dns_rdataset_next(val->dsset)) { @@ -2453,7 +2534,7 @@ validatezonekey(dns_validator_t *val) { if (ds.digest_type == DNS_DSDIGEST_SHA256 && ds.length == ISC_SHA256_DIGESTLENGTH) { - digest_type = DNS_DSDIGEST_SHA256; + digest_types[DNS_DSDIGEST_SHA1] = 0; break; } } @@ -2471,7 +2552,7 @@ validatezonekey(dns_validator_t *val) { ds.digest_type)) continue; - if (ds.digest_type != digest_type) + if (digest_types[ds.digest_type] == 0) continue; if (!dns_resolver_algorithm_supported(val->view->resolver, @@ -2485,29 +2566,10 @@ validatezonekey(dns_validator_t *val) { dns_rdataset_clone(val->event->rdataset, &trdataset); /* - * Look for the KEY that matches the DS record. + * Find matching DNSKEY from DS. */ - for (result = dns_rdataset_first(&trdataset); - result == ISC_R_SUCCESS; - result = dns_rdataset_next(&trdataset)) - { - dns_rdata_reset(&keyrdata); - dns_rdataset_current(&trdataset, &keyrdata); - result = dns_rdata_tostruct(&keyrdata, &key, NULL); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - keytag = compute_keytag(&keyrdata, &key); - if (ds.key_tag != keytag || - ds.algorithm != key.algorithm) - continue; - dns_rdata_reset(&newdsrdata); - result = dns_ds_buildrdata(val->event->name, - &keyrdata, ds.digest_type, - dsbuf, &newdsrdata); - if (result != ISC_R_SUCCESS) - continue; - if (dns_rdata_compare(&dsrdata, &newdsrdata) == 0) - break; - } + result = keyfromds(val, &trdataset, &dsrdata, ds.digest_type, + ds.key_tag, ds.algorithm, &keyrdata); if (result != ISC_R_SUCCESS) { dns_rdataset_disassociate(&trdataset); validator_log(val, ISC_LOG_DEBUG(3), @@ -2515,38 +2577,11 @@ validatezonekey(dns_validator_t *val) { continue; } - for (result = dns_rdataset_first(val->event->sigrdataset); - result == ISC_R_SUCCESS; - result = dns_rdataset_next(val->event->sigrdataset)) - { - dns_rdata_reset(&sigrdata); - dns_rdataset_current(val->event->sigrdataset, - &sigrdata); - result = dns_rdata_tostruct(&sigrdata, &sig, NULL); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - if (ds.key_tag != sig.keyid || - ds.algorithm != sig.algorithm) - continue; - if (!dns_name_equal(val->event->name, &sig.signer)) { - validator_log(val, ISC_LOG_DEBUG(3), - "DNSKEY signer mismatch"); - continue; - } - dstkey = NULL; - result = dns_dnssec_keyfromrdata(val->event->name, - &keyrdata, - val->view->mctx, - &dstkey); - if (result != ISC_R_SUCCESS) - /* - * This really shouldn't happen, but... - */ - continue; - result = verify(val, dstkey, &sigrdata, sig.keyid); - dst_key_free(&dstkey); - if (result == ISC_R_SUCCESS) - break; - } + /* + * Check that this DNSKEY signed the DNSKEY rrset. + */ + result = checkkey(val, &keyrdata, ds.key_tag, ds.algorithm); + dns_rdataset_disassociate(&trdataset); if (result == ISC_R_SUCCESS) break; @@ -2555,20 +2590,24 @@ validatezonekey(dns_validator_t *val) { } if (result == ISC_R_SUCCESS) { marksecure(event); - validator_log(val, ISC_LOG_DEBUG(3), "marking as secure"); + validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (DS)"); return (result); } else if (result == ISC_R_NOMORE && !supported_algorithm) { if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, - "must be secure failure"); + "must be secure failure, " + "no supported algorithm/digest (DS)"); return (DNS_R_MUSTBESECURE); } validator_log(val, ISC_LOG_DEBUG(3), "no supported algorithm/digest (DS)"); markanswer(val, "validatezonekey (3)"); return (ISC_R_SUCCESS); - } else + } else { + validator_log(val, ISC_LOG_INFO, + "no valid signature found (DS)"); return (DNS_R_NOVALIDSIG); + } } /*% @@ -3094,9 +3133,7 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) { findnsec3proofs(val); if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val)) { validator_log(val, ISC_LOG_DEBUG(3), - "noqname proof found"); - validator_log(val, ISC_LOG_DEBUG(3), - "marking as secure"); + "marking as secure, noqname proof found"); marksecure(val->event); return (ISC_R_SUCCESS); } else if (FOUNDOPTOUT(val) && @@ -3143,7 +3180,6 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) { marksecure(val->event); return (ISC_R_SUCCESS); } - findnsec3proofs(val); if (val->authfail != 0 && val->authcount == val->authfail) return (DNS_R_BROKENCHAIN); @@ -3345,7 +3381,8 @@ startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) { namebuf); if (dns_name_issubdomain(val->event->name, val->view->dlv)) { - validator_log(val, ISC_LOG_WARNING, "must be secure failure"); + validator_log(val, ISC_LOG_WARNING, "must be secure failure, " + " %s is under DLV (startfinddlvsep)", namebuf); return (DNS_R_MUSTBESECURE); } @@ -3397,10 +3434,12 @@ finddlvsep(dns_validator_t *val, isc_boolean_t resume) { INSIST(val->view->dlv != NULL); if (!resume) { - if (dns_name_issubdomain(val->event->name, val->view->dlv)) { + dns_name_format(val->event->name, namebuf, + sizeof(namebuf)); validator_log(val, ISC_LOG_WARNING, - "must be secure failure"); + "must be secure failure, " + "%s is under DLV (finddlvsep)", namebuf); return (DNS_R_MUSTBESECURE); } @@ -3468,8 +3507,11 @@ finddlvsep(dns_validator_t *val, isc_boolean_t resume) { return (result); return (DNS_R_WAIT); } - if (val->frdataset.trust < dns_trust_secure) + if (val->frdataset.trust < dns_trust_secure) { + validator_log(val, ISC_LOG_DEBUG(3), + "DLV not validated"); return (DNS_R_NOVALIDSIG); + } val->havedlvsep = ISC_TRUE; dns_rdataset_clone(&val->frdataset, &val->dlv); return (ISC_R_SUCCESS); @@ -3554,10 +3596,13 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) if (result == ISC_R_NOTFOUND) { if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, - "must be secure failure"); + "must be secure failure, " + "not beneath secure root"); result = DNS_R_MUSTBESECURE; goto out; - } + } else + validator_log(val, ISC_LOG_DEBUG(3), + "not beneath secure root"); if (val->view->dlv == NULL || DLVTRIED(val)) { markanswer(val, "proveunsecure (1)"); return (ISC_R_SUCCESS); @@ -3577,7 +3622,7 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) /* * If we have a DS rdataset and it is secure then check if * the DS rdataset has a supported algorithm combination. - * If not this is a insecure delegation as far as this + * If not this is an insecure delegation as far as this * resolver is concerned. Fall back to DLV if available. */ if (have_ds && val->frdataset.trust >= dns_trust_secure && @@ -3588,7 +3633,8 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) if ((val->view->dlv == NULL || DLVTRIED(val)) && val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, - "must be secure failure at '%s'", + "must be secure failure at '%s', " + "can't fall back to DLV", namebuf); result = DNS_R_MUSTBESECURE; goto out; @@ -3630,7 +3676,7 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) { /* * There is no DS. If this is a delegation, - * we maybe done. + * we may be done. */ /* * If we have "trust == answer" then this namespace @@ -3643,7 +3689,7 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) &val->frdataset, NULL, dsvalidated, "proveunsecure"); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) goto out; return (DNS_R_WAIT); } @@ -3655,12 +3701,13 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) if (result == DNS_R_NXRRSET && !dns_rdataset_isassociated(&val->frdataset) && dns_view_findzonecut2(val->view, tname, found, - 0, 0, ISC_FALSE, ISC_FALSE, - NULL, NULL) == ISC_R_SUCCESS && + 0, 0, ISC_FALSE, ISC_FALSE, + NULL, NULL) == ISC_R_SUCCESS && dns_name_equal(tname, found)) { if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, - "must be secure failure"); + "must be secure failure, " + "no DS at zone cut"); return (DNS_R_MUSTBESECURE); } if (val->view->dlv == NULL || DLVTRIED(val)) { @@ -3676,13 +3723,18 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) * there's no way of validating existing * negative response blobs, give up. */ + validator_log(val, ISC_LOG_WARNING, + "can't validate existing " + "negative responses (no DS)"); result = DNS_R_NOVALIDSIG; goto out; } if (isdelegation(tname, &val->frdataset, result)) { if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, - "must be secure failure"); + "must be secure failure, " + "%s is a delegation", + namebuf); return (DNS_R_MUSTBESECURE); } if (val->view->dlv == NULL || DLVTRIED(val)) { @@ -3705,7 +3757,10 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, - "must be secure failure"); + "must be secure failure, " + "no supported algorithm/" + "digest (%s/DS)", + namebuf); result = DNS_R_MUSTBESECURE; goto out; } @@ -3723,6 +3778,8 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) } else if (!dns_rdataset_isassociated(&val->fsigrdataset)) { + validator_log(val, ISC_LOG_DEBUG(3), + "DS is unsigned"); result = DNS_R_NOVALIDSIG; goto out; } @@ -3771,6 +3828,10 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) * there's no way of validating existing * negative response blobs, give up. */ + validator_log(val, ISC_LOG_WARNING, + "can't validate existing " + "negative responses " + "(not a zone cut)"); result = DNS_R_NOVALIDSIG; goto out; } @@ -3790,7 +3851,7 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) /* Couldn't complete insecurity proof */ validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed"); - return (DNS_R_NOTINSECURE); /* Couldn't complete insecurity proof */ + return (DNS_R_NOTINSECURE); out: if (dns_rdataset_isassociated(&val->frdataset)) @@ -3829,7 +3890,7 @@ dlv_validator_start(dns_validator_t *val) { * \li 3. a negative answer (secure or unsecure). * * Note a answer that appears to be a secure positive answer may actually - * be a unsecure positive answer. + * be an unsecure positive answer. */ static void validator_start(isc_task_t *task, isc_event_t *event) { @@ -3895,6 +3956,10 @@ validator_start(isc_task_t *task, isc_event_t *event) { val->attributes |= VALATTR_INSECURITY; result = proveunsecure(val, ISC_FALSE, ISC_FALSE); + if (result == DNS_R_NOTINSECURE) + validator_log(val, ISC_LOG_INFO, + "got insecure response; " + "parent indicates it should be secure"); } else if (val->event->rdataset == NULL && val->event->sigrdataset == NULL) { @@ -3967,6 +4032,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, return (ISC_R_NOMEMORY); val->view = NULL; dns_view_weakattach(view, &val->view); + event = (dns_validatorevent_t *) isc_event_allocate(view->mctx, task, DNS_EVENT_VALIDATORSTART, @@ -3995,8 +4061,12 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, val->fetch = NULL; val->subvalidator = NULL; val->parent = NULL; + val->keytable = NULL; - dns_keytable_attach(val->view->secroots, &val->keytable); + result = dns_view_getsecroots(val->view, &val->keytable); + if (result != ISC_R_SUCCESS) + return (result); + val->keynode = NULL; val->key = NULL; val->siginfo = NULL; diff --git a/lib/dns/view.c b/lib/dns/view.c index 809cc15..24f925a 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,13 +15,16 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: view.c,v 1.150.84.6 2010-09-24 08:09:08 marka Exp $ */ +/* $Id: view.c,v 1.178 2011-01-13 09:53:04 marka Exp $ */ /*! \file */ #include +#include #include +#include +#include #include #include /* Required for HP/UX (and others?) */ #include @@ -33,17 +36,24 @@ #include #include #include +#ifdef BIND9 +#include +#endif +#include #include #include #include +#include #include #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -85,6 +95,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, if (result != ISC_R_SUCCESS) goto cleanup_name; +#ifdef BIND9 view->zonetable = NULL; result = dns_zt_create(mctx, rdclass, &view->zonetable); if (result != ISC_R_SUCCESS) { @@ -94,24 +105,8 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, result = ISC_R_UNEXPECTED; goto cleanup_mutex; } - view->secroots = NULL; - result = dns_keytable_create(mctx, &view->secroots); - if (result != ISC_R_SUCCESS) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "dns_keytable_create() failed: %s", - isc_result_totext(result)); - result = ISC_R_UNEXPECTED; - goto cleanup_zt; - } - view->trustedkeys = NULL; - result = dns_keytable_create(mctx, &view->trustedkeys); - if (result != ISC_R_SUCCESS) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "dns_keytable_create() failed: %s", - isc_result_totext(result)); - result = ISC_R_UNEXPECTED; - goto cleanup_secroots; - } +#endif + view->secroots_priv = NULL; view->fwdtable = NULL; result = dns_fwdtable_create(mctx, &view->fwdtable); if (result != ISC_R_SUCCESS) { @@ -119,7 +114,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, "dns_fwdtable_create() failed: %s", isc_result_totext(result)); result = ISC_R_UNEXPECTED; - goto cleanup_trustedkeys; + goto cleanup_zt; } view->acache = NULL; @@ -155,6 +150,9 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, view->rootexclude = NULL; view->resstats = NULL; view->resquerystats = NULL; + view->cacheshared = ISC_FALSE; + ISC_LIST_INIT(view->dns64); + view->dns64cnt = 0; /* * Initialize configuration data with default values. @@ -179,6 +177,10 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, view->notifyacl = NULL; view->updateacl = NULL; view->upfwdacl = NULL; + view->denyansweracl = NULL; + view->answeracl_exclude = NULL; + view->denyanswernames = NULL; + view->answernames_exclude = NULL; view->requestixfr = ISC_TRUE; view->provideixfr = ISC_TRUE; view->maxcachettl = 7 * 24 * 3600; @@ -188,11 +190,20 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, view->flush = ISC_FALSE; view->dlv = NULL; view->maxudp = 0; + view->v4_aaaa = dns_v4_aaaa_ok; + view->v4_aaaa_acl = NULL; + ISC_LIST_INIT(view->rpz_zones); dns_fixedname_init(&view->dlv_fixed); + view->managed_keys = NULL; +#ifdef BIND9 + view->new_zone_file = NULL; + view->new_zone_config = NULL; + view->cfg_destroy = NULL; result = dns_order_create(view->mctx, &view->order); if (result != ISC_R_SUCCESS) goto cleanup_dynkeys; +#endif result = dns_peerlist_new(view->mctx, &view->peers); if (result != ISC_R_SUCCESS) @@ -222,10 +233,12 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_peerlist_detach(&view->peers); cleanup_order: +#ifdef BIND9 dns_order_detach(&view->order); cleanup_dynkeys: - dns_tsigkeyring_destroy(&view->dynamickeys); +#endif + dns_tsigkeyring_detach(&view->dynamickeys); cleanup_references: isc_refcount_destroy(&view->references); @@ -233,16 +246,12 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, cleanup_fwdtable: dns_fwdtable_destroy(&view->fwdtable); - cleanup_trustedkeys: - dns_keytable_detach(&view->trustedkeys); - - cleanup_secroots: - dns_keytable_detach(&view->secroots); - cleanup_zt: +#ifdef BIND9 dns_zt_detach(&view->zonetable); cleanup_mutex: +#endif DESTROYLOCK(&view->lock); cleanup_name: @@ -256,6 +265,10 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, static inline void destroy(dns_view_t *view) { +#ifdef BIND9 + dns_dns64_t *dns64; +#endif + REQUIRE(!ISC_LINK_LINKED(view, link)); REQUIRE(isc_refcount_current(&view->references) == 0); REQUIRE(view->weakrefs == 0); @@ -263,23 +276,62 @@ destroy(dns_view_t *view) { REQUIRE(ADBSHUTDOWN(view)); REQUIRE(REQSHUTDOWN(view)); +#ifdef BIND9 if (view->order != NULL) dns_order_detach(&view->order); +#endif if (view->peers != NULL) dns_peerlist_detach(&view->peers); - if (view->dynamickeys != NULL) - dns_tsigkeyring_destroy(&view->dynamickeys); + + if (view->dynamickeys != NULL) { + isc_result_t result; + char template[20]; + char keyfile[20]; + FILE *fp = NULL; + int n; + + n = snprintf(keyfile, sizeof(keyfile), "%s.tsigkeys", + view->name); + if (n > 0 && (size_t)n < sizeof(keyfile)) { + result = isc_file_mktemplate(keyfile, template, + sizeof(template)); + if (result == ISC_R_SUCCESS) + (void)isc_file_openuniqueprivate(template, &fp); + } + if (fp == NULL) + dns_tsigkeyring_detach(&view->dynamickeys); + else { + result = dns_tsigkeyring_dumpanddetach( + &view->dynamickeys, fp); + if (result == ISC_R_SUCCESS) { + if (fclose(fp) == 0) + result = isc_file_rename(template, + keyfile); + if (result != ISC_R_SUCCESS) + (void)remove(template); + } else { + (void)fclose(fp); + (void)remove(template); + } + } + } if (view->statickeys != NULL) - dns_tsigkeyring_destroy(&view->statickeys); + dns_tsigkeyring_detach(&view->statickeys); if (view->adb != NULL) dns_adb_detach(&view->adb); if (view->resolver != NULL) dns_resolver_detach(&view->resolver); +#ifdef BIND9 if (view->acache != NULL) { if (view->cachedb != NULL) dns_acache_putdb(view->acache, view->cachedb); dns_acache_detach(&view->acache); } + dns_rpz_view_destroy(view); +#else + INSIST(view->acache == NULL); + INSIST(ISC_LIST_EMPTY(view->rpz_zones)); +#endif if (view->requestmgr != NULL) dns_requestmgr_detach(&view->requestmgr); if (view->task != NULL) @@ -318,6 +370,16 @@ destroy(dns_view_t *view) { dns_acl_detach(&view->updateacl); if (view->upfwdacl != NULL) dns_acl_detach(&view->upfwdacl); + if (view->denyansweracl != NULL) + dns_acl_detach(&view->denyansweracl); + if (view->v4_aaaa_acl != NULL) + dns_acl_detach(&view->v4_aaaa_acl); + if (view->answeracl_exclude != NULL) + dns_rbt_destroy(&view->answeracl_exclude); + if (view->denyanswernames != NULL) + dns_rbt_destroy(&view->denyanswernames); + if (view->answernames_exclude != NULL) + dns_rbt_destroy(&view->answernames_exclude); if (view->delonly != NULL) { dns_name_t *name; int i; @@ -357,8 +419,19 @@ destroy(dns_view_t *view) { isc_stats_detach(&view->resstats); if (view->resquerystats != NULL) dns_stats_detach(&view->resquerystats); - dns_keytable_detach(&view->trustedkeys); - dns_keytable_detach(&view->secroots); + if (view->secroots_priv != NULL) + dns_keytable_detach(&view->secroots_priv); +#ifdef BIND9 + for (dns64 = ISC_LIST_HEAD(view->dns64); + dns64 != NULL; + dns64 = ISC_LIST_HEAD(view->dns64)) { + dns_dns64_unlink(&view->dns64, dns64); + dns_dns64_destroy(&dns64); + } + if (view->managed_keys != NULL) + dns_zone_detach(&view->managed_keys); + dns_view_setnewzones(view, ISC_FALSE, NULL, NULL); +#endif dns_fwdtable_destroy(&view->fwdtable); dns_aclenv_destroy(&view->aclenv); DESTROYLOCK(&view->lock); @@ -414,12 +487,19 @@ view_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) { dns_adb_shutdown(view->adb); if (!REQSHUTDOWN(view)) dns_requestmgr_shutdown(view->requestmgr); +#ifdef BIND9 if (view->acache != NULL) dns_acache_shutdown(view->acache); if (view->flush) dns_zt_flushanddetach(&view->zonetable); else dns_zt_detach(&view->zonetable); + if (view->managed_keys != NULL) { + if (view->flush) + dns_zone_flush(view->managed_keys); + dns_zone_detach(&view->managed_keys); + } +#endif done = all_done(view); UNLOCK(&view->lock); } @@ -440,6 +520,7 @@ dns_view_detach(dns_view_t **viewp) { view_flushanddetach(viewp, ISC_FALSE); } +#ifdef BIND9 static isc_result_t dialup(dns_zone_t *zone, void *dummy) { UNUSED(dummy); @@ -452,6 +533,7 @@ dns_view_dialup(dns_view_t *view) { REQUIRE(DNS_VIEW_VALID(view)); (void)dns_zt_apply(view->zonetable, ISC_FALSE, dialup, NULL); } +#endif void dns_view_weakattach(dns_view_t *source, dns_view_t **targetp) { @@ -633,12 +715,20 @@ dns_view_createresolver(dns_view_t *view, void dns_view_setcache(dns_view_t *view, dns_cache_t *cache) { + dns_view_setcache2(view, cache, ISC_FALSE); +} + +void +dns_view_setcache2(dns_view_t *view, dns_cache_t *cache, isc_boolean_t shared) { REQUIRE(DNS_VIEW_VALID(view)); REQUIRE(!view->frozen); + view->cacheshared = shared; if (view->cache != NULL) { +#ifdef BIND9 if (view->acache != NULL) dns_acache_putdb(view->acache, view->cachedb); +#endif dns_db_detach(&view->cachedb); dns_cache_detach(&view->cache); } @@ -646,8 +736,17 @@ dns_view_setcache(dns_view_t *view, dns_cache_t *cache) { dns_cache_attachdb(cache, &view->cachedb); INSIST(DNS_DB_VALID(view->cachedb)); +#ifdef BIND9 if (view->acache != NULL) dns_acache_setdb(view->acache, view->cachedb); +#endif +} + +isc_boolean_t +dns_view_iscacheshared(dns_view_t *view) { + REQUIRE(DNS_VIEW_VALID(view)); + + return (view->cacheshared); } void @@ -665,26 +764,52 @@ dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring) { REQUIRE(DNS_VIEW_VALID(view)); REQUIRE(ring != NULL); if (view->statickeys != NULL) - dns_tsigkeyring_destroy(&view->statickeys); - view->statickeys = ring; + dns_tsigkeyring_detach(&view->statickeys); + dns_tsigkeyring_attach(ring, &view->statickeys); } void -dns_view_setdstport(dns_view_t *view, in_port_t dstport) { +dns_view_setdynamickeyring(dns_view_t *view, dns_tsig_keyring_t *ring) { REQUIRE(DNS_VIEW_VALID(view)); - view->dstport = dstport; + REQUIRE(ring != NULL); + if (view->dynamickeys != NULL) + dns_tsigkeyring_detach(&view->dynamickeys); + dns_tsigkeyring_attach(ring, &view->dynamickeys); } -isc_result_t -dns_view_addzone(dns_view_t *view, dns_zone_t *zone) { - isc_result_t result; +void +dns_view_getdynamickeyring(dns_view_t *view, dns_tsig_keyring_t **ringp) { + REQUIRE(DNS_VIEW_VALID(view)); + REQUIRE(ringp != NULL && *ringp == NULL); + if (view->dynamickeys != NULL) + dns_tsigkeyring_attach(view->dynamickeys, ringp); +} + +void +dns_view_restorekeyring(dns_view_t *view) { + FILE *fp; + char keyfile[20]; + int n; REQUIRE(DNS_VIEW_VALID(view)); - REQUIRE(!view->frozen); - result = dns_zt_mount(view->zonetable, zone); + if (view->dynamickeys != NULL) { + n = snprintf(keyfile, sizeof(keyfile), "%s.tsigkeys", + view->name); + if (n > 0 && (size_t)n < sizeof(keyfile)) { + fp = fopen(keyfile, "r"); + if (fp != NULL) { + dns_keyring_restore(view->dynamickeys, fp); + (void)fclose(fp); + } + } + } +} - return (result); +void +dns_view_setdstport(dns_view_t *view, in_port_t dstport) { + REQUIRE(DNS_VIEW_VALID(view)); + view->dstport = dstport; } void @@ -699,6 +824,29 @@ dns_view_freeze(dns_view_t *view) { view->frozen = ISC_TRUE; } +#ifdef BIND9 +void +dns_view_thaw(dns_view_t *view) { + REQUIRE(DNS_VIEW_VALID(view)); + REQUIRE(view->frozen); + + view->frozen = ISC_FALSE; +} + +isc_result_t +dns_view_addzone(dns_view_t *view, dns_zone_t *zone) { + isc_result_t result; + + REQUIRE(DNS_VIEW_VALID(view)); + REQUIRE(!view->frozen); + + result = dns_zt_mount(view->zonetable, zone); + + return (result); +} +#endif + +#ifdef BIND9 isc_result_t dns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep) { isc_result_t result; @@ -713,20 +861,37 @@ dns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep) { return (result); } +#endif isc_result_t dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, isc_stdtime_t now, unsigned int options, isc_boolean_t use_hints, dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname, - dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) + dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { + return (dns_view_find2(view, name, type, now, options, use_hints, + ISC_FALSE, dbp, nodep, foundname, rdataset, + sigrdataset)); +} + +isc_result_t +dns_view_find2(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, + isc_stdtime_t now, unsigned int options, + isc_boolean_t use_hints, isc_boolean_t use_static_stub, + dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname, + dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { isc_result_t result; dns_db_t *db, *zdb; dns_dbnode_t *node, *znode; - isc_boolean_t is_cache; + isc_boolean_t is_cache, is_staticstub_zone; dns_rdataset_t zrdataset, zsigrdataset; dns_zone_t *zone; +#ifndef BIND9 + UNUSED(use_hints); + UNUSED(use_static_stub); +#endif + /* * Find an rdataset whose owner name is 'name', and whose type is * 'type'. @@ -752,15 +917,30 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, zone = NULL; db = NULL; node = NULL; + is_staticstub_zone = ISC_FALSE; +#ifdef BIND9 result = dns_zt_find(view->zonetable, name, 0, NULL, &zone); + if (zone != NULL && dns_zone_gettype(zone) == dns_zone_staticstub && + !use_static_stub) { + result = ISC_R_NOTFOUND; + } if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { result = dns_zone_getdb(zone, &db); if (result != ISC_R_SUCCESS && view->cachedb != NULL) dns_db_attach(view->cachedb, &db); else if (result != ISC_R_SUCCESS) goto cleanup; + if (dns_zone_gettype(zone) == dns_zone_staticstub && + dns_name_equal(name, dns_zone_getorigin(zone))) { + is_staticstub_zone = ISC_TRUE; + } } else if (result == ISC_R_NOTFOUND && view->cachedb != NULL) dns_db_attach(view->cachedb, &db); +#else + result = ISC_R_NOTFOUND; + if (view->cachedb != NULL) + dns_db_attach(view->cachedb, &db); +#endif /* BIND9 */ else goto cleanup; @@ -773,8 +953,7 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, result = dns_db_find(db, name, NULL, type, options, now, &node, foundname, rdataset, sigrdataset); - if (result == DNS_R_DELEGATION || - result == ISC_R_NOTFOUND) { + if (result == DNS_R_DELEGATION || result == ISC_R_NOTFOUND) { if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); if (sigrdataset != NULL && @@ -784,10 +963,13 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, dns_db_detachnode(db, &node); if (!is_cache) { dns_db_detach(&db); - if (view->cachedb != NULL) { + if (view->cachedb != NULL && !is_staticstub_zone) { /* * Either the answer is in the cache, or we * don't know it. + * Note that if the result comes from a + * static-stub zone we stop the search here + * (see the function description in view.h). */ is_cache = ISC_TRUE; dns_db_attach(view->cachedb, &db); @@ -817,7 +999,7 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, */ result = ISC_R_NOTFOUND; } else if (result == DNS_R_GLUE) { - if (view->cachedb != NULL) { + if (view->cachedb != NULL && !is_staticstub_zone) { /* * We found an answer, but the cache may be better. * Remember what we've got and go look in the cache. @@ -843,6 +1025,7 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, result = ISC_R_SUCCESS; } +#ifdef BIND9 if (result == ISC_R_NOTFOUND && use_hints && view->hints != NULL) { if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); @@ -877,6 +1060,7 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, if (db == NULL && node != NULL) dns_db_detachnode(view->hints, &node); } +#endif /* BIND9 */ cleanup: if (dns_rdataset_isassociated(&zrdataset)) { @@ -905,8 +1089,10 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, } else INSIST(node == NULL); +#ifdef BIND9 if (zone != NULL) dns_zone_detach(&zone); +#endif return (result); } @@ -969,12 +1155,12 @@ dns_view_findzonecut(dns_view_t *view, dns_name_t *name, dns_name_t *fname, isc_result_t dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname, isc_stdtime_t now, unsigned int options, - isc_boolean_t use_hints, isc_boolean_t use_cache, + isc_boolean_t use_hints, isc_boolean_t use_cache, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { isc_result_t result; dns_db_t *db; - isc_boolean_t is_cache, use_zone, try_hints; + isc_boolean_t is_cache, use_zone, try_hints, is_staticstub_zone; dns_zone_t *zone; dns_name_t *zfname; dns_rdataset_t zrdataset, zsigrdataset; @@ -986,6 +1172,7 @@ dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname, db = NULL; zone = NULL; use_zone = ISC_FALSE; + is_staticstub_zone = ISC_FALSE; try_hints = ISC_FALSE; zfname = NULL; @@ -999,9 +1186,16 @@ dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname, /* * Find the right database. */ +#ifdef BIND9 result = dns_zt_find(view->zonetable, name, 0, NULL, &zone); - if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) + if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { result = dns_zone_getdb(zone, &db); + if (dns_zone_gettype(zone) == dns_zone_staticstub) + is_staticstub_zone = ISC_TRUE; + } +#else + result = ISC_R_NOTFOUND; +#endif if (result == ISC_R_NOTFOUND) { /* * We're not directly authoritative for this query name, nor @@ -1064,7 +1258,9 @@ dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname, fname, rdataset, sigrdataset); if (result == ISC_R_SUCCESS) { if (zfname != NULL && - !dns_name_issubdomain(fname, zfname)) { + (!dns_name_issubdomain(fname, zfname) || + (dns_zone_staticstub && + dns_name_equal(fname, zfname)))) { /* * We found a zonecut in the cache, but our * zone delegation is better. @@ -1133,8 +1329,10 @@ dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname, } if (db != NULL) dns_db_detach(&db); +#ifdef BIND9 if (zone != NULL) dns_zone_detach(&zone); +#endif return (result); } @@ -1161,6 +1359,7 @@ dns_viewlist_find(dns_viewlist_t *list, const char *name, return (ISC_R_SUCCESS); } +#ifdef BIND9 isc_result_t dns_viewlist_findzone(dns_viewlist_t *list, dns_name_t *name, isc_boolean_t allclasses, dns_rdataclass_t rdclass, @@ -1225,6 +1424,7 @@ dns_view_loadnew(dns_view_t *view, isc_boolean_t stop) { return (dns_zt_loadnew(view->zonetable, stop)); } +#endif /* BIND9 */ isc_result_t dns_view_gettsig(dns_view_t *view, dns_name_t *keyname, dns_tsigkey_t **keyp) @@ -1269,6 +1469,7 @@ dns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg) { view->dynamickeys)); } +#ifdef BIND9 isc_result_t dns_view_dumpdbtostream(dns_view_t *view, FILE *fp) { isc_result_t result; @@ -1284,26 +1485,38 @@ dns_view_dumpdbtostream(dns_view_t *view, FILE *fp) { dns_resolver_printbadcache(view->resolver, fp); return (ISC_R_SUCCESS); } +#endif isc_result_t dns_view_flushcache(dns_view_t *view) { + return (dns_view_flushcache2(view, ISC_FALSE)); +} + +isc_result_t +dns_view_flushcache2(dns_view_t *view, isc_boolean_t fixuponly) { isc_result_t result; REQUIRE(DNS_VIEW_VALID(view)); if (view->cachedb == NULL) return (ISC_R_SUCCESS); - result = dns_cache_flush(view->cache); - if (result != ISC_R_SUCCESS) - return (result); + if (!fixuponly) { + result = dns_cache_flush(view->cache); + if (result != ISC_R_SUCCESS) + return (result); + } +#ifdef BIND9 if (view->acache != NULL) dns_acache_putdb(view->acache, view->cachedb); +#endif dns_db_detach(&view->cachedb); dns_cache_attachdb(view->cache, &view->cachedb); +#ifdef BIND9 if (view->acache != NULL) dns_acache_setdb(view->acache, view->cachedb); if (view->resolver != NULL) dns_resolver_flushbadcache(view->resolver, NULL); +#endif dns_adb_flush(view->adb); return (ISC_R_SUCCESS); @@ -1437,11 +1650,13 @@ dns_view_getrootdelonly(dns_view_t *view) { return (view->rootdelonly); } +#ifdef BIND9 isc_result_t dns_view_freezezones(dns_view_t *view, isc_boolean_t value) { REQUIRE(DNS_VIEW_VALID(view)); return (dns_zt_freezezones(view->zonetable, value)); } +#endif void dns_view_setresstats(dns_view_t *view, isc_stats_t *stats) { @@ -1478,3 +1693,97 @@ dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp) { if (view->resquerystats != NULL) dns_stats_attach(view->resquerystats, statsp); } + +isc_result_t +dns_view_initsecroots(dns_view_t *view, isc_mem_t *mctx) { + REQUIRE(DNS_VIEW_VALID(view)); + if (view->secroots_priv != NULL) + dns_keytable_detach(&view->secroots_priv); + return (dns_keytable_create(mctx, &view->secroots_priv)); +} + +isc_result_t +dns_view_getsecroots(dns_view_t *view, dns_keytable_t **ktp) { + REQUIRE(DNS_VIEW_VALID(view)); + REQUIRE(ktp != NULL && *ktp == NULL); + if (view->secroots_priv == NULL) + return (ISC_R_NOTFOUND); + dns_keytable_attach(view->secroots_priv, ktp); + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_view_issecuredomain(dns_view_t *view, dns_name_t *name, + isc_boolean_t *secure_domain) { + REQUIRE(DNS_VIEW_VALID(view)); + return (dns_keytable_issecuredomain(view->secroots_priv, name, + secure_domain)); +} + +void +dns_view_untrust(dns_view_t *view, dns_name_t *keyname, + dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) +{ + isc_result_t result; + unsigned char data[4096]; + dns_rdata_t rdata = DNS_RDATA_INIT; + isc_buffer_t buffer; + dst_key_t *key = NULL; + dns_keytable_t *sr = NULL; + + /* + * Clear the revoke bit, if set, so that the key will match what's + * in secroots now. + */ + dnskey->flags &= ~DNS_KEYFLAG_REVOKE; + + /* Convert dnskey to DST key. */ + isc_buffer_init(&buffer, data, sizeof(data)); + dns_rdata_fromstruct(&rdata, dnskey->common.rdclass, + dns_rdatatype_dnskey, dnskey, &buffer); + result = dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &key); + if (result != ISC_R_SUCCESS) + return; + result = dns_view_getsecroots(view, &sr); + if (result == ISC_R_SUCCESS) { + dns_keytable_deletekeynode(sr, key); + dns_keytable_detach(&sr); + } + dst_key_free(&key); +} + +#define NZF ".nzf" + +void +dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx, + void (*cfg_destroy)(void **)) +{ + REQUIRE(DNS_VIEW_VALID(view)); + REQUIRE((cfgctx != NULL && cfg_destroy != NULL) || !allow); + +#ifdef BIND9 + if (view->new_zone_file != NULL) { + isc_mem_free(view->mctx, view->new_zone_file); + view->new_zone_file = NULL; + } + + if (view->new_zone_config != NULL) { + view->cfg_destroy(&view->new_zone_config); + view->cfg_destroy = NULL; + } + + if (allow) { + char buffer[ISC_SHA256_DIGESTSTRINGLENGTH + sizeof(NZF)]; + isc_sha256_data((void *)view->name, strlen(view->name), buffer); + /* Truncate the hash at 16 chars; full length is overkill */ + isc_string_printf(buffer + 16, sizeof(NZF), "%s", NZF); + view->new_zone_file = isc_mem_strdup(view->mctx, buffer); + view->new_zone_config = cfgctx; + view->cfg_destroy = cfg_destroy; + } +#else + UNUSED(allow); + UNUSED(cfgctx); + UNUSED(cfg_destroy); +#endif +} diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c index b3f2e95..210bca9 100644 --- a/lib/dns/xfrin.c +++ b/lib/dns/xfrin.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2008, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: xfrin.c,v 1.166 2008-09-25 04:12:39 marka Exp $ */ +/* $Id: xfrin.c,v 1.166.522.2.2.1 2011-06-02 23:47:35 tbox Exp $ */ /*! \file */ @@ -83,8 +83,9 @@ typedef enum { XFRST_IXFR_DEL, XFRST_IXFR_ADDSOA, XFRST_IXFR_ADD, + XFRST_IXFR_END, XFRST_AXFR, - XFRST_END + XFRST_AXFR_END } xfrin_state_t; /*% @@ -203,6 +204,7 @@ static isc_result_t axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, dns_rdata_t *rdata); static isc_result_t axfr_apply(dns_xfrin_ctx_t *xfr); static isc_result_t axfr_commit(dns_xfrin_ctx_t *xfr); +static isc_result_t axfr_finalize(dns_xfrin_ctx_t *xfr); static isc_result_t ixfr_init(dns_xfrin_ctx_t *xfr); static isc_result_t ixfr_apply(dns_xfrin_ctx_t *xfr); @@ -318,6 +320,16 @@ axfr_commit(dns_xfrin_ctx_t *xfr) { CHECK(axfr_apply(xfr)); CHECK(dns_db_endload(xfr->db, &xfr->axfr.add_private)); + + result = ISC_R_SUCCESS; + failure: + return (result); +} + +static isc_result_t +axfr_finalize(dns_xfrin_ctx_t *xfr) { + isc_result_t result; + CHECK(dns_zone_replacedb(xfr->zone, xfr->db, ISC_TRUE)); result = ISC_R_SUCCESS; @@ -541,7 +553,7 @@ xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, isc_uint32_t ttl, isc_uint32_t soa_serial = dns_soa_getserial(rdata); if (soa_serial == xfr->end_serial) { CHECK(ixfr_commit(xfr)); - xfr->state = XFRST_END; + xfr->state = XFRST_IXFR_END; break; } else if (soa_serial != xfr->ixfr.current_serial) { xfrin_log(xfr, ISC_LOG_ERROR, @@ -572,11 +584,12 @@ xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, isc_uint32_t ttl, CHECK(axfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata)); if (rdata->type == dns_rdatatype_soa) { CHECK(axfr_commit(xfr)); - xfr->state = XFRST_END; + xfr->state = XFRST_AXFR_END; break; } break; - case XFRST_END: + case XFRST_AXFR_END: + case XFRST_IXFR_END: FAIL(DNS_R_EXTRADATA); default: INSIST(0); @@ -1318,8 +1331,9 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) { } else if (dns_message_gettsigkey(msg) != NULL) { xfr->sincetsig++; - if (xfr->sincetsig > 100 || - xfr->nmsg == 0 || xfr->state == XFRST_END) + if (xfr->sincetsig > 100 || xfr->nmsg == 0 || + xfr->state == XFRST_AXFR_END || + xfr->state == XFRST_IXFR_END) { result = DNS_R_EXPECTEDTSIG; goto failure; @@ -1345,16 +1359,22 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) { dns_message_destroy(&msg); - if (xfr->state == XFRST_GOTSOA) { + switch (xfr->state) { + case XFRST_GOTSOA: xfr->reqtype = dns_rdatatype_axfr; xfr->state = XFRST_INITIALSOA; CHECK(xfrin_send_request(xfr)); - } else if (xfr->state == XFRST_END) { + break; + case XFRST_AXFR_END: + CHECK(axfr_finalize(xfr)); + /* FALLTHROUGH */ + case XFRST_IXFR_END: /* * Close the journal. */ if (xfr->ixfr.journal != NULL) dns_journal_destroy(&xfr->ixfr.journal); + /* * Inform the caller we succeeded. */ @@ -1368,7 +1388,8 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) { */ xfr->shuttingdown = ISC_TRUE; maybe_free(xfr); - } else { + break; + default: /* * Read the next message. */ diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 108aefb..c727c2e 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.c,v 1.483.36.23 2010-12-14 00:48:22 marka Exp $ */ +/* $Id: zone.c,v 1.582.8.7 2011-02-18 23:23:08 each Exp $ */ /*! \file */ @@ -47,6 +47,8 @@ #include #include #include +#include +#include #include #include #include @@ -56,6 +58,8 @@ #include #include #include +#include +#include #include #include #include @@ -66,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -129,6 +134,7 @@ typedef struct dns_signing dns_signing_t; typedef ISC_LIST(dns_signing_t) dns_signinglist_t; typedef struct dns_nsec3chain dns_nsec3chain_t; typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t; +typedef struct dns_keyfetch dns_keyfetch_t; #define DNS_ZONE_CHECKLOCK #ifdef DNS_ZONE_CHECKLOCK @@ -200,6 +206,8 @@ struct dns_zone { isc_time_t keywarntime; isc_time_t signingtime; isc_time_t nsec3chaintime; + isc_time_t refreshkeytime; + isc_uint32_t refreshkeycount; isc_uint32_t refresh; isc_uint32_t retry; isc_uint32_t expire; @@ -273,13 +281,13 @@ struct dns_zone { /*% * Statistics counters about zone management. */ - isc_stats_t *stats; + isc_stats_t *stats; /*% * Optional per-zone statistics counters. Counted outside of this * module. */ - isc_boolean_t requeststats_on; - isc_stats_t *requeststats; + isc_boolean_t requeststats_on; + isc_stats_t *requeststats; isc_uint32_t notifydelay; dns_isselffunc_t isself; void *isselfarg; @@ -304,6 +312,21 @@ struct dns_zone { isc_uint32_t signatures; isc_uint32_t nodes; dns_rdatatype_t privatetype; + + /*% + * Autosigning/key-maintenance options + */ + isc_uint32_t keyopts; + + /*% + * True if added by "rndc addzone" + */ + isc_boolean_t added; + + /*% + * whether a rpz radix was needed when last loaded + */ + isc_boolean_t rpz_zone; }; #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0)) @@ -339,7 +362,7 @@ struct dns_zone { * from SOA (if not set, we * are still using * default timer values) */ -#define DNS_ZONEFLG_FORCEXFER 0x00008000U /*%< Force a zone xfer */ +#define DNS_ZONEFLG_FORCEXFER 0x00008000U /*%< Force a zone xfer */ #define DNS_ZONEFLG_NOREFRESH 0x00010000U #define DNS_ZONEFLG_DIALNOTIFY 0x00020000U #define DNS_ZONEFLG_DIALREFRESH 0x00040000U @@ -352,8 +375,11 @@ struct dns_zone { #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U #define DNS_ZONEFLG_REFRESHING 0x04000000U /*%< Refreshing keydata */ #define DNS_ZONEFLG_THAW 0x08000000U +/* #define DNS_ZONEFLG_XXXXX 0x10000000U XXXMPA unused. */ +#define DNS_ZONEFLG_NODELAY 0x20000000U #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0) +#define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0) /* Flags for zone_load() */ #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U /* Do not stat() master files */ @@ -484,7 +510,7 @@ struct dns_io { * DNSKEY as result of an update. */ struct dns_signing { - unsigned int magic; + unsigned int magic; dns_db_t *db; dns_dbiterator_t *dbiterator; dns_secalg_t algorithm; @@ -495,15 +521,15 @@ struct dns_signing { }; struct dns_nsec3chain { - unsigned int magic; + unsigned int magic; dns_db_t *db; dns_dbiterator_t *dbiterator; dns_rdata_nsec3param_t nsec3param; unsigned char salt[255]; isc_boolean_t done; - isc_boolean_t seen_nsec; - isc_boolean_t delete_nsec; - isc_boolean_t save_delete_nsec; + isc_boolean_t seen_nsec; + isc_boolean_t delete_nsec; + isc_boolean_t save_delete_nsec; ISC_LINK(dns_nsec3chain_t) link; }; /*%< @@ -528,6 +554,19 @@ struct dns_nsec3chain { * so it can be recovered in the event of a error. */ +struct dns_keyfetch { + dns_fixedname_t name; + dns_rdataset_t keydataset; + dns_rdataset_t dnskeyset; + dns_rdataset_t dnskeysigset; + dns_zone_t *zone; + dns_db_t *db; + dns_fetch_t *fetch; +}; + +#define HOUR 3600 +#define DAY (24*HOUR) +#define MONTH (30*DAY) #define SEND_BUFFER_SIZE 2048 @@ -538,6 +577,10 @@ static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel, static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...) ISC_FORMAT_PRINTF(3, 4); static void queue_xfrin(dns_zone_t *zone); +static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver, + dns_diff_t *diff, dns_diffop_t op, + dns_name_t *name, dns_ttl_t ttl, + dns_rdata_t *rdata); static void zone_unload(dns_zone_t *zone); static void zone_expire(dns_zone_t *zone); static void zone_iattach(dns_zone_t *source, dns_zone_t **target); @@ -613,6 +656,10 @@ static isc_boolean_t dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_time_t *now); static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid, isc_boolean_t delete); +static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver, + dns_dbnode_t *node, dns_name_t *name, + dns_diff_t *diff); +static void zone_rekey(dns_zone_t *zone); #define ENTER zone_debuglog(zone, me, 1, "enter") @@ -710,6 +757,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { zone->type = dns_zone_none; zone->flags = 0; zone->options = 0; + zone->keyopts = 0; zone->db_argc = 0; zone->db_argv = NULL; isc_time_settoepoch(&zone->expiretime); @@ -721,6 +769,8 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { isc_time_settoepoch(&zone->keywarntime); isc_time_settoepoch(&zone->signingtime); isc_time_settoepoch(&zone->nsec3chaintime); + isc_time_settoepoch(&zone->refreshkeytime); + zone->refreshkeycount = 0; zone->refresh = DNS_ZONE_DEFAULTREFRESH; zone->retry = DNS_ZONE_DEFAULTRETRY; zone->expire = 0; @@ -787,6 +837,8 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { zone->signatures = 10; zone->nodes = 100; zone->privatetype = (dns_rdatatype_t)0xffffU; + zone->added = ISC_FALSE; + zone->rpz_zone = ISC_FALSE; zone->magic = ZONE_MAGIC; @@ -1304,8 +1356,8 @@ dns_zone_getjournal(dns_zone_t *zone) { * master file (if any) is written by the server, rather than being * updated manually and read by the server. * - * This is true for slave zones, stub zones, and zones that allow - * dynamic updates either by having an update policy ("ssutable") + * This is true for slave zones, stub zones, key zones, and zones that + * allow dynamic updates either by having an update policy ("ssutable") * or an "allow-update" ACL with a value other than exactly "{ none; }". */ static isc_boolean_t @@ -1314,6 +1366,7 @@ zone_isdynamic(dns_zone_t *zone) { return (ISC_TF(zone->type == dns_zone_slave || zone->type == dns_zone_stub || + zone->type == dns_zone_key || (!zone->update_disabled && zone->ssutable != NULL) || (!zone->update_disabled && zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl)))); @@ -1383,11 +1436,12 @@ zone_load(dns_zone_t *zone, unsigned int flags) { */ if (zone->masterfile != NULL) { /* - * The file is already loaded. If we are just doing a + * The file is already loaded. If we are just doing a * "rndc reconfig", we are done. */ if (!isc_time_isepoch(&zone->loadtime) && - (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) { + (flags & DNS_ZONELOADFLAG_NOSTAT) != 0 && + zone->rpz_zone == dns_rpz_needed()) { result = ISC_R_SUCCESS; goto cleanup; } @@ -1396,7 +1450,8 @@ zone_load(dns_zone_t *zone, unsigned int flags) { if (result == ISC_R_SUCCESS) { if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE) && - isc_time_compare(&filetime, &zone->loadtime) <= 0) { + isc_time_compare(&filetime, &zone->loadtime) <= 0 && + zone->rpz_zone == dns_rpz_needed()) { dns_zone_log(zone, ISC_LOG_DEBUG(1), "skipping load: master file " "older than last load"); @@ -1404,6 +1459,7 @@ zone_load(dns_zone_t *zone, unsigned int flags) { goto cleanup; } loadtime = filetime; + zone->rpz_zone = dns_rpz_needed(); } } @@ -1526,6 +1582,8 @@ get_master_options(dns_zone_t *zone) { options = DNS_MASTER_ZONE; if (zone->type == dns_zone_slave) options |= DNS_MASTER_SLAVE; + if (zone->type == dns_zone_key) + options |= DNS_MASTER_KEY; if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS)) options |= DNS_MASTER_CHECKNS; if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS)) @@ -1541,7 +1599,8 @@ get_master_options(dns_zone_t *zone) { if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD)) options |= DNS_MASTER_CHECKWILDCARD; if (zone->type == dns_zone_master && - (zone->update_acl != NULL || zone->ssutable != NULL)) + ((zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl)) || + zone->ssutable != NULL)) options |= DNS_MASTER_RESIGN; return (options); } @@ -1740,11 +1799,12 @@ zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name, dns_name_format(name, namebuf, sizeof namebuf); if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN || result == DNS_R_EMPTYNAME) { + if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) + level = ISC_LOG_WARNING; dns_zone_log(zone, level, "%s/MX '%s' has no address records (A or AAAA)", ownerbuf, namebuf); - /* XXX950 make fatal for 9.5.0. */ - return (ISC_TRUE); + return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE); } if (result == DNS_R_CNAME) { @@ -1986,6 +2046,113 @@ zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name, } static isc_boolean_t +zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner, + dns_rdataset_t *rdataset) +{ + dns_rdataset_t tmprdataset; + isc_result_t result; + isc_boolean_t answer = ISC_TRUE; + isc_boolean_t format = ISC_TRUE; + int level = ISC_LOG_WARNING; + char ownerbuf[DNS_NAME_FORMATSIZE]; + char typebuf[DNS_RDATATYPE_FORMATSIZE]; + unsigned int count1 = 0; + + if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL)) + level = ISC_LOG_ERROR; + + dns_rdataset_init(&tmprdataset); + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + dns_rdata_t rdata1 = DNS_RDATA_INIT; + unsigned int count2 = 0; + + count1++; + dns_rdataset_current(rdataset, &rdata1); + dns_rdataset_clone(rdataset, &tmprdataset); + for (result = dns_rdataset_first(&tmprdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&tmprdataset)) { + dns_rdata_t rdata2 = DNS_RDATA_INIT; + count2++; + if (count1 >= count2) + continue; + dns_rdataset_current(&tmprdataset, &rdata2); + if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) { + if (format) { + dns_name_format(owner, ownerbuf, + sizeof ownerbuf); + dns_rdatatype_format(rdata1.type, + typebuf, + sizeof(typebuf)); + format = ISC_FALSE; + } + dns_zone_log(zone, level, "%s/%s has " + "semantically identical records", + ownerbuf, typebuf); + if (level == ISC_LOG_ERROR) + answer = ISC_FALSE; + break; + } + } + dns_rdataset_disassociate(&tmprdataset); + if (!format) + break; + } + return (answer); +} + +static isc_boolean_t +zone_check_dup(dns_zone_t *zone, dns_db_t *db) { + dns_dbiterator_t *dbiterator = NULL; + dns_dbnode_t *node = NULL; + dns_fixedname_t fixed; + dns_name_t *name; + dns_rdataset_t rdataset; + dns_rdatasetiter_t *rdsit = NULL; + isc_boolean_t ok = ISC_TRUE; + isc_result_t result; + + dns_fixedname_init(&fixed); + name = dns_fixedname_name(&fixed); + dns_rdataset_init(&rdataset); + + result = dns_db_createiterator(db, 0, &dbiterator); + if (result != ISC_R_SUCCESS) + return (ISC_TRUE); + + for (result = dns_dbiterator_first(dbiterator); + result == ISC_R_SUCCESS; + result = dns_dbiterator_next(dbiterator)) { + result = dns_dbiterator_current(dbiterator, &node, name); + if (result != ISC_R_SUCCESS) + continue; + + result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit); + if (result != ISC_R_SUCCESS) + continue; + + for (result = dns_rdatasetiter_first(rdsit); + result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(rdsit)) { + dns_rdatasetiter_current(rdsit, &rdataset); + if (!zone_rrset_check_dup(zone, name, &rdataset)) + ok = ISC_FALSE; + dns_rdataset_disassociate(&rdataset); + } + dns_rdatasetiter_destroy(&rdsit); + dns_db_detachnode(db, &node); + } + + if (node != NULL) + dns_db_detachnode(db, &node); + dns_dbiterator_destroy(&dbiterator); + + return (ok); +} + +static isc_boolean_t integrity_checks(dns_zone_t *zone, dns_db_t *db) { dns_dbiterator_t *dbiterator = NULL; dns_dbnode_t *node = NULL; @@ -2052,6 +2219,7 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) { result = dns_rdataset_next(&rdataset); } dns_rdataset_disassociate(&rdataset); + goto next; checkmx: result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx, @@ -2104,7 +2272,7 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) { /* * OpenSSL verification of RSA keys with exponent 3 is known to be - * broken prior OpenSSL 0.9.8c/0.9.7k. Look for such keys and warn + * broken prior OpenSSL 0.9.8c/0.9.7k. Look for such keys and warn * if they are in use. */ static void @@ -2168,7 +2336,6 @@ zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) { dns_db_detachnode(db, &node); if (version != NULL) dns_db_closeversion(db, &version, ISC_FALSE); - } static void @@ -2189,15 +2356,18 @@ resume_signingwithkey(dns_zone_t *zone) { zone->privatetype, dns_rdatatype_none, 0, &rdataset, NULL); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) { + INSIST(!dns_rdataset_isassociated(&rdataset)); goto cleanup; + } for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { dns_rdataset_current(&rdataset, &rdata); - if (rdata.length != 5 || rdata.data[4] != 0) { + if (rdata.length != 5 || + rdata.data[0] == 0 || rdata.data[4] != 0) { dns_rdata_reset(&rdata); continue; } @@ -2219,7 +2389,6 @@ resume_signingwithkey(dns_zone_t *zone) { dns_db_detachnode(zone->db, &node); if (version != NULL) dns_db_closeversion(zone->db, &version, ISC_FALSE); - } static isc_result_t @@ -2228,6 +2397,9 @@ zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) { isc_result_t result; isc_time_t now; unsigned int options = 0; + char saltbuf[255*2+1]; + char flags[sizeof("REMOVE|CREATE|NONSEC|OPTOUT")]; + int i; nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain); if (nsec3chain == NULL) @@ -2249,6 +2421,40 @@ zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) { nsec3chain->delete_nsec = ISC_FALSE; nsec3chain->save_delete_nsec = ISC_FALSE; + if (nsec3param->flags == 0) + strlcpy(flags, "NONE", sizeof(flags)); + else { + flags[0] = '\0'; + if (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) + strlcat(flags, "REMOVE", sizeof(flags)); + if (nsec3param->flags & DNS_NSEC3FLAG_CREATE) { + if (flags[0] == '\0') + strlcpy(flags, "CREATE", sizeof(flags)); + else + strlcat(flags, "|CREATE", sizeof(flags)); + } + if (nsec3param->flags & DNS_NSEC3FLAG_NONSEC) { + if (flags[0] == '\0') + strlcpy(flags, "NONSEC", sizeof(flags)); + else + strlcat(flags, "|NONSEC", sizeof(flags)); + } + if (nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) { + if (flags[0] == '\0') + strlcpy(flags, "OPTOUT", sizeof(flags)); + else + strlcat(flags, "|OPTOUT", sizeof(flags)); + } + } + if (nsec3param->salt_length == 0) + strlcpy(saltbuf, "-", sizeof(saltbuf)); + else + for (i = 0; i < nsec3param->salt_length; i++) + sprintf(&saltbuf[i*2], "%02X", nsec3chain->salt[i]); + dns_zone_log(zone, ISC_LOG_INFO, + "zone_addnsec3chain(%u,%s,%u,%s)", + nsec3param->hash, flags, nsec3param->iterations, + saltbuf); for (current = ISC_LIST_HEAD(zone->nsec3chain); current != NULL; current = ISC_LIST_NEXT(current, link)) { @@ -2298,11 +2504,13 @@ static void resume_addnsec3chain(dns_zone_t *zone) { dns_dbnode_t *node = NULL; dns_dbversion_t *version = NULL; - dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdataset_t rdataset; isc_result_t result; dns_rdata_nsec3param_t nsec3param; + if (zone->privatetype == 0) + return; + result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node); if (result != ISC_R_SUCCESS) goto cleanup; @@ -2310,17 +2518,25 @@ resume_addnsec3chain(dns_zone_t *zone) { dns_db_currentversion(zone->db, &version); dns_rdataset_init(&rdataset); result = dns_db_findrdataset(zone->db, node, version, - dns_rdatatype_nsec3param, - dns_rdatatype_none, 0, - &rdataset, NULL); - if (result != ISC_R_SUCCESS) + zone->privatetype, dns_rdatatype_none, + 0, &rdataset, NULL); + if (result != ISC_R_SUCCESS) { + INSIST(!dns_rdataset_isassociated(&rdataset)); goto cleanup; + } for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { - dns_rdataset_current(&rdataset, &rdata); + unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_t private = DNS_RDATA_INIT; + + dns_rdataset_current(&rdataset, &private); + if (!dns_nsec3param_fromprivate(&private, &rdata, buf, + sizeof(buf))) + continue; result = dns_rdata_tostruct(&rdata, &nsec3param, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); if ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 || @@ -2332,10 +2548,8 @@ resume_addnsec3chain(dns_zone_t *zone) { dns_result_totext(result)); } } - dns_rdata_reset(&rdata); } dns_rdataset_disassociate(&rdataset); - cleanup: if (node != NULL) dns_db_detachnode(zone->db, &node); @@ -2353,8 +2567,8 @@ set_resigntime(dns_zone_t *zone) { dns_rdataset_init(&rdataset); dns_fixedname_init(&fixed); - result = dns_db_getsigningtime(zone->db, &rdataset, - dns_fixedname_name(&fixed)); + result = dns_db_getsigningtime(zone->db, &rdataset, + dns_fixedname_name(&fixed)); if (result != ISC_R_SUCCESS) { isc_time_settoepoch(&zone->resigntime); return; @@ -2392,10 +2606,12 @@ check_nsec3param(dns_zone_t *zone, dns_db_t *db) { dns_rdatatype_nsec3param, dns_rdatatype_none, 0, &rdataset, NULL); if (result == ISC_R_NOTFOUND) { + INSIST(!dns_rdataset_isassociated(&rdataset)); result = ISC_R_SUCCESS; goto cleanup; } if (result != ISC_R_SUCCESS) { + INSIST(!dns_rdataset_isassociated(&rdataset)); dns_zone_log(zone, ISC_LOG_ERROR, "nsec3param lookup failure: %s", dns_result_totext(result)); @@ -2456,1230 +2672,1837 @@ check_nsec3param(dns_zone_t *zone, dns_db_t *db) { return (result); } +/* + * Set the timer for refreshing the key zone to the soonest future time + * of the set (current timer, keydata->refresh, keydata->addhd, + * keydata->removehd). + */ +static void +set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key, + isc_stdtime_t now) { + const char me[] = "set_refreshkeytimer"; + isc_stdtime_t then; + isc_time_t timenow, timethen; + char timebuf[80]; + + ENTER; + then = key->refresh; + if (key->addhd > now && key->addhd < then) + then = key->addhd; + if (key->removehd > now && key->removehd < then) + then = key->removehd; + + TIME_NOW(&timenow); + if (then > now) + DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen); + else + timethen = timenow; + if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 || + isc_time_compare(&timethen, &zone->refreshkeytime) < 0) + zone->refreshkeytime = timethen; + + isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80); + dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf); + zone_settimer(zone, &timenow); +} + +/* + * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone. + * If the key zone is changed, set '*changed' to ISC_TRUE. + */ static isc_result_t -zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, - isc_result_t result) +create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, + dns_diff_t *diff, dns_keytable_t *keytable, + dns_keynode_t **keynodep, isc_boolean_t *changed) { - unsigned int soacount = 0; - unsigned int nscount = 0; - unsigned int errors = 0; - isc_uint32_t serial, oldserial, refresh, retry, expire, minimum; - isc_time_t now; - isc_boolean_t needdump = ISC_FALSE; - isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE); - unsigned int options; + const char me[] = "create_keydata"; + isc_result_t result = ISC_R_SUCCESS; + isc_buffer_t keyb, dstb; + unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE]; + dns_rdata_keydata_t keydata; + dns_rdata_dnskey_t dnskey; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_keynode_t *keynode; + isc_stdtime_t now; + isc_region_t r; + dst_key_t *key; - TIME_NOW(&now); + REQUIRE(keynodep != NULL); + keynode = *keynodep; - /* - * Initiate zone transfer? We may need a error code that - * indicates that the "permanent" form does not exist. - * XXX better error feedback to log. - */ - if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) { - if (zone->type == dns_zone_slave || - zone->type == dns_zone_stub) { - if (result == ISC_R_FILENOTFOUND) - dns_zone_log(zone, ISC_LOG_DEBUG(1), - "no master file"); - else if (result != DNS_R_NOMASTERFILE) - dns_zone_log(zone, ISC_LOG_ERROR, - "loading from master file %s " - "failed: %s", - zone->masterfile, - dns_result_totext(result)); - } else - dns_zone_log(zone, ISC_LOG_ERROR, - "loading from master file %s failed: %s", - zone->masterfile, - dns_result_totext(result)); - goto cleanup; - } + ENTER; + isc_stdtime_get(&now); - dns_zone_log(zone, ISC_LOG_DEBUG(2), - "number of nodes in database: %u", - dns_db_nodecount(db)); + /* Loop in case there's more than one key. */ + while (result == ISC_R_SUCCESS) { + dns_keynode_t *nextnode = NULL; - if (result == DNS_R_SEENINCLUDE) - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE); - else - DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE); + key = dns_keynode_key(keynode); + if (key == NULL) + goto skip; - /* - * Apply update log, if any, on initial load. - */ - if (zone->journal != NULL && - ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) && - ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) - { - if (zone->type == dns_zone_master && - (zone->update_acl != NULL || zone->ssutable != NULL)) - options = DNS_JOURNALOPT_RESIGN; - else - options = 0; - result = dns_journal_rollforward2(zone->mctx, db, options, - zone->sigresigninginterval, - zone->journal); - if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND && - result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL && - result != ISC_R_RANGE) { - dns_zone_log(zone, ISC_LOG_ERROR, - "journal rollforward failed: %s", - dns_result_totext(result)); - goto cleanup; - } - if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) { - dns_zone_log(zone, ISC_LOG_ERROR, - "journal rollforward failed: " - "journal out of sync with zone"); - goto cleanup; + isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf)); + CHECK(dst_key_todns(key, &dstb)); + + /* Convert DST key to DNSKEY. */ + dns_rdata_reset(&rdata); + isc_buffer_usedregion(&dstb, &r); + dns_rdata_fromregion(&rdata, dst_key_class(key), + dns_rdatatype_dnskey, &r); + + /* DSTKEY to KEYDATA. */ + CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL)); + CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0, + NULL)); + + /* KEYDATA to rdata. */ + dns_rdata_reset(&rdata); + isc_buffer_init(&keyb, key_buf, sizeof(key_buf)); + CHECK(dns_rdata_fromstruct(&rdata, + zone->rdclass, dns_rdatatype_keydata, + &keydata, &keyb)); + + /* Add rdata to zone. */ + CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, + dst_key_name(key), 0, &rdata)); + *changed = ISC_TRUE; + + skip: + result = dns_keytable_nextkeynode(keytable, keynode, &nextnode); + if (result != ISC_R_NOTFOUND) { + dns_keytable_detachkeynode(keytable, &keynode); + keynode = nextnode; } - dns_zone_log(zone, ISC_LOG_DEBUG(1), - "journal rollforward completed " - "successfully: %s", - dns_result_totext(result)); - if (result == ISC_R_SUCCESS) - needdump = ISC_TRUE; } - zone->loadtime = loadtime; + /* Refresh new keys from the zone apex as soon as possible. */ + if (*changed) + set_refreshkeytimer(zone, &keydata, now); - dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded"); - /* - * Obtain ns, soa and cname counts for top of zone. - */ - INSIST(db != NULL); - result = zone_get_from_db(zone, db, &nscount, &soacount, &serial, - &refresh, &retry, &expire, &minimum, - &errors); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, - "could not find NS and/or SOA records"); + if (keynode != NULL) + dns_keytable_detachkeynode(keytable, &keynode); + *keynodep = NULL; + + return (ISC_R_SUCCESS); + + failure: + return (result); +} + +/* + * Remove from the key zone all the KEYDATA records found in rdataset. + */ +static isc_result_t +delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, + dns_name_t *name, dns_rdataset_t *rdataset) +{ + dns_rdata_t rdata = DNS_RDATA_INIT; + isc_result_t result, uresult; + + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + dns_rdata_reset(&rdata); + dns_rdataset_current(rdataset, &rdata); + uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, + name, 0, &rdata); + if (uresult != ISC_R_SUCCESS) + return (uresult); } + if (result == ISC_R_NOMORE) + result = ISC_R_SUCCESS; + return (result); +} - /* - * Master / Slave / Stub zones require both NS and SOA records at - * the top of the zone. - */ +/* + * Compute the DNSSEC key ID for a DNSKEY record. + */ +static isc_result_t +compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx, + dns_keytag_t *tag) +{ + isc_result_t result; + dns_rdata_t rdata = DNS_RDATA_INIT; + unsigned char data[4096]; + isc_buffer_t buffer; + dst_key_t *dstkey = NULL; - switch (zone->type) { - case dns_zone_master: - case dns_zone_slave: - case dns_zone_stub: - if (soacount != 1) { - dns_zone_log(zone, ISC_LOG_ERROR, - "has %d SOA records", soacount); - result = DNS_R_BADZONE; - } - if (nscount == 0) { - dns_zone_log(zone, ISC_LOG_ERROR, - "has no NS records"); - result = DNS_R_BADZONE; - } - if (result != ISC_R_SUCCESS) - goto cleanup; - if (zone->type == dns_zone_master && errors != 0) { - result = DNS_R_BADZONE; - goto cleanup; - } - if (zone->type != dns_zone_stub) { - result = check_nsec3param(zone, db); - if (result != ISC_R_SUCCESS) - goto cleanup; - } - if (zone->type == dns_zone_master && - DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) && - !integrity_checks(zone, db)) { - result = DNS_R_BADZONE; - goto cleanup; - } - - if (zone->db != NULL) { - /* - * This is checked in zone_replacedb() for slave zones - * as they don't reload from disk. - */ - result = zone_get_from_db(zone, zone->db, NULL, NULL, - &oldserial, NULL, NULL, NULL, - NULL, NULL); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) && - !isc_serial_gt(serial, oldserial)) { - isc_uint32_t serialmin, serialmax; + isc_buffer_init(&buffer, data, sizeof(data)); + dns_rdata_fromstruct(&rdata, dnskey->common.rdclass, + dns_rdatatype_dnskey, dnskey, &buffer); - INSIST(zone->type == dns_zone_master); + result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey); + if (result == ISC_R_SUCCESS) + *tag = dst_key_id(dstkey); + dst_key_free(&dstkey); - serialmin = (oldserial + 1) & 0xffffffffU; - serialmax = (oldserial + 0x7fffffffU) & - 0xffffffffU; - dns_zone_log(zone, ISC_LOG_ERROR, - "ixfr-from-differences: " - "new serial (%u) out of range " - "[%u - %u]", serial, serialmin, - serialmax); - result = DNS_R_BADZONE; - goto cleanup; - } else if (!isc_serial_ge(serial, oldserial)) - dns_zone_log(zone, ISC_LOG_ERROR, - "zone serial has gone backwards"); - else if (serial == oldserial && !hasinclude) - dns_zone_log(zone, ISC_LOG_ERROR, - "zone serial unchanged. " - "zone may fail to transfer " - "to slaves."); - } + return (result); +} - if (zone->type == dns_zone_master && - (zone->update_acl != NULL || zone->ssutable != NULL) && - zone->sigresigninginterval < (3 * refresh) && - dns_db_issecure(db)) - { - dns_zone_log(zone, ISC_LOG_WARNING, - "sig-re-signing-interval less than " - "3 * refresh."); - } +/* + * Add key to the security roots for all views. + */ +static void +trust_key(dns_viewlist_t *viewlist, dns_name_t *keyname, + dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) { + isc_result_t result; + dns_rdata_t rdata = DNS_RDATA_INIT; + unsigned char data[4096]; + isc_buffer_t buffer; + dns_view_t *view; + dns_keytable_t *sr = NULL; + dst_key_t *dstkey = NULL; - zone->refresh = RANGE(refresh, - zone->minrefresh, zone->maxrefresh); - zone->retry = RANGE(retry, - zone->minretry, zone->maxretry); - zone->expire = RANGE(expire, zone->refresh + zone->retry, - DNS_MAX_EXPIRE); - zone->minimum = minimum; - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS); + /* Convert dnskey to DST key. */ + isc_buffer_init(&buffer, data, sizeof(data)); + dns_rdata_fromstruct(&rdata, dnskey->common.rdclass, + dns_rdatatype_dnskey, dnskey, &buffer); - if (zone->type == dns_zone_slave || - zone->type == dns_zone_stub) { - isc_time_t t; - isc_uint32_t delay; + for (view = ISC_LIST_HEAD(*viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) { - result = isc_file_getmodtime(zone->journal, &t); - if (result != ISC_R_SUCCESS) - result = isc_file_getmodtime(zone->masterfile, - &t); - if (result == ISC_R_SUCCESS) - DNS_ZONE_TIME_ADD(&t, zone->expire, - &zone->expiretime); - else - DNS_ZONE_TIME_ADD(&now, zone->retry, - &zone->expiretime); + result = dns_view_getsecroots(view, &sr); + if (result != ISC_R_SUCCESS) + continue; - delay = isc_random_jitter(zone->retry, - (zone->retry * 3) / 4); - DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime); - if (isc_time_compare(&zone->refreshtime, - &zone->expiretime) >= 0) - zone->refreshtime = now; - } - break; - default: - UNEXPECTED_ERROR(__FILE__, __LINE__, - "unexpected zone type %d", zone->type); - result = ISC_R_UNEXPECTED; - goto cleanup; + CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey)); + CHECK(dns_keytable_add(sr, ISC_TRUE, &dstkey)); + dns_keytable_detach(&sr); } - /* - * Check for weak DNSKEY's. - */ - if (zone->type == dns_zone_master) - zone_check_dnskeys(zone, db); + failure: + if (dstkey != NULL) + dst_key_free(&dstkey); + if (sr != NULL) + dns_keytable_detach(&sr); + return; +} -#if 0 - /* destroy notification example. */ - { - isc_event_t *e = isc_event_allocate(zone->mctx, NULL, - DNS_EVENT_DBDESTROYED, - dns_zonemgr_dbdestroyed, - zone, - sizeof(isc_event_t)); - dns_db_ondestroy(db, zone->task, &e); - } -#endif +/* + * Remove key from the security roots for all views. + */ +static void +untrust_key(dns_viewlist_t *viewlist, dns_name_t *keyname, isc_mem_t *mctx, + dns_rdata_dnskey_t *dnskey) +{ + dns_view_t *view; - ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write); - if (zone->db != NULL) { - result = zone_replacedb(zone, db, ISC_FALSE); - ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write); - if (result != ISC_R_SUCCESS) - goto cleanup; - } else { - zone_attachdb(zone, db); - ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write); - DNS_ZONE_SETFLAG(zone, - DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY); - } - result = ISC_R_SUCCESS; - if (needdump) - zone_needdump(zone, DNS_DUMP_DELAY); - if (zone->task != NULL) { - if (zone->type == dns_zone_master) { - set_resigntime(zone); - resume_signingwithkey(zone); - resume_addnsec3chain(zone); - } - zone_settimer(zone, &now); - } + for (view = ISC_LIST_HEAD(*viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + dns_view_untrust(view, keyname, dnskey, mctx); +} - if (! dns_db_ispersistent(db)) - dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", serial, - dns_db_issecure(db) ? " (signed)" : ""); +/* + * Add a null key to the security roots for all views, so that all queries + * to the zone will fail. + */ +static void +fail_secure(dns_viewlist_t *viewlist, dns_name_t *keyname) { + isc_result_t result; + dns_view_t *view; - return (result); + for (view = ISC_LIST_HEAD(*viewlist); + view != NULL; + view = ISC_LIST_NEXT(view, link)) { + dns_keytable_t *sr = NULL; - cleanup: - if (zone->type == dns_zone_slave || - zone->type == dns_zone_stub) { - if (zone->journal != NULL) - zone_saveunique(zone, zone->journal, "jn-XXXXXXXX"); - if (zone->masterfile != NULL) - zone_saveunique(zone, zone->masterfile, "db-XXXXXXXX"); + result = dns_view_getsecroots(view, &sr); + if (result != ISC_R_SUCCESS) + continue; - /* Mark the zone for immediate refresh. */ - zone->refreshtime = now; - if (zone->task != NULL) - zone_settimer(zone, &now); - result = ISC_R_SUCCESS; - } else if (zone->type == dns_zone_master) - dns_zone_log(zone, ISC_LOG_ERROR, "not loaded due to errors."); - return (result); + dns_keytable_marksecure(sr, keyname); + dns_keytable_detach(&sr); + } } -static isc_boolean_t -exit_check(dns_zone_t *zone) { +/* + * Scan a set of KEYDATA records from the key zone. The ones that are + * valid (i.e., the add holddown timer has expired) become trusted keys for + * all views. + */ +static void +load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) { + isc_result_t result; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_keydata_t keydata; + dns_rdata_dnskey_t dnskey; + isc_mem_t *mctx = zone->mctx; + dns_view_t *view = zone->view; + dns_viewlist_t *viewlist = view->viewlist; + int trusted = 0, revoked = 0, pending = 0; + isc_stdtime_t now; - REQUIRE(LOCKED_ZONE(zone)); + isc_stdtime_get(&now); - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) && - zone->irefs == 0) - { - /* - * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0. - */ - INSIST(isc_refcount_current(&zone->erefs) == 0); - return (ISC_TRUE); + /* For each view, delete references to this key from secroots. */ + for (view = ISC_LIST_HEAD(*viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) { + dns_keytable_t *sr = NULL; + + result = dns_view_getsecroots(view, &sr); + if (result != ISC_R_SUCCESS) + continue; + + dns_keytable_delete(sr, name); + dns_keytable_detach(&sr); } - return (ISC_FALSE); -} -static isc_boolean_t -zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_name_t *name) { - isc_result_t result; - char namebuf[DNS_NAME_FORMATSIZE]; - char altbuf[DNS_NAME_FORMATSIZE]; - dns_fixedname_t fixed; - dns_name_t *foundname; - int level; + /* Now insert all the accepted trust anchors from this keydata set. */ + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + dns_rdata_reset(&rdata); + dns_rdataset_current(rdataset, &rdata); - if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS)) - return (ISC_TRUE); + /* Convert rdata to keydata. */ + dns_rdata_tostruct(&rdata, &keydata, NULL); - if (zone->type == dns_zone_master) - level = ISC_LOG_ERROR; - else - level = ISC_LOG_WARNING; + /* Set the key refresh timer. */ + set_refreshkeytimer(zone, &keydata, now); - dns_fixedname_init(&fixed); - foundname = dns_fixedname_name(&fixed); + /* If the removal timer is nonzero, this key was revoked. */ + if (keydata.removehd != 0) { + revoked++; + continue; + } - result = dns_db_find(db, name, NULL, dns_rdatatype_a, - 0, 0, NULL, foundname, NULL, NULL); - if (result == ISC_R_SUCCESS) - return (ISC_TRUE); + /* + * If the add timer is still pending, this key is not + * trusted yet. + */ + if (now < keydata.addhd) { + pending++; + continue; + } - if (result == DNS_R_NXRRSET) { - result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, - 0, 0, NULL, foundname, NULL, NULL); - if (result == ISC_R_SUCCESS) - return (ISC_TRUE); - } + /* Convert keydata to dnskey. */ + dns_keydata_todnskey(&keydata, &dnskey, NULL); - dns_name_format(name, namebuf, sizeof namebuf); - if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN || - result == DNS_R_EMPTYNAME) { - dns_zone_log(zone, level, - "NS '%s' has no address records (A or AAAA)", - namebuf); - /* XXX950 Make fatal ISC_FALSE for 9.5.0. */ - return (ISC_TRUE); + /* Add to keytables. */ + trusted++; + trust_key(viewlist, name, &dnskey, mctx); } - if (result == DNS_R_CNAME) { - dns_zone_log(zone, level, "NS '%s' is a CNAME (illegal)", - namebuf); - /* XXX950 Make fatal ISC_FALSE for 9.5.0. */ - return (ISC_TRUE); + if (trusted == 0 && pending != 0) { + char namebuf[DNS_NAME_FORMATSIZE]; + dns_name_format(name, namebuf, sizeof namebuf); + dns_zone_log(zone, ISC_LOG_ERROR, + "No valid trust anchors for '%s'!", namebuf); + dns_zone_log(zone, ISC_LOG_ERROR, + "%d key(s) revoked, %d still pending", + revoked, pending); + dns_zone_log(zone, ISC_LOG_ERROR, + "All queries to '%s' will fail", namebuf); + fail_secure(viewlist, name); } - - if (result == DNS_R_DNAME) { - dns_name_format(foundname, altbuf, sizeof altbuf); - dns_zone_log(zone, level, - "NS '%s' is below a DNAME '%s' (illegal)", - namebuf, altbuf); - /* XXX950 Make fatal ISC_FALSE for 9.5.0. */ - return (ISC_TRUE); - } - - return (ISC_TRUE); -} +} static isc_result_t -zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node, - dns_dbversion_t *version, unsigned int *nscount, - unsigned int *errors) +do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver, + dns_diff_t *diff) { + dns_diff_t temp_diff; isc_result_t result; - unsigned int count = 0; - unsigned int ecount = 0; - dns_rdataset_t rdataset; - dns_rdata_t rdata; - dns_rdata_ns_t ns; - dns_rdataset_init(&rdataset); - result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns, - dns_rdatatype_none, 0, &rdataset, NULL); - if (result == ISC_R_NOTFOUND) - goto success; - if (result != ISC_R_SUCCESS) - goto invalidate_rdataset; + /* + * Create a singleton diff. + */ + dns_diff_init(diff->mctx, &temp_diff); + temp_diff.resign = diff->resign; + ISC_LIST_APPEND(temp_diff.tuples, *tuple, link); - result = dns_rdataset_first(&rdataset); - while (result == ISC_R_SUCCESS) { - if (errors != NULL && zone->rdclass == dns_rdataclass_in && - (zone->type == dns_zone_master || - zone->type == dns_zone_slave)) { - dns_rdata_init(&rdata); - dns_rdataset_current(&rdataset, &rdata); - result = dns_rdata_tostruct(&rdata, &ns, NULL); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - if (dns_name_issubdomain(&ns.name, &zone->origin) && - !zone_check_ns(zone, db, &ns.name)) - ecount++; - } - count++; - result = dns_rdataset_next(&rdataset); + /* + * Apply it to the database. + */ + result = dns_diff_apply(&temp_diff, db, ver); + ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link); + if (result != ISC_R_SUCCESS) { + dns_difftuple_free(tuple); + return (result); } - dns_rdataset_disassociate(&rdataset); - - success: - if (nscount != NULL) - *nscount = count; - if (errors != NULL) - *errors = ecount; - result = ISC_R_SUCCESS; - - invalidate_rdataset: - dns_rdataset_invalidate(&rdataset); + /* + * Merge it into the current pending journal entry. + */ + dns_diff_appendminimal(diff, tuple); - return (result); + /* + * Do not clear temp_diff. + */ + return (ISC_R_SUCCESS); } static isc_result_t -zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, - unsigned int *soacount, - isc_uint32_t *serial, isc_uint32_t *refresh, - isc_uint32_t *retry, isc_uint32_t *expire, - isc_uint32_t *minimum) +update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, + dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl, + dns_rdata_t *rdata) { + dns_difftuple_t *tuple = NULL; isc_result_t result; - unsigned int count; - dns_rdataset_t rdataset; - dns_rdata_t rdata = DNS_RDATA_INIT; - dns_rdata_soa_t soa; - - dns_rdataset_init(&rdataset); - result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa, - dns_rdatatype_none, 0, &rdataset, NULL); - if (result == ISC_R_NOTFOUND) { - if (soacount != NULL) - *soacount = 0; - if (serial != NULL) - *serial = 0; - if (refresh != NULL) - *refresh = 0; - if (retry != NULL) - *retry = 0; - if (expire != NULL) - *expire = 0; - if (minimum != NULL) - *minimum = 0; - result = ISC_R_SUCCESS; - goto invalidate_rdataset; - } + result = dns_difftuple_create(diff->mctx, op, + name, ttl, rdata, &tuple); if (result != ISC_R_SUCCESS) - goto invalidate_rdataset; + return (result); + return (do_one_tuple(&tuple, db, ver, diff)); +} - count = 0; - result = dns_rdataset_first(&rdataset); - while (result == ISC_R_SUCCESS) { - dns_rdata_init(&rdata); - dns_rdataset_current(&rdataset, &rdata); - count++; - if (count == 1) { - result = dns_rdata_tostruct(&rdata, &soa, NULL); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - } +static isc_result_t +increment_soa_serial(dns_db_t *db, dns_dbversion_t *ver, + dns_diff_t *diff, isc_mem_t *mctx) { + dns_difftuple_t *deltuple = NULL; + dns_difftuple_t *addtuple = NULL; + isc_uint32_t serial; + isc_result_t result; - result = dns_rdataset_next(&rdataset); - dns_rdata_reset(&rdata); - } - dns_rdataset_disassociate(&rdataset); + CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple)); + CHECK(dns_difftuple_copy(deltuple, &addtuple)); + addtuple->op = DNS_DIFFOP_ADD; - if (soacount != NULL) - *soacount = count; + serial = dns_soa_getserial(&addtuple->rdata); - if (count > 0) { - if (serial != NULL) - *serial = soa.serial; - if (refresh != NULL) - *refresh = soa.refresh; - if (retry != NULL) - *retry = soa.retry; - if (expire != NULL) - *expire = soa.expire; - if (minimum != NULL) - *minimum = soa.minimum; - } + /* RFC1982 */ + serial = (serial + 1) & 0xFFFFFFFF; + if (serial == 0) + serial = 1; + dns_soa_setserial(serial, &addtuple->rdata); + CHECK(do_one_tuple(&deltuple, db, ver, diff)); + CHECK(do_one_tuple(&addtuple, db, ver, diff)); result = ISC_R_SUCCESS; - invalidate_rdataset: - dns_rdataset_invalidate(&rdataset); + failure: + if (addtuple != NULL) + dns_difftuple_free(&addtuple); + if (deltuple != NULL) + dns_difftuple_free(&deltuple); + return (result); +} + +/* + * Write all transactions in 'diff' to the zone journal file. + */ +static isc_result_t +zone_journal(dns_zone_t *zone, dns_diff_t *diff, const char *caller) { + const char me[] = "zone_journal"; + const char *journalfile; + isc_result_t result = ISC_R_SUCCESS; + dns_journal_t *journal = NULL; + + ENTER; + journalfile = dns_zone_getjournal(zone); + if (journalfile != NULL) { + result = dns_journal_open(zone->mctx, journalfile, + ISC_TRUE, &journal); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "%s:dns_journal_open -> %s\n", + caller, dns_result_totext(result)); + return (result); + } + result = dns_journal_write_transaction(journal, diff); + dns_journal_destroy(&journal); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "%s:dns_journal_write_transaction -> %s\n", + caller, dns_result_totext(result)); + return (result); + } + } return (result); } /* - * zone must be locked. + * Create an SOA record for a newly-created zone */ static isc_result_t -zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount, - unsigned int *soacount, isc_uint32_t *serial, - isc_uint32_t *refresh, isc_uint32_t *retry, - isc_uint32_t *expire, isc_uint32_t *minimum, - unsigned int *errors) -{ - dns_dbversion_t *version; +add_soa(dns_zone_t *zone, dns_db_t *db) { isc_result_t result; - isc_result_t answer = ISC_R_SUCCESS; - dns_dbnode_t *node; - - REQUIRE(db != NULL); - REQUIRE(zone != NULL); + dns_rdata_t rdata = DNS_RDATA_INIT; + unsigned char buf[DNS_SOA_BUFFERSIZE]; + dns_dbversion_t *ver = NULL; + dns_diff_t diff; - version = NULL; - dns_db_currentversion(db, &version); + dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA"); - node = NULL; - result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node); + dns_diff_init(zone->mctx, &diff); + result = dns_db_newversion(db, &ver); if (result != ISC_R_SUCCESS) { - answer = result; - goto closeversion; + dns_zone_log(zone, ISC_LOG_ERROR, + "add_soa:dns_db_newversion -> %s\n", + dns_result_totext(result)); + goto failure; } - if (nscount != NULL || errors != NULL) { - result = zone_count_ns_rr(zone, db, node, version, - nscount, errors); - if (result != ISC_R_SUCCESS) - answer = result; + /* Build SOA record */ + result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass, + 0, 0, 0, 0, 0, buf, &rdata); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "add_soa:dns_soa_buildrdata -> %s\n", + dns_result_totext(result)); + goto failure; } - if (soacount != NULL || serial != NULL || refresh != NULL - || retry != NULL || expire != NULL || minimum != NULL) { - result = zone_load_soa_rr(db, node, version, soacount, - serial, refresh, retry, expire, - minimum); - if (result != ISC_R_SUCCESS) - answer = result; - } + result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD, + &zone->origin, 0, &rdata); - dns_db_detachnode(db, &node); - closeversion: - dns_db_closeversion(db, &version, ISC_FALSE); +failure: + dns_diff_clear(&diff); + if (ver != NULL) + dns_db_closeversion(db, &ver, ISC_TF(result == ISC_R_SUCCESS)); - return (answer); + return (result); } -void -dns_zone_attach(dns_zone_t *source, dns_zone_t **target) { - REQUIRE(DNS_ZONE_VALID(source)); - REQUIRE(target != NULL && *target == NULL); - isc_refcount_increment(&source->erefs, NULL); - *target = source; -} +/* + * Synchronize the set of initializing keys found in managed-keys {} + * statements with the set of trust anchors found in the managed-keys.bind + * zone. If a domain is no longer named in managed-keys, delete all keys + * from that domain from the key zone. If a domain is mentioned in in + * managed-keys but there are no references to it in the key zone, load + * the key zone with the initializing key(s) for that domain. + */ +static isc_result_t +sync_keyzone(dns_zone_t *zone, dns_db_t *db) { + isc_result_t result = ISC_R_SUCCESS; + isc_boolean_t changed = ISC_FALSE; + dns_rbtnodechain_t chain; + dns_fixedname_t fn; + dns_name_t foundname, *origin; + dns_keynode_t *keynode = NULL; + dns_view_t *view = zone->view; + dns_keytable_t *sr = NULL; + dns_dbversion_t *ver = NULL; + dns_diff_t diff; + dns_rriterator_t rrit; -void -dns_zone_detach(dns_zone_t **zonep) { - dns_zone_t *zone; - unsigned int refs; - isc_boolean_t free_now = ISC_FALSE; + dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys"); - REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep)); + dns_name_init(&foundname, NULL); + dns_fixedname_init(&fn); + origin = dns_fixedname_name(&fn); - zone = *zonep; + dns_diff_init(zone->mctx, &diff); - isc_refcount_decrement(&zone->erefs, &refs); + CHECK(dns_view_getsecroots(view, &sr)); - if (refs == 0) { - LOCK_ZONE(zone); - /* - * We just detached the last external reference. - */ - if (zone->task != NULL) { - /* - * This zone is being managed. Post - * its control event and let it clean - * up synchronously in the context of - * its task. - */ - isc_event_t *ev = &zone->ctlevent; - isc_task_send(zone->task, &ev); - } else { - /* - * This zone is not being managed; it has - * no task and can have no outstanding - * events. Free it immediately. - */ - /* - * Unmanaged zones should not have non-null views; - * we have no way of detaching from the view here - * without causing deadlock because this code is called - * with the view already locked. - */ - INSIST(zone->view == NULL); - free_now = ISC_TRUE; - } - UNLOCK_ZONE(zone); + result = dns_db_newversion(db, &ver); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "sync_keyzone:dns_db_newversion -> %s\n", + dns_result_totext(result)); + goto failure; } - *zonep = NULL; - if (free_now) - zone_free(zone); -} - -void -dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) { - REQUIRE(DNS_ZONE_VALID(source)); - REQUIRE(target != NULL && *target == NULL); - LOCK_ZONE(source); - zone_iattach(source, target); - UNLOCK_ZONE(source); -} - -static void -zone_iattach(dns_zone_t *source, dns_zone_t **target) { /* - * 'source' locked by caller. + * Walk the zone DB. If we find any keys whose names are no longer + * in managed-keys (or *are* in trusted-keys, meaning they are + * permanent and not RFC5011-maintained), delete them from the + * zone. Otherwise call load_secroots(), which loads keys into + * secroots as appropriate. */ - REQUIRE(LOCKED_ZONE(source)); - REQUIRE(DNS_ZONE_VALID(source)); - REQUIRE(target != NULL && *target == NULL); - INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0); - source->irefs++; - INSIST(source->irefs != 0); - *target = source; -} + dns_rriterator_init(&rrit, db, ver, 0); + for (result = dns_rriterator_first(&rrit); + result == ISC_R_SUCCESS; + result = dns_rriterator_nextrrset(&rrit)) { + dns_rdataset_t *rdataset; + dns_name_t *rrname = NULL; + isc_uint32_t ttl; + + dns_rriterator_current(&rrit, &rrname, &ttl, + &rdataset, NULL); + if (!dns_rdataset_isassociated(rdataset)) { + dns_rriterator_destroy(&rrit); + goto failure; + } -static void -zone_idetach(dns_zone_t **zonep) { - dns_zone_t *zone; + if (rdataset->type != dns_rdatatype_keydata) + continue; + + result = dns_keytable_find(sr, rrname, &keynode); + if ((result != ISC_R_SUCCESS && + result != DNS_R_PARTIALMATCH) || + dns_keynode_managed(keynode) == ISC_FALSE) { + CHECK(delete_keydata(db, ver, &diff, + rrname, rdataset)); + changed = ISC_TRUE; + } else { + load_secroots(zone, rrname, rdataset); + } + + if (keynode != NULL) + dns_keytable_detachkeynode(sr, &keynode); + } + dns_rriterator_destroy(&rrit); /* - * 'zone' locked by caller. + * Now walk secroots to find any managed keys that aren't + * in the zone. If we find any, we add them to the zone. */ - REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep)); - zone = *zonep; - REQUIRE(LOCKED_ZONE(*zonep)); - *zonep = NULL; - - INSIST(zone->irefs > 0); - zone->irefs--; - INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0); -} + RWLOCK(&sr->rwlock, isc_rwlocktype_write); + dns_rbtnodechain_init(&chain, zone->mctx); + result = dns_rbtnodechain_first(&chain, sr->table, &foundname, origin); + if (result == ISC_R_NOTFOUND) + result = ISC_R_NOMORE; + while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) { + dns_rbtnode_t *rbtnode = NULL; + + dns_rbtnodechain_current(&chain, &foundname, origin, &rbtnode); + if (rbtnode->data == NULL) + goto skip; + + dns_keytable_attachkeynode(sr, rbtnode->data, &keynode); + if (dns_keynode_managed(keynode)) { + dns_fixedname_t fname; + dns_name_t *keyname; + dst_key_t *key; + + key = dns_keynode_key(keynode); + dns_fixedname_init(&fname); + + if (key == NULL) /* fail_secure() was called. */ + goto skip; + + keyname = dst_key_name(key); + result = dns_db_find(db, keyname, ver, + dns_rdatatype_keydata, + DNS_DBFIND_NOWILD, 0, NULL, + dns_fixedname_name(&fname), + NULL, NULL); + if (result != ISC_R_SUCCESS) + result = create_keydata(zone, db, ver, &diff, + sr, &keynode, &changed); + if (result != ISC_R_SUCCESS) + break; + } + skip: + result = dns_rbtnodechain_next(&chain, &foundname, origin); + if (keynode != NULL) + dns_keytable_detachkeynode(sr, &keynode); + } + RWUNLOCK(&sr->rwlock, isc_rwlocktype_write); -void -dns_zone_idetach(dns_zone_t **zonep) { - dns_zone_t *zone; - isc_boolean_t free_needed; + if (result == ISC_R_NOMORE) + result = ISC_R_SUCCESS; - REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep)); - zone = *zonep; - *zonep = NULL; + if (changed) { + /* Write changes to journal file. */ + result = increment_soa_serial(db, ver, &diff, zone->mctx); + if (result == ISC_R_SUCCESS) + zone_journal(zone, &diff, "sync_keyzone"); - LOCK_ZONE(zone); - INSIST(zone->irefs > 0); - zone->irefs--; - free_needed = exit_check(zone); - UNLOCK_ZONE(zone); - if (free_needed) - zone_free(zone); -} + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED); + zone_needdump(zone, 30); + } -isc_mem_t * -dns_zone_getmctx(dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); + failure: + if (keynode != NULL) + dns_keytable_detachkeynode(sr, &keynode); + if (sr != NULL) + dns_keytable_detach(&sr); + if (ver != NULL) + dns_db_closeversion(db, &ver, changed); + dns_diff_clear(&diff); - return (zone->mctx); + return (result); } -dns_zonemgr_t * -dns_zone_getmgr(dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); +static isc_result_t +zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, + isc_result_t result) +{ + unsigned int soacount = 0; + unsigned int nscount = 0; + unsigned int errors = 0; + isc_uint32_t serial, oldserial, refresh, retry, expire, minimum; + isc_time_t now; + isc_boolean_t needdump = ISC_FALSE; + isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE); + isc_boolean_t nomaster = ISC_FALSE; + unsigned int options; - return (zone->zmgr); -} + TIME_NOW(&now); -void -dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) { - REQUIRE(DNS_ZONE_VALID(zone)); + /* + * Initiate zone transfer? We may need a error code that + * indicates that the "permanent" form does not exist. + * XXX better error feedback to log. + */ + if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) { + if (zone->type == dns_zone_slave || + zone->type == dns_zone_stub) { + if (result == ISC_R_FILENOTFOUND) + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "no master file"); + else if (result != DNS_R_NOMASTERFILE) + dns_zone_log(zone, ISC_LOG_ERROR, + "loading from master file %s " + "failed: %s", + zone->masterfile, + dns_result_totext(result)); + } else { + dns_zone_log(zone, ISC_LOG_ERROR, + "loading from master file %s failed: %s", + zone->masterfile, + dns_result_totext(result)); + nomaster = ISC_TRUE; + } - LOCK_ZONE(zone); - if (value) - DNS_ZONE_SETFLAG(zone, flags); - else - DNS_ZONE_CLRFLAG(zone, flags); - UNLOCK_ZONE(zone); -} + if (zone->type != dns_zone_key) + goto cleanup; + } -void -dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value) -{ - REQUIRE(DNS_ZONE_VALID(zone)); + dns_zone_log(zone, ISC_LOG_DEBUG(2), + "number of nodes in database: %u", + dns_db_nodecount(db)); - LOCK_ZONE(zone); - if (value) - zone->options |= option; + if (result == DNS_R_SEENINCLUDE) + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE); else - zone->options &= ~option; - UNLOCK_ZONE(zone); -} - -unsigned int -dns_zone_getoptions(dns_zone_t *zone) { - - REQUIRE(DNS_ZONE_VALID(zone)); + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE); - return (zone->options); -} + /* + * If there's no master file for a key zone, then the zone is new: + * create an SOA record. (We do this now, instead of later, so that + * if there happens to be a journal file, we can roll forward from + * a sane starting point.) + */ + if (nomaster && zone->type == dns_zone_key) { + result = add_soa(zone, db); + if (result != ISC_R_SUCCESS) + goto cleanup; + } -isc_result_t -dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) { - REQUIRE(DNS_ZONE_VALID(zone)); + /* + * Apply update log, if any, on initial load. + */ + if (zone->journal != NULL && + ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) && + ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) + { + if (zone->type == dns_zone_master && + (zone->update_acl != NULL || zone->ssutable != NULL)) + options = DNS_JOURNALOPT_RESIGN; + else + options = 0; + result = dns_journal_rollforward2(zone->mctx, db, options, + zone->sigresigninginterval, + zone->journal); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND && + result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL && + result != ISC_R_RANGE) { + dns_zone_log(zone, ISC_LOG_ERROR, + "journal rollforward failed: %s", + dns_result_totext(result)); + goto cleanup; + } + if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) { + dns_zone_log(zone, ISC_LOG_ERROR, + "journal rollforward failed: " + "journal out of sync with zone"); + goto cleanup; + } + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "journal rollforward completed " + "successfully: %s", + dns_result_totext(result)); + if (result == ISC_R_SUCCESS) + needdump = ISC_TRUE; + } - LOCK_ZONE(zone); - zone->xfrsource4 = *xfrsource; - UNLOCK_ZONE(zone); + zone->loadtime = loadtime; - return (ISC_R_SUCCESS); -} + dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded"); + /* + * Obtain ns, soa and cname counts for top of zone. + */ + INSIST(db != NULL); + result = zone_get_from_db(zone, db, &nscount, &soacount, &serial, + &refresh, &retry, &expire, &minimum, + &errors); + if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) { + dns_zone_log(zone, ISC_LOG_ERROR, + "could not find NS and/or SOA records"); + } -isc_sockaddr_t * -dns_zone_getxfrsource4(dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); - return (&zone->xfrsource4); -} + /* + * Master / Slave / Stub zones require both NS and SOA records at + * the top of the zone. + */ -isc_result_t -dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) { - REQUIRE(DNS_ZONE_VALID(zone)); - - LOCK_ZONE(zone); - zone->xfrsource6 = *xfrsource; - UNLOCK_ZONE(zone); - - return (ISC_R_SUCCESS); -} - -isc_sockaddr_t * -dns_zone_getxfrsource6(dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); - return (&zone->xfrsource6); -} - -isc_result_t -dns_zone_setaltxfrsource4(dns_zone_t *zone, - const isc_sockaddr_t *altxfrsource) -{ - REQUIRE(DNS_ZONE_VALID(zone)); - - LOCK_ZONE(zone); - zone->altxfrsource4 = *altxfrsource; - UNLOCK_ZONE(zone); + switch (zone->type) { + case dns_zone_dlz: + case dns_zone_master: + case dns_zone_slave: + case dns_zone_stub: + if (soacount != 1) { + dns_zone_log(zone, ISC_LOG_ERROR, + "has %d SOA records", soacount); + result = DNS_R_BADZONE; + } + if (nscount == 0) { + dns_zone_log(zone, ISC_LOG_ERROR, + "has no NS records"); + result = DNS_R_BADZONE; + } + if (result != ISC_R_SUCCESS) + goto cleanup; + if (zone->type == dns_zone_master && errors != 0) { + result = DNS_R_BADZONE; + goto cleanup; + } + if (zone->type != dns_zone_stub) { + result = check_nsec3param(zone, db); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + if (zone->type == dns_zone_master && + DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) && + !integrity_checks(zone, db)) { + result = DNS_R_BADZONE; + goto cleanup; + } - return (ISC_R_SUCCESS); -} + if (zone->type == dns_zone_master && + DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) && + !zone_check_dup(zone, db)) { + result = DNS_R_BADZONE; + goto cleanup; + } -isc_sockaddr_t * -dns_zone_getaltxfrsource4(dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); - return (&zone->altxfrsource4); -} + if (zone->db != NULL) { + /* + * This is checked in zone_replacedb() for slave zones + * as they don't reload from disk. + */ + result = zone_get_from_db(zone, zone->db, NULL, NULL, + &oldserial, NULL, NULL, NULL, + NULL, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) && + !isc_serial_gt(serial, oldserial)) { + isc_uint32_t serialmin, serialmax; -isc_result_t -dns_zone_setaltxfrsource6(dns_zone_t *zone, - const isc_sockaddr_t *altxfrsource) -{ - REQUIRE(DNS_ZONE_VALID(zone)); + INSIST(zone->type == dns_zone_master); - LOCK_ZONE(zone); - zone->altxfrsource6 = *altxfrsource; - UNLOCK_ZONE(zone); + serialmin = (oldserial + 1) & 0xffffffffU; + serialmax = (oldserial + 0x7fffffffU) & + 0xffffffffU; + dns_zone_log(zone, ISC_LOG_ERROR, + "ixfr-from-differences: " + "new serial (%u) out of range " + "[%u - %u]", serial, serialmin, + serialmax); + result = DNS_R_BADZONE; + goto cleanup; + } else if (!isc_serial_ge(serial, oldserial)) + dns_zone_log(zone, ISC_LOG_ERROR, + "zone serial (%u/%u) has gone " + "backwards", serial, oldserial); + else if (serial == oldserial && !hasinclude) + dns_zone_log(zone, ISC_LOG_ERROR, + "zone serial (%u) unchanged. " + "zone may fail to transfer " + "to slaves.", serial); + } - return (ISC_R_SUCCESS); -} + if (zone->type == dns_zone_master && + (zone->update_acl != NULL || zone->ssutable != NULL) && + zone->sigresigninginterval < (3 * refresh) && + dns_db_issecure(db)) + { + dns_zone_log(zone, ISC_LOG_WARNING, + "sig-re-signing-interval less than " + "3 * refresh."); + } -isc_sockaddr_t * -dns_zone_getaltxfrsource6(dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); - return (&zone->altxfrsource6); -} + zone->refresh = RANGE(refresh, + zone->minrefresh, zone->maxrefresh); + zone->retry = RANGE(retry, + zone->minretry, zone->maxretry); + zone->expire = RANGE(expire, zone->refresh + zone->retry, + DNS_MAX_EXPIRE); + zone->minimum = minimum; + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS); -isc_result_t -dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) { - REQUIRE(DNS_ZONE_VALID(zone)); + if (zone->type == dns_zone_slave || + zone->type == dns_zone_stub) { + isc_time_t t; + isc_uint32_t delay; - LOCK_ZONE(zone); - zone->notifysrc4 = *notifysrc; - UNLOCK_ZONE(zone); + result = isc_file_getmodtime(zone->journal, &t); + if (result != ISC_R_SUCCESS) + result = isc_file_getmodtime(zone->masterfile, + &t); + if (result == ISC_R_SUCCESS) + DNS_ZONE_TIME_ADD(&t, zone->expire, + &zone->expiretime); + else + DNS_ZONE_TIME_ADD(&now, zone->retry, + &zone->expiretime); - return (ISC_R_SUCCESS); -} + delay = isc_random_jitter(zone->retry, + (zone->retry * 3) / 4); + DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime); + if (isc_time_compare(&zone->refreshtime, + &zone->expiretime) >= 0) + zone->refreshtime = now; + } + break; -isc_sockaddr_t * -dns_zone_getnotifysrc4(dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); - return (&zone->notifysrc4); -} + case dns_zone_key: + result = sync_keyzone(zone, db); + if (result != ISC_R_SUCCESS) + goto cleanup; + break; -isc_result_t -dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) { - REQUIRE(DNS_ZONE_VALID(zone)); + default: + UNEXPECTED_ERROR(__FILE__, __LINE__, + "unexpected zone type %d", zone->type); + result = ISC_R_UNEXPECTED; + goto cleanup; + } - LOCK_ZONE(zone); - zone->notifysrc6 = *notifysrc; - UNLOCK_ZONE(zone); + /* + * Check for weak DNSKEY's. + */ + if (zone->type == dns_zone_master) + zone_check_dnskeys(zone, db); - return (ISC_R_SUCCESS); -} + /* + * Schedule DNSSEC key refresh. + */ + if (zone->type == dns_zone_master && + DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) + zone->refreshkeytime = now; -isc_sockaddr_t * -dns_zone_getnotifysrc6(dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); - return (&zone->notifysrc6); -} +#if 0 + /* destroy notification example. */ + { + isc_event_t *e = isc_event_allocate(zone->mctx, NULL, + DNS_EVENT_DBDESTROYED, + dns_zonemgr_dbdestroyed, + zone, + sizeof(isc_event_t)); + dns_db_ondestroy(db, zone->task, &e); + } +#endif -isc_result_t -dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify, - isc_uint32_t count) -{ - isc_sockaddr_t *new; + ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write); + if (zone->db != NULL) { + result = zone_replacedb(zone, db, ISC_FALSE); + ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write); + if (result != ISC_R_SUCCESS) + goto cleanup; + } else { + zone_attachdb(zone, db); + ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write); + DNS_ZONE_SETFLAG(zone, + DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY); + } - REQUIRE(DNS_ZONE_VALID(zone)); - REQUIRE(count == 0 || notify != NULL); + result = ISC_R_SUCCESS; - LOCK_ZONE(zone); - if (zone->notify != NULL) { - isc_mem_put(zone->mctx, zone->notify, - zone->notifycnt * sizeof(*new)); - zone->notify = NULL; - zone->notifycnt = 0; + if (needdump) { + if (zone->type == dns_zone_key) + zone_needdump(zone, 30); + else + zone_needdump(zone, DNS_DUMP_DELAY); } - if (count != 0) { - new = isc_mem_get(zone->mctx, count * sizeof(*new)); - if (new == NULL) { - UNLOCK_ZONE(zone); - return (ISC_R_NOMEMORY); + + if (zone->task != NULL) { + if (zone->type == dns_zone_master) { + set_resigntime(zone); + resume_signingwithkey(zone); + resume_addnsec3chain(zone); } - memcpy(new, notify, count * sizeof(*new)); - zone->notify = new; - zone->notifycnt = count; + zone_settimer(zone, &now); } - UNLOCK_ZONE(zone); - return (ISC_R_SUCCESS); -} -isc_result_t -dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters, - isc_uint32_t count) -{ - isc_result_t result; + if (! dns_db_ispersistent(db)) + dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", serial, + dns_db_issecure(db) ? " (DNSSEC signed)" : ""); - result = dns_zone_setmasterswithkeys(zone, masters, NULL, count); return (result); -} -static isc_boolean_t -same_masters(const isc_sockaddr_t *old, const isc_sockaddr_t *new, - isc_uint32_t count) -{ - unsigned int i; + cleanup: + if (zone->type == dns_zone_slave || + zone->type == dns_zone_stub || + zone->type == dns_zone_key) { + if (zone->journal != NULL) + zone_saveunique(zone, zone->journal, "jn-XXXXXXXX"); + if (zone->masterfile != NULL) + zone_saveunique(zone, zone->masterfile, "db-XXXXXXXX"); - for (i = 0; i < count; i++) - if (!isc_sockaddr_equal(&old[i], &new[i])) - return (ISC_FALSE); - return (ISC_TRUE); + /* Mark the zone for immediate refresh. */ + zone->refreshtime = now; + if (zone->task != NULL) + zone_settimer(zone, &now); + result = ISC_R_SUCCESS; + } else if (zone->type == dns_zone_master) + dns_zone_log(zone, ISC_LOG_ERROR, "not loaded due to errors."); + return (result); } static isc_boolean_t -same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) { - unsigned int i; +exit_check(dns_zone_t *zone) { - if (old == NULL && new == NULL) - return (ISC_TRUE); - if (old == NULL || new == NULL) - return (ISC_FALSE); + REQUIRE(LOCKED_ZONE(zone)); - for (i = 0; i < count; i++) { - if (old[i] == NULL && new[i] == NULL) - continue; - if (old[i] == NULL || new[i] == NULL || - !dns_name_equal(old[i], new[i])) - return (ISC_FALSE); + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) && + zone->irefs == 0) + { + /* + * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0. + */ + INSIST(isc_refcount_current(&zone->erefs) == 0); + return (ISC_TRUE); } - return (ISC_TRUE); + return (ISC_FALSE); } -isc_result_t -dns_zone_setmasterswithkeys(dns_zone_t *zone, - const isc_sockaddr_t *masters, - dns_name_t **keynames, - isc_uint32_t count) +static isc_boolean_t +zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version, + dns_name_t *name, isc_boolean_t logit) { - isc_sockaddr_t *new; - isc_result_t result = ISC_R_SUCCESS; - dns_name_t **newname; - isc_boolean_t *newok; - unsigned int i; + isc_result_t result; + char namebuf[DNS_NAME_FORMATSIZE]; + char altbuf[DNS_NAME_FORMATSIZE]; + dns_fixedname_t fixed; + dns_name_t *foundname; + int level; - REQUIRE(DNS_ZONE_VALID(zone)); - REQUIRE(count == 0 || masters != NULL); - if (keynames != NULL) { - REQUIRE(count != 0); - } + if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS)) + return (ISC_TRUE); - LOCK_ZONE(zone); - /* - * The refresh code assumes that 'masters' wouldn't change under it. - * If it will change then kill off any current refresh in progress - * and update the masters info. If it won't change then we can just - * unlock and exit. - */ - if (count != zone->masterscnt || - !same_masters(zone->masters, masters, count) || - !same_keynames(zone->masterkeynames, keynames, count)) { - if (zone->request != NULL) - dns_request_cancel(zone->request); - } else - goto unlock; - if (zone->masters != NULL) { - isc_mem_put(zone->mctx, zone->masters, - zone->masterscnt * sizeof(*new)); - zone->masters = NULL; + if (zone->type == dns_zone_master) + level = ISC_LOG_ERROR; + else + level = ISC_LOG_WARNING; + + dns_fixedname_init(&fixed); + foundname = dns_fixedname_name(&fixed); + + result = dns_db_find(db, name, version, dns_rdatatype_a, + 0, 0, NULL, foundname, NULL, NULL); + if (result == ISC_R_SUCCESS) + return (ISC_TRUE); + + if (result == DNS_R_NXRRSET) { + result = dns_db_find(db, name, version, dns_rdatatype_aaaa, + 0, 0, NULL, foundname, NULL, NULL); + if (result == ISC_R_SUCCESS) + return (ISC_TRUE); } - if (zone->masterkeynames != NULL) { - for (i = 0; i < zone->masterscnt; i++) { - if (zone->masterkeynames[i] != NULL) { - dns_name_free(zone->masterkeynames[i], - zone->mctx); - isc_mem_put(zone->mctx, - zone->masterkeynames[i], - sizeof(dns_name_t)); - zone->masterkeynames[i] = NULL; - } + + if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN || + result == DNS_R_EMPTYNAME) { + if (logit) { + dns_name_format(name, namebuf, sizeof namebuf); + dns_zone_log(zone, level, "NS '%s' has no address " + "records (A or AAAA)", namebuf); } - isc_mem_put(zone->mctx, zone->masterkeynames, - zone->masterscnt * sizeof(dns_name_t *)); - zone->masterkeynames = NULL; - } - if (zone->mastersok != NULL) { - isc_mem_put(zone->mctx, zone->mastersok, - zone->masterscnt * sizeof(isc_boolean_t)); - zone->mastersok = NULL; + return (ISC_FALSE); } - zone->masterscnt = 0; - /* - * If count == 0, don't allocate any space for masters, mastersok or - * keynames so internally, those pointers are NULL if count == 0 - */ - if (count == 0) - goto unlock; - /* - * masters must contain count elements! - */ - new = isc_mem_get(zone->mctx, count * sizeof(*new)); - if (new == NULL) { - result = ISC_R_NOMEMORY; - goto unlock; + if (result == DNS_R_CNAME) { + if (logit) { + dns_name_format(name, namebuf, sizeof namebuf); + dns_zone_log(zone, level, "NS '%s' is a CNAME " + "(illegal)", namebuf); + } + return (ISC_FALSE); } - memcpy(new, masters, count * sizeof(*new)); - - /* - * Similarly for mastersok. - */ - newok = isc_mem_get(zone->mctx, count * sizeof(*newok)); - if (newok == NULL) { - result = ISC_R_NOMEMORY; - isc_mem_put(zone->mctx, new, count * sizeof(*new)); - goto unlock; - }; - for (i = 0; i < count; i++) - newok[i] = ISC_FALSE; - /* - * if keynames is non-NULL, it must contain count elements! - */ - newname = NULL; - if (keynames != NULL) { - newname = isc_mem_get(zone->mctx, count * sizeof(*newname)); - if (newname == NULL) { - result = ISC_R_NOMEMORY; - isc_mem_put(zone->mctx, new, count * sizeof(*new)); - isc_mem_put(zone->mctx, newok, count * sizeof(*newok)); - goto unlock; - } - for (i = 0; i < count; i++) - newname[i] = NULL; - for (i = 0; i < count; i++) { - if (keynames[i] != NULL) { - newname[i] = isc_mem_get(zone->mctx, - sizeof(dns_name_t)); - if (newname[i] == NULL) - goto allocfail; - dns_name_init(newname[i], NULL); - result = dns_name_dup(keynames[i], zone->mctx, - newname[i]); - if (result != ISC_R_SUCCESS) { - allocfail: - for (i = 0; i < count; i++) - if (newname[i] != NULL) - dns_name_free( - newname[i], - zone->mctx); - isc_mem_put(zone->mctx, new, - count * sizeof(*new)); - isc_mem_put(zone->mctx, newok, - count * sizeof(*newok)); - isc_mem_put(zone->mctx, newname, - count * sizeof(*newname)); - goto unlock; - } - } + if (result == DNS_R_DNAME) { + if (logit) { + dns_name_format(name, namebuf, sizeof namebuf); + dns_name_format(foundname, altbuf, sizeof altbuf); + dns_zone_log(zone, level, "NS '%s' is below a DNAME " + "'%s' (illegal)", namebuf, altbuf); } + return (ISC_FALSE); } - /* - * Everything is ok so attach to the zone. - */ - zone->masters = new; - zone->mastersok = newok; - zone->masterkeynames = newname; - zone->masterscnt = count; - DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS); - - unlock: - UNLOCK_ZONE(zone); - return (result); -} - -isc_result_t -dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) { - isc_result_t result = ISC_R_SUCCESS; - - REQUIRE(DNS_ZONE_VALID(zone)); - - ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); - if (zone->db == NULL) - result = DNS_R_NOTLOADED; - else - dns_db_attach(zone->db, dpb); - ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); - - return (result); + return (ISC_TRUE); } -/* - * Co-ordinates the starting of routine jobs. - */ +static isc_result_t +zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node, + dns_dbversion_t *version, unsigned int *nscount, + unsigned int *errors, isc_boolean_t logit) +{ + isc_result_t result; + unsigned int count = 0; + unsigned int ecount = 0; + dns_rdataset_t rdataset; + dns_rdata_t rdata; + dns_rdata_ns_t ns; -void -dns_zone_maintenance(dns_zone_t *zone) { - const char me[] = "dns_zone_maintenance"; - isc_time_t now; + dns_rdataset_init(&rdataset); + result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns, + dns_rdatatype_none, 0, &rdataset, NULL); + if (result == ISC_R_NOTFOUND) { + INSIST(!dns_rdataset_isassociated(&rdataset)); + goto success; + } + if (result != ISC_R_SUCCESS) { + INSIST(!dns_rdataset_isassociated(&rdataset)); + goto invalidate_rdataset; + } - REQUIRE(DNS_ZONE_VALID(zone)); - ENTER; + result = dns_rdataset_first(&rdataset); + while (result == ISC_R_SUCCESS) { + if (errors != NULL && zone->rdclass == dns_rdataclass_in && + (zone->type == dns_zone_master || + zone->type == dns_zone_slave)) { + dns_rdata_init(&rdata); + dns_rdataset_current(&rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &ns, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + if (dns_name_issubdomain(&ns.name, &zone->origin) && + !zone_check_ns(zone, db, version, &ns.name, logit)) + ecount++; + } + count++; + result = dns_rdataset_next(&rdataset); + } + dns_rdataset_disassociate(&rdataset); - LOCK_ZONE(zone); - TIME_NOW(&now); - zone_settimer(zone, &now); - UNLOCK_ZONE(zone); -} + success: + if (nscount != NULL) + *nscount = count; + if (errors != NULL) + *errors = ecount; -static inline isc_boolean_t -was_dumping(dns_zone_t *zone) { - isc_boolean_t dumping; + result = ISC_R_SUCCESS; - REQUIRE(LOCKED_ZONE(zone)); + invalidate_rdataset: + dns_rdataset_invalidate(&rdataset); - dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING); - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING); - if (!dumping) { - DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP); - isc_time_settoepoch(&zone->dumptime); - } - return (dumping); + return (result); } -#define MAXZONEKEYS 10 - static isc_result_t -do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver, - dns_diff_t *diff) +zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, + unsigned int *soacount, + isc_uint32_t *serial, isc_uint32_t *refresh, + isc_uint32_t *retry, isc_uint32_t *expire, + isc_uint32_t *minimum) { - dns_diff_t temp_diff; isc_result_t result; + unsigned int count; + dns_rdataset_t rdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_soa_t soa; - /* - * Create a singleton diff. - */ - dns_diff_init(diff->mctx, &temp_diff); - temp_diff.resign = diff->resign; - ISC_LIST_APPEND(temp_diff.tuples, *tuple, link); - - /* - * Apply it to the database. - */ - result = dns_diff_apply(&temp_diff, db, ver); - ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link); + dns_rdataset_init(&rdataset); + result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa, + dns_rdatatype_none, 0, &rdataset, NULL); + if (result == ISC_R_NOTFOUND) { + INSIST(!dns_rdataset_isassociated(&rdataset)); + if (soacount != NULL) + *soacount = 0; + if (serial != NULL) + *serial = 0; + if (refresh != NULL) + *refresh = 0; + if (retry != NULL) + *retry = 0; + if (expire != NULL) + *expire = 0; + if (minimum != NULL) + *minimum = 0; + result = ISC_R_SUCCESS; + goto invalidate_rdataset; + } if (result != ISC_R_SUCCESS) { - dns_difftuple_free(tuple); - return (result); + INSIST(!dns_rdataset_isassociated(&rdataset)); + goto invalidate_rdataset; } - /* - * Merge it into the current pending journal entry. - */ - dns_diff_appendminimal(diff, tuple); - - /* - * Do not clear temp_diff. - */ - return (ISC_R_SUCCESS); -} - -static isc_result_t -increment_soa_serial(dns_db_t *db, dns_dbversion_t *ver, - dns_diff_t *diff, isc_mem_t *mctx) -{ - dns_difftuple_t *deltuple = NULL; - dns_difftuple_t *addtuple = NULL; - isc_uint32_t serial; - isc_result_t result; + count = 0; + result = dns_rdataset_first(&rdataset); + while (result == ISC_R_SUCCESS) { + dns_rdata_init(&rdata); + dns_rdataset_current(&rdataset, &rdata); + count++; + if (count == 1) { + result = dns_rdata_tostruct(&rdata, &soa, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + } - CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple)); - CHECK(dns_difftuple_copy(deltuple, &addtuple)); - addtuple->op = DNS_DIFFOP_ADD; + result = dns_rdataset_next(&rdataset); + dns_rdata_reset(&rdata); + } + dns_rdataset_disassociate(&rdataset); - serial = dns_soa_getserial(&addtuple->rdata); + if (soacount != NULL) + *soacount = count; - /* RFC1982 */ - serial = (serial + 1) & 0xFFFFFFFF; - if (serial == 0) - serial = 1; + if (count > 0) { + if (serial != NULL) + *serial = soa.serial; + if (refresh != NULL) + *refresh = soa.refresh; + if (retry != NULL) + *retry = soa.retry; + if (expire != NULL) + *expire = soa.expire; + if (minimum != NULL) + *minimum = soa.minimum; + } - dns_soa_setserial(serial, &addtuple->rdata); - CHECK(do_one_tuple(&deltuple, db, ver, diff)); - CHECK(do_one_tuple(&addtuple, db, ver, diff)); result = ISC_R_SUCCESS; - failure: - if (addtuple != NULL) - dns_difftuple_free(&addtuple); - if (deltuple != NULL) - dns_difftuple_free(&deltuple); + invalidate_rdataset: + dns_rdataset_invalidate(&rdataset); + return (result); } +/* + * zone must be locked. + */ static isc_result_t -update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, - dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl, - dns_rdata_t *rdata) +zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount, + unsigned int *soacount, isc_uint32_t *serial, + isc_uint32_t *refresh, isc_uint32_t *retry, + isc_uint32_t *expire, isc_uint32_t *minimum, + unsigned int *errors) { - dns_difftuple_t *tuple = NULL; isc_result_t result; - result = dns_difftuple_create(diff->mctx, op, - name, ttl, rdata, &tuple); - if (result != ISC_R_SUCCESS) - return (result); - return (do_one_tuple(&tuple, db, ver, diff)); -} + isc_result_t answer = ISC_R_SUCCESS; + dns_dbversion_t *version = NULL; + dns_dbnode_t *node; -static isc_boolean_t -ksk_sanity(dns_db_t *db, dns_dbversion_t *ver) { - isc_boolean_t ret = ISC_FALSE; - isc_boolean_t have_ksk = ISC_FALSE, have_nonksk = ISC_FALSE; - isc_result_t result; - dns_dbnode_t *node = NULL; - dns_rdataset_t rdataset; - dns_rdata_t rdata = DNS_RDATA_INIT; - dns_rdata_dnskey_t dnskey; + REQUIRE(db != NULL); + REQUIRE(zone != NULL); - dns_rdataset_init(&rdataset); - CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node)); - CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0, - &rdataset, NULL)); - CHECK(dns_rdataset_first(&rdataset)); - while (result == ISC_R_SUCCESS && (!have_ksk || !have_nonksk)) { - dns_rdataset_current(&rdataset, &rdata); - CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL)); - if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH)) - == DNS_KEYOWNER_ZONE) { - if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) - have_ksk = ISC_TRUE; - else - have_nonksk = ISC_TRUE; - } - dns_rdata_reset(&rdata); - result = dns_rdataset_next(&rdataset); + dns_db_currentversion(db, &version); + + node = NULL; + result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node); + if (result != ISC_R_SUCCESS) { + answer = result; + goto closeversion; } - if (have_ksk && have_nonksk) - ret = ISC_TRUE; - failure: - if (dns_rdataset_isassociated(&rdataset)) - dns_rdataset_disassociate(&rdataset); - if (node != NULL) - dns_db_detachnode(db, &node); - return (ret); -} -static isc_result_t -find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, - isc_mem_t *mctx, unsigned int maxkeys, - dst_key_t **keys, unsigned int *nkeys) -{ - isc_result_t result; - dns_dbnode_t *node = NULL; - const char *directory = dns_zone_getkeydirectory(zone); + if (nscount != NULL || errors != NULL) { + result = zone_count_ns_rr(zone, db, node, version, + nscount, errors, ISC_TRUE); + if (result != ISC_R_SUCCESS) + answer = result; + } - CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node)); - result = dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db), - directory, mctx, maxkeys, keys, - nkeys); - if (result == ISC_R_NOTFOUND) - result = ISC_R_SUCCESS; - failure: - if (node != NULL) - dns_db_detachnode(db, &node); - return (result); + if (soacount != NULL || serial != NULL || refresh != NULL + || retry != NULL || expire != NULL || minimum != NULL) { + result = zone_load_soa_rr(db, node, version, soacount, + serial, refresh, retry, expire, + minimum); + if (result != ISC_R_SUCCESS) + answer = result; + } + + dns_db_detachnode(db, &node); + closeversion: + dns_db_closeversion(db, &version, ISC_FALSE); + + return (answer); } -static isc_result_t -offline(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, dns_name_t *name, - dns_ttl_t ttl, dns_rdata_t *rdata) -{ - isc_result_t result; +void +dns_zone_attach(dns_zone_t *source, dns_zone_t **target) { + REQUIRE(DNS_ZONE_VALID(source)); + REQUIRE(target != NULL && *target == NULL); + isc_refcount_increment(&source->erefs, NULL); + *target = source; +} + +void +dns_zone_detach(dns_zone_t **zonep) { + dns_zone_t *zone; + unsigned int refs; + isc_boolean_t free_now = ISC_FALSE; + + REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep)); + + zone = *zonep; + + isc_refcount_decrement(&zone->erefs, &refs); + + if (refs == 0) { + LOCK_ZONE(zone); + /* + * We just detached the last external reference. + */ + if (zone->task != NULL) { + /* + * This zone is being managed. Post + * its control event and let it clean + * up synchronously in the context of + * its task. + */ + isc_event_t *ev = &zone->ctlevent; + isc_task_send(zone->task, &ev); + } else { + /* + * This zone is not being managed; it has + * no task and can have no outstanding + * events. Free it immediately. + */ + /* + * Unmanaged zones should not have non-null views; + * we have no way of detaching from the view here + * without causing deadlock because this code is called + * with the view already locked. + */ + INSIST(zone->view == NULL); + free_now = ISC_TRUE; + } + UNLOCK_ZONE(zone); + } + *zonep = NULL; + if (free_now) + zone_free(zone); +} + +void +dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) { + REQUIRE(DNS_ZONE_VALID(source)); + REQUIRE(target != NULL && *target == NULL); + LOCK_ZONE(source); + zone_iattach(source, target); + UNLOCK_ZONE(source); +} + +static void +zone_iattach(dns_zone_t *source, dns_zone_t **target) { + + /* + * 'source' locked by caller. + */ + REQUIRE(LOCKED_ZONE(source)); + REQUIRE(DNS_ZONE_VALID(source)); + REQUIRE(target != NULL && *target == NULL); + INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0); + source->irefs++; + INSIST(source->irefs != 0); + *target = source; +} + +static void +zone_idetach(dns_zone_t **zonep) { + dns_zone_t *zone; + + /* + * 'zone' locked by caller. + */ + REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep)); + zone = *zonep; + REQUIRE(LOCKED_ZONE(*zonep)); + *zonep = NULL; + + INSIST(zone->irefs > 0); + zone->irefs--; + INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0); +} + +void +dns_zone_idetach(dns_zone_t **zonep) { + dns_zone_t *zone; + isc_boolean_t free_needed; + + REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep)); + zone = *zonep; + *zonep = NULL; + + LOCK_ZONE(zone); + INSIST(zone->irefs > 0); + zone->irefs--; + free_needed = exit_check(zone); + UNLOCK_ZONE(zone); + if (free_needed) + zone_free(zone); +} + +isc_mem_t * +dns_zone_getmctx(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + + return (zone->mctx); +} + +dns_zonemgr_t * +dns_zone_getmgr(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + + return (zone->zmgr); +} + +void +dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) { + REQUIRE(DNS_ZONE_VALID(zone)); + + LOCK_ZONE(zone); + if (value) + DNS_ZONE_SETFLAG(zone, flags); + else + DNS_ZONE_CLRFLAG(zone, flags); + UNLOCK_ZONE(zone); +} + +void +dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value) +{ + REQUIRE(DNS_ZONE_VALID(zone)); + + LOCK_ZONE(zone); + if (value) + zone->options |= option; + else + zone->options &= ~option; + UNLOCK_ZONE(zone); +} + +unsigned int +dns_zone_getoptions(dns_zone_t *zone) { + + REQUIRE(DNS_ZONE_VALID(zone)); + + return (zone->options); +} + +void +dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, isc_boolean_t value) +{ + REQUIRE(DNS_ZONE_VALID(zone)); + + LOCK_ZONE(zone); + if (value) + zone->keyopts |= keyopt; + else + zone->keyopts &= ~keyopt; + UNLOCK_ZONE(zone); +} + +unsigned int +dns_zone_getkeyopts(dns_zone_t *zone) { + + REQUIRE(DNS_ZONE_VALID(zone)); + + return (zone->keyopts); +} + +isc_result_t +dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) { + REQUIRE(DNS_ZONE_VALID(zone)); + + LOCK_ZONE(zone); + zone->xfrsource4 = *xfrsource; + UNLOCK_ZONE(zone); + + return (ISC_R_SUCCESS); +} + +isc_sockaddr_t * +dns_zone_getxfrsource4(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + return (&zone->xfrsource4); +} + +isc_result_t +dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) { + REQUIRE(DNS_ZONE_VALID(zone)); + + LOCK_ZONE(zone); + zone->xfrsource6 = *xfrsource; + UNLOCK_ZONE(zone); + + return (ISC_R_SUCCESS); +} + +isc_sockaddr_t * +dns_zone_getxfrsource6(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + return (&zone->xfrsource6); +} + +isc_result_t +dns_zone_setaltxfrsource4(dns_zone_t *zone, + const isc_sockaddr_t *altxfrsource) +{ + REQUIRE(DNS_ZONE_VALID(zone)); + + LOCK_ZONE(zone); + zone->altxfrsource4 = *altxfrsource; + UNLOCK_ZONE(zone); + + return (ISC_R_SUCCESS); +} + +isc_sockaddr_t * +dns_zone_getaltxfrsource4(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + return (&zone->altxfrsource4); +} + +isc_result_t +dns_zone_setaltxfrsource6(dns_zone_t *zone, + const isc_sockaddr_t *altxfrsource) +{ + REQUIRE(DNS_ZONE_VALID(zone)); + + LOCK_ZONE(zone); + zone->altxfrsource6 = *altxfrsource; + UNLOCK_ZONE(zone); + + return (ISC_R_SUCCESS); +} + +isc_sockaddr_t * +dns_zone_getaltxfrsource6(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + return (&zone->altxfrsource6); +} + +isc_result_t +dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) { + REQUIRE(DNS_ZONE_VALID(zone)); + + LOCK_ZONE(zone); + zone->notifysrc4 = *notifysrc; + UNLOCK_ZONE(zone); + + return (ISC_R_SUCCESS); +} + +isc_sockaddr_t * +dns_zone_getnotifysrc4(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + return (&zone->notifysrc4); +} + +isc_result_t +dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) { + REQUIRE(DNS_ZONE_VALID(zone)); + + LOCK_ZONE(zone); + zone->notifysrc6 = *notifysrc; + UNLOCK_ZONE(zone); + + return (ISC_R_SUCCESS); +} + +isc_sockaddr_t * +dns_zone_getnotifysrc6(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + return (&zone->notifysrc6); +} + +isc_result_t +dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify, + isc_uint32_t count) +{ + isc_sockaddr_t *new; + + REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(count == 0 || notify != NULL); + + LOCK_ZONE(zone); + if (zone->notify != NULL) { + isc_mem_put(zone->mctx, zone->notify, + zone->notifycnt * sizeof(*new)); + zone->notify = NULL; + zone->notifycnt = 0; + } + if (count != 0) { + new = isc_mem_get(zone->mctx, count * sizeof(*new)); + if (new == NULL) { + UNLOCK_ZONE(zone); + return (ISC_R_NOMEMORY); + } + memcpy(new, notify, count * sizeof(*new)); + zone->notify = new; + zone->notifycnt = count; + } + UNLOCK_ZONE(zone); + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters, + isc_uint32_t count) +{ + isc_result_t result; + + result = dns_zone_setmasterswithkeys(zone, masters, NULL, count); + return (result); +} + +static isc_boolean_t +same_masters(const isc_sockaddr_t *old, const isc_sockaddr_t *new, + isc_uint32_t count) +{ + unsigned int i; + + for (i = 0; i < count; i++) + if (!isc_sockaddr_equal(&old[i], &new[i])) + return (ISC_FALSE); + return (ISC_TRUE); +} + +static isc_boolean_t +same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) { + unsigned int i; + + if (old == NULL && new == NULL) + return (ISC_TRUE); + if (old == NULL || new == NULL) + return (ISC_FALSE); + + for (i = 0; i < count; i++) { + if (old[i] == NULL && new[i] == NULL) + continue; + if (old[i] == NULL || new[i] == NULL || + !dns_name_equal(old[i], new[i])) + return (ISC_FALSE); + } + return (ISC_TRUE); +} + +isc_result_t +dns_zone_setmasterswithkeys(dns_zone_t *zone, + const isc_sockaddr_t *masters, + dns_name_t **keynames, + isc_uint32_t count) +{ + isc_sockaddr_t *new; + isc_result_t result = ISC_R_SUCCESS; + dns_name_t **newname; + isc_boolean_t *newok; + unsigned int i; + + REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(count == 0 || masters != NULL); + if (keynames != NULL) { + REQUIRE(count != 0); + } + + LOCK_ZONE(zone); + /* + * The refresh code assumes that 'masters' wouldn't change under it. + * If it will change then kill off any current refresh in progress + * and update the masters info. If it won't change then we can just + * unlock and exit. + */ + if (count != zone->masterscnt || + !same_masters(zone->masters, masters, count) || + !same_keynames(zone->masterkeynames, keynames, count)) { + if (zone->request != NULL) + dns_request_cancel(zone->request); + } else + goto unlock; + if (zone->masters != NULL) { + isc_mem_put(zone->mctx, zone->masters, + zone->masterscnt * sizeof(*new)); + zone->masters = NULL; + } + if (zone->masterkeynames != NULL) { + for (i = 0; i < zone->masterscnt; i++) { + if (zone->masterkeynames[i] != NULL) { + dns_name_free(zone->masterkeynames[i], + zone->mctx); + isc_mem_put(zone->mctx, + zone->masterkeynames[i], + sizeof(dns_name_t)); + zone->masterkeynames[i] = NULL; + } + } + isc_mem_put(zone->mctx, zone->masterkeynames, + zone->masterscnt * sizeof(dns_name_t *)); + zone->masterkeynames = NULL; + } + if (zone->mastersok != NULL) { + isc_mem_put(zone->mctx, zone->mastersok, + zone->masterscnt * sizeof(isc_boolean_t)); + zone->mastersok = NULL; + } + zone->masterscnt = 0; + /* + * If count == 0, don't allocate any space for masters, mastersok or + * keynames so internally, those pointers are NULL if count == 0 + */ + if (count == 0) + goto unlock; + + /* + * masters must contain count elements! + */ + new = isc_mem_get(zone->mctx, count * sizeof(*new)); + if (new == NULL) { + result = ISC_R_NOMEMORY; + goto unlock; + } + memcpy(new, masters, count * sizeof(*new)); + + /* + * Similarly for mastersok. + */ + newok = isc_mem_get(zone->mctx, count * sizeof(*newok)); + if (newok == NULL) { + result = ISC_R_NOMEMORY; + isc_mem_put(zone->mctx, new, count * sizeof(*new)); + goto unlock; + }; + for (i = 0; i < count; i++) + newok[i] = ISC_FALSE; + + /* + * if keynames is non-NULL, it must contain count elements! + */ + newname = NULL; + if (keynames != NULL) { + newname = isc_mem_get(zone->mctx, count * sizeof(*newname)); + if (newname == NULL) { + result = ISC_R_NOMEMORY; + isc_mem_put(zone->mctx, new, count * sizeof(*new)); + isc_mem_put(zone->mctx, newok, count * sizeof(*newok)); + goto unlock; + } + for (i = 0; i < count; i++) + newname[i] = NULL; + for (i = 0; i < count; i++) { + if (keynames[i] != NULL) { + newname[i] = isc_mem_get(zone->mctx, + sizeof(dns_name_t)); + if (newname[i] == NULL) + goto allocfail; + dns_name_init(newname[i], NULL); + result = dns_name_dup(keynames[i], zone->mctx, + newname[i]); + if (result != ISC_R_SUCCESS) { + allocfail: + for (i = 0; i < count; i++) + if (newname[i] != NULL) + dns_name_free( + newname[i], + zone->mctx); + isc_mem_put(zone->mctx, new, + count * sizeof(*new)); + isc_mem_put(zone->mctx, newok, + count * sizeof(*newok)); + isc_mem_put(zone->mctx, newname, + count * sizeof(*newname)); + goto unlock; + } + } + } + } + + /* + * Everything is ok so attach to the zone. + */ + zone->masters = new; + zone->mastersok = newok; + zone->masterkeynames = newname; + zone->masterscnt = count; + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS); + + unlock: + UNLOCK_ZONE(zone); + return (result); +} + +isc_result_t +dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) { + isc_result_t result = ISC_R_SUCCESS; + + REQUIRE(DNS_ZONE_VALID(zone)); + + ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); + if (zone->db == NULL) + result = DNS_R_NOTLOADED; + else + dns_db_attach(zone->db, dpb); + ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); + + return (result); +} + +void +dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) { + REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(zone->type == dns_zone_staticstub); + + ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write); + REQUIRE(zone->db == NULL); + dns_db_attach(db, &zone->db); + ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write); +} + +/* + * Co-ordinates the starting of routine jobs. + */ + +void +dns_zone_maintenance(dns_zone_t *zone) { + const char me[] = "dns_zone_maintenance"; + isc_time_t now; + + REQUIRE(DNS_ZONE_VALID(zone)); + ENTER; + + LOCK_ZONE(zone); + TIME_NOW(&now); + zone_settimer(zone, &now); + UNLOCK_ZONE(zone); +} + +static inline isc_boolean_t +was_dumping(dns_zone_t *zone) { + isc_boolean_t dumping; + + REQUIRE(LOCKED_ZONE(zone)); + + dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING); + if (!dumping) { + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP); + isc_time_settoepoch(&zone->dumptime); + } + return (dumping); +} + +#define MAXZONEKEYS 10 + +static isc_result_t +find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, + isc_mem_t *mctx, unsigned int maxkeys, + dst_key_t **keys, unsigned int *nkeys) +{ + isc_result_t result; + dns_dbnode_t *node = NULL; + const char *directory = dns_zone_getkeydirectory(zone); + + CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node)); + result = dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db), + directory, mctx, maxkeys, keys, + nkeys); + if (result == ISC_R_NOTFOUND) + result = ISC_R_SUCCESS; + failure: + if (node != NULL) + dns_db_detachnode(db, &node); + return (result); +} + +static isc_result_t +offline(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, dns_name_t *name, + dns_ttl_t ttl, dns_rdata_t *rdata) +{ + isc_result_t result; if ((rdata->flags & DNS_RDATA_OFFLINE) != 0) return (ISC_R_SUCCESS); @@ -3752,10 +4575,14 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, (isc_stdtime_t) 0, &rdataset, NULL); dns_db_detachnode(db, &node); - if (result == ISC_R_NOTFOUND) + if (result == ISC_R_NOTFOUND) { + INSIST(!dns_rdataset_isassociated(&rdataset)); return (ISC_R_SUCCESS); - if (result != ISC_R_SUCCESS) + } + if (result != ISC_R_SUCCESS) { + INSIST(!dns_rdataset_isassociated(&rdataset)); goto failure; + } for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; @@ -3841,7 +4668,8 @@ static isc_result_t add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception, - isc_stdtime_t expire, isc_boolean_t check_ksk) + isc_stdtime_t expire, isc_boolean_t check_ksk, + isc_boolean_t keyset_kskonly) { isc_result_t result; dns_dbnode_t *node = NULL; @@ -3849,7 +4677,7 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_rdata_t sig_rdata = DNS_RDATA_INIT; unsigned char data[1024]; /* XXX */ isc_buffer_t buffer; - unsigned int i; + unsigned int i, j; dns_rdataset_init(&rdataset); isc_buffer_init(&buffer, data, sizeof(data)); @@ -3865,18 +4693,59 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, result = dns_db_findrdataset(db, node, ver, type, 0, (isc_stdtime_t) 0, &rdataset, NULL); dns_db_detachnode(db, &node); - if (result == ISC_R_NOTFOUND) + if (result == ISC_R_NOTFOUND) { + INSIST(!dns_rdataset_isassociated(&rdataset)); return (ISC_R_SUCCESS); - if (result != ISC_R_SUCCESS) + } + if (result != ISC_R_SUCCESS) { + INSIST(!dns_rdataset_isassociated(&rdataset)); goto failure; + } + +#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0) +#define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0) +#define ALG(x) dst_key_alg(x) for (i = 0; i < nkeys; i++) { - if (check_ksk && type != dns_rdatatype_dnskey && - (dst_key_flags(keys[i]) & DNS_KEYFLAG_KSK) != 0) - continue; + isc_boolean_t both = ISC_FALSE; + if (!dst_key_isprivate(keys[i])) continue; + + if (check_ksk && !REVOKE(keys[i])) { + isc_boolean_t have_ksk, have_nonksk; + if (KSK(keys[i])) { + have_ksk = ISC_TRUE; + have_nonksk = ISC_FALSE; + } else { + have_ksk = ISC_FALSE; + have_nonksk = ISC_TRUE; + } + for (j = 0; j < nkeys; j++) { + if (j == i || ALG(keys[i]) != ALG(keys[j])) + continue; + if (REVOKE(keys[j])) + continue; + if (KSK(keys[j])) + have_ksk = ISC_TRUE; + else + have_nonksk = ISC_TRUE; + both = have_ksk && have_nonksk; + if (both) + break; + } + } + if (both) { + if (type == dns_rdatatype_dnskey) { + if (!KSK(keys[i]) && keyset_kskonly) + continue; + } else if (KSK(keys[i])) + continue; + } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) + continue; + /* Calculate the signature, creating a RRSIG RDATA. */ + isc_buffer_clear(&buffer); CHECK(dns_dnssec_sign(name, &rdataset, keys[i], &inception, &expire, mctx, &buffer, &sig_rdata)); @@ -3898,7 +4767,6 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, static void zone_resigninc(dns_zone_t *zone) { - const char *journalfile; dns_db_t *db = NULL; dns_dbversion_t *version = NULL; dns_diff_t sig_diff; @@ -3907,7 +4775,7 @@ zone_resigninc(dns_zone_t *zone) { dns_rdataset_t rdataset; dns_rdatatype_t covers; dst_key_t *zone_keys[MAXZONEKEYS]; - isc_boolean_t check_ksk; + isc_boolean_t check_ksk, keyset_kskonly = ISC_FALSE; isc_result_t result; isc_stdtime_t now, inception, soaexpire, expire, stop; isc_uint32_t jitter; @@ -3962,8 +4830,7 @@ zone_resigninc(dns_zone_t *zone) { stop = now + 5; check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK); - if (check_ksk) - check_ksk = ksk_sanity(db, version); + keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY); name = dns_fixedname_name(&fixed); result = dns_db_getsigningtime(db, &rdataset, name); @@ -4007,14 +4874,14 @@ zone_resigninc(dns_zone_t *zone) { } result = add_sigs(db, version, name, covers, &sig_diff, zone_keys, nkeys, zone->mctx, inception, - expire, check_ksk); + expire, check_ksk, keyset_kskonly); if (result != ISC_R_SUCCESS) { dns_zone_log(zone, ISC_LOG_ERROR, "zone_resigninc:add_sigs -> %s\n", dns_result_totext(result)); break; } - result = dns_db_getsigningtime(db, &rdataset, + result = dns_db_getsigningtime(db, &rdataset, dns_fixedname_name(&fixed)); if (nkeys == 0 && result == ISC_R_NOTFOUND) { result = ISC_R_SUCCESS; @@ -4052,7 +4919,7 @@ zone_resigninc(dns_zone_t *zone) { */ result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa, &sig_diff, zone_keys, nkeys, zone->mctx, inception, - soaexpire, check_ksk); + soaexpire, check_ksk, keyset_kskonly); if (result != ISC_R_SUCCESS) { dns_zone_log(zone, ISC_LOG_ERROR, "zone_resigninc:add_sigs -> %s\n", @@ -4060,31 +4927,10 @@ zone_resigninc(dns_zone_t *zone) { goto failure; } - journalfile = dns_zone_getjournal(zone); - if (journalfile != NULL) { - dns_journal_t *journal = NULL; - result = dns_journal_open(zone->mctx, journalfile, - ISC_TRUE, &journal); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, - "zone_resigninc:dns_journal_open -> %s\n", - dns_result_totext(result)); - goto failure; - } - - result = dns_journal_write_transaction(journal, &sig_diff); - dns_journal_destroy(&journal); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, - "zone_resigninc:dns_journal_write_transaction -> %s\n", - dns_result_totext(result)); - goto failure; - } - } + /* Write changes to journal file. */ + zone_journal(zone, &sig_diff, "zone_resigninc"); - /* - * Everything has succeeded. Commit the changes. - */ + /* Everything has succeeded. Commit the changes. */ dns_db_closeversion(db, &version, ISC_TRUE); failure: @@ -4151,16 +4997,6 @@ next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname, return (result); } -static void -set_bit(unsigned char *array, unsigned int index) { - unsigned int shift, mask; - - shift = 7 - (index % 8); - mask = 1 << shift; - - array[index / 8] |= mask; -} - static isc_boolean_t signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, dns_rdatatype_t type, dst_key_t *key) @@ -4173,8 +5009,10 @@ signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, dns_rdataset_init(&rdataset); result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig, type, 0, &rdataset, NULL); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) { + INSIST(!dns_rdataset_isassociated(&rdataset)); return (ISC_FALSE); + } for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { @@ -4209,21 +5047,6 @@ add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, CHECK(next_active(db, version, name, next, bottom)); CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer, &rdata)); - if (dns_name_equal(dns_db_origin(db), name)) { - /* - * Set the OPT bit to indicate that this is a - * partially secure zone. - */ - isc_region_t region; - - dns_rdata_toregion(&rdata, ®ion); - dns_name_fromregion(next, ®ion); - isc_region_consume(®ion, next->length); - INSIST(region.length > (2 + dns_rdatatype_opt / 8) && - region.base[0] == 0 && - region.base[1] > dns_rdatatype_opt / 8); - set_bit(region.base + 2, dns_rdatatype_opt); - } CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl, &rdata)); failure: @@ -4236,8 +5059,8 @@ sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node, isc_boolean_t build_nsec, dst_key_t *key, isc_stdtime_t inception, isc_stdtime_t expire, unsigned int minimum, isc_boolean_t is_ksk, - isc_boolean_t *delegation, dns_diff_t *diff, - isc_int32_t *signatures, isc_mem_t *mctx) + isc_boolean_t keyset_kskonly, isc_boolean_t *delegation, + dns_diff_t *diff, isc_int32_t *signatures, isc_mem_t *mctx) { isc_result_t result; dns_rdatasetiter_t *iterator = NULL; @@ -4255,6 +5078,7 @@ sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node, result = ISC_R_SUCCESS; return (result); } + dns_rdataset_init(&rdataset); isc_buffer_init(&buffer, data, sizeof(data)); seen_rr = seen_soa = seen_ns = seen_dname = seen_nsec = @@ -4275,7 +5099,8 @@ sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node, seen_nsec = ISC_TRUE; else if (rdataset.type == dns_rdatatype_nsec3) seen_nsec3 = ISC_TRUE; - seen_rr = ISC_TRUE; + if (rdataset.type != dns_rdatatype_rrsig) + seen_rr = ISC_TRUE; dns_rdataset_disassociate(&rdataset); } if (result != ISC_R_NOMORE) @@ -4299,9 +5124,15 @@ sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node, if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) { /* Build and add NSEC. */ bottom = (seen_ns && !seen_soa) || seen_dname; - CHECK(add_nsec(db, version, name, node, minimum, bottom, diff)); - /* Count a NSEC generation as a signature generation. */ - (*signatures)--; + /* + * Build a NSEC record except at the origin. + */ + if (!dns_name_equal(name, dns_db_origin(db))) { + CHECK(add_nsec(db, version, name, node, minimum, + bottom, diff)); + /* Count a NSEC generation as a signature generation. */ + (*signatures)--; + } } result = dns_rdatasetiter_first(iterator); while (result == ISC_R_SUCCESS) { @@ -4309,7 +5140,10 @@ sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node, if (rdataset.type == dns_rdatatype_soa || rdataset.type == dns_rdatatype_rrsig) goto next_rdataset; - if (is_ksk && rdataset.type != dns_rdatatype_dnskey) + if (rdataset.type == dns_rdatatype_dnskey) { + if (!is_ksk && keyset_kskonly) + goto next_rdataset; + } else if (is_ksk) goto next_rdataset; if (*delegation && rdataset.type != dns_rdatatype_ds && @@ -4318,6 +5152,7 @@ sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node, if (signed_with_key(db, node, version, rdataset.type, key)) goto next_rdataset; /* Calculate the signature, creating a RRSIG RDATA. */ + isc_buffer_clear(&buffer); CHECK(dns_dnssec_sign(name, &rdataset, key, &inception, &expire, mctx, &buffer, &rdata)); /* Update the database and journal with the RRSIG. */ @@ -4334,7 +5169,7 @@ sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node, result = ISC_R_SUCCESS; if (seen_dname) *delegation = ISC_TRUE; -failure: + failure: if (dns_rdataset_isassociated(&rdataset)) dns_rdataset_disassociate(&rdataset); if (iterator != NULL) @@ -4342,63 +5177,45 @@ failure: return (result); } +/* + * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist. + */ static isc_result_t updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, - dns_ttl_t minimum, isc_boolean_t *secureupdated, dns_diff_t *diff) + dns_ttl_t minimum, isc_boolean_t update_only, dns_diff_t *diff) { isc_result_t result; - dns_rdata_t rdata = DNS_RDATA_INIT; - unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE]; dns_rdataset_t rdataset; - dns_rdata_nsec_t nsec; dns_dbnode_t *node = NULL; - /* - * Check to see if the OPT bit has already been cleared. - */ CHECK(dns_db_getoriginnode(db, &node)); - dns_rdataset_init(&rdataset); - CHECK(dns_db_findrdataset(db, node, version, dns_rdatatype_nsec, - dns_rdatatype_none, 0, &rdataset, NULL)); - CHECK(dns_rdataset_first(&rdataset)); - dns_rdataset_current(&rdataset, &rdata); - - /* - * Find the NEXT name for building the new record. - */ - CHECK(dns_rdata_tostruct(&rdata, &nsec, NULL)); - - /* - * Delete the old NSEC record. - */ - CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_DEL, name, minimum, - &rdata)); - dns_rdata_reset(&rdata); - - /* - * Add the new NSEC record. - */ - CHECK(dns_nsec_buildrdata(db, version, node, &nsec.next, nsecbuffer, - &rdata)); - CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, minimum, - &rdata)); - dns_rdata_reset(&rdata); - - if (secureupdated != NULL) - *secureupdated = ISC_TRUE; - + if (update_only) { + dns_rdataset_init(&rdataset); + result = dns_db_findrdataset(db, node, version, + dns_rdatatype_nsec, + dns_rdatatype_none, + 0, &rdataset, NULL); + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); + if (result == ISC_R_NOTFOUND) + goto success; + if (result != ISC_R_SUCCESS) + goto failure; + } + CHECK(delete_nsec(db, version, node, name, diff)); + CHECK(add_nsec(db, version, name, node, minimum, ISC_FALSE, diff)); + success: + result = ISC_R_SUCCESS; failure: if (node != NULL) dns_db_detachnode(db, &node); - if (dns_rdataset_isassociated(&rdataset)) - dns_rdataset_disassociate(&rdataset); return (result); } static isc_result_t -updatesignwithkey(dns_signing_t *signing, dns_dbversion_t *version, - dns_name_t *name, dns_rdatatype_t privatetype, - dns_diff_t *diff) +updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing, + dns_dbversion_t *version, isc_boolean_t build_nsec3, + dns_ttl_t minimum, dns_diff_t *diff) { isc_result_t result; dns_dbnode_t *node = NULL; @@ -4406,43 +5223,68 @@ updatesignwithkey(dns_signing_t *signing, dns_dbversion_t *version, dns_rdata_t rdata = DNS_RDATA_INIT; unsigned char data[5]; isc_boolean_t seen_done = ISC_FALSE; + isc_boolean_t have_rr = ISC_FALSE; dns_rdataset_init(&rdataset); result = dns_db_getoriginnode(signing->db, &node); if (result != ISC_R_SUCCESS) goto failure; - result = dns_db_findrdataset(signing->db, node, version, privatetype, - dns_rdatatype_none, 0, &rdataset, NULL); + result = dns_db_findrdataset(signing->db, node, version, + zone->privatetype, dns_rdatatype_none, + 0, &rdataset, NULL); if (result == ISC_R_NOTFOUND) { + INSIST(!dns_rdataset_isassociated(&rdataset)); result = ISC_R_SUCCESS; goto failure; } - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) { + INSIST(!dns_rdataset_isassociated(&rdataset)); goto failure; + } for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { dns_rdataset_current(&rdataset, &rdata); + /* + * If we don't match the algorithm or keyid skip the record. + */ if (rdata.length != 5 || rdata.data[0] != signing->algorithm || rdata.data[1] != ((signing->keyid >> 8) & 0xff) || rdata.data[2] != (signing->keyid & 0xff)) { + have_rr = ISC_TRUE; dns_rdata_reset(&rdata); continue; } - if (!signing->delete && rdata.data[4] != 0) + /* + * We have a match. If we were signing (!signing->delete) + * and we already have a record indicating that we have + * finished signing (rdata.data[4] != 0) then keep it. + * Otherwise it needs to be deleted as we have removed all + * the signatures (signing->delete), so any record indicating + * completion is now out of date, or we have finished signing + * with the new record so we no longer need to remember that + * we need to sign the zone with the matching key across a + * nameserver re-start. + */ + if (!signing->delete && rdata.data[4] != 0) { seen_done = ISC_TRUE; - else + have_rr = ISC_TRUE; + } else CHECK(update_one_rr(signing->db, version, diff, - DNS_DIFFOP_DEL, name, + DNS_DIFFOP_DEL, &zone->origin, rdataset.ttl, &rdata)); dns_rdata_reset(&rdata); } if (result == ISC_R_NOMORE) result = ISC_R_SUCCESS; if (!signing->delete && !seen_done) { - + /* + * If we were signing then we need to indicate that we have + * finished signing the zone with this key. If it is already + * there we don't need to add it a second time. + */ data[0] = signing->algorithm; data[1] = (signing->keyid >> 8) & 0xff; data[2] = signing->keyid & 0xff; @@ -4450,11 +5292,23 @@ updatesignwithkey(dns_signing_t *signing, dns_dbversion_t *version, data[4] = 1; rdata.length = sizeof(data); rdata.data = data; - rdata.type = privatetype; + rdata.type = zone->privatetype; rdata.rdclass = dns_db_class(signing->db); CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD, - name, rdataset.ttl, &rdata)); + &zone->origin, rdataset.ttl, &rdata)); + } else if (!have_rr) { + dns_name_t *origin = dns_db_origin(signing->db); + /* + * Rebuild the NSEC/NSEC3 record for the origin as we no + * longer have any private records. + */ + if (build_nsec3) + CHECK(dns_nsec3_addnsec3s(signing->db, version, origin, + minimum, ISC_FALSE, diff)); + CHECK(updatesecure(signing->db, version, origin, minimum, + ISC_TRUE, diff)); } + failure: if (dns_rdataset_isassociated(&rdataset)) dns_rdataset_disassociate(&rdataset); @@ -4463,9 +5317,15 @@ updatesignwithkey(dns_signing_t *signing, dns_dbversion_t *version, return (result); } +/* + * If 'active' is set then we are not done with the chain yet so only + * delete the nsec3param record which indicates a full chain exists + * (flags == 0). + */ static isc_result_t fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain, - isc_boolean_t active, dns_diff_t *diff) + isc_boolean_t active, dns_rdatatype_t privatetype, + dns_diff_t *diff) { dns_dbnode_t *node = NULL; dns_name_t *name = dns_db_origin(db); @@ -4484,7 +5344,7 @@ fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain, result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0, 0, &rdataset, NULL); if (result == ISC_R_NOTFOUND) - goto add; + goto try_private; if (result != ISC_R_SUCCESS) goto failure; @@ -4520,6 +5380,50 @@ fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain, if (result != ISC_R_NOMORE) goto failure; + dns_rdataset_disassociate(&rdataset); + + try_private: + + if (active) + goto add; + /* + * Delete all private records which match that in nsec3chain. + */ + result = dns_db_findrdataset(db, node, ver, privatetype, + 0, 0, &rdataset, NULL); + if (result == ISC_R_NOTFOUND) + goto add; + if (result != ISC_R_SUCCESS) + goto failure; + + for (result = dns_rdataset_first(&rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&rdataset)) { + dns_rdata_t private = DNS_RDATA_INIT; + unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; + + dns_rdataset_current(&rdataset, &private); + if (!dns_nsec3param_fromprivate(&private, &rdata, + buf, sizeof(buf))) + continue; + CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL)); + + if (nsec3param.hash != chain->nsec3param.hash || + nsec3param.iterations != chain->nsec3param.iterations || + nsec3param.salt_length != chain->nsec3param.salt_length || + memcmp(nsec3param.salt, chain->nsec3param.salt, + nsec3param.salt_length)) { + dns_rdata_reset(&rdata); + continue; + } + + CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, + name, rdataset.ttl, &private)); + dns_rdata_reset(&rdata); + } + if (result != ISC_R_NOMORE) + goto failure; + add: if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) { result = ISC_R_SUCCESS; @@ -4620,7 +5524,7 @@ deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node, static isc_result_t need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver, const dns_rdata_nsec3param_t *param, - isc_boolean_t *answer, isc_boolean_t *updatensec) + isc_boolean_t *answer) { dns_dbnode_t *node = NULL; dns_rdata_t rdata = DNS_RDATA_INIT; @@ -4634,29 +5538,19 @@ need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver, RUNTIME_CHECK(result == ISC_R_SUCCESS); dns_rdataset_init(&rdataset); + result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0, &rdataset, NULL); - if (result == ISC_R_NOTFOUND) - goto check_nsec3param; - - if (result != ISC_R_SUCCESS) - goto failure; - - CHECK(dns_rdataset_first(&rdataset)); - dns_rdataset_current(&rdataset, &rdata); - - if (!dns_nsec_typepresent(&rdata, dns_rdatatype_opt)) { - /* - * We have a complete NSEC chain. Signal to update - * the apex NSEC record. - */ - *updatensec = ISC_TRUE; - goto failure; + if (result == ISC_R_SUCCESS) { + dns_rdataset_disassociate(&rdataset); + dns_db_detachnode(db, &node); + return (result); + } + if (result != ISC_R_NOTFOUND) { + dns_db_detachnode(db, &node); + return (result); } - dns_rdataset_disassociate(&rdataset); - dns_rdata_reset(&rdata); - check_nsec3param: result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0, 0, &rdataset, NULL); if (result == ISC_R_NOTFOUND) { @@ -4705,13 +5599,60 @@ need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver, return (result); } +static isc_result_t +update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version, + dst_key_t *zone_keys[], unsigned int nkeys, dns_zone_t *zone, + isc_stdtime_t inception, isc_stdtime_t expire, isc_stdtime_t now, + isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly, + dns_diff_t *sig_diff) +{ + dns_difftuple_t *tuple; + isc_result_t result; + + for (tuple = ISC_LIST_HEAD(diff->tuples); + tuple != NULL; + tuple = ISC_LIST_HEAD(diff->tuples)) { + result = del_sigs(zone, db, version, &tuple->name, + tuple->rdata.type, sig_diff, + zone_keys, nkeys, now); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "update_sigs:del_sigs -> %s\n", + dns_result_totext(result)); + return (result); + } + result = add_sigs(db, version, &tuple->name, + tuple->rdata.type, sig_diff, + zone_keys, nkeys, zone->mctx, inception, + expire, check_ksk, keyset_kskonly); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "update_sigs:add_sigs -> %s\n", + dns_result_totext(result)); + return (result); + } + + do { + dns_difftuple_t *next = ISC_LIST_NEXT(tuple, link); + while (next != NULL && + (tuple->rdata.type != next->rdata.type || + !dns_name_equal(&tuple->name, &next->name))) + next = ISC_LIST_NEXT(next, link); + ISC_LIST_UNLINK(diff->tuples, tuple, link); + dns_diff_appendminimal(sig_diff, &tuple); + INSIST(tuple == NULL); + tuple = next; + } while (tuple != NULL); + } + return (ISC_R_SUCCESS); +} + /* * Incrementally build and sign a new NSEC3 chain using the parameters * requested. */ static void zone_nsec3chain(dns_zone_t *zone) { - const char *journalfile; dns_db_t *db = NULL; dns_dbnode_t *node = NULL; dns_dbversion_t *version = NULL; @@ -4727,7 +5668,7 @@ zone_nsec3chain(dns_zone_t *zone) { dns_nsec3chainlist_t cleanup; dst_key_t *zone_keys[MAXZONEKEYS]; isc_int32_t signatures; - isc_boolean_t check_ksk, is_ksk; + isc_boolean_t check_ksk, keyset_kskonly, is_ksk; isc_boolean_t delegation; isc_boolean_t first; isc_result_t result; @@ -4740,9 +5681,9 @@ zone_nsec3chain(dns_zone_t *zone) { isc_boolean_t seen_soa, seen_ns, seen_dname, seen_ds; isc_boolean_t seen_nsec, seen_nsec3, seen_rr; dns_rdatasetiter_t *iterator = NULL; - dns_difftuple_t *tuple; isc_boolean_t buildnsecchain; isc_boolean_t updatensec = ISC_FALSE; + dns_rdatatype_t privatetype = zone->privatetype; dns_rdataset_init(&rdataset); dns_fixedname_init(&fixed); @@ -4799,8 +5740,7 @@ zone_nsec3chain(dns_zone_t *zone) { stop = now + 5; check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK); - if (check_ksk) - check_ksk = ksk_sanity(db, version); + keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY); /* * We keep pulling nodes off each iterator in turn until @@ -4924,9 +5864,17 @@ zone_nsec3chain(dns_zone_t *zone) { * Process one node. */ dns_dbiterator_pause(nsec3chain->dbiterator); - CHECK(dns_nsec3_addnsec3(db, version, name, - &nsec3chain->nsec3param, - zone->minimum, unsecure, &nsec3_diff)); + result = dns_nsec3_addnsec3(db, version, name, + &nsec3chain->nsec3param, + zone->minimum, unsecure, + &nsec3_diff); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:" + "dns_nsec3_addnsec3 -> %s\n", + dns_result_totext(result)); + goto failure; + } + /* * Treat each call to dns_nsec3_addnsec3() as if it's cost is * two signatures. Additionally there will, in general, be @@ -4948,7 +5896,8 @@ zone_nsec3chain(dns_zone_t *zone) { if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) { CHECK(fixup_nsec3param(db, version, nsec3chain, - ISC_FALSE, ¶m_diff)); + ISC_FALSE, privatetype, + ¶m_diff)); LOCK_ZONE(zone); ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link); @@ -4962,12 +5911,14 @@ zone_nsec3chain(dns_zone_t *zone) { CHECK(fixup_nsec3param(db, version, nsec3chain, ISC_TRUE, + privatetype, ¶m_diff)); nsec3chain->delete_nsec = ISC_TRUE; goto same_addchain; } CHECK(fixup_nsec3param(db, version, nsec3chain, - ISC_FALSE, ¶m_diff)); + ISC_FALSE, privatetype, + ¶m_diff)); LOCK_ZONE(zone); ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link); @@ -5028,10 +5979,22 @@ zone_nsec3chain(dns_zone_t *zone) { * of removing this NSEC3 chain. */ if (first && !updatensec && - (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0) - CHECK(need_nsec_chain(db, version, - &nsec3chain->nsec3param, - &buildnsecchain, &updatensec)); + (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0) { + result = need_nsec_chain(db, version, + &nsec3chain->nsec3param, + &buildnsecchain); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "zone_nsec3chain:" + "need_nsec_chain -> %s\n", + dns_result_totext(result)); + goto failure; + } + } + + if (first) + dns_zone_log(zone, ISC_LOG_DEBUG(3), "zone_nsec3chain:" + "buildnsecchain = %u\n", buildnsecchain); dns_dbiterator_current(nsec3chain->dbiterator, &node, name); delegation = ISC_FALSE; @@ -5040,16 +6003,33 @@ zone_nsec3chain(dns_zone_t *zone) { /* * Delete the NSECPARAM record that matches this chain. */ - if (first) - CHECK(fixup_nsec3param(db, version, nsec3chain, - ISC_TRUE, ¶m_diff)); + if (first) { + result = fixup_nsec3param(db, version, + nsec3chain, + ISC_TRUE, privatetype, + ¶m_diff); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "zone_nsec3chain:" + "fixup_nsec3param -> %s\n", + dns_result_totext(result)); + goto failure; + } + } /* * Delete the NSEC3 records. */ - CHECK(deletematchingnsec3(db, version, node, name, - &nsec3chain->nsec3param, - &nsec3_diff)); + result = deletematchingnsec3(db, version, node, name, + &nsec3chain->nsec3param, + &nsec3_diff); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "zone_nsec3chain:" + "deletematchingnsec3 -> %s\n", + dns_result_totext(result)); + goto failure; + } goto next_removenode; } @@ -5100,7 +6080,8 @@ zone_nsec3chain(dns_zone_t *zone) { seen_nsec = ISC_TRUE; else if (rdataset.type == dns_rdatatype_nsec3) seen_nsec3 = ISC_TRUE; - seen_rr = ISC_TRUE; + if (rdataset.type != dns_rdatatype_rrsig) + seen_rr = ISC_TRUE; dns_rdataset_disassociate(&rdataset); } dns_rdatasetiter_destroy(&iterator); @@ -5110,8 +6091,14 @@ zone_nsec3chain(dns_zone_t *zone) { if ((seen_ns && !seen_soa) || seen_dname) delegation = ISC_TRUE; - CHECK(add_nsec(db, version, name, node, zone->minimum, - delegation, &nsec_diff)); + /* + * Add a NSEC record except at the origin. + */ + if (!dns_name_equal(name, dns_db_origin(db))) { + dns_dbiterator_pause(nsec3chain->dbiterator); + CHECK(add_nsec(db, version, name, node, zone->minimum, + delegation, &nsec_diff)); + } next_removenode: first = ISC_FALSE; @@ -5133,8 +6120,17 @@ zone_nsec3chain(dns_zone_t *zone) { UNLOCK_ZONE(zone); ISC_LIST_APPEND(cleanup, nsec3chain, link); dns_dbiterator_pause(nsec3chain->dbiterator); - CHECK(fixup_nsec3param(db, version, nsec3chain, - ISC_FALSE, ¶m_diff)); + result = fixup_nsec3param(db, version, + nsec3chain, ISC_FALSE, + privatetype, + ¶m_diff); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "zone_nsec3chain:" + "fixup_nsec3param -> %s\n", + dns_result_totext(result)); + goto failure; + } goto next_removechain; } else if (result != ISC_R_SUCCESS) { dns_zone_log(zone, ISC_LOG_ERROR, @@ -5166,107 +6162,101 @@ zone_nsec3chain(dns_zone_t *zone) { } /* - * Add / update signatures for the NSEC3 records. + * We may need to update the NSEC/NSEC3 records for the zone apex. */ - for (tuple = ISC_LIST_HEAD(nsec3_diff.tuples); - tuple != NULL; - tuple = ISC_LIST_HEAD(nsec3_diff.tuples)) { - /* - * We have changed the NSEC3 RRset above so we need to update - * the signatures. - */ - result = del_sigs(zone, db, version, &tuple->name, - dns_rdatatype_nsec3, &sig_diff, - zone_keys, nkeys, now); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, - "zone_nsec3chain:del_sigs -> %s\n", - dns_result_totext(result)); - goto failure; - } - result = add_sigs(db, version, &tuple->name, - dns_rdatatype_nsec3, &sig_diff, zone_keys, - nkeys, zone->mctx, inception, expire, - check_ksk); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, - "zone_nsec3chain:add_sigs -> %s\n", - dns_result_totext(result)); - goto failure; + if (!ISC_LIST_EMPTY(param_diff.tuples)) { + isc_boolean_t rebuild_nsec = ISC_FALSE, + rebuild_nsec3 = ISC_FALSE; + result = dns_db_getoriginnode(db, &node); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + result = dns_db_allrdatasets(db, node, version, 0, &iterator); + for (result = dns_rdatasetiter_first(iterator); + result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(iterator)) { + dns_rdatasetiter_current(iterator, &rdataset); + if (rdataset.type == dns_rdatatype_nsec) + rebuild_nsec = ISC_TRUE; + if (rdataset.type == dns_rdatatype_nsec3param) + rebuild_nsec3 = ISC_TRUE; + dns_rdataset_disassociate(&rdataset); } + dns_rdatasetiter_destroy(&iterator); + dns_db_detachnode(db, &node); - do { - dns_difftuple_t *next = ISC_LIST_NEXT(tuple, link); - while (next != NULL && - !dns_name_equal(&tuple->name, &next->name)) - next = ISC_LIST_NEXT(next, link); - ISC_LIST_UNLINK(nsec3_diff.tuples, tuple, link); - dns_diff_appendminimal(&sig_diff, &tuple); - INSIST(tuple == NULL); - tuple = next; - } while (tuple != NULL); - } - - for (tuple = ISC_LIST_HEAD(param_diff.tuples); - tuple != NULL; - tuple = ISC_LIST_HEAD(param_diff.tuples)) { - /* - * We have changed the NSEC3PARAM RRset above so we need to - * update the signatures. - */ - result = del_sigs(zone, db, version, &tuple->name, - dns_rdatatype_nsec3param, &sig_diff, - zone_keys, nkeys, now); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, - "zone_nsec3chain:del_sigs -> %s\n", - dns_result_totext(result)); - goto failure; + if (rebuild_nsec) { + if (nsec3chain != NULL) + dns_dbiterator_pause(nsec3chain->dbiterator); + result = updatesecure(db, version, &zone->origin, + zone->minimum, ISC_TRUE, + &nsec_diff); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "zone_nsec3chain:" + "updatesecure -> %s\n", + dns_result_totext(result)); + goto failure; + } } - result = add_sigs(db, version, &tuple->name, - dns_rdatatype_nsec3param, &sig_diff, - zone_keys, nkeys, zone->mctx, inception, - expire, check_ksk); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, - "zone_nsec3chain:add_sigs -> %s\n", - dns_result_totext(result)); - goto failure; + if (rebuild_nsec3) { + result = dns_nsec3_addnsec3s(db, version, + dns_db_origin(db), + zone->minimum, ISC_FALSE, + &nsec3_diff); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "zone_nsec3chain:" + "dns_nsec3_addnsec3s -> %s\n", + dns_result_totext(result)); + goto failure; + } } - ISC_LIST_UNLINK(param_diff.tuples, tuple, link); - dns_diff_appendminimal(&sig_diff, &tuple); - INSIST(tuple == NULL); } - if (updatensec) - CHECK(updatesecure(db, version, &zone->origin, zone->minimum, - NULL, &nsec_diff)); + /* + * Add / update signatures for the NSEC3 records. + */ + result = update_sigs(&nsec3_diff, db, version, zone_keys, + nkeys, zone, inception, expire, now, + check_ksk, keyset_kskonly, &sig_diff); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:" + "update_sigs -> %s\n", dns_result_totext(result)); + goto failure; + } - for (tuple = ISC_LIST_HEAD(nsec_diff.tuples); - tuple != NULL; - tuple = ISC_LIST_HEAD(nsec_diff.tuples)) { - result = del_sigs(zone, db, version, &tuple->name, - dns_rdatatype_nsec, &sig_diff, - zone_keys, nkeys, now); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, - "zone_nsec3chain:del_sigs -> %s\n", - dns_result_totext(result)); - goto failure; - } - result = add_sigs(db, version, &tuple->name, - dns_rdatatype_nsec, &sig_diff, - zone_keys, nkeys, zone->mctx, inception, - expire, check_ksk); + /* + * We have changed the NSEC3PARAM or private RRsets + * above so we need to update the signatures. + */ + result = update_sigs(¶m_diff, db, version, zone_keys, + nkeys, zone, inception, expire, now, + check_ksk, keyset_kskonly, &sig_diff); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:" + "update_sigs -> %s\n", dns_result_totext(result)); + goto failure; + } + + if (updatensec) { + if (nsec3chain != NULL) + dns_dbiterator_pause(nsec3chain->dbiterator); + result = updatesecure(db, version, &zone->origin, + zone->minimum, ISC_FALSE, &nsec_diff); if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, - "zone_nsec3chain:add_sigs -> %s\n", + dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:" + "updatesecure -> %s\n", dns_result_totext(result)); goto failure; } - ISC_LIST_UNLINK(nsec_diff.tuples, tuple, link); - dns_diff_appendminimal(&sig_diff, &tuple); - INSIST(tuple == NULL); + } + + result = update_sigs(&nsec_diff, db, version, zone_keys, + nkeys, zone, inception, expire, now, + check_ksk, keyset_kskonly, &sig_diff); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:" + "update_sigs -> %s\n", dns_result_totext(result)); + goto failure; } /* @@ -5288,41 +6278,22 @@ zone_nsec3chain(dns_zone_t *zone) { if (result != ISC_R_SUCCESS) { dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:" "increment_soa_serial -> %s\n", - dns_result_totext(result)); - goto failure; - } - - result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa, - &sig_diff, zone_keys, nkeys, zone->mctx, inception, - soaexpire, check_ksk); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:" - "add_sigs -> %s\n", dns_result_totext(result)); - goto failure; - } - - journalfile = dns_zone_getjournal(zone); - if (journalfile != NULL) { - dns_journal_t *journal = NULL; - result = dns_journal_open(zone->mctx, journalfile, - ISC_TRUE, &journal); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:" - "dns_journal_open -> %s\n", - dns_result_totext(result)); - goto failure; - } + dns_result_totext(result)); + goto failure; + } - result = dns_journal_write_transaction(journal, &sig_diff); - dns_journal_destroy(&journal); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:" - "dns_journal_write_transaction -> %s\n", - dns_result_totext(result)); - goto failure; - } + result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa, + &sig_diff, zone_keys, nkeys, zone->mctx, inception, + soaexpire, check_ksk, keyset_kskonly); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:" + "add_sigs -> %s\n", dns_result_totext(result)); + goto failure; } + /* Write changes to journal file. */ + zone_journal(zone, &sig_diff, "zone_nsec3chain"); + LOCK_ZONE(zone); zone_needdump(zone, DNS_DUMP_DELAY); UNLOCK_ZONE(zone); @@ -5358,6 +6329,9 @@ zone_nsec3chain(dns_zone_t *zone) { set_resigntime(zone); failure: + if (result != ISC_R_SUCCESS) + dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s\n", + dns_result_totext(result)); /* * On error roll back the current nsec3chain. */ @@ -5414,6 +6388,8 @@ zone_nsec3chain(dns_zone_t *zone) { for (i = 0; i < nkeys; i++) dst_key_free(&zone_keys[i]); + if (node != NULL) + dns_db_detachnode(db, &node); if (version != NULL) { dns_db_closeversion(db, &version, ISC_FALSE); dns_db_detach(&db); @@ -5506,11 +6482,11 @@ del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, */ static void zone_sign(dns_zone_t *zone) { - const char *journalfile; dns_db_t *db = NULL; dns_dbnode_t *node = NULL; dns_dbversion_t *version = NULL; dns_diff_t sig_diff; + dns_diff_t post_diff; dns_fixedname_t fixed; dns_fixedname_t nextfixed; dns_name_t *name, *nextname; @@ -5519,19 +6495,19 @@ zone_sign(dns_zone_t *zone) { dns_signinglist_t cleanup; dst_key_t *zone_keys[MAXZONEKEYS]; isc_int32_t signatures; - isc_boolean_t check_ksk, is_ksk; + isc_boolean_t check_ksk, keyset_kskonly, is_ksk; isc_boolean_t commit = ISC_FALSE; isc_boolean_t delegation; - isc_boolean_t finishedakey = ISC_FALSE; - isc_boolean_t secureupdated = ISC_FALSE; - isc_boolean_t build_nsec3 = ISC_FALSE, build_nsec = ISC_FALSE; + isc_boolean_t build_nsec = ISC_FALSE; + isc_boolean_t build_nsec3 = ISC_FALSE; isc_boolean_t first; isc_result_t result; isc_stdtime_t now, inception, soaexpire, expire, stop; isc_uint32_t jitter; - unsigned int i; + unsigned int i, j; unsigned int nkeys = 0; isc_uint32_t nodes; + isc_boolean_t was_ksk; dns_rdataset_init(&rdataset); dns_fixedname_init(&fixed); @@ -5540,6 +6516,7 @@ zone_sign(dns_zone_t *zone) { nextname = dns_fixedname_name(&nextfixed); dns_diff_init(zone->mctx, &sig_diff); sig_diff.resign = zone->sigresigninginterval; + dns_diff_init(zone->mctx, &post_diff); ISC_LIST_INIT(cleanup); /* @@ -5584,10 +6561,6 @@ zone_sign(dns_zone_t *zone) { expire = soaexpire - jitter % 3600; stop = now + 5; - check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK); - if (check_ksk) - check_ksk = ksk_sanity(db, version); - /* * We keep pulling nodes off each iterator in turn until * we have no more nodes to pull off or we reach the limits @@ -5597,39 +6570,17 @@ zone_sign(dns_zone_t *zone) { signatures = zone->signatures; signing = ISC_LIST_HEAD(zone->signing); first = ISC_TRUE; - /* - * See if we have a NSEC chain. - */ - result = dns_db_getoriginnode(db, &node); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec, - dns_rdatatype_none, 0, &rdataset, NULL); - dns_db_detachnode(db, &node); - if (result == ISC_R_SUCCESS) { + + check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK); + keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY); + + /* Determine which type of chain to build */ + CHECK(dns_private_chains(db, version, zone->privatetype, + &build_nsec, &build_nsec3)); + + /* If neither chain is found, default to NSEC */ + if (!build_nsec && !build_nsec3) build_nsec = ISC_TRUE; - dns_rdataset_disassociate(&rdataset); - } else if (result != ISC_R_NOTFOUND) { - goto failure; - } else { - /* - * No NSEC chain present. - * See if we need to build a NSEC3 chain? - */ - result = dns_nsec3_active(db, version, ISC_TRUE, &build_nsec3); - if (result == ISC_R_SUCCESS) { - if (build_nsec3) - build_nsec3 = ISC_FALSE; - else { - result = dns_nsec3_active(db, version, - ISC_FALSE, - &build_nsec3); - if (build_nsec3) - secureupdated = ISC_TRUE; - else - build_nsec = ISC_TRUE; - } - } - } while (signing != NULL && nodes-- > 0 && signatures > 0) { nextsigning = ISC_LIST_NEXT(signing, link); @@ -5637,7 +6588,7 @@ zone_sign(dns_zone_t *zone) { ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); if (signing->done || signing->db != zone->db) { /* - * The zone has been reloaded. We will have + * The zone has been reloaded. We will have * created new signings as part of the reload * process so we can destroy this one. */ @@ -5651,9 +6602,31 @@ zone_sign(dns_zone_t *zone) { if (signing->db != db) goto next_signing; - is_ksk = ISC_FALSE; delegation = ISC_FALSE; + was_ksk = ISC_FALSE; + + if (first && signing->delete) { + /* + * Remove the key we are deleting from consideration. + */ + for (i = 0, j = 0; i < nkeys; i++) { + /* + * Find the key we want to remove. + */ + if (ALG(zone_keys[i]) == signing->algorithm && + dst_key_id(zone_keys[i]) == signing->keyid) + { + if (KSK(zone_keys[i])) + dst_key_free(&zone_keys[i]); + continue; + } + zone_keys[j] = zone_keys[i]; + j++; + } + nkeys = j; + } + dns_dbiterator_current(signing->dbiterator, &node, name); if (signing->delete) { @@ -5661,8 +6634,8 @@ zone_sign(dns_zone_t *zone) { CHECK(del_sig(db, version, name, node, nkeys, signing->algorithm, signing->keyid, &sig_diff)); - goto next_node; } + /* * On the first pass we need to check if the current node * has not been obscured. @@ -5694,26 +6667,77 @@ zone_sign(dns_zone_t *zone) { */ dns_dbiterator_pause(signing->dbiterator); for (i = 0; i < nkeys; i++) { + isc_boolean_t both = ISC_FALSE; + + /* + * Find the keys we want to sign with. + */ + if (!dst_key_isprivate(zone_keys[i])) + continue; + + /* + * When adding look for the specific key. + */ + if (!signing->delete && + (dst_key_alg(zone_keys[i]) != signing->algorithm || + dst_key_id(zone_keys[i]) != signing->keyid)) + continue; + /* - * Find the key we want to sign with. + * When deleting make sure we are properly signed + * with the algorithm that was being removed. */ - if (dst_key_alg(zone_keys[i]) != signing->algorithm || - dst_key_id(zone_keys[i]) != signing->keyid || - !dst_key_isprivate(zone_keys[i])) + if (signing->delete && + ALG(zone_keys[i]) != signing->algorithm) continue; + /* * Do we do KSK processing? */ - if (check_ksk && - (dst_key_flags(zone_keys[i]) & DNS_KEYFLAG_KSK) != 0) - is_ksk = ISC_TRUE; + if (check_ksk && !REVOKE(zone_keys[i])) { + isc_boolean_t have_ksk, have_nonksk; + if (KSK(zone_keys[i])) { + have_ksk = ISC_TRUE; + have_nonksk = ISC_FALSE; + } else { + have_ksk = ISC_FALSE; + have_nonksk = ISC_TRUE; + } + for (j = 0; j < nkeys; j++) { + if (j == i || + ALG(zone_keys[i]) != + ALG(zone_keys[j])) + continue; + if (REVOKE(zone_keys[j])) + continue; + if (KSK(zone_keys[j])) + have_ksk = ISC_TRUE; + else + have_nonksk = ISC_TRUE; + both = have_ksk && have_nonksk; + if (both) + break; + } + } + if (both || REVOKE(zone_keys[i])) + is_ksk = KSK(zone_keys[i]); + else + is_ksk = ISC_FALSE; + CHECK(sign_a_node(db, name, node, version, build_nsec3, build_nsec, zone_keys[i], inception, expire, zone->minimum, is_ksk, - &delegation, &sig_diff, &signatures, - zone->mctx)); - break; + ISC_TF(both && keyset_kskonly), + &delegation, &sig_diff, + &signatures, zone->mctx)); + /* + * If we are adding we are done. Look for other keys + * of the same algorithm if deleting. + */ + if (!signing->delete) + break; } + /* * Go onto next node. */ @@ -5726,9 +6750,7 @@ zone_sign(dns_zone_t *zone) { ISC_LIST_UNLINK(zone->signing, signing, link); ISC_LIST_APPEND(cleanup, signing, link); dns_dbiterator_pause(signing->dbiterator); - finishedakey = ISC_TRUE; - if (!is_ksk && !secureupdated && nkeys != 0 && - build_nsec) { + if (nkeys != 0 && build_nsec) { /* * We have finished regenerating the * zone with a zone signing key. @@ -5740,8 +6762,8 @@ zone_sign(dns_zone_t *zone) { result = updatesecure(db, version, &zone->origin, zone->minimum, - &secureupdated, - &sig_diff); + ISC_FALSE, + &post_diff); if (result != ISC_R_SUCCESS) { dns_zone_log(zone, ISC_LOG_ERROR, @@ -5750,16 +6772,19 @@ zone_sign(dns_zone_t *zone) { goto failure; } } - result = updatesignwithkey(signing, version, - &zone->origin, - zone->privatetype, - &sig_diff); + result = updatesignwithkey(zone, signing, + version, + build_nsec3, + zone->minimum, + &post_diff); if (result != ISC_R_SUCCESS) { dns_zone_log(zone, ISC_LOG_ERROR, - "updatesignwithkey -> %s\n", + "updatesignwithkey " + "-> %s\n", dns_result_totext(result)); goto failure; } + build_nsec = ISC_FALSE; goto next_signing; } else if (result != ISC_R_SUCCESS) { dns_zone_log(zone, ISC_LOG_ERROR, @@ -5777,205 +6802,979 @@ zone_sign(dns_zone_t *zone) { } while (1); continue; - next_signing: - dns_dbiterator_pause(signing->dbiterator); - signing = nextsigning; - first = ISC_TRUE; - } + next_signing: + dns_dbiterator_pause(signing->dbiterator); + signing = nextsigning; + first = ISC_TRUE; + } + + if (ISC_LIST_HEAD(post_diff.tuples) != NULL) { + result = update_sigs(&post_diff, db, version, zone_keys, + nkeys, zone, inception, expire, now, + check_ksk, keyset_kskonly, &sig_diff); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, "zone_sign:" + "update_sigs -> %s\n", + dns_result_totext(result)); + goto failure; + } + } + + /* + * Have we changed anything? + */ + if (ISC_LIST_HEAD(sig_diff.tuples) == NULL) { + result = ISC_R_SUCCESS; + goto pauseall; + } + + commit = ISC_TRUE; + + result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa, + &sig_diff, zone_keys, nkeys, now); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "zone_sign:del_sigs -> %s\n", + dns_result_totext(result)); + goto failure; + } + + result = increment_soa_serial(db, version, &sig_diff, zone->mctx); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "zone_sign:increment_soa_serial -> %s\n", + dns_result_totext(result)); + goto failure; + } + + /* + * Generate maximum life time signatures so that the above loop + * termination is sensible. + */ + result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa, + &sig_diff, zone_keys, nkeys, zone->mctx, inception, + soaexpire, check_ksk, keyset_kskonly); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "zone_sign:add_sigs -> %s\n", + dns_result_totext(result)); + goto failure; + } + + /* + * Write changes to journal file. + */ + result = zone_journal(zone, &sig_diff, "zone_sign"); + if (result != ISC_R_SUCCESS) + goto failure; + + pauseall: + /* + * Pause all iterators so that dns_db_closeversion() can succeed. + */ + for (signing = ISC_LIST_HEAD(zone->signing); + signing != NULL; + signing = ISC_LIST_NEXT(signing, link)) + dns_dbiterator_pause(signing->dbiterator); + + for (signing = ISC_LIST_HEAD(cleanup); + signing != NULL; + signing = ISC_LIST_NEXT(signing, link)) + dns_dbiterator_pause(signing->dbiterator); + + /* + * Everything has succeeded. Commit the changes. + */ + dns_db_closeversion(db, &version, commit); + + /* + * Everything succeeded so we can clean these up now. + */ + signing = ISC_LIST_HEAD(cleanup); + while (signing != NULL) { + ISC_LIST_UNLINK(cleanup, signing, link); + dns_db_detach(&signing->db); + dns_dbiterator_destroy(&signing->dbiterator); + isc_mem_put(zone->mctx, signing, sizeof *signing); + signing = ISC_LIST_HEAD(cleanup); + } + + set_resigntime(zone); + + if (commit) { + LOCK_ZONE(zone); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY); + zone_needdump(zone, DNS_DUMP_DELAY); + UNLOCK_ZONE(zone); + } + + failure: + /* + * Rollback the cleanup list. + */ + signing = ISC_LIST_HEAD(cleanup); + while (signing != NULL) { + ISC_LIST_UNLINK(cleanup, signing, link); + ISC_LIST_PREPEND(zone->signing, signing, link); + dns_dbiterator_first(signing->dbiterator); + dns_dbiterator_pause(signing->dbiterator); + signing = ISC_LIST_HEAD(cleanup); + } + + for (signing = ISC_LIST_HEAD(zone->signing); + signing != NULL; + signing = ISC_LIST_NEXT(signing, link)) + dns_dbiterator_pause(signing->dbiterator); + + dns_diff_clear(&sig_diff); + + for (i = 0; i < nkeys; i++) + dst_key_free(&zone_keys[i]); + + if (node != NULL) + dns_db_detachnode(db, &node); + + if (version != NULL) { + dns_db_closeversion(db, &version, ISC_FALSE); + dns_db_detach(&db); + } else if (db != NULL) + dns_db_detach(&db); + + if (ISC_LIST_HEAD(zone->signing) != NULL) { + isc_interval_t i; + if (zone->update_disabled || result != ISC_R_SUCCESS) + isc_interval_set(&i, 60, 0); /* 1 minute */ + else + isc_interval_set(&i, 0, 10000000); /* 10 ms */ + isc_time_nowplusinterval(&zone->signingtime, &i); + } else + isc_time_settoepoch(&zone->signingtime); +} + +static void +normalize_key(dns_rdata_t *rr, dns_rdata_t *target, + unsigned char *data, int size) { + dns_rdata_dnskey_t dnskey; + dns_rdata_keydata_t keydata; + isc_buffer_t buf; + + dns_rdata_reset(target); + isc_buffer_init(&buf, data, size); + + switch (rr->type) { + case dns_rdatatype_dnskey: + dns_rdata_tostruct(rr, &dnskey, NULL); + dnskey.flags &= ~DNS_KEYFLAG_REVOKE; + dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey, + &dnskey, &buf); + break; + case dns_rdatatype_keydata: + dns_rdata_tostruct(rr, &keydata, NULL); + dns_keydata_todnskey(&keydata, &dnskey, NULL); + dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey, + &dnskey, &buf); + break; + default: + INSIST(0); + } +} + +/* + * 'rdset' contains either a DNSKEY rdataset from the zone apex, or + * a KEYDATA rdataset from the key zone. + * + * 'rr' contains either a DNSKEY record, or a KEYDATA record + * + * After normalizing keys to the same format (DNSKEY, with revoke bit + * cleared), return ISC_TRUE if a key that matches 'rr' is found in + * 'rdset', or ISC_FALSE if not. + */ + +static isc_boolean_t +matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) { + unsigned char data1[4096], data2[4096]; + dns_rdata_t rdata, rdata1, rdata2; + isc_result_t result; + + dns_rdata_init(&rdata); + dns_rdata_init(&rdata1); + dns_rdata_init(&rdata2); + + normalize_key(rr, &rdata1, data1, sizeof(data1)); + + for (result = dns_rdataset_first(rdset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdset)) { + dns_rdata_reset(&rdata); + dns_rdataset_current(rdset, &rdata); + normalize_key(&rdata, &rdata2, data2, sizeof(data2)); + if (dns_rdata_compare(&rdata1, &rdata2) == 0) + return (ISC_TRUE); + } + + return (ISC_FALSE); +} + +/* + * Calculate the refresh interval for a keydata zone, per + * RFC5011: MAX(1 hr, + * MIN(15 days, + * 1/2 * OrigTTL, + * 1/2 * RRSigExpirationInterval)) + * or for retries: MAX(1 hr, + * MIN(1 day, + * 1/10 * OrigTTL, + * 1/10 * RRSigExpirationInterval)) + */ +static inline isc_stdtime_t +refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) { + isc_result_t result; + isc_uint32_t t; + dns_rdataset_t *rdset; + dns_rdata_t sigrr = DNS_RDATA_INIT; + dns_rdata_sig_t sig; + isc_stdtime_t now; + + isc_stdtime_get(&now); + + if (dns_rdataset_isassociated(&kfetch->dnskeysigset)) + rdset = &kfetch->dnskeysigset; + else + return (now + HOUR); + + result = dns_rdataset_first(rdset); + if (result != ISC_R_SUCCESS) + return (now + HOUR); + + dns_rdataset_current(rdset, &sigrr); + result = dns_rdata_tostruct(&sigrr, &sig, NULL); - if (secureupdated) { - /* - * We have changed the NSEC RRset above so we need to update - * the signatures. - */ - result = del_sigs(zone, db, version, &zone->origin, - dns_rdatatype_nsec, &sig_diff, zone_keys, - nkeys, now); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, - "zone_sign:del_sigs -> %s\n", - dns_result_totext(result)); - goto failure; + if (!retry) { + t = sig.originalttl / 2; + + if (isc_serial_gt(sig.timeexpire, now)) { + isc_uint32_t exp = (sig.timeexpire - now) / 2; + if (t > exp) + t = exp; } - result = add_sigs(db, version, &zone->origin, - dns_rdatatype_nsec, &sig_diff, zone_keys, - nkeys, zone->mctx, inception, soaexpire, - check_ksk); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, - "zone_sign:add_sigs -> %s\n", - dns_result_totext(result)); - goto failure; + + if (t > (15*DAY)) + t = (15*DAY); + + if (t < HOUR) + t = HOUR; + } else { + t = sig.originalttl / 10; + + if (isc_serial_gt(sig.timeexpire, now)) { + isc_uint32_t exp = (sig.timeexpire - now) / 10; + if (t > exp) + t = exp; } + + if (t > DAY) + t = DAY; + + if (t < HOUR) + t = HOUR; } - if (finishedakey) { - /* - * We have changed the RRset above so we need to update - * the signatures. - */ - result = del_sigs(zone, db, version, &zone->origin, - zone->privatetype, &sig_diff, - zone_keys, nkeys, now); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, - "zone_sign:del_sigs -> %s\n", - dns_result_totext(result)); - goto failure; - } - result = add_sigs(db, version, &zone->origin, - zone->privatetype, &sig_diff, - zone_keys, nkeys, zone->mctx, inception, - soaexpire, check_ksk); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, - "zone_sign:add_sigs -> %s\n", - dns_result_totext(result)); - goto failure; - } + return (now + t); +} + +/* + * This routine is called when no changes are needed in a KEYDATA + * record except to simply update the refresh timer. Caller should + * hold zone lock. + */ +static isc_result_t +minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff) +{ + isc_result_t result; + isc_buffer_t keyb; + unsigned char key_buf[4096]; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_keydata_t keydata; + dns_name_t *name; + dns_zone_t *zone = kfetch->zone; + isc_stdtime_t now; + + name = dns_fixedname_name(&kfetch->name); + isc_stdtime_get(&now); + + for (result = dns_rdataset_first(&kfetch->keydataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&kfetch->keydataset)) { + dns_rdata_reset(&rdata); + dns_rdataset_current(&kfetch->keydataset, &rdata); + + /* Delete old version */ + CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL, + name, 0, &rdata)); + + /* Update refresh timer */ + CHECK(dns_rdata_tostruct(&rdata, &keydata, NULL)); + keydata.refresh = refresh_time(kfetch, ISC_TRUE); + set_refreshkeytimer(zone, &keydata, now); + + dns_rdata_reset(&rdata); + isc_buffer_init(&keyb, key_buf, sizeof(key_buf)); + CHECK(dns_rdata_fromstruct(&rdata, + zone->rdclass, dns_rdatatype_keydata, + &keydata, &keyb)); + + /* Insert updated version */ + CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD, + name, 0, &rdata)); } + result = ISC_R_SUCCESS; + failure: + return (result); +} - /* - * Have we changed anything? - */ - if (ISC_LIST_HEAD(sig_diff.tuples) == NULL) - goto pauseall; +/* + * Verify that DNSKEY set is signed by the key specified in 'keydata'. + */ +static isc_boolean_t +revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) { + isc_result_t result; + dns_name_t *keyname; + isc_mem_t *mctx; + dns_rdata_t sigrr = DNS_RDATA_INIT; + dns_rdata_t rr = DNS_RDATA_INIT; + dns_rdata_rrsig_t sig; + dns_rdata_dnskey_t dnskey; + dst_key_t *dstkey = NULL; + unsigned char key_buf[4096]; + isc_buffer_t keyb; + isc_boolean_t answer = ISC_FALSE; + + REQUIRE(kfetch != NULL && keydata != NULL); + REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset)); + + keyname = dns_fixedname_name(&kfetch->name); + mctx = kfetch->zone->view->mctx; + + /* Generate a key from keydata */ + isc_buffer_init(&keyb, key_buf, sizeof(key_buf)); + dns_keydata_todnskey(keydata, &dnskey, NULL); + dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey, + &dnskey, &keyb); + result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey); + if (result != ISC_R_SUCCESS) + return (ISC_FALSE); - commit = ISC_TRUE; + /* See if that key generated any of the signatures */ + for (result = dns_rdataset_first(&kfetch->dnskeysigset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&kfetch->dnskeysigset)) { + dns_fixedname_t fixed; + dns_fixedname_init(&fixed); - result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa, - &sig_diff, zone_keys, nkeys, now); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, - "zone_sign:del_sigs -> %s\n", - dns_result_totext(result)); - goto failure; + dns_rdata_reset(&sigrr); + dns_rdataset_current(&kfetch->dnskeysigset, &sigrr); + result = dns_rdata_tostruct(&sigrr, &sig, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + if (dst_key_alg(dstkey) == sig.algorithm && + (dst_key_id(dstkey) == sig.keyid || + (sig.algorithm != 1 && sig.keyid == + ((dst_key_id(dstkey) + 128) & 0xffff)))) { + result = dns_dnssec_verify2(keyname, + &kfetch->dnskeyset, + dstkey, ISC_FALSE, mctx, &sigrr, + dns_fixedname_name(&fixed)); + + dns_zone_log(kfetch->zone, ISC_LOG_DEBUG(3), + "Confirm revoked DNSKEY is self-signed: " + "%s", dns_result_totext(result)); + + if (result == ISC_R_SUCCESS) { + answer = ISC_TRUE; + break; + } + } } - result = increment_soa_serial(db, version, &sig_diff, zone->mctx); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, - "zone_sign:increment_soa_serial -> %s\n", - dns_result_totext(result)); + dst_key_free(&dstkey); + return (answer); +} + +/* + * A DNSKEY set has been fetched from the zone apex of a zone whose trust + * anchors are being managed; scan the keyset, and update the key zone and the + * local trust anchors according to RFC5011. + */ +static void +keyfetch_done(isc_task_t *task, isc_event_t *event) { + isc_result_t result, eresult; + dns_fetchevent_t *devent; + dns_keyfetch_t *kfetch; + dns_zone_t *zone; + isc_mem_t *mctx = NULL; + dns_keytable_t *secroots = NULL; + dns_dbversion_t *ver = NULL; + dns_diff_t diff; + isc_boolean_t changed = ISC_FALSE; + isc_boolean_t alldone = ISC_FALSE; + dns_name_t *keyname; + dns_rdata_t sigrr = DNS_RDATA_INIT; + dns_rdata_t dnskeyrr = DNS_RDATA_INIT; + dns_rdata_t keydatarr = DNS_RDATA_INIT; + dns_rdata_rrsig_t sig; + dns_rdata_dnskey_t dnskey; + dns_rdata_keydata_t keydata; + isc_boolean_t initializing; + char namebuf[DNS_NAME_FORMATSIZE]; + unsigned char key_buf[4096]; + isc_buffer_t keyb; + dst_key_t *dstkey; + isc_stdtime_t now; + int pending = 0; + isc_boolean_t secure; + + UNUSED(task); + INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE); + INSIST(event->ev_arg != NULL); + + kfetch = event->ev_arg; + zone = kfetch->zone; + isc_mem_attach(zone->mctx, &mctx); + keyname = dns_fixedname_name(&kfetch->name); + + devent = (dns_fetchevent_t *) event; + eresult = devent->result; + + /* Free resources which are not of interest */ + if (devent->node != NULL) + dns_db_detachnode(devent->db, &devent->node); + if (devent->db != NULL) + dns_db_detach(&devent->db); + isc_event_free(&event); + dns_resolver_destroyfetch(&kfetch->fetch); + + isc_stdtime_get(&now); + dns_name_format(keyname, namebuf, sizeof(namebuf)); + + result = dns_view_getsecroots(zone->view, &secroots); + INSIST(result == ISC_R_SUCCESS); + + LOCK_ZONE(zone); + dns_db_newversion(kfetch->db, &ver); + dns_diff_init(mctx, &diff); + + zone->refreshkeycount--; + alldone = ISC_TF(zone->refreshkeycount == 0); + + if (alldone) + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING); + + /* Fetch failed */ + if (eresult != ISC_R_SUCCESS || + !dns_rdataset_isassociated(&kfetch->dnskeyset)) { + dns_zone_log(zone, ISC_LOG_WARNING, + "Unable to fetch DNSKEY set " + "'%s': %s", namebuf, dns_result_totext(eresult)); + CHECK(minimal_update(kfetch, ver, &diff)); + changed = ISC_TRUE; goto failure; } - /* - * Generate maximum life time signatures so that the above loop - * termination is sensible. - */ - result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa, - &sig_diff, zone_keys, nkeys, zone->mctx, inception, - soaexpire, check_ksk); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, - "zone_sign:add_sigs -> %s\n", - dns_result_totext(result)); + /* No RRSIGs found */ + if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) { + dns_zone_log(zone, ISC_LOG_WARNING, + "No DNSKEY RRSIGs found for " + "'%s': %s", namebuf, dns_result_totext(eresult)); + CHECK(minimal_update(kfetch, ver, &diff)); + changed = ISC_TRUE; goto failure; } /* - * Write changes to journal file. + * Validate the dnskeyset against the current trusted keys. */ - journalfile = dns_zone_getjournal(zone); - if (journalfile != NULL) { - dns_journal_t *journal = NULL; - result = dns_journal_open(zone->mctx, journalfile, - ISC_TRUE, &journal); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, - "zone_sign:dns_journal_open -> %s\n", - dns_result_totext(result)); - goto failure; - } + for (result = dns_rdataset_first(&kfetch->dnskeysigset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&kfetch->dnskeysigset)) { + dns_keynode_t *keynode = NULL; - result = dns_journal_write_transaction(journal, &sig_diff); - dns_journal_destroy(&journal); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, - "zone_sign:dns_journal_write_transaction -> %s\n", - dns_result_totext(result)); - goto failure; + dns_rdata_reset(&sigrr); + dns_rdataset_current(&kfetch->dnskeysigset, &sigrr); + result = dns_rdata_tostruct(&sigrr, &sig, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + result = dns_keytable_find(secroots, keyname, &keynode); + while (result == ISC_R_SUCCESS) { + dns_keynode_t *nextnode = NULL; + dns_fixedname_t fixed; + dns_fixedname_init(&fixed); + + dstkey = dns_keynode_key(keynode); + if (dstkey == NULL) /* fail_secure() was called */ + break; + + if (dst_key_alg(dstkey) == sig.algorithm && + dst_key_id(dstkey) == sig.keyid) { + result = dns_dnssec_verify2(keyname, + &kfetch->dnskeyset, + dstkey, ISC_FALSE, + zone->view->mctx, &sigrr, + dns_fixedname_name(&fixed)); + + dns_zone_log(zone, ISC_LOG_DEBUG(3), + "Verifying DNSKEY set for zone " + "'%s': %s", namebuf, + dns_result_totext(result)); + + if (result == ISC_R_SUCCESS) { + kfetch->dnskeyset.trust = + dns_trust_secure; + kfetch->dnskeysigset.trust = + dns_trust_secure; + dns_keytable_detachkeynode(secroots, + &keynode); + break; + } + } + + result = dns_keytable_nextkeynode(secroots, + keynode, &nextnode); + dns_keytable_detachkeynode(secroots, &keynode); + keynode = nextnode; } + + if (kfetch->dnskeyset.trust == dns_trust_secure) + break; } - pauseall: /* - * Pause all iterators so that dns_db_closeversion() can succeed. + * If we were not able to verify the answer using the current + * trusted keys then all we can do is look at any revoked keys. */ - for (signing = ISC_LIST_HEAD(zone->signing); - signing != NULL; - signing = ISC_LIST_NEXT(signing, link)) - dns_dbiterator_pause(signing->dbiterator); - - for (signing = ISC_LIST_HEAD(cleanup); - signing != NULL; - signing = ISC_LIST_NEXT(signing, link)) - dns_dbiterator_pause(signing->dbiterator); + secure = ISC_TF(kfetch->dnskeyset.trust == dns_trust_secure); /* - * Everything has succeeded. Commit the changes. + * First scan keydataset to find keys that are not in dnskeyset + * - Missing keys which are not scheduled for removal, + * log a warning + * - Missing keys which are scheduled for removal and + * the remove hold-down timer has completed should + * be removed from the key zone + * - Missing keys whose acceptance timers have not yet + * completed, log a warning and reset the acceptance + * timer to 30 days in the future + * - All keys not being removed have their refresh timers + * updated */ - dns_db_closeversion(db, &version, commit); + initializing = ISC_TRUE; + for (result = dns_rdataset_first(&kfetch->keydataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&kfetch->keydataset)) { + dns_rdata_reset(&keydatarr); + dns_rdataset_current(&kfetch->keydataset, &keydatarr); + dns_rdata_tostruct(&keydatarr, &keydata, NULL); + + /* + * If any keydata record has a nonzero add holddown, then + * there was a pre-existing trust anchor for this domain; + * that means we are *not* initializing it and shouldn't + * automatically trust all the keys we find at the zone apex. + */ + initializing = initializing && ISC_TF(keydata.addhd == 0); + + if (! matchkey(&kfetch->dnskeyset, &keydatarr)) { + isc_boolean_t deletekey = ISC_FALSE; + + if (!secure) { + if (now > keydata.removehd) + deletekey = ISC_TRUE; + } else if (now < keydata.addhd) { + dns_zone_log(zone, ISC_LOG_WARNING, + "Pending key unexpectedly missing " + "from %s; restarting acceptance " + "timer", namebuf); + keydata.addhd = now + MONTH; + keydata.refresh = refresh_time(kfetch, + ISC_FALSE); + } else if (keydata.addhd == 0) { + keydata.addhd = now; + } else if (keydata.removehd == 0) { + dns_zone_log(zone, ISC_LOG_WARNING, + "Active key unexpectedly missing " + "from %s", namebuf); + keydata.refresh = now + HOUR; + } else if (now > keydata.removehd) { + deletekey = ISC_TRUE; + } else { + keydata.refresh = refresh_time(kfetch, + ISC_FALSE); + } + + if (secure || deletekey) { + /* Delete old version */ + CHECK(update_one_rr(kfetch->db, ver, &diff, + DNS_DIFFOP_DEL, keyname, 0, + &keydatarr)); + changed = ISC_TRUE; + } + + if (!secure || deletekey) + continue; + + dns_rdata_reset(&keydatarr); + isc_buffer_init(&keyb, key_buf, sizeof(key_buf)); + dns_rdata_fromstruct(&keydatarr, zone->rdclass, + dns_rdatatype_keydata, + &keydata, &keyb); + + /* Insert updated version */ + CHECK(update_one_rr(kfetch->db, ver, &diff, + DNS_DIFFOP_ADD, keyname, 0, + &keydatarr)); + changed = ISC_TRUE; + + set_refreshkeytimer(zone, &keydata, now); + } + } /* - * Everything succeeded so we can clean these up now. + * Next scan dnskeyset: + * - If new keys are found (i.e., lacking a match in keydataset) + * add them to the key zone and set the acceptance timer + * to 30 days in the future (or to immediately if we've + * determined that we're initializing the zone for the + * first time) + * - Previously-known keys that have been revoked + * must be scheduled for removal from the key zone (or, + * if they hadn't been accepted as trust anchors yet + * anyway, removed at once) + * - Previously-known unrevoked keys whose acceptance timers + * have completed are promoted to trust anchors + * - All keys not being removed have their refresh + * timers updated */ - signing = ISC_LIST_HEAD(cleanup); - while (signing != NULL) { - ISC_LIST_UNLINK(cleanup, signing, link); - dns_db_detach(&signing->db); - dns_dbiterator_destroy(&signing->dbiterator); - isc_mem_put(zone->mctx, signing, sizeof *signing); - signing = ISC_LIST_HEAD(cleanup); + for (result = dns_rdataset_first(&kfetch->dnskeyset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&kfetch->dnskeyset)) { + isc_boolean_t revoked = ISC_FALSE; + isc_boolean_t newkey = ISC_FALSE; + isc_boolean_t updatekey = ISC_FALSE; + isc_boolean_t deletekey = ISC_FALSE; + isc_boolean_t trustkey = ISC_FALSE; + + dns_rdata_reset(&dnskeyrr); + dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr); + dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL); + + /* Skip ZSK's */ + if (!ISC_TF(dnskey.flags & DNS_KEYFLAG_KSK)) + continue; + + revoked = ISC_TF(dnskey.flags & DNS_KEYFLAG_REVOKE); + + if (matchkey(&kfetch->keydataset, &dnskeyrr)) { + dns_rdata_reset(&keydatarr); + dns_rdataset_current(&kfetch->keydataset, &keydatarr); + dns_rdata_tostruct(&keydatarr, &keydata, NULL); + + if (revoked && revocable(kfetch, &keydata)) { + if (keydata.addhd > now) { + /* + * Key wasn't trusted yet, and now + * it's been revoked? Just remove it + */ + deletekey = ISC_TRUE; + } else if (keydata.removehd == 0) { + /* Remove from secroots */ + untrust_key(zone->view->viewlist, + keyname, mctx, &dnskey); + + /* If initializing, delete now */ + if (keydata.addhd == 0) + deletekey = ISC_TRUE; + else + keydata.removehd = now + MONTH; + } else if (keydata.removehd < now) { + /* Scheduled for removal */ + deletekey = ISC_TRUE; + } + } else if (revoked) { + if (secure && keydata.removehd == 0) { + dns_zone_log(zone, ISC_LOG_WARNING, + "Active key for zone " + "'%s' is revoked but " + "did not self-sign; " + "ignoring.", namebuf); + continue; + } + } else if (secure) { + if (keydata.removehd != 0) { + /* + * Key isn't revoked--but it + * seems it used to be. + * Remove it now and add it + * back as if it were a fresh key. + */ + deletekey = ISC_TRUE; + newkey = ISC_TRUE; + } else if (keydata.addhd > now) + pending++; + else if (keydata.addhd == 0) + keydata.addhd = now; + + if (keydata.addhd <= now) + trustkey = ISC_TRUE; + } + + if (!deletekey && !newkey) + updatekey = ISC_TRUE; + } else if (secure) { + /* + * Key wasn't in the key zone but it's + * revoked now anyway, so just skip it + */ + if (revoked) + continue; + + /* Key wasn't in the key zone: add it */ + newkey = ISC_TRUE; + + if (initializing) { + dns_keytag_t tag = 0; + CHECK(compute_tag(keyname, &dnskey, + mctx, &tag)); + dns_zone_log(zone, ISC_LOG_WARNING, + "Initializing automatic trust " + "anchor management for zone '%s'; " + "DNSKEY ID %d is now trusted, " + "waiving the normal 30-day " + "waiting period.", + namebuf, tag); + trustkey = ISC_TRUE; + } + } + + /* Delete old version */ + if (deletekey || !newkey) { + CHECK(update_one_rr(kfetch->db, ver, &diff, + DNS_DIFFOP_DEL, keyname, 0, + &keydatarr)); + changed = ISC_TRUE; + } + + if (updatekey) { + /* Set refresh timer */ + keydata.refresh = refresh_time(kfetch, ISC_FALSE); + dns_rdata_reset(&keydatarr); + isc_buffer_init(&keyb, key_buf, sizeof(key_buf)); + dns_rdata_fromstruct(&keydatarr, zone->rdclass, + dns_rdatatype_keydata, + &keydata, &keyb); + + /* Insert updated version */ + CHECK(update_one_rr(kfetch->db, ver, &diff, + DNS_DIFFOP_ADD, keyname, 0, + &keydatarr)); + changed = ISC_TRUE; + } else if (newkey) { + /* Convert DNSKEY to KEYDATA */ + dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL); + dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0, + NULL); + keydata.addhd = initializing ? now : now + MONTH; + keydata.refresh = refresh_time(kfetch, ISC_FALSE); + dns_rdata_reset(&keydatarr); + isc_buffer_init(&keyb, key_buf, sizeof(key_buf)); + dns_rdata_fromstruct(&keydatarr, zone->rdclass, + dns_rdatatype_keydata, + &keydata, &keyb); + + /* Insert into key zone */ + CHECK(update_one_rr(kfetch->db, ver, &diff, + DNS_DIFFOP_ADD, keyname, 0, + &keydatarr)); + changed = ISC_TRUE; + } + + if (trustkey) { + /* Trust this key in all views */ + dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL); + trust_key(zone->view->viewlist, keyname, &dnskey, + mctx); + } + + if (!deletekey) + set_refreshkeytimer(zone, &keydata, now); + } + + /* + * RFC5011 says, "A trust point that has all of its trust anchors + * revoked is considered deleted and is treated as if the trust + * point was never configured." But if someone revoked their + * active key before the standby was trusted, that would mean the + * zone would suddenly be nonsecured. We avoid this by checking to + * see if there's pending keydata. If so, we put a null key in + * the security roots; then all queries to the zone will fail. + */ + if (pending != 0) + fail_secure(zone->view->viewlist, keyname); + + failure: + if (changed) { + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED); + zone_needdump(zone, 30); } - set_resigntime(zone); + UNLOCK_ZONE(zone); + + /* Write changes to journal file. */ + if (alldone) { + result = increment_soa_serial(kfetch->db, ver, &diff, mctx); + if (result == ISC_R_SUCCESS) + result = zone_journal(zone, &diff, "keyfetch_done"); + } + + dns_diff_clear(&diff); + dns_db_closeversion(kfetch->db, &ver, changed); + dns_db_detach(&kfetch->db); + dns_zone_detach(&kfetch->zone); + + if (dns_rdataset_isassociated(&kfetch->keydataset)) + dns_rdataset_disassociate(&kfetch->keydataset); + if (dns_rdataset_isassociated(&kfetch->dnskeyset)) + dns_rdataset_disassociate(&kfetch->dnskeyset); + if (dns_rdataset_isassociated(&kfetch->dnskeysigset)) + dns_rdataset_disassociate(&kfetch->dnskeysigset); + + dns_name_free(keyname, mctx); + isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t)); + isc_mem_detach(&mctx); + + if (secroots != NULL) + dns_keytable_detach(&secroots); +} + +/* + * Refresh the data in the key zone. Initiate a fetch to get new DNSKEY + * records from the zone apex. + */ +static void +zone_refreshkeys(dns_zone_t *zone) { + const char me[] = "zone_refreshkeys"; + isc_result_t result; + dns_rriterator_t rrit; + dns_db_t *db = NULL; + dns_dbversion_t *ver = NULL; + dns_diff_t diff; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_keydata_t kd; + isc_stdtime_t now; + isc_boolean_t commit = ISC_FALSE; + + ENTER; + REQUIRE(zone->db != NULL); + + isc_stdtime_get(&now); + + ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); + dns_db_attach(zone->db, &db); + ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); + + LOCK_ZONE(zone); + dns_db_newversion(db, &ver); + dns_diff_init(zone->mctx, &diff); + + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING); + + dns_rriterator_init(&rrit, db, ver, 0); + for (result = dns_rriterator_first(&rrit); + result == ISC_R_SUCCESS; + result = dns_rriterator_nextrrset(&rrit)) { + isc_stdtime_t timer = 0xffffffff; + dns_keyfetch_t *kfetch; + dns_rdataset_t *kdset; + dns_name_t *name = NULL; + isc_uint32_t ttl; + + dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL); + if (!dns_rdataset_isassociated(kdset)) + continue; + + if (kdset->type != dns_rdatatype_keydata) + continue; - if (commit) { - LOCK_ZONE(zone); - zone_needdump(zone, DNS_DUMP_DELAY); - UNLOCK_ZONE(zone); - } + /* + * Scan the stored keys looking for ones that need + * removal or refreshing + */ + for (result = dns_rdataset_first(kdset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(kdset)) { + dns_rdata_reset(&rdata); + dns_rdataset_current(kdset, &rdata); + result = dns_rdata_tostruct(&rdata, &kd, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); - failure: - /* - * Rollback the cleanup list. - */ - signing = ISC_LIST_HEAD(cleanup); - while (signing != NULL) { - ISC_LIST_UNLINK(cleanup, signing, link); - ISC_LIST_APPEND(zone->signing, signing, link); - dns_dbiterator_first(signing->dbiterator); - dns_dbiterator_pause(signing->dbiterator); - signing = ISC_LIST_HEAD(cleanup); - } + /* Removal timer expired? */ + if (kd.removehd != 0 && kd.removehd < now) { + CHECK(update_one_rr(db, ver, &diff, + DNS_DIFFOP_DEL, name, ttl, + &rdata)); + continue; + } - for (signing = ISC_LIST_HEAD(zone->signing); - signing != NULL; - signing = ISC_LIST_NEXT(signing, link)) - dns_dbiterator_pause(signing->dbiterator); + /* Acceptance timer expired? */ + if (kd.addhd != 0 && kd.addhd < now) + timer = kd.addhd; - dns_diff_clear(&sig_diff); + /* Or do we just need to refresh the keyset? */ + if (timer > kd.refresh) + timer = kd.refresh; + } - for (i = 0; i < nkeys; i++) - dst_key_free(&zone_keys[i]); + if (timer > now) + continue; - if (version != NULL) { - dns_db_closeversion(db, &version, ISC_FALSE); - dns_db_detach(&db); - } else if (db != NULL) - dns_db_detach(&db); + zone->refreshkeycount++; + + kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t)); + kfetch->zone = NULL; + dns_zone_attach(zone, &kfetch->zone); + dns_fixedname_init(&kfetch->name); + dns_name_dup(name, zone->mctx, + dns_fixedname_name(&kfetch->name)); + dns_rdataset_init(&kfetch->dnskeyset); + dns_rdataset_init(&kfetch->dnskeysigset); + dns_rdataset_init(&kfetch->keydataset); + dns_rdataset_clone(kdset, &kfetch->keydataset); + kfetch->db = NULL; + dns_db_attach(db, &kfetch->db); + kfetch->fetch = NULL; + + dns_resolver_createfetch(zone->view->resolver, + dns_fixedname_name(&kfetch->name), + dns_rdatatype_dnskey, + NULL, NULL, NULL, + DNS_FETCHOPT_NOVALIDATE, + zone->task, keyfetch_done, kfetch, + &kfetch->dnskeyset, + &kfetch->dnskeysigset, + &kfetch->fetch); + } + if (!ISC_LIST_EMPTY(diff.tuples)) { + CHECK(increment_soa_serial(db, ver, &diff, zone->mctx)); + commit = ISC_TRUE; + zone_journal(zone, &diff, "sync_keyzone"); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED); + zone_needdump(zone, 30); + } + failure: + UNLOCK_ZONE(zone); - if (ISC_LIST_HEAD(zone->signing) != NULL) { - isc_interval_t i; - if (zone->update_disabled || result != ISC_R_SUCCESS) - isc_interval_set(&i, 60, 0); /* 1 minute */ - else - isc_interval_set(&i, 0, 10000000); /* 10 ms */ - isc_time_nowplusinterval(&zone->signingtime, &i); - } else - isc_time_settoepoch(&zone->signingtime); + dns_rriterator_destroy(&rrit); + dns_diff_clear(&diff); + dns_db_closeversion(db, &ver, commit); + dns_db_detach(&db); } static void @@ -5991,7 +7790,7 @@ zone_maintenance(dns_zone_t *zone) { /* * Configuring the view of this zone may have * failed, for example because the config file - * had a syntax error. In that case, the view + * had a syntax error. In that case, the view * adb or resolver, and we had better not try * to do maintenance on it. */ @@ -6038,6 +7837,7 @@ zone_maintenance(dns_zone_t *zone) { switch (zone->type) { case dns_zone_master: case dns_zone_slave: + case dns_zone_key: LOCK_ZONE(zone); if (zone->masterfile != NULL && isc_time_compare(&now, &zone->dumptime) >= 0 && @@ -6059,6 +7859,24 @@ zone_maintenance(dns_zone_t *zone) { break; } + /* + * Do we need to refresh keys? + */ + switch (zone->type) { + case dns_zone_key: + if (isc_time_compare(&now, &zone->refreshkeytime) >= 0 && + DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) && + !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) + zone_refreshkeys(zone); + break; + case dns_zone_master: + if (!isc_time_isepoch(&zone->refreshkeytime) && + isc_time_compare(&now, &zone->refreshkeytime) >= 0) + zone_rekey(zone); + default: + break; + } + switch (zone->type) { case dns_zone_master: case dns_zone_slave: @@ -6098,7 +7916,8 @@ void dns_zone_markdirty(dns_zone_t *zone) { LOCK_ZONE(zone); - set_resigntime(zone); /* XXXMPA make separate call back */ + if (zone->type == dns_zone_master) + set_resigntime(zone); /* XXXMPA make separate call back */ zone_needdump(zone, DNS_DUMP_DELAY); UNLOCK_ZONE(zone); } @@ -7087,154 +8906,411 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { result = dns_name_dup(&ns.name, zone->mctx, ¬ify->ns); if (result != ISC_R_SUCCESS) { LOCK_ZONE(zone); - notify_destroy(notify, ISC_TRUE); + notify_destroy(notify, ISC_TRUE); + UNLOCK_ZONE(zone); + continue; + } + LOCK_ZONE(zone); + ISC_LIST_APPEND(zone->notifies, notify, link); + UNLOCK_ZONE(zone); + notify_find_address(notify); + notify = NULL; + result = dns_rdataset_next(&nsrdset); + } + dns_rdataset_disassociate(&nsrdset); + + cleanup3: + if (dns_name_dynamic(&master)) + dns_name_free(&master, zone->mctx); + cleanup2: + dns_db_detachnode(zonedb, &node); + cleanup1: + dns_db_closeversion(zonedb, &version, ISC_FALSE); + dns_db_detach(&zonedb); +} + +/*** + *** Private + ***/ + +static inline isc_result_t +save_nsrrset(dns_message_t *message, dns_name_t *name, + dns_db_t *db, dns_dbversion_t *version) +{ + dns_rdataset_t *nsrdataset = NULL; + dns_rdataset_t *rdataset = NULL; + dns_dbnode_t *node = NULL; + dns_rdata_ns_t ns; + isc_result_t result; + dns_rdata_t rdata = DNS_RDATA_INIT; + + /* + * Extract NS RRset from message. + */ + result = dns_message_findname(message, DNS_SECTION_ANSWER, name, + dns_rdatatype_ns, dns_rdatatype_none, + NULL, &nsrdataset); + if (result != ISC_R_SUCCESS) + goto fail; + + /* + * Add NS rdataset. + */ + result = dns_db_findnode(db, name, ISC_TRUE, &node); + if (result != ISC_R_SUCCESS) + goto fail; + result = dns_db_addrdataset(db, node, version, 0, + nsrdataset, 0, NULL); + dns_db_detachnode(db, &node); + if (result != ISC_R_SUCCESS) + goto fail; + /* + * Add glue rdatasets. + */ + for (result = dns_rdataset_first(nsrdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(nsrdataset)) { + dns_rdataset_current(nsrdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &ns, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + dns_rdata_reset(&rdata); + if (!dns_name_issubdomain(&ns.name, name)) + continue; + rdataset = NULL; + result = dns_message_findname(message, DNS_SECTION_ADDITIONAL, + &ns.name, dns_rdatatype_aaaa, + dns_rdatatype_none, NULL, + &rdataset); + if (result == ISC_R_SUCCESS) { + result = dns_db_findnode(db, &ns.name, + ISC_TRUE, &node); + if (result != ISC_R_SUCCESS) + goto fail; + result = dns_db_addrdataset(db, node, version, 0, + rdataset, 0, NULL); + dns_db_detachnode(db, &node); + if (result != ISC_R_SUCCESS) + goto fail; + } + rdataset = NULL; + result = dns_message_findname(message, DNS_SECTION_ADDITIONAL, + &ns.name, dns_rdatatype_a, + dns_rdatatype_none, NULL, + &rdataset); + if (result == ISC_R_SUCCESS) { + result = dns_db_findnode(db, &ns.name, + ISC_TRUE, &node); + if (result != ISC_R_SUCCESS) + goto fail; + result = dns_db_addrdataset(db, node, version, 0, + rdataset, 0, NULL); + dns_db_detachnode(db, &node); + if (result != ISC_R_SUCCESS) + goto fail; + } + } + if (result != ISC_R_NOMORE) + goto fail; + + return (ISC_R_SUCCESS); + +fail: + return (result); +} + +static void +stub_callback(isc_task_t *task, isc_event_t *event) { + const char me[] = "stub_callback"; + dns_requestevent_t *revent = (dns_requestevent_t *)event; + dns_stub_t *stub = NULL; + dns_message_t *msg = NULL; + dns_zone_t *zone = NULL; + char master[ISC_SOCKADDR_FORMATSIZE]; + char source[ISC_SOCKADDR_FORMATSIZE]; + isc_uint32_t nscnt, cnamecnt; + isc_result_t result; + isc_time_t now; + isc_boolean_t exiting = ISC_FALSE; + isc_interval_t i; + unsigned int j; + + stub = revent->ev_arg; + INSIST(DNS_STUB_VALID(stub)); + + UNUSED(task); + + zone = stub->zone; + + ENTER; + + TIME_NOW(&now); + + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) { + zone_debuglog(zone, me, 1, "exiting"); + exiting = ISC_TRUE; + goto next_master; + } + + isc_sockaddr_format(&zone->masteraddr, master, sizeof(master)); + isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source)); + + if (revent->result != ISC_R_SUCCESS) { + if (revent->result == ISC_R_TIMEDOUT && + !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) { + LOCK_ZONE(zone); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS); + UNLOCK_ZONE(zone); + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "refreshing stub: timeout retrying " + " without EDNS master %s (source %s)", + master, source); + goto same_master; + } + dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr, + &zone->sourceaddr, &now); + dns_zone_log(zone, ISC_LOG_INFO, + "could not refresh stub from master %s" + " (source %s): %s", master, source, + dns_result_totext(revent->result)); + goto next_master; + } + + result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg); + if (result != ISC_R_SUCCESS) + goto next_master; + + result = dns_request_getresponse(revent->request, msg, 0); + if (result != ISC_R_SUCCESS) + goto next_master; + + /* + * Unexpected rcode. + */ + if (msg->rcode != dns_rcode_noerror) { + char rcode[128]; + isc_buffer_t rb; + + isc_buffer_init(&rb, rcode, sizeof(rcode)); + (void)dns_rcode_totext(msg->rcode, &rb); + + if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) && + (msg->rcode == dns_rcode_servfail || + msg->rcode == dns_rcode_notimp || + msg->rcode == dns_rcode_formerr)) { + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "refreshing stub: rcode (%.*s) retrying " + "without EDNS master %s (source %s)", + (int)rb.used, rcode, master, source); + LOCK_ZONE(zone); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS); UNLOCK_ZONE(zone); - continue; + goto same_master; + } + + dns_zone_log(zone, ISC_LOG_INFO, + "refreshing stub: " + "unexpected rcode (%.*s) from %s (source %s)", + (int)rb.used, rcode, master, source); + goto next_master; + } + + /* + * We need complete messages. + */ + if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) { + if (dns_request_usedtcp(revent->request)) { + dns_zone_log(zone, ISC_LOG_INFO, + "refreshing stub: truncated TCP " + "response from master %s (source %s)", + master, source); + goto next_master; } LOCK_ZONE(zone); - ISC_LIST_APPEND(zone->notifies, notify, link); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC); UNLOCK_ZONE(zone); - notify_find_address(notify); - notify = NULL; - result = dns_rdataset_next(&nsrdset); + goto same_master; } - dns_rdataset_disassociate(&nsrdset); - cleanup3: - if (dns_name_dynamic(&master)) - dns_name_free(&master, zone->mctx); - cleanup2: - dns_db_detachnode(zonedb, &node); - cleanup1: - dns_db_closeversion(zonedb, &version, ISC_FALSE); - dns_db_detach(&zonedb); -} + /* + * If non-auth log and next master. + */ + if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) { + dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: " + "non-authoritative answer from " + "master %s (source %s)", master, source); + goto next_master; + } -/*** - *** Private - ***/ + /* + * Sanity checks. + */ + cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname); + nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns); -static inline isc_result_t -save_nsrrset(dns_message_t *message, dns_name_t *name, - dns_db_t *db, dns_dbversion_t *version) -{ - dns_rdataset_t *nsrdataset = NULL; - dns_rdataset_t *rdataset = NULL; - dns_dbnode_t *node = NULL; - dns_rdata_ns_t ns; - isc_result_t result; - dns_rdata_t rdata = DNS_RDATA_INIT; + if (cnamecnt != 0) { + dns_zone_log(zone, ISC_LOG_INFO, + "refreshing stub: unexpected CNAME response " + "from master %s (source %s)", master, source); + goto next_master; + } + + if (nscnt == 0) { + dns_zone_log(zone, ISC_LOG_INFO, + "refreshing stub: no NS records in response " + "from master %s (source %s)", master, source); + goto next_master; + } /* - * Extract NS RRset from message. + * Save answer. */ - result = dns_message_findname(message, DNS_SECTION_ANSWER, name, - dns_rdatatype_ns, dns_rdatatype_none, - NULL, &nsrdataset); - if (result != ISC_R_SUCCESS) - goto fail; + result = save_nsrrset(msg, &zone->origin, stub->db, stub->version); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_INFO, + "refreshing stub: unable to save NS records " + "from master %s (source %s)", master, source); + goto next_master; + } /* - * Add NS rdataset. + * Tidy up. */ - result = dns_db_findnode(db, name, ISC_TRUE, &node); - if (result != ISC_R_SUCCESS) - goto fail; - result = dns_db_addrdataset(db, node, version, 0, - nsrdataset, 0, NULL); - dns_db_detachnode(db, &node); - if (result != ISC_R_SUCCESS) - goto fail; + dns_db_closeversion(stub->db, &stub->version, ISC_TRUE); + ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write); + if (zone->db == NULL) + zone_attachdb(zone, stub->db); + ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write); + dns_db_detach(&stub->db); + + if (zone->masterfile != NULL) { + dns_zone_dump(zone); + TIME_NOW(&zone->loadtime); + } + + dns_message_destroy(&msg); + isc_event_free(&event); + LOCK_ZONE(zone); + dns_request_destroy(&zone->request); + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH); + DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime); + isc_interval_set(&i, zone->expire, 0); + DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime); + zone_settimer(zone, &now); + UNLOCK_ZONE(zone); + goto free_stub; + + next_master: + if (stub->version != NULL) + dns_db_closeversion(stub->db, &stub->version, ISC_FALSE); + if (stub->db != NULL) + dns_db_detach(&stub->db); + if (msg != NULL) + dns_message_destroy(&msg); + isc_event_free(&event); + LOCK_ZONE(zone); + dns_request_destroy(&zone->request); /* - * Add glue rdatasets. + * Skip to next failed / untried master. */ - for (result = dns_rdataset_first(nsrdataset); - result == ISC_R_SUCCESS; - result = dns_rdataset_next(nsrdataset)) { - dns_rdataset_current(nsrdataset, &rdata); - result = dns_rdata_tostruct(&rdata, &ns, NULL); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - dns_rdata_reset(&rdata); - if (!dns_name_issubdomain(&ns.name, name)) - continue; - rdataset = NULL; - result = dns_message_findname(message, DNS_SECTION_ADDITIONAL, - &ns.name, dns_rdatatype_aaaa, - dns_rdatatype_none, NULL, - &rdataset); - if (result == ISC_R_SUCCESS) { - result = dns_db_findnode(db, &ns.name, - ISC_TRUE, &node); - if (result != ISC_R_SUCCESS) - goto fail; - result = dns_db_addrdataset(db, node, version, 0, - rdataset, 0, NULL); - dns_db_detachnode(db, &node); - if (result != ISC_R_SUCCESS) - goto fail; - } - rdataset = NULL; - result = dns_message_findname(message, DNS_SECTION_ADDITIONAL, - &ns.name, dns_rdatatype_a, - dns_rdatatype_none, NULL, - &rdataset); - if (result == ISC_R_SUCCESS) { - result = dns_db_findnode(db, &ns.name, - ISC_TRUE, &node); - if (result != ISC_R_SUCCESS) - goto fail; - result = dns_db_addrdataset(db, node, version, 0, - rdataset, 0, NULL); - dns_db_detachnode(db, &node); - if (result != ISC_R_SUCCESS) - goto fail; + do { + zone->curmaster++; + } while (zone->curmaster < zone->masterscnt && + zone->mastersok[zone->curmaster]); + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS); + if (exiting || zone->curmaster >= zone->masterscnt) { + isc_boolean_t done = ISC_TRUE; + if (!exiting && + DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) && + !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) { + /* + * Did we get a good answer from all the masters? + */ + for (j = 0; j < zone->masterscnt; j++) + if (zone->mastersok[j] == ISC_FALSE) { + done = ISC_FALSE; + break; + } + } else + done = ISC_TRUE; + if (!done) { + zone->curmaster = 0; + /* + * Find the next failed master. + */ + while (zone->curmaster < zone->masterscnt && + zone->mastersok[zone->curmaster]) + zone->curmaster++; + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC); + } else { + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH); + + zone_settimer(zone, &now); + UNLOCK_ZONE(zone); + goto free_stub; } } - if (result != ISC_R_NOMORE) - goto fail; + queue_soa_query(zone); + UNLOCK_ZONE(zone); + goto free_stub; - return (ISC_R_SUCCESS); + same_master: + if (msg != NULL) + dns_message_destroy(&msg); + isc_event_free(&event); + LOCK_ZONE(zone); + dns_request_destroy(&zone->request); + UNLOCK_ZONE(zone); + ns_query(zone, NULL, stub); + goto done; -fail: - return (result); + free_stub: + stub->magic = 0; + dns_zone_idetach(&stub->zone); + INSIST(stub->db == NULL); + INSIST(stub->version == NULL); + isc_mem_put(stub->mctx, stub, sizeof(*stub)); + + done: + INSIST(event == NULL); + return; } +/* + * An SOA query has finished (successfully or not). + */ static void -stub_callback(isc_task_t *task, isc_event_t *event) { - const char me[] = "stub_callback"; +refresh_callback(isc_task_t *task, isc_event_t *event) { + const char me[] = "refresh_callback"; dns_requestevent_t *revent = (dns_requestevent_t *)event; - dns_stub_t *stub = NULL; + dns_zone_t *zone; dns_message_t *msg = NULL; - dns_zone_t *zone = NULL; + isc_uint32_t soacnt, cnamecnt, soacount, nscount; + isc_time_t now; char master[ISC_SOCKADDR_FORMATSIZE]; char source[ISC_SOCKADDR_FORMATSIZE]; - isc_uint32_t nscnt, cnamecnt; + dns_rdataset_t *rdataset = NULL; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_soa_t soa; isc_result_t result; - isc_time_t now; - isc_boolean_t exiting = ISC_FALSE; - isc_interval_t i; + isc_uint32_t serial, oldserial; unsigned int j; - stub = revent->ev_arg; - INSIST(DNS_STUB_VALID(stub)); + zone = revent->ev_arg; + INSIST(DNS_ZONE_VALID(zone)); UNUSED(task); - zone = stub->zone; - ENTER; - TIME_NOW(&now); - - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) { - zone_debuglog(zone, me, 1, "exiting"); - exiting = ISC_TRUE; - goto next_master; - } + /* + * if timeout log and next master; + */ isc_sockaddr_format(&zone->masteraddr, master, sizeof(master)); isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source)); + TIME_NOW(&now); + if (revent->result != ISC_R_SUCCESS) { if (revent->result == ISC_R_TIMEDOUT && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) { @@ -7242,27 +9318,54 @@ stub_callback(isc_task_t *task, isc_event_t *event) { DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS); UNLOCK_ZONE(zone); dns_zone_log(zone, ISC_LOG_DEBUG(1), - "refreshing stub: timeout retrying " - " without EDNS master %s (source %s)", - master, source); + "refresh: timeout retrying without EDNS " + "master %s (source %s)", master, source); goto same_master; } - dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr, - &zone->sourceaddr, &now); - dns_zone_log(zone, ISC_LOG_INFO, - "could not refresh stub from master %s" - " (source %s): %s", master, source, - dns_result_totext(revent->result)); + if (revent->result == ISC_R_TIMEDOUT && + !dns_request_usedtcp(revent->request)) { + dns_zone_log(zone, ISC_LOG_INFO, + "refresh: retry limit for " + "master %s exceeded (source %s)", + master, source); + /* Try with slave with TCP. */ + if (zone->type == dns_zone_slave && + DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) { + if (!dns_zonemgr_unreachable(zone->zmgr, + &zone->masteraddr, + &zone->sourceaddr, + &now)) { + LOCK_ZONE(zone); + DNS_ZONE_SETFLAG(zone, + DNS_ZONEFLG_SOABEFOREAXFR); + UNLOCK_ZONE(zone); + goto tcp_transfer; + } + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "refresh: skipped tcp fallback" + "as master %s (source %s) is " + "unreachable (cached)", + master, source); + } + } else + dns_zone_log(zone, ISC_LOG_INFO, + "refresh: failure trying master " + "%s (source %s): %s", master, source, + dns_result_totext(revent->result)); goto next_master; } result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg); if (result != ISC_R_SUCCESS) goto next_master; - result = dns_request_getresponse(revent->request, msg, 0); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_INFO, + "refresh: failure trying master " + "%s (source %s): %s", master, source, + dns_result_totext(result)); goto next_master; + } /* * Unexpected rcode. @@ -7279,112 +9382,217 @@ stub_callback(isc_task_t *task, isc_event_t *event) { msg->rcode == dns_rcode_notimp || msg->rcode == dns_rcode_formerr)) { dns_zone_log(zone, ISC_LOG_DEBUG(1), - "refreshing stub: rcode (%.*s) retrying " - "without EDNS master %s (source %s)", + "refresh: rcode (%.*s) retrying without " + "EDNS master %s (source %s)", (int)rb.used, rcode, master, source); LOCK_ZONE(zone); DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS); UNLOCK_ZONE(zone); goto same_master; } - dns_zone_log(zone, ISC_LOG_INFO, - "refreshing stub: " - "unexpected rcode (%.*s) from %s (source %s)", - (int)rb.used, rcode, master, source); + "refresh: unexpected rcode (%.*s) from " + "master %s (source %s)", (int)rb.used, rcode, + master, source); + /* + * Perhaps AXFR/IXFR is allowed even if SOA queries aren't. + */ + if (msg->rcode == dns_rcode_refused && + zone->type == dns_zone_slave) + goto tcp_transfer; goto next_master; } /* - * We need complete messages. + * If truncated punt to zone transfer which will query again. */ if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) { - if (dns_request_usedtcp(revent->request)) { + if (zone->type == dns_zone_slave) { dns_zone_log(zone, ISC_LOG_INFO, - "refreshing stub: truncated TCP " - "response from master %s (source %s)", + "refresh: truncated UDP answer, " + "initiating TCP zone xfer " + "for master %s (source %s)", + master, source); + LOCK_ZONE(zone); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR); + UNLOCK_ZONE(zone); + goto tcp_transfer; + } else { + INSIST(zone->type == dns_zone_stub); + if (dns_request_usedtcp(revent->request)) { + dns_zone_log(zone, ISC_LOG_INFO, + "refresh: truncated TCP response " + "from master %s (source %s)", + master, source); + goto next_master; + } + LOCK_ZONE(zone); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC); + UNLOCK_ZONE(zone); + goto same_master; + } + } + + /* + * if non-auth log and next master; + */ + if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) { + dns_zone_log(zone, ISC_LOG_INFO, + "refresh: non-authoritative answer from " + "master %s (source %s)", master, source); + goto next_master; + } + + cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname); + soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa); + nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns); + soacount = message_count(msg, DNS_SECTION_AUTHORITY, + dns_rdatatype_soa); + + /* + * There should not be a CNAME record at top of zone. + */ + if (cnamecnt != 0) { + dns_zone_log(zone, ISC_LOG_INFO, + "refresh: CNAME at top of zone " + "in master %s (source %s)", master, source); + goto next_master; + } + + /* + * if referral log and next master; + */ + if (soacnt == 0 && soacount == 0 && nscount != 0) { + dns_zone_log(zone, ISC_LOG_INFO, + "refresh: referral response " + "from master %s (source %s)", master, source); + goto next_master; + } + + /* + * if nodata log and next master; + */ + if (soacnt == 0 && (nscount == 0 || soacount != 0)) { + dns_zone_log(zone, ISC_LOG_INFO, + "refresh: NODATA response " + "from master %s (source %s)", master, source); + goto next_master; + } + + /* + * Only one soa at top of zone. + */ + if (soacnt != 1) { + dns_zone_log(zone, ISC_LOG_INFO, + "refresh: answer SOA count (%d) != 1 " + "from master %s (source %s)", + soacnt, master, source); + goto next_master; + } + /* + * Extract serial + */ + rdataset = NULL; + result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin, + dns_rdatatype_soa, dns_rdatatype_none, + NULL, &rdataset); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_INFO, + "refresh: unable to get SOA record " + "from master %s (source %s)", master, source); + goto next_master; + } + + result = dns_rdataset_first(rdataset); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_INFO, + "refresh: dns_rdataset_first() failed"); + goto next_master; + } + + dns_rdataset_current(rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &soa, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + serial = soa.serial; + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) { + result = dns_zone_getserial2(zone, &oldserial); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + zone_debuglog(zone, me, 1, "serial: new %u, old %u", + serial, oldserial); + } else + zone_debuglog(zone, me, 1, "serial: new %u, old not loaded", + serial); + if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) || + DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) || + isc_serial_gt(serial, oldserial)) { + if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr, + &zone->sourceaddr, &now)) { + dns_zone_log(zone, ISC_LOG_INFO, + "refresh: skipping %s as master %s " + "(source %s) is unreachable (cached)", + zone->type == dns_zone_slave ? + "zone transfer" : "NS query", master, source); goto next_master; } - LOCK_ZONE(zone); - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC); - UNLOCK_ZONE(zone); - goto same_master; - } - - /* - * If non-auth log and next master. - */ - if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) { - dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: " - "non-authoritative answer from " - "master %s (source %s)", master, source); - goto next_master; - } - - /* - * Sanity checks. - */ - cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname); - nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns); - - if (cnamecnt != 0) { - dns_zone_log(zone, ISC_LOG_INFO, - "refreshing stub: unexpected CNAME response " - "from master %s (source %s)", master, source); - goto next_master; - } - - if (nscnt == 0) { - dns_zone_log(zone, ISC_LOG_INFO, - "refreshing stub: no NS records in response " - "from master %s (source %s)", master, source); + tcp_transfer: + isc_event_free(&event); + LOCK_ZONE(zone); + dns_request_destroy(&zone->request); + UNLOCK_ZONE(zone); + if (zone->type == dns_zone_slave) { + queue_xfrin(zone); + } else { + INSIST(zone->type == dns_zone_stub); + ns_query(zone, rdataset, NULL); + } + if (msg != NULL) + dns_message_destroy(&msg); + } else if (isc_serial_eq(soa.serial, oldserial)) { + if (zone->masterfile != NULL) { + result = ISC_R_FAILURE; + if (zone->journal != NULL) + result = isc_file_settime(zone->journal, &now); + if (result == ISC_R_SUCCESS && + !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) && + !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) { + result = isc_file_settime(zone->masterfile, + &now); + } else if (result != ISC_R_SUCCESS) + result = isc_file_settime(zone->masterfile, + &now); + /* Someone removed the file from underneath us! */ + if (result == ISC_R_FILENOTFOUND) { + LOCK_ZONE(zone); + zone_needdump(zone, DNS_DUMP_DELAY); + UNLOCK_ZONE(zone); + } else if (result != ISC_R_SUCCESS) + dns_zone_log(zone, ISC_LOG_ERROR, + "refresh: could not set file " + "modification time of '%s': %s", + zone->masterfile, + dns_result_totext(result)); + } + DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime); + DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime); + zone->mastersok[zone->curmaster] = ISC_TRUE; goto next_master; - } - - /* - * Save answer. - */ - result = save_nsrrset(msg, &zone->origin, stub->db, stub->version); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_INFO, - "refreshing stub: unable to save NS records " - "from master %s (source %s)", master, source); + } else { + if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER)) + dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) " + "received from master %s < ours (%u)", + soa.serial, master, oldserial); + else + zone_debuglog(zone, me, 1, "ahead"); + zone->mastersok[zone->curmaster] = ISC_TRUE; goto next_master; } - - /* - * Tidy up. - */ - dns_db_closeversion(stub->db, &stub->version, ISC_TRUE); - ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write); - if (zone->db == NULL) - zone_attachdb(zone, stub->db); - ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write); - dns_db_detach(&stub->db); - - if (zone->masterfile != NULL) { - dns_zone_dump(zone); - TIME_NOW(&zone->loadtime); - } - - dns_message_destroy(&msg); - isc_event_free(&event); - LOCK_ZONE(zone); - dns_request_destroy(&zone->request); - DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH); - DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime); - isc_interval_set(&i, zone->expire, 0); - DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime); - zone_settimer(zone, &now); - UNLOCK_ZONE(zone); - goto free_stub; + if (msg != NULL) + dns_message_destroy(&msg); + goto detach; next_master: - if (stub->version != NULL) - dns_db_closeversion(stub->db, &stub->version, ISC_FALSE); - if (stub->db != NULL) - dns_db_detach(&stub->db); if (msg != NULL) dns_message_destroy(&msg); isc_event_free(&event); @@ -7398,10 +9606,9 @@ stub_callback(isc_task_t *task, isc_event_t *event) { } while (zone->curmaster < zone->masterscnt && zone->mastersok[zone->curmaster]); DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS); - if (exiting || zone->curmaster >= zone->masterscnt) { + if (zone->curmaster >= zone->masterscnt) { isc_boolean_t done = ISC_TRUE; - if (!exiting && - DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) && + if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) { /* * Did we get a good answer from all the masters? @@ -7414,6 +9621,7 @@ stub_callback(isc_task_t *task, isc_event_t *event) { } else done = ISC_TRUE; if (!done) { + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC); zone->curmaster = 0; /* * Find the next failed master. @@ -7421,4224 +9629,4643 @@ stub_callback(isc_task_t *task, isc_event_t *event) { while (zone->curmaster < zone->masterscnt && zone->mastersok[zone->curmaster]) zone->curmaster++; - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC); - } else { - DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH); + goto requeue; + } + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH); + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) { + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH); + zone->refreshtime = now; + } + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC); + zone_settimer(zone, &now); + UNLOCK_ZONE(zone); + goto detach; + } + + requeue: + queue_soa_query(zone); + UNLOCK_ZONE(zone); + goto detach; + + same_master: + if (msg != NULL) + dns_message_destroy(&msg); + isc_event_free(&event); + LOCK_ZONE(zone); + dns_request_destroy(&zone->request); + queue_soa_query(zone); + UNLOCK_ZONE(zone); + + detach: + dns_zone_idetach(&zone); + return; +} + +static void +queue_soa_query(dns_zone_t *zone) { + const char me[] = "queue_soa_query"; + isc_event_t *e; + dns_zone_t *dummy = NULL; + isc_result_t result; + + ENTER; + /* + * Locked by caller + */ + REQUIRE(LOCKED_ZONE(zone)); + + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) { + cancel_refresh(zone); + return; + } + + e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE, + soa_query, zone, sizeof(isc_event_t)); + if (e == NULL) { + cancel_refresh(zone); + return; + } + + /* + * Attach so that we won't clean up + * until the event is delivered. + */ + zone_iattach(zone, &dummy); + + e->ev_arg = zone; + e->ev_sender = NULL; + result = isc_ratelimiter_enqueue(zone->zmgr->rl, zone->task, &e); + if (result != ISC_R_SUCCESS) { + zone_idetach(&dummy); + isc_event_free(&e); + cancel_refresh(zone); + } +} + +static inline isc_result_t +create_query(dns_zone_t *zone, dns_rdatatype_t rdtype, + dns_message_t **messagep) +{ + dns_message_t *message = NULL; + dns_name_t *qname = NULL; + dns_rdataset_t *qrdataset = NULL; + isc_result_t result; + + result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, + &message); + if (result != ISC_R_SUCCESS) + goto cleanup; + + message->opcode = dns_opcode_query; + message->rdclass = zone->rdclass; + + result = dns_message_gettempname(message, &qname); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = dns_message_gettemprdataset(message, &qrdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + + /* + * Make question. + */ + dns_name_init(qname, NULL); + dns_name_clone(&zone->origin, qname); + dns_rdataset_init(qrdataset); + dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype); + ISC_LIST_APPEND(qname->list, qrdataset, link); + dns_message_addname(message, qname, DNS_SECTION_QUESTION); + + *messagep = message; + return (ISC_R_SUCCESS); + + cleanup: + if (qname != NULL) + dns_message_puttempname(message, &qname); + if (qrdataset != NULL) + dns_message_puttemprdataset(message, &qrdataset); + if (message != NULL) + dns_message_destroy(&message); + return (result); +} + +static isc_result_t +add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) { + dns_rdataset_t *rdataset = NULL; + dns_rdatalist_t *rdatalist = NULL; + dns_rdata_t *rdata = NULL; + isc_result_t result; + + result = dns_message_gettemprdatalist(message, &rdatalist); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = dns_message_gettemprdata(message, &rdata); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = dns_message_gettemprdataset(message, &rdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + dns_rdataset_init(rdataset); + + rdatalist->type = dns_rdatatype_opt; + rdatalist->covers = 0; + + /* + * Set Maximum UDP buffer size. + */ + rdatalist->rdclass = udpsize; + + /* + * Set EXTENDED-RCODE, VERSION, DO and Z to 0. + */ + rdatalist->ttl = 0; + + /* Set EDNS options if applicable */ + if (reqnsid) { + unsigned char data[4]; + isc_buffer_t buf; - zone_settimer(zone, &now); - UNLOCK_ZONE(zone); - goto free_stub; - } + isc_buffer_init(&buf, data, sizeof(data)); + isc_buffer_putuint16(&buf, DNS_OPT_NSID); + isc_buffer_putuint16(&buf, 0); + rdata->data = data; + rdata->length = sizeof(data); + } else { + rdata->data = NULL; + rdata->length = 0; } - queue_soa_query(zone); - UNLOCK_ZONE(zone); - goto free_stub; - same_master: - if (msg != NULL) - dns_message_destroy(&msg); - isc_event_free(&event); - LOCK_ZONE(zone); - dns_request_destroy(&zone->request); - UNLOCK_ZONE(zone); - ns_query(zone, NULL, stub); - goto done; + rdata->rdclass = rdatalist->rdclass; + rdata->type = rdatalist->type; + rdata->flags = 0; - free_stub: - stub->magic = 0; - dns_zone_idetach(&stub->zone); - INSIST(stub->db == NULL); - INSIST(stub->version == NULL); - isc_mem_put(stub->mctx, stub, sizeof(*stub)); + ISC_LIST_INIT(rdatalist->rdata); + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) + == ISC_R_SUCCESS); - done: - INSIST(event == NULL); - return; + return (dns_message_setopt(message, rdataset)); + + cleanup: + if (rdatalist != NULL) + dns_message_puttemprdatalist(message, &rdatalist); + if (rdataset != NULL) + dns_message_puttemprdataset(message, &rdataset); + if (rdata != NULL) + dns_message_puttemprdata(message, &rdata); + + return (result); } -/* - * An SOA query has finished (successfully or not). - */ static void -refresh_callback(isc_task_t *task, isc_event_t *event) { - const char me[] = "refresh_callback"; - dns_requestevent_t *revent = (dns_requestevent_t *)event; - dns_zone_t *zone; - dns_message_t *msg = NULL; - isc_uint32_t soacnt, cnamecnt, soacount, nscount; - isc_time_t now; - char master[ISC_SOCKADDR_FORMATSIZE]; - char source[ISC_SOCKADDR_FORMATSIZE]; - dns_rdataset_t *rdataset = NULL; - dns_rdata_t rdata = DNS_RDATA_INIT; - dns_rdata_soa_t soa; - isc_result_t result; - isc_uint32_t serial, oldserial; - unsigned int j; +soa_query(isc_task_t *task, isc_event_t *event) { + const char me[] = "soa_query"; + isc_result_t result = ISC_R_FAILURE; + dns_message_t *message = NULL; + dns_zone_t *zone = event->ev_arg; + dns_zone_t *dummy = NULL; + isc_netaddr_t masterip; + dns_tsigkey_t *key = NULL; + isc_uint32_t options; + isc_boolean_t cancel = ISC_TRUE; + int timeout; + isc_boolean_t have_xfrsource, reqnsid; + isc_uint16_t udpsize = SEND_BUFFER_SIZE; - zone = revent->ev_arg; - INSIST(DNS_ZONE_VALID(zone)); + REQUIRE(DNS_ZONE_VALID(zone)); UNUSED(task); ENTER; + LOCK_ZONE(zone); + if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) || + DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || + zone->view->requestmgr == NULL) { + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) + cancel = ISC_FALSE; + goto cleanup; + } + /* - * if timeout log and next master; + * XXX Optimisation: Create message when zone is setup and reuse. */ + result = create_query(zone, dns_rdatatype_soa, &message); + if (result != ISC_R_SUCCESS) + goto cleanup; - isc_sockaddr_format(&zone->masteraddr, master, sizeof(master)); - isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source)); + again: + INSIST(zone->masterscnt > 0); + INSIST(zone->curmaster < zone->masterscnt); - TIME_NOW(&now); + zone->masteraddr = zone->masters[zone->curmaster]; - if (revent->result != ISC_R_SUCCESS) { - if (revent->result == ISC_R_TIMEDOUT && - !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) { - LOCK_ZONE(zone); - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS); - UNLOCK_ZONE(zone); - dns_zone_log(zone, ISC_LOG_DEBUG(1), - "refresh: timeout retrying without EDNS " - "master %s (source %s)", master, source); - goto same_master; + isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr); + /* + * First, look for a tsig key in the master statement, then + * try for a server key. + */ + if ((zone->masterkeynames != NULL) && + (zone->masterkeynames[zone->curmaster] != NULL)) { + dns_view_t *view = dns_zone_getview(zone); + dns_name_t *keyname = zone->masterkeynames[zone->curmaster]; + result = dns_view_gettsig(view, keyname, &key); + if (result != ISC_R_SUCCESS) { + char namebuf[DNS_NAME_FORMATSIZE]; + dns_name_format(keyname, namebuf, sizeof(namebuf)); + dns_zone_log(zone, ISC_LOG_ERROR, + "unable to find key: %s", namebuf); + goto skip_master; } - if (revent->result == ISC_R_TIMEDOUT && - !dns_request_usedtcp(revent->request)) { - dns_zone_log(zone, ISC_LOG_INFO, - "refresh: retry limit for " - "master %s exceeded (source %s)", - master, source); - /* Try with slave with TCP. */ - if (zone->type == dns_zone_slave && - DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) { - if (!dns_zonemgr_unreachable(zone->zmgr, - &zone->masteraddr, - &zone->sourceaddr, - &now)) { - LOCK_ZONE(zone); - DNS_ZONE_SETFLAG(zone, - DNS_ZONEFLG_SOABEFOREAXFR); - UNLOCK_ZONE(zone); - goto tcp_transfer; - } - dns_zone_log(zone, ISC_LOG_DEBUG(1), - "refresh: skipped tcp fallback" - "as master %s (source %s) is " - "unreachable (cached)", - master, source); - } - } else - dns_zone_log(zone, ISC_LOG_INFO, - "refresh: failure trying master " - "%s (source %s): %s", master, source, - dns_result_totext(revent->result)); - goto next_master; } + if (key == NULL) { + result = dns_view_getpeertsig(zone->view, &masterip, &key); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) { + char addrbuf[ISC_NETADDR_FORMATSIZE]; + isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf)); + dns_zone_log(zone, ISC_LOG_ERROR, + "unable to find TSIG key for %s", addrbuf); + goto skip_master; + } + } + + have_xfrsource = ISC_FALSE; + reqnsid = zone->view->requestnsid; + if (zone->view->peers != NULL) { + dns_peer_t *peer = NULL; + isc_boolean_t edns; + result = dns_peerlist_peerbyaddr(zone->view->peers, + &masterip, &peer); + if (result == ISC_R_SUCCESS) { + result = dns_peer_getsupportedns(peer, &edns); + if (result == ISC_R_SUCCESS && !edns) + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS); + result = dns_peer_gettransfersource(peer, + &zone->sourceaddr); + if (result == ISC_R_SUCCESS) + have_xfrsource = ISC_TRUE; + if (zone->view->resolver != NULL) + udpsize = + dns_resolver_getudpsize(zone->view->resolver); + (void)dns_peer_getudpsize(peer, &udpsize); + (void)dns_peer_getrequestnsid(peer, &reqnsid); + } + } + + switch (isc_sockaddr_pf(&zone->masteraddr)) { + case PF_INET: + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) { + if (isc_sockaddr_equal(&zone->altxfrsource4, + &zone->xfrsource4)) + goto skip_master; + zone->sourceaddr = zone->altxfrsource4; + } else if (!have_xfrsource) + zone->sourceaddr = zone->xfrsource4; + break; + case PF_INET6: + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) { + if (isc_sockaddr_equal(&zone->altxfrsource6, + &zone->xfrsource6)) + goto skip_master; + zone->sourceaddr = zone->altxfrsource6; + } else if (!have_xfrsource) + zone->sourceaddr = zone->xfrsource6; + break; + default: + result = ISC_R_NOTIMPLEMENTED; + goto cleanup; + } + + options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ? + DNS_REQUESTOPT_TCP : 0; + + if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) { + result = add_opt(message, udpsize, reqnsid); + if (result != ISC_R_SUCCESS) + zone_debuglog(zone, me, 1, + "unable to add opt record: %s", + dns_result_totext(result)); + } + + zone_iattach(zone, &dummy); + timeout = 15; + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) + timeout = 30; + result = dns_request_createvia2(zone->view->requestmgr, message, + &zone->sourceaddr, &zone->masteraddr, + options, key, timeout * 3, timeout, + zone->task, refresh_callback, zone, + &zone->request); + if (result != ISC_R_SUCCESS) { + zone_idetach(&dummy); + zone_debuglog(zone, me, 1, + "dns_request_createvia2() failed: %s", + dns_result_totext(result)); + goto cleanup; + } else { + if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET) + inc_stats(zone, dns_zonestatscounter_soaoutv4); + else + inc_stats(zone, dns_zonestatscounter_soaoutv6); + } + cancel = ISC_FALSE; - result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg); + cleanup: + if (key != NULL) + dns_tsigkey_detach(&key); if (result != ISC_R_SUCCESS) - goto next_master; - result = dns_request_getresponse(revent->request, msg, 0); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_INFO, - "refresh: failure trying master " - "%s (source %s): %s", master, source, - dns_result_totext(result)); - goto next_master; - } + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH); + if (message != NULL) + dns_message_destroy(&message); + if (cancel) + cancel_refresh(zone); + isc_event_free(&event); + UNLOCK_ZONE(zone); + dns_zone_idetach(&zone); + return; + skip_master: + if (key != NULL) + dns_tsigkey_detach(&key); /* - * Unexpected rcode. + * Skip to next failed / untried master. */ - if (msg->rcode != dns_rcode_noerror) { - char rcode[128]; - isc_buffer_t rb; + do { + zone->curmaster++; + } while (zone->curmaster < zone->masterscnt && + zone->mastersok[zone->curmaster]); + if (zone->curmaster < zone->masterscnt) + goto again; + zone->curmaster = 0; + goto cleanup; +} - isc_buffer_init(&rb, rcode, sizeof(rcode)); - (void)dns_rcode_totext(msg->rcode, &rb); +static void +ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) { + const char me[] = "ns_query"; + isc_result_t result; + dns_message_t *message = NULL; + isc_netaddr_t masterip; + dns_tsigkey_t *key = NULL; + dns_dbnode_t *node = NULL; + int timeout; + isc_boolean_t have_xfrsource = ISC_FALSE, reqnsid; + isc_uint16_t udpsize = SEND_BUFFER_SIZE; + + REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE((soardataset != NULL && stub == NULL) || + (soardataset == NULL && stub != NULL)); + REQUIRE(stub == NULL || DNS_STUB_VALID(stub)); + + ENTER; + + LOCK_ZONE(zone); + if (stub == NULL) { + stub = isc_mem_get(zone->mctx, sizeof(*stub)); + if (stub == NULL) + goto cleanup; + stub->magic = STUB_MAGIC; + stub->mctx = zone->mctx; + stub->zone = NULL; + stub->db = NULL; + stub->version = NULL; - if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) && - (msg->rcode == dns_rcode_servfail || - msg->rcode == dns_rcode_notimp || - msg->rcode == dns_rcode_formerr)) { - dns_zone_log(zone, ISC_LOG_DEBUG(1), - "refresh: rcode (%.*s) retrying without " - "EDNS master %s (source %s)", - (int)rb.used, rcode, master, source); - LOCK_ZONE(zone); - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS); - UNLOCK_ZONE(zone); - goto same_master; - } - dns_zone_log(zone, ISC_LOG_INFO, - "refresh: unexpected rcode (%.*s) from " - "master %s (source %s)", (int)rb.used, rcode, - master, source); /* - * Perhaps AXFR/IXFR is allowed even if SOA queries aren't. + * Attach so that the zone won't disappear from under us. */ - if (msg->rcode == dns_rcode_refused && - zone->type == dns_zone_slave) - goto tcp_transfer; - goto next_master; - } + zone_iattach(zone, &stub->zone); - /* - * If truncated punt to zone transfer which will query again. - */ - if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) { - if (zone->type == dns_zone_slave) { - dns_zone_log(zone, ISC_LOG_INFO, - "refresh: truncated UDP answer, " - "initiating TCP zone xfer " - "for master %s (source %s)", - master, source); - LOCK_ZONE(zone); - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR); - UNLOCK_ZONE(zone); - goto tcp_transfer; + /* + * If a db exists we will update it, otherwise we create a + * new one and attach it to the zone once we have the NS + * RRset and glue. + */ + ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); + if (zone->db != NULL) { + dns_db_attach(zone->db, &stub->db); + ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); } else { - INSIST(zone->type == dns_zone_stub); - if (dns_request_usedtcp(revent->request)) { - dns_zone_log(zone, ISC_LOG_INFO, - "refresh: truncated TCP response " - "from master %s (source %s)", - master, source); - goto next_master; + ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); + + INSIST(zone->db_argc >= 1); + result = dns_db_create(zone->mctx, zone->db_argv[0], + &zone->origin, dns_dbtype_stub, + zone->rdclass, + zone->db_argc - 1, + zone->db_argv + 1, + &stub->db); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "refreshing stub: " + "could not create " + "database: %s", + dns_result_totext(result)); + goto cleanup; } - LOCK_ZONE(zone); - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC); - UNLOCK_ZONE(zone); - goto same_master; + dns_db_settask(stub->db, zone->task); + } + + dns_db_newversion(stub->db, &stub->version); + + /* + * Update SOA record. + */ + result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE, + &node); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_INFO, + "refreshing stub: " + "dns_db_findnode() failed: %s", + dns_result_totext(result)); + goto cleanup; + } + + result = dns_db_addrdataset(stub->db, node, stub->version, 0, + soardataset, 0, NULL); + dns_db_detachnode(stub->db, &node); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_INFO, + "refreshing stub: " + "dns_db_addrdataset() failed: %s", + dns_result_totext(result)); + goto cleanup; } } /* - * if non-auth log and next master; + * XXX Optimisation: Create message when zone is setup and reuse. */ - if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) { - dns_zone_log(zone, ISC_LOG_INFO, - "refresh: non-authoritative answer from " - "master %s (source %s)", master, source); - goto next_master; - } + result = create_query(zone, dns_rdatatype_ns, &message); - cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname); - soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa); - nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns); - soacount = message_count(msg, DNS_SECTION_AUTHORITY, - dns_rdatatype_soa); + INSIST(zone->masterscnt > 0); + INSIST(zone->curmaster < zone->masterscnt); + zone->masteraddr = zone->masters[zone->curmaster]; + isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr); /* - * There should not be a CNAME record at top of zone. + * First, look for a tsig key in the master statement, then + * try for a server key. */ - if (cnamecnt != 0) { - dns_zone_log(zone, ISC_LOG_INFO, - "refresh: CNAME at top of zone " - "in master %s (source %s)", master, source); - goto next_master; + if ((zone->masterkeynames != NULL) && + (zone->masterkeynames[zone->curmaster] != NULL)) { + dns_view_t *view = dns_zone_getview(zone); + dns_name_t *keyname = zone->masterkeynames[zone->curmaster]; + result = dns_view_gettsig(view, keyname, &key); + if (result != ISC_R_SUCCESS) { + char namebuf[DNS_NAME_FORMATSIZE]; + dns_name_format(keyname, namebuf, sizeof(namebuf)); + dns_zone_log(zone, ISC_LOG_ERROR, + "unable to find key: %s", namebuf); + } } + if (key == NULL) + (void)dns_view_getpeertsig(zone->view, &masterip, &key); - /* - * if referral log and next master; - */ - if (soacnt == 0 && soacount == 0 && nscount != 0) { - dns_zone_log(zone, ISC_LOG_INFO, - "refresh: referral response " - "from master %s (source %s)", master, source); - goto next_master; - } + reqnsid = zone->view->requestnsid; + if (zone->view->peers != NULL) { + dns_peer_t *peer = NULL; + isc_boolean_t edns; + result = dns_peerlist_peerbyaddr(zone->view->peers, + &masterip, &peer); + if (result == ISC_R_SUCCESS) { + result = dns_peer_getsupportedns(peer, &edns); + if (result == ISC_R_SUCCESS && !edns) + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS); + result = dns_peer_gettransfersource(peer, + &zone->sourceaddr); + if (result == ISC_R_SUCCESS) + have_xfrsource = ISC_TRUE; + if (zone->view->resolver != NULL) + udpsize = + dns_resolver_getudpsize(zone->view->resolver); + (void)dns_peer_getudpsize(peer, &udpsize); + (void)dns_peer_getrequestnsid(peer, &reqnsid); + } - /* - * if nodata log and next master; - */ - if (soacnt == 0 && (nscount == 0 || soacount != 0)) { - dns_zone_log(zone, ISC_LOG_INFO, - "refresh: NODATA response " - "from master %s (source %s)", master, source); - goto next_master; + } + if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) { + result = add_opt(message, udpsize, reqnsid); + if (result != ISC_R_SUCCESS) + zone_debuglog(zone, me, 1, + "unable to add opt record: %s", + dns_result_totext(result)); } /* - * Only one soa at top of zone. + * Always use TCP so that we shouldn't truncate in additional section. */ - if (soacnt != 1) { - dns_zone_log(zone, ISC_LOG_INFO, - "refresh: answer SOA count (%d) != 1 " - "from master %s (source %s)", - soacnt, master, source); - goto next_master; + switch (isc_sockaddr_pf(&zone->masteraddr)) { + case PF_INET: + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) + zone->sourceaddr = zone->altxfrsource4; + else if (!have_xfrsource) + zone->sourceaddr = zone->xfrsource4; + break; + case PF_INET6: + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) + zone->sourceaddr = zone->altxfrsource6; + else if (!have_xfrsource) + zone->sourceaddr = zone->xfrsource6; + break; + default: + result = ISC_R_NOTIMPLEMENTED; + goto cleanup; } - /* - * Extract serial - */ - rdataset = NULL; - result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin, - dns_rdatatype_soa, dns_rdatatype_none, - NULL, &rdataset); + timeout = 15; + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) + timeout = 30; + result = dns_request_createvia2(zone->view->requestmgr, message, + &zone->sourceaddr, &zone->masteraddr, + DNS_REQUESTOPT_TCP, key, timeout * 3, + timeout, zone->task, stub_callback, + stub, &zone->request); if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_INFO, - "refresh: unable to get SOA record " - "from master %s (source %s)", master, source); - goto next_master; + zone_debuglog(zone, me, 1, + "dns_request_createvia() failed: %s", + dns_result_totext(result)); + goto cleanup; } + dns_message_destroy(&message); + goto unlock; - result = dns_rdataset_first(rdataset); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_INFO, - "refresh: dns_rdataset_first() failed"); - goto next_master; + cleanup: + cancel_refresh(zone); + if (stub != NULL) { + stub->magic = 0; + if (stub->version != NULL) + dns_db_closeversion(stub->db, &stub->version, + ISC_FALSE); + if (stub->db != NULL) + dns_db_detach(&stub->db); + if (stub->zone != NULL) + zone_idetach(&stub->zone); + isc_mem_put(stub->mctx, stub, sizeof(*stub)); } + if (message != NULL) + dns_message_destroy(&message); + unlock: + if (key != NULL) + dns_tsigkey_detach(&key); + UNLOCK_ZONE(zone); + return; +} - dns_rdataset_current(rdataset, &rdata); - result = dns_rdata_tostruct(&rdata, &soa, NULL); - RUNTIME_CHECK(result == ISC_R_SUCCESS); +/* + * Handle the control event. Note that although this event causes the zone + * to shut down, it is not a shutdown event in the sense of the task library. + */ +static void +zone_shutdown(isc_task_t *task, isc_event_t *event) { + dns_zone_t *zone = (dns_zone_t *) event->ev_arg; + isc_boolean_t free_needed, linked = ISC_FALSE; - serial = soa.serial; - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) { - result = dns_zone_getserial2(zone, &oldserial); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - zone_debuglog(zone, me, 1, "serial: new %u, old %u", - serial, oldserial); - } else - zone_debuglog(zone, me, 1, "serial: new %u, old not loaded", - serial); - if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) || - DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) || - isc_serial_gt(serial, oldserial)) { - if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr, - &zone->sourceaddr, &now)) { - dns_zone_log(zone, ISC_LOG_INFO, - "refresh: skipping %s as master %s " - "(source %s) is unreachable (cached)", - zone->type == dns_zone_slave ? - "zone transfer" : "NS query", - master, source); - goto next_master; - } - tcp_transfer: - isc_event_free(&event); - LOCK_ZONE(zone); - dns_request_destroy(&zone->request); - UNLOCK_ZONE(zone); - if (zone->type == dns_zone_slave) { - queue_xfrin(zone); - } else { - INSIST(zone->type == dns_zone_stub); - ns_query(zone, rdataset, NULL); - } - if (msg != NULL) - dns_message_destroy(&msg); - } else if (isc_serial_eq(soa.serial, oldserial)) { - if (zone->masterfile != NULL) { - result = ISC_R_FAILURE; - if (zone->journal != NULL) - result = isc_file_settime(zone->journal, &now); - if (result == ISC_R_SUCCESS && - !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) && - !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) { - result = isc_file_settime(zone->masterfile, - &now); - } else if (result != ISC_R_SUCCESS) - result = isc_file_settime(zone->masterfile, - &now); - /* Someone removed the file from underneath us! */ - if (result == ISC_R_FILENOTFOUND) { - LOCK_ZONE(zone); - zone_needdump(zone, DNS_DUMP_DELAY); - UNLOCK_ZONE(zone); - } else if (result != ISC_R_SUCCESS) - dns_zone_log(zone, ISC_LOG_ERROR, - "refresh: could not set file " - "modification time of '%s': %s", - zone->masterfile, - dns_result_totext(result)); - } - DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime); - DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime); - zone->mastersok[zone->curmaster] = ISC_TRUE; - goto next_master; - } else { - if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER)) - dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) " - "received from master %s < ours (%u)", - soa.serial, master, oldserial); - else - zone_debuglog(zone, me, 1, "ahead"); - zone->mastersok[zone->curmaster] = ISC_TRUE; - goto next_master; - } - if (msg != NULL) - dns_message_destroy(&msg); - goto detach; + UNUSED(task); + REQUIRE(DNS_ZONE_VALID(zone)); + INSIST(event->ev_type == DNS_EVENT_ZONECONTROL); + INSIST(isc_refcount_current(&zone->erefs) == 0); + zone_debuglog(zone, "zone_shutdown", 3, "shutting down"); - next_master: - if (msg != NULL) - dns_message_destroy(&msg); - isc_event_free(&event); - LOCK_ZONE(zone); - dns_request_destroy(&zone->request); /* - * Skip to next failed / untried master. + * Stop things being restarted after we cancel them below. */ - do { - zone->curmaster++; - } while (zone->curmaster < zone->masterscnt && - zone->mastersok[zone->curmaster]); - DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS); - if (zone->curmaster >= zone->masterscnt) { - isc_boolean_t done = ISC_TRUE; - if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) && - !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) { - /* - * Did we get a good answer from all the masters? - */ - for (j = 0; j < zone->masterscnt; j++) - if (zone->mastersok[j] == ISC_FALSE) { - done = ISC_FALSE; - break; - } - } else - done = ISC_TRUE; - if (!done) { - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC); - zone->curmaster = 0; - /* - * Find the next failed master. - */ - while (zone->curmaster < zone->masterscnt && - zone->mastersok[zone->curmaster]) - zone->curmaster++; - goto requeue; - } - DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH); - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) { - DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH); - zone->refreshtime = now; - } - DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC); - zone_settimer(zone, &now); - UNLOCK_ZONE(zone); - goto detach; - } - - requeue: - queue_soa_query(zone); - UNLOCK_ZONE(zone); - goto detach; - - same_master: - if (msg != NULL) - dns_message_destroy(&msg); - isc_event_free(&event); LOCK_ZONE(zone); - dns_request_destroy(&zone->request); - queue_soa_query(zone); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING); UNLOCK_ZONE(zone); - detach: - dns_zone_idetach(&zone); - return; -} - -static void -queue_soa_query(dns_zone_t *zone) { - const char me[] = "queue_soa_query"; - isc_event_t *e; - dns_zone_t *dummy = NULL; - isc_result_t result; + /* + * If we were waiting for xfrin quota, step out of + * the queue. + * If there's no zone manager, we can't be waiting for the + * xfrin quota + */ + if (zone->zmgr != NULL) { + RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write); + if (zone->statelist == &zone->zmgr->waiting_for_xfrin) { + ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone, + statelink); + linked = ISC_TRUE; + zone->statelist = NULL; + } + RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write); + } - ENTER; /* - * Locked by caller + * In task context, no locking required. See zone_xfrdone(). */ - REQUIRE(LOCKED_ZONE(zone)); + if (zone->xfr != NULL) + dns_xfrin_shutdown(zone->xfr); - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) { - cancel_refresh(zone); - return; + LOCK_ZONE(zone); + if (linked) { + INSIST(zone->irefs > 0); + zone->irefs--; } - - e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE, - soa_query, zone, sizeof(isc_event_t)); - if (e == NULL) { - cancel_refresh(zone); - return; + if (zone->request != NULL) { + dns_request_cancel(zone->request); } - /* - * Attach so that we won't clean up - * until the event is delivered. - */ - zone_iattach(zone, &dummy); + if (zone->readio != NULL) + zonemgr_cancelio(zone->readio); - e->ev_arg = zone; - e->ev_sender = NULL; - result = isc_ratelimiter_enqueue(zone->zmgr->rl, zone->task, &e); - if (result != ISC_R_SUCCESS) { - zone_idetach(&dummy); - isc_event_free(&e); - cancel_refresh(zone); - } -} + if (zone->lctx != NULL) + dns_loadctx_cancel(zone->lctx); -static inline isc_result_t -create_query(dns_zone_t *zone, dns_rdatatype_t rdtype, - dns_message_t **messagep) -{ - dns_message_t *message = NULL; - dns_name_t *qname = NULL; - dns_rdataset_t *qrdataset = NULL; - isc_result_t result; + if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) || + !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) { + if (zone->writeio != NULL) + zonemgr_cancelio(zone->writeio); - result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, - &message); - if (result != ISC_R_SUCCESS) - goto cleanup; + if (zone->dctx != NULL) + dns_dumpctx_cancel(zone->dctx); + } - message->opcode = dns_opcode_query; - message->rdclass = zone->rdclass; + notify_cancel(zone); - result = dns_message_gettempname(message, &qname); - if (result != ISC_R_SUCCESS) - goto cleanup; + if (zone->timer != NULL) { + isc_timer_detach(&zone->timer); + INSIST(zone->irefs > 0); + zone->irefs--; + } - result = dns_message_gettemprdataset(message, &qrdataset); - if (result != ISC_R_SUCCESS) - goto cleanup; + if (zone->view != NULL) + dns_view_weakdetach(&zone->view); /* - * Make question. + * We have now canceled everything set the flag to allow exit_check() + * to succeed. We must not unlock between setting this flag and + * calling exit_check(). */ - dns_name_init(qname, NULL); - dns_name_clone(&zone->origin, qname); - dns_rdataset_init(qrdataset); - dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype); - ISC_LIST_APPEND(qname->list, qrdataset, link); - dns_message_addname(message, qname, DNS_SECTION_QUESTION); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN); + free_needed = exit_check(zone); + UNLOCK_ZONE(zone); + if (free_needed) + zone_free(zone); +} - *messagep = message; - return (ISC_R_SUCCESS); +static void +zone_timer(isc_task_t *task, isc_event_t *event) { + const char me[] = "zone_timer"; + dns_zone_t *zone = (dns_zone_t *)event->ev_arg; - cleanup: - if (qname != NULL) - dns_message_puttempname(message, &qname); - if (qrdataset != NULL) - dns_message_puttemprdataset(message, &qrdataset); - if (message != NULL) - dns_message_destroy(&message); - return (result); + UNUSED(task); + REQUIRE(DNS_ZONE_VALID(zone)); + + ENTER; + + zone_maintenance(zone); + + isc_event_free(&event); } -static isc_result_t -add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) { - dns_rdataset_t *rdataset = NULL; - dns_rdatalist_t *rdatalist = NULL; - dns_rdata_t *rdata = NULL; +static void +zone_settimer(dns_zone_t *zone, isc_time_t *now) { + const char me[] = "zone_settimer"; + isc_time_t next; isc_result_t result; - result = dns_message_gettemprdatalist(message, &rdatalist); - if (result != ISC_R_SUCCESS) - goto cleanup; - result = dns_message_gettemprdata(message, &rdata); - if (result != ISC_R_SUCCESS) - goto cleanup; - result = dns_message_gettemprdataset(message, &rdataset); - if (result != ISC_R_SUCCESS) - goto cleanup; - dns_rdataset_init(rdataset); + ENTER; + REQUIRE(DNS_ZONE_VALID(zone)); + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) + return; - rdatalist->type = dns_rdatatype_opt; - rdatalist->covers = 0; + isc_time_settoepoch(&next); - /* - * Set Maximum UDP buffer size. - */ - rdatalist->rdclass = udpsize; + switch (zone->type) { + case dns_zone_master: + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY)) + next = zone->notifytime; + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) && + !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) { + INSIST(!isc_time_isepoch(&zone->dumptime)); + if (isc_time_isepoch(&next) || + isc_time_compare(&zone->dumptime, &next) < 0) + next = zone->dumptime; + } + if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) && + !isc_time_isepoch(&zone->refreshkeytime)) { + if (isc_time_isepoch(&next) || + isc_time_compare(&zone->refreshkeytime, &next) < 0) + next = zone->refreshkeytime; + } + if (!isc_time_isepoch(&zone->resigntime)) { + if (isc_time_isepoch(&next) || + isc_time_compare(&zone->resigntime, &next) < 0) + next = zone->resigntime; + } + if (!isc_time_isepoch(&zone->keywarntime)) { + if (isc_time_isepoch(&next) || + isc_time_compare(&zone->keywarntime, &next) < 0) + next = zone->keywarntime; + } + if (!isc_time_isepoch(&zone->signingtime)) { + if (isc_time_isepoch(&next) || + isc_time_compare(&zone->signingtime, &next) < 0) + next = zone->signingtime; + } + if (!isc_time_isepoch(&zone->nsec3chaintime)) { + if (isc_time_isepoch(&next) || + isc_time_compare(&zone->nsec3chaintime, &next) < 0) + next = zone->nsec3chaintime; + } + break; - /* - * Set EXTENDED-RCODE, VERSION, DO and Z to 0. - */ - rdatalist->ttl = 0; + case dns_zone_slave: + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY)) + next = zone->notifytime; + /*FALLTHROUGH*/ - /* Set EDNS options if applicable */ - if (reqnsid) { - unsigned char data[4]; - isc_buffer_t buf; + case dns_zone_stub: + if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) && + !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) && + !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) && + !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) { + INSIST(!isc_time_isepoch(&zone->refreshtime)); + if (isc_time_isepoch(&next) || + isc_time_compare(&zone->refreshtime, &next) < 0) + next = zone->refreshtime; + } + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) { + INSIST(!isc_time_isepoch(&zone->expiretime)); + if (isc_time_isepoch(&next) || + isc_time_compare(&zone->expiretime, &next) < 0) + next = zone->expiretime; + } + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) && + !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) { + INSIST(!isc_time_isepoch(&zone->dumptime)); + if (isc_time_isepoch(&next) || + isc_time_compare(&zone->dumptime, &next) < 0) + next = zone->dumptime; + } + break; - isc_buffer_init(&buf, data, sizeof(data)); - isc_buffer_putuint16(&buf, DNS_OPT_NSID); - isc_buffer_putuint16(&buf, 0); - rdata->data = data; - rdata->length = sizeof(data); + case dns_zone_key: + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) && + !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) { + INSIST(!isc_time_isepoch(&zone->dumptime)); + if (isc_time_isepoch(&next) || + isc_time_compare(&zone->dumptime, &next) < 0) + next = zone->dumptime; + } + if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) { + if (isc_time_isepoch(&next) || + (!isc_time_isepoch(&zone->refreshkeytime) && + isc_time_compare(&zone->refreshkeytime, &next) < 0)) + next = zone->refreshkeytime; + } + break; + + default: + break; + } + + if (isc_time_isepoch(&next)) { + zone_debuglog(zone, me, 10, "settimer inactive"); + result = isc_timer_reset(zone->timer, isc_timertype_inactive, + NULL, NULL, ISC_TRUE); + if (result != ISC_R_SUCCESS) + dns_zone_log(zone, ISC_LOG_ERROR, + "could not deactivate zone timer: %s", + isc_result_totext(result)); } else { - rdata->data = NULL; - rdata->length = 0; + if (isc_time_compare(&next, now) <= 0) + next = *now; + result = isc_timer_reset(zone->timer, isc_timertype_once, + &next, NULL, ISC_TRUE); + if (result != ISC_R_SUCCESS) + dns_zone_log(zone, ISC_LOG_ERROR, + "could not reset zone timer: %s", + isc_result_totext(result)); } +} - rdata->rdclass = rdatalist->rdclass; - rdata->type = rdatalist->type; - rdata->flags = 0; +static void +cancel_refresh(dns_zone_t *zone) { + const char me[] = "cancel_refresh"; + isc_time_t now; - ISC_LIST_INIT(rdatalist->rdata); - ISC_LIST_APPEND(rdatalist->rdata, rdata, link); - RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) - == ISC_R_SUCCESS); + /* + * 'zone' locked by caller. + */ - return (dns_message_setopt(message, rdataset)); + REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(LOCKED_ZONE(zone)); - cleanup: - if (rdatalist != NULL) - dns_message_puttemprdatalist(message, &rdatalist); - if (rdataset != NULL) - dns_message_puttemprdataset(message, &rdataset); - if (rdata != NULL) - dns_message_puttemprdata(message, &rdata); + ENTER; - return (result); + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH); + TIME_NOW(&now); + zone_settimer(zone, &now); } -static void -soa_query(isc_task_t *task, isc_event_t *event) { - const char me[] = "soa_query"; - isc_result_t result = ISC_R_FAILURE; +static isc_result_t +notify_createmessage(dns_zone_t *zone, unsigned int flags, + dns_message_t **messagep) +{ + dns_db_t *zonedb = NULL; + dns_dbnode_t *node = NULL; + dns_dbversion_t *version = NULL; dns_message_t *message = NULL; - dns_zone_t *zone = event->ev_arg; - dns_zone_t *dummy = NULL; - isc_netaddr_t masterip; - dns_tsigkey_t *key = NULL; - isc_uint32_t options; - isc_boolean_t cancel = ISC_TRUE; - int timeout; - isc_boolean_t have_xfrsource, reqnsid; - isc_uint16_t udpsize = SEND_BUFFER_SIZE; + dns_rdataset_t rdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + + dns_name_t *tempname = NULL; + dns_rdata_t *temprdata = NULL; + dns_rdatalist_t *temprdatalist = NULL; + dns_rdataset_t *temprdataset = NULL; + + isc_result_t result; + isc_region_t r; + isc_buffer_t *b = NULL; REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(messagep != NULL && *messagep == NULL); - UNUSED(task); + result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, + &message); + if (result != ISC_R_SUCCESS) + return (result); - ENTER; + message->opcode = dns_opcode_notify; + message->flags |= DNS_MESSAGEFLAG_AA; + message->rdclass = zone->rdclass; - LOCK_ZONE(zone); - if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) || - DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || - zone->view->requestmgr == NULL) { - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) - cancel = ISC_FALSE; + result = dns_message_gettempname(message, &tempname); + if (result != ISC_R_SUCCESS) goto cleanup; - } - /* - * XXX Optimisation: Create message when zone is setup and reuse. - */ - result = create_query(zone, dns_rdatatype_soa, &message); + result = dns_message_gettemprdataset(message, &temprdataset); if (result != ISC_R_SUCCESS) goto cleanup; - again: - INSIST(zone->masterscnt > 0); - INSIST(zone->curmaster < zone->masterscnt); - - zone->masteraddr = zone->masters[zone->curmaster]; - - isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr); /* - * First, look for a tsig key in the master statement, then - * try for a server key. + * Make question. */ - if ((zone->masterkeynames != NULL) && - (zone->masterkeynames[zone->curmaster] != NULL)) { - dns_view_t *view = dns_zone_getview(zone); - dns_name_t *keyname = zone->masterkeynames[zone->curmaster]; - result = dns_view_gettsig(view, keyname, &key); - if (result != ISC_R_SUCCESS) { - char namebuf[DNS_NAME_FORMATSIZE]; - dns_name_format(keyname, namebuf, sizeof(namebuf)); - dns_zone_log(zone, ISC_LOG_ERROR, - "unable to find key: %s", namebuf); - goto skip_master; - } - } - if (key == NULL) { - result = dns_view_getpeertsig(zone->view, &masterip, &key); - if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) { - char addrbuf[ISC_NETADDR_FORMATSIZE]; - isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf)); - dns_zone_log(zone, ISC_LOG_ERROR, - "unable to find TSIG key for %s", addrbuf); - goto skip_master; - } - } + dns_name_init(tempname, NULL); + dns_name_clone(&zone->origin, tempname); + dns_rdataset_init(temprdataset); + dns_rdataset_makequestion(temprdataset, zone->rdclass, + dns_rdatatype_soa); + ISC_LIST_APPEND(tempname->list, temprdataset, link); + dns_message_addname(message, tempname, DNS_SECTION_QUESTION); + tempname = NULL; + temprdataset = NULL; - have_xfrsource = ISC_FALSE; - reqnsid = zone->view->requestnsid; - if (zone->view->peers != NULL) { - dns_peer_t *peer = NULL; - isc_boolean_t edns; - result = dns_peerlist_peerbyaddr(zone->view->peers, - &masterip, &peer); - if (result == ISC_R_SUCCESS) { - result = dns_peer_getsupportedns(peer, &edns); - if (result == ISC_R_SUCCESS && !edns) - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS); - result = dns_peer_gettransfersource(peer, - &zone->sourceaddr); - if (result == ISC_R_SUCCESS) - have_xfrsource = ISC_TRUE; - if (zone->view->resolver != NULL) - udpsize = - dns_resolver_getudpsize(zone->view->resolver); - (void)dns_peer_getudpsize(peer, &udpsize); - (void)dns_peer_getrequestnsid(peer, &reqnsid); - } - } + if ((flags & DNS_NOTIFY_NOSOA) != 0) + goto done; - switch (isc_sockaddr_pf(&zone->masteraddr)) { - case PF_INET: - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) { - if (isc_sockaddr_equal(&zone->altxfrsource4, - &zone->xfrsource4)) - goto skip_master; - zone->sourceaddr = zone->altxfrsource4; - } else if (!have_xfrsource) - zone->sourceaddr = zone->xfrsource4; - break; - case PF_INET6: - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) { - if (isc_sockaddr_equal(&zone->altxfrsource6, - &zone->xfrsource6)) - goto skip_master; - zone->sourceaddr = zone->altxfrsource6; - } else if (!have_xfrsource) - zone->sourceaddr = zone->xfrsource6; - break; - default: - result = ISC_R_NOTIMPLEMENTED; - goto cleanup; - } + result = dns_message_gettempname(message, &tempname); + if (result != ISC_R_SUCCESS) + goto soa_cleanup; + result = dns_message_gettemprdata(message, &temprdata); + if (result != ISC_R_SUCCESS) + goto soa_cleanup; + result = dns_message_gettemprdataset(message, &temprdataset); + if (result != ISC_R_SUCCESS) + goto soa_cleanup; + result = dns_message_gettemprdatalist(message, &temprdatalist); + if (result != ISC_R_SUCCESS) + goto soa_cleanup; - options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ? - DNS_REQUESTOPT_TCP : 0; + ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); + INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */ + dns_db_attach(zone->db, &zonedb); + ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); - if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) { - result = add_opt(message, udpsize, reqnsid); - if (result != ISC_R_SUCCESS) - zone_debuglog(zone, me, 1, - "unable to add opt record: %s", - dns_result_totext(result)); - } + dns_name_init(tempname, NULL); + dns_name_clone(&zone->origin, tempname); + dns_db_currentversion(zonedb, &version); + result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node); + if (result != ISC_R_SUCCESS) + goto soa_cleanup; + + dns_rdataset_init(&rdataset); + result = dns_db_findrdataset(zonedb, node, version, + dns_rdatatype_soa, + dns_rdatatype_none, 0, &rdataset, + NULL); + if (result != ISC_R_SUCCESS) + goto soa_cleanup; + result = dns_rdataset_first(&rdataset); + if (result != ISC_R_SUCCESS) + goto soa_cleanup; + dns_rdataset_current(&rdataset, &rdata); + dns_rdata_toregion(&rdata, &r); + result = isc_buffer_allocate(zone->mctx, &b, r.length); + if (result != ISC_R_SUCCESS) + goto soa_cleanup; + isc_buffer_putmem(b, r.base, r.length); + isc_buffer_usedregion(b, &r); + dns_rdata_init(temprdata); + dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r); + dns_message_takebuffer(message, &b); + result = dns_rdataset_next(&rdataset); + dns_rdataset_disassociate(&rdataset); + if (result != ISC_R_NOMORE) + goto soa_cleanup; + temprdatalist->rdclass = rdata.rdclass; + temprdatalist->type = rdata.type; + temprdatalist->covers = 0; + temprdatalist->ttl = rdataset.ttl; + ISC_LIST_INIT(temprdatalist->rdata); + ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link); + + dns_rdataset_init(temprdataset); + result = dns_rdatalist_tordataset(temprdatalist, temprdataset); + if (result != ISC_R_SUCCESS) + goto soa_cleanup; + + ISC_LIST_APPEND(tempname->list, temprdataset, link); + dns_message_addname(message, tempname, DNS_SECTION_ANSWER); + temprdatalist = NULL; + temprdataset = NULL; + temprdata = NULL; + tempname = NULL; + + soa_cleanup: + if (node != NULL) + dns_db_detachnode(zonedb, &node); + if (version != NULL) + dns_db_closeversion(zonedb, &version, ISC_FALSE); + if (zonedb != NULL) + dns_db_detach(&zonedb); + if (tempname != NULL) + dns_message_puttempname(message, &tempname); + if (temprdata != NULL) + dns_message_puttemprdata(message, &temprdata); + if (temprdataset != NULL) + dns_message_puttemprdataset(message, &temprdataset); + if (temprdatalist != NULL) + dns_message_puttemprdatalist(message, &temprdatalist); - zone_iattach(zone, &dummy); - timeout = 15; - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) - timeout = 30; - result = dns_request_createvia2(zone->view->requestmgr, message, - &zone->sourceaddr, &zone->masteraddr, - options, key, timeout * 3, timeout, - zone->task, refresh_callback, zone, - &zone->request); - if (result != ISC_R_SUCCESS) { - zone_idetach(&dummy); - zone_debuglog(zone, me, 1, - "dns_request_createvia2() failed: %s", - dns_result_totext(result)); - goto cleanup; - } else { - if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET) - inc_stats(zone, dns_zonestatscounter_soaoutv4); - else - inc_stats(zone, dns_zonestatscounter_soaoutv6); - } - cancel = ISC_FALSE; + done: + *messagep = message; + return (ISC_R_SUCCESS); cleanup: - if (key != NULL) - dns_tsigkey_detach(&key); - if (result != ISC_R_SUCCESS) - DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH); - if (message != NULL) - dns_message_destroy(&message); - if (cancel) - cancel_refresh(zone); - isc_event_free(&event); - UNLOCK_ZONE(zone); - dns_zone_idetach(&zone); - return; - - skip_master: - if (key != NULL) - dns_tsigkey_detach(&key); - /* - * Skip to next failed / untried master. - */ - do { - zone->curmaster++; - } while (zone->curmaster < zone->masterscnt && - zone->mastersok[zone->curmaster]); - if (zone->curmaster < zone->masterscnt) - goto again; - zone->curmaster = 0; - goto cleanup; + if (tempname != NULL) + dns_message_puttempname(message, &tempname); + if (temprdataset != NULL) + dns_message_puttemprdataset(message, &temprdataset); + dns_message_destroy(&message); + return (result); } -static void -ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) { - const char me[] = "ns_query"; +isc_result_t +dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from, + dns_message_t *msg) +{ + unsigned int i; + dns_rdata_soa_t soa; + dns_rdataset_t *rdataset = NULL; + dns_rdata_t rdata = DNS_RDATA_INIT; isc_result_t result; - dns_message_t *message = NULL; - isc_netaddr_t masterip; - dns_tsigkey_t *key = NULL; - dns_dbnode_t *node = NULL; - int timeout; - isc_boolean_t have_xfrsource = ISC_FALSE, reqnsid; - isc_uint16_t udpsize = SEND_BUFFER_SIZE; + char fromtext[ISC_SOCKADDR_FORMATSIZE]; + int match = 0; + isc_netaddr_t netaddr; REQUIRE(DNS_ZONE_VALID(zone)); - REQUIRE((soardataset != NULL && stub == NULL) || - (soardataset == NULL && stub != NULL)); - REQUIRE(stub == NULL || DNS_STUB_VALID(stub)); - ENTER; + /* + * If type != T_SOA return DNS_R_NOTIMP. We don't yet support + * ROLLOVER. + * + * SOA: RFC1996 + * Check that 'from' is a valid notify source, (zone->masters). + * Return DNS_R_REFUSED if not. + * + * If the notify message contains a serial number check it + * against the zones serial and return if <= current serial + * + * If a refresh check is progress, if so just record the + * fact we received a NOTIFY and from where and return. + * We will perform a new refresh check when the current one + * completes. Return ISC_R_SUCCESS. + * + * Otherwise initiate a refresh check using 'from' as the + * first address to check. Return ISC_R_SUCCESS. + */ - LOCK_ZONE(zone); - if (stub == NULL) { - stub = isc_mem_get(zone->mctx, sizeof(*stub)); - if (stub == NULL) - goto cleanup; - stub->magic = STUB_MAGIC; - stub->mctx = zone->mctx; - stub->zone = NULL; - stub->db = NULL; - stub->version = NULL; + isc_sockaddr_format(from, fromtext, sizeof(fromtext)); - /* - * Attach so that the zone won't disappear from under us. - */ - zone_iattach(zone, &stub->zone); + /* + * We only handle NOTIFY (SOA) at the present. + */ + LOCK_ZONE(zone); + if (isc_sockaddr_pf(from) == PF_INET) + inc_stats(zone, dns_zonestatscounter_notifyinv4); + else + inc_stats(zone, dns_zonestatscounter_notifyinv6); + if (msg->counts[DNS_SECTION_QUESTION] == 0 || + dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin, + dns_rdatatype_soa, dns_rdatatype_none, + NULL, NULL) != ISC_R_SUCCESS) { + UNLOCK_ZONE(zone); + if (msg->counts[DNS_SECTION_QUESTION] == 0) { + dns_zone_log(zone, ISC_LOG_NOTICE, + "NOTIFY with no " + "question section from: %s", fromtext); + return (DNS_R_FORMERR); + } + dns_zone_log(zone, ISC_LOG_NOTICE, + "NOTIFY zone does not match"); + return (DNS_R_NOTIMP); + } - /* - * If a db exists we will update it, otherwise we create a - * new one and attach it to the zone once we have the NS - * RRset and glue. - */ - ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); - if (zone->db != NULL) { - dns_db_attach(zone->db, &stub->db); - ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); - } else { - ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); + /* + * If we are a master zone just succeed. + */ + if (zone->type == dns_zone_master) { + UNLOCK_ZONE(zone); + return (ISC_R_SUCCESS); + } - INSIST(zone->db_argc >= 1); - result = dns_db_create(zone->mctx, zone->db_argv[0], - &zone->origin, dns_dbtype_stub, - zone->rdclass, - zone->db_argc - 1, - zone->db_argv + 1, - &stub->db); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, - "refreshing stub: " - "could not create " - "database: %s", - dns_result_totext(result)); - goto cleanup; - } - dns_db_settask(stub->db, zone->task); + isc_netaddr_fromsockaddr(&netaddr, from); + for (i = 0; i < zone->masterscnt; i++) { + if (isc_sockaddr_eqaddr(from, &zone->masters[i])) + break; + if (zone->view->aclenv.match_mapped && + IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) && + isc_sockaddr_pf(&zone->masters[i]) == AF_INET) { + isc_netaddr_t na1, na2; + isc_netaddr_fromv4mapped(&na1, &netaddr); + isc_netaddr_fromsockaddr(&na2, &zone->masters[i]); + if (isc_netaddr_equal(&na1, &na2)) + break; } + } - dns_db_newversion(stub->db, &stub->version); + /* + * Accept notify requests from non masters if they are on + * 'zone->notify_acl'. + */ + if (i >= zone->masterscnt && zone->notify_acl != NULL && + dns_acl_match(&netaddr, NULL, zone->notify_acl, + &zone->view->aclenv, + &match, NULL) == ISC_R_SUCCESS && + match > 0) + { + /* Accept notify. */ + } else if (i >= zone->masterscnt) { + UNLOCK_ZONE(zone); + dns_zone_log(zone, ISC_LOG_INFO, + "refused notify from non-master: %s", fromtext); + inc_stats(zone, dns_zonestatscounter_notifyrej); + return (DNS_R_REFUSED); + } - /* - * Update SOA record. - */ - result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE, - &node); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_INFO, - "refreshing stub: " - "dns_db_findnode() failed: %s", - dns_result_totext(result)); - goto cleanup; - } + /* + * If the zone is loaded and there are answers check the serial + * to see if we need to do a refresh. Do not worry about this + * check if we are a dialup zone as we use the notify request + * to trigger a refresh check. + */ + if (msg->counts[DNS_SECTION_ANSWER] > 0 && + DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) && + !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) { + result = dns_message_findname(msg, DNS_SECTION_ANSWER, + &zone->origin, + dns_rdatatype_soa, + dns_rdatatype_none, NULL, + &rdataset); + if (result == ISC_R_SUCCESS) + result = dns_rdataset_first(rdataset); + if (result == ISC_R_SUCCESS) { + isc_uint32_t serial = 0, oldserial; - result = dns_db_addrdataset(stub->db, node, stub->version, 0, - soardataset, 0, NULL); - dns_db_detachnode(stub->db, &node); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_INFO, - "refreshing stub: " - "dns_db_addrdataset() failed: %s", - dns_result_totext(result)); - goto cleanup; + dns_rdataset_current(rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &soa, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + serial = soa.serial; + /* + * The following should safely be performed without DB + * lock and succeed in this context. + */ + result = zone_get_from_db(zone, zone->db, NULL, NULL, + &oldserial, NULL, NULL, NULL, + NULL, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + if (isc_serial_le(serial, oldserial)) { + dns_zone_log(zone, + ISC_LOG_INFO, + "notify from %s: " + "zone is up to date", + fromtext); + UNLOCK_ZONE(zone); + return (ISC_R_SUCCESS); + } } } /* - * XXX Optimisation: Create message when zone is setup and reuse. + * If we got this far and there was a refresh in progress just + * let it complete. Record where we got the notify from so we + * can perform a refresh check when the current one completes */ - result = create_query(zone, dns_rdatatype_ns, &message); + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) { + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH); + zone->notifyfrom = *from; + UNLOCK_ZONE(zone); + dns_zone_log(zone, ISC_LOG_INFO, + "notify from %s: refresh in progress, " + "refresh check queued", + fromtext); + return (ISC_R_SUCCESS); + } + zone->notifyfrom = *from; + UNLOCK_ZONE(zone); + dns_zone_refresh(zone); + return (ISC_R_SUCCESS); +} - INSIST(zone->masterscnt > 0); - INSIST(zone->curmaster < zone->masterscnt); - zone->masteraddr = zone->masters[zone->curmaster]; +void +dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) { - isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr); - /* - * First, look for a tsig key in the master statement, then - * try for a server key. - */ - if ((zone->masterkeynames != NULL) && - (zone->masterkeynames[zone->curmaster] != NULL)) { - dns_view_t *view = dns_zone_getview(zone); - dns_name_t *keyname = zone->masterkeynames[zone->curmaster]; - result = dns_view_gettsig(view, keyname, &key); - if (result != ISC_R_SUCCESS) { - char namebuf[DNS_NAME_FORMATSIZE]; - dns_name_format(keyname, namebuf, sizeof(namebuf)); - dns_zone_log(zone, ISC_LOG_ERROR, - "unable to find key: %s", namebuf); - } - } - if (key == NULL) - (void)dns_view_getpeertsig(zone->view, &masterip, &key); + REQUIRE(DNS_ZONE_VALID(zone)); - reqnsid = zone->view->requestnsid; - if (zone->view->peers != NULL) { - dns_peer_t *peer = NULL; - isc_boolean_t edns; - result = dns_peerlist_peerbyaddr(zone->view->peers, - &masterip, &peer); - if (result == ISC_R_SUCCESS) { - result = dns_peer_getsupportedns(peer, &edns); - if (result == ISC_R_SUCCESS && !edns) - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS); - result = dns_peer_gettransfersource(peer, - &zone->sourceaddr); - if (result == ISC_R_SUCCESS) - have_xfrsource = ISC_TRUE; - if (zone->view->resolver != NULL) - udpsize = - dns_resolver_getudpsize(zone->view->resolver); - (void)dns_peer_getudpsize(peer, &udpsize); - (void)dns_peer_getrequestnsid(peer, &reqnsid); - } + LOCK_ZONE(zone); + if (zone->notify_acl != NULL) + dns_acl_detach(&zone->notify_acl); + dns_acl_attach(acl, &zone->notify_acl); + UNLOCK_ZONE(zone); +} - } - if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) { - result = add_opt(message, udpsize, reqnsid); - if (result != ISC_R_SUCCESS) - zone_debuglog(zone, me, 1, - "unable to add opt record: %s", - dns_result_totext(result)); - } +void +dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) { - /* - * Always use TCP so that we shouldn't truncate in additional section. - */ - switch (isc_sockaddr_pf(&zone->masteraddr)) { - case PF_INET: - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) - zone->sourceaddr = zone->altxfrsource4; - else if (!have_xfrsource) - zone->sourceaddr = zone->xfrsource4; - break; - case PF_INET6: - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) - zone->sourceaddr = zone->altxfrsource6; - else if (!have_xfrsource) - zone->sourceaddr = zone->xfrsource6; - break; - default: - result = ISC_R_NOTIMPLEMENTED; - goto cleanup; - } - timeout = 15; - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) - timeout = 30; - result = dns_request_createvia2(zone->view->requestmgr, message, - &zone->sourceaddr, &zone->masteraddr, - DNS_REQUESTOPT_TCP, key, timeout * 3, - timeout, zone->task, stub_callback, - stub, &zone->request); - if (result != ISC_R_SUCCESS) { - zone_debuglog(zone, me, 1, - "dns_request_createvia() failed: %s", - dns_result_totext(result)); - goto cleanup; - } - dns_message_destroy(&message); - goto unlock; + REQUIRE(DNS_ZONE_VALID(zone)); - cleanup: - cancel_refresh(zone); - if (stub != NULL) { - stub->magic = 0; - if (stub->version != NULL) - dns_db_closeversion(stub->db, &stub->version, - ISC_FALSE); - if (stub->db != NULL) - dns_db_detach(&stub->db); - if (stub->zone != NULL) - zone_idetach(&stub->zone); - isc_mem_put(stub->mctx, stub, sizeof(*stub)); - } - if (message != NULL) - dns_message_destroy(&message); - unlock: - if (key != NULL) - dns_tsigkey_detach(&key); + LOCK_ZONE(zone); + if (zone->query_acl != NULL) + dns_acl_detach(&zone->query_acl); + dns_acl_attach(acl, &zone->query_acl); UNLOCK_ZONE(zone); - return; } -/* - * Handle the control event. Note that although this event causes the zone - * to shut down, it is not a shutdown event in the sense of the task library. - */ -static void -zone_shutdown(isc_task_t *task, isc_event_t *event) { - dns_zone_t *zone = (dns_zone_t *) event->ev_arg; - isc_boolean_t free_needed, linked = ISC_FALSE; +void +dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) { - UNUSED(task); REQUIRE(DNS_ZONE_VALID(zone)); - INSIST(event->ev_type == DNS_EVENT_ZONECONTROL); - INSIST(isc_refcount_current(&zone->erefs) == 0); - zone_debuglog(zone, "zone_shutdown", 3, "shutting down"); - /* - * Stop things being restarted after we cancel them below. - */ LOCK_ZONE(zone); - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING); + if (zone->queryon_acl != NULL) + dns_acl_detach(&zone->queryon_acl); + dns_acl_attach(acl, &zone->queryon_acl); UNLOCK_ZONE(zone); +} - /* - * If we were waiting for xfrin quota, step out of - * the queue. - * If there's no zone manager, we can't be waiting for the - * xfrin quota - */ - if (zone->zmgr != NULL) { - RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write); - if (zone->statelist == &zone->zmgr->waiting_for_xfrin) { - ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone, - statelink); - linked = ISC_TRUE; - zone->statelist = NULL; - } - RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write); - } +void +dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) { - /* - * In task context, no locking required. See zone_xfrdone(). - */ - if (zone->xfr != NULL) - dns_xfrin_shutdown(zone->xfr); + REQUIRE(DNS_ZONE_VALID(zone)); LOCK_ZONE(zone); - if (linked) { - INSIST(zone->irefs > 0); - zone->irefs--; - } - if (zone->request != NULL) { - dns_request_cancel(zone->request); - } + if (zone->update_acl != NULL) + dns_acl_detach(&zone->update_acl); + dns_acl_attach(acl, &zone->update_acl); + UNLOCK_ZONE(zone); +} - if (zone->readio != NULL) - zonemgr_cancelio(zone->readio); +void +dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) { - if (zone->lctx != NULL) - dns_loadctx_cancel(zone->lctx); + REQUIRE(DNS_ZONE_VALID(zone)); - if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) || - !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) { - if (zone->writeio != NULL) - zonemgr_cancelio(zone->writeio); + LOCK_ZONE(zone); + if (zone->forward_acl != NULL) + dns_acl_detach(&zone->forward_acl); + dns_acl_attach(acl, &zone->forward_acl); + UNLOCK_ZONE(zone); +} - if (zone->dctx != NULL) - dns_dumpctx_cancel(zone->dctx); - } +void +dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) { - notify_cancel(zone); + REQUIRE(DNS_ZONE_VALID(zone)); - if (zone->timer != NULL) { - isc_timer_detach(&zone->timer); - INSIST(zone->irefs > 0); - zone->irefs--; - } + LOCK_ZONE(zone); + if (zone->xfr_acl != NULL) + dns_acl_detach(&zone->xfr_acl); + dns_acl_attach(acl, &zone->xfr_acl); + UNLOCK_ZONE(zone); +} - if (zone->view != NULL) - dns_view_weakdetach(&zone->view); +dns_acl_t * +dns_zone_getnotifyacl(dns_zone_t *zone) { - /* - * We have now canceled everything set the flag to allow exit_check() - * to succeed. We must not unlock between setting this flag and - * calling exit_check(). - */ - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN); - free_needed = exit_check(zone); - UNLOCK_ZONE(zone); - if (free_needed) - zone_free(zone); + REQUIRE(DNS_ZONE_VALID(zone)); + + return (zone->notify_acl); } -static void -zone_timer(isc_task_t *task, isc_event_t *event) { - const char me[] = "zone_timer"; - dns_zone_t *zone = (dns_zone_t *)event->ev_arg; +dns_acl_t * +dns_zone_getqueryacl(dns_zone_t *zone) { - UNUSED(task); REQUIRE(DNS_ZONE_VALID(zone)); - ENTER; + return (zone->query_acl); +} - zone_maintenance(zone); +dns_acl_t * +dns_zone_getqueryonacl(dns_zone_t *zone) { - isc_event_free(&event); + REQUIRE(DNS_ZONE_VALID(zone)); + + return (zone->queryon_acl); } -static void -zone_settimer(dns_zone_t *zone, isc_time_t *now) { - const char me[] = "zone_settimer"; - isc_time_t next; - isc_result_t result; +dns_acl_t * +dns_zone_getupdateacl(dns_zone_t *zone) { REQUIRE(DNS_ZONE_VALID(zone)); - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) - return; - isc_time_settoepoch(&next); + return (zone->update_acl); +} - switch (zone->type) { - case dns_zone_master: - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY)) - next = zone->notifytime; - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) && - !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) { - INSIST(!isc_time_isepoch(&zone->dumptime)); - if (isc_time_isepoch(&next) || - isc_time_compare(&zone->dumptime, &next) < 0) - next = zone->dumptime; - } - if (!isc_time_isepoch(&zone->resigntime)) { - if (isc_time_isepoch(&next) || - isc_time_compare(&zone->resigntime, &next) < 0) - next = zone->resigntime; - } - if (!isc_time_isepoch(&zone->keywarntime)) { - if (isc_time_isepoch(&next) || - isc_time_compare(&zone->keywarntime, &next) < 0) - next = zone->keywarntime; - } - if (!isc_time_isepoch(&zone->signingtime)) { - if (isc_time_isepoch(&next) || - isc_time_compare(&zone->signingtime, &next) < 0) - next = zone->signingtime; - } - if (!isc_time_isepoch(&zone->nsec3chaintime)) { - if (isc_time_isepoch(&next) || - isc_time_compare(&zone->nsec3chaintime, &next) < 0) - next = zone->nsec3chaintime; - } - break; +dns_acl_t * +dns_zone_getforwardacl(dns_zone_t *zone) { - case dns_zone_slave: - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY)) - next = zone->notifytime; - /*FALLTHROUGH*/ + REQUIRE(DNS_ZONE_VALID(zone)); - case dns_zone_stub: - if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) && - !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) && - !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) && - !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) { - INSIST(!isc_time_isepoch(&zone->refreshtime)); - if (isc_time_isepoch(&next) || - isc_time_compare(&zone->refreshtime, &next) < 0) - next = zone->refreshtime; - } - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) { - INSIST(!isc_time_isepoch(&zone->expiretime)); - if (isc_time_isepoch(&next) || - isc_time_compare(&zone->expiretime, &next) < 0) - next = zone->expiretime; - } - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) && - !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) { - INSIST(!isc_time_isepoch(&zone->dumptime)); - if (isc_time_isepoch(&next) || - isc_time_compare(&zone->dumptime, &next) < 0) - next = zone->dumptime; - } - break; + return (zone->forward_acl); +} - default: - break; - } +dns_acl_t * +dns_zone_getxfracl(dns_zone_t *zone) { - if (isc_time_isepoch(&next)) { - zone_debuglog(zone, me, 10, "settimer inactive"); - result = isc_timer_reset(zone->timer, isc_timertype_inactive, - NULL, NULL, ISC_TRUE); - if (result != ISC_R_SUCCESS) - dns_zone_log(zone, ISC_LOG_ERROR, - "could not deactivate zone timer: %s", - isc_result_totext(result)); - } else { - if (isc_time_compare(&next, now) <= 0) - next = *now; - result = isc_timer_reset(zone->timer, isc_timertype_once, - &next, NULL, ISC_TRUE); - if (result != ISC_R_SUCCESS) - dns_zone_log(zone, ISC_LOG_ERROR, - "could not reset zone timer: %s", - isc_result_totext(result)); - } + REQUIRE(DNS_ZONE_VALID(zone)); + + return (zone->xfr_acl); } -static void -cancel_refresh(dns_zone_t *zone) { - const char me[] = "cancel_refresh"; - isc_time_t now; +void +dns_zone_clearupdateacl(dns_zone_t *zone) { - /* - * 'zone' locked by caller. - */ + REQUIRE(DNS_ZONE_VALID(zone)); + + LOCK_ZONE(zone); + if (zone->update_acl != NULL) + dns_acl_detach(&zone->update_acl); + UNLOCK_ZONE(zone); +} + +void +dns_zone_clearforwardacl(dns_zone_t *zone) { REQUIRE(DNS_ZONE_VALID(zone)); - REQUIRE(LOCKED_ZONE(zone)); - ENTER; + LOCK_ZONE(zone); + if (zone->forward_acl != NULL) + dns_acl_detach(&zone->forward_acl); + UNLOCK_ZONE(zone); +} - DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH); - TIME_NOW(&now); - zone_settimer(zone, &now); +void +dns_zone_clearnotifyacl(dns_zone_t *zone) { + + REQUIRE(DNS_ZONE_VALID(zone)); + + LOCK_ZONE(zone); + if (zone->notify_acl != NULL) + dns_acl_detach(&zone->notify_acl); + UNLOCK_ZONE(zone); } -static isc_result_t -notify_createmessage(dns_zone_t *zone, unsigned int flags, - dns_message_t **messagep) -{ - dns_db_t *zonedb = NULL; - dns_dbnode_t *node = NULL; - dns_dbversion_t *version = NULL; - dns_message_t *message = NULL; - dns_rdataset_t rdataset; - dns_rdata_t rdata = DNS_RDATA_INIT; +void +dns_zone_clearqueryacl(dns_zone_t *zone) { - dns_name_t *tempname = NULL; - dns_rdata_t *temprdata = NULL; - dns_rdatalist_t *temprdatalist = NULL; - dns_rdataset_t *temprdataset = NULL; + REQUIRE(DNS_ZONE_VALID(zone)); - isc_result_t result; - isc_region_t r; - isc_buffer_t *b = NULL; + LOCK_ZONE(zone); + if (zone->query_acl != NULL) + dns_acl_detach(&zone->query_acl); + UNLOCK_ZONE(zone); +} + +void +dns_zone_clearqueryonacl(dns_zone_t *zone) { REQUIRE(DNS_ZONE_VALID(zone)); - REQUIRE(messagep != NULL && *messagep == NULL); - result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, - &message); - if (result != ISC_R_SUCCESS) - return (result); + LOCK_ZONE(zone); + if (zone->queryon_acl != NULL) + dns_acl_detach(&zone->queryon_acl); + UNLOCK_ZONE(zone); +} - message->opcode = dns_opcode_notify; - message->flags |= DNS_MESSAGEFLAG_AA; - message->rdclass = zone->rdclass; +void +dns_zone_clearxfracl(dns_zone_t *zone) { - result = dns_message_gettempname(message, &tempname); - if (result != ISC_R_SUCCESS) - goto cleanup; + REQUIRE(DNS_ZONE_VALID(zone)); - result = dns_message_gettemprdataset(message, &temprdataset); - if (result != ISC_R_SUCCESS) - goto cleanup; + LOCK_ZONE(zone); + if (zone->xfr_acl != NULL) + dns_acl_detach(&zone->xfr_acl); + UNLOCK_ZONE(zone); +} - /* - * Make question. - */ - dns_name_init(tempname, NULL); - dns_name_clone(&zone->origin, tempname); - dns_rdataset_init(temprdataset); - dns_rdataset_makequestion(temprdataset, zone->rdclass, - dns_rdatatype_soa); - ISC_LIST_APPEND(tempname->list, temprdataset, link); - dns_message_addname(message, tempname, DNS_SECTION_QUESTION); - tempname = NULL; - temprdataset = NULL; +isc_boolean_t +dns_zone_getupdatedisabled(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + return (zone->update_disabled); - if ((flags & DNS_NOTIFY_NOSOA) != 0) - goto done; +} - result = dns_message_gettempname(message, &tempname); - if (result != ISC_R_SUCCESS) - goto soa_cleanup; - result = dns_message_gettemprdata(message, &temprdata); - if (result != ISC_R_SUCCESS) - goto soa_cleanup; - result = dns_message_gettemprdataset(message, &temprdataset); - if (result != ISC_R_SUCCESS) - goto soa_cleanup; - result = dns_message_gettemprdatalist(message, &temprdatalist); - if (result != ISC_R_SUCCESS) - goto soa_cleanup; +void +dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) { + REQUIRE(DNS_ZONE_VALID(zone)); + zone->update_disabled = state; +} + +isc_boolean_t +dns_zone_getzeronosoattl(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + return (zone->zero_no_soa_ttl); + +} - ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); - INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */ - dns_db_attach(zone->db, &zonedb); - ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); +void +dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) { + REQUIRE(DNS_ZONE_VALID(zone)); + zone->zero_no_soa_ttl = state; +} - dns_name_init(tempname, NULL); - dns_name_clone(&zone->origin, tempname); - dns_db_currentversion(zonedb, &version); - result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node); - if (result != ISC_R_SUCCESS) - goto soa_cleanup; +void +dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) { - dns_rdataset_init(&rdataset); - result = dns_db_findrdataset(zonedb, node, version, - dns_rdatatype_soa, - dns_rdatatype_none, 0, &rdataset, - NULL); - if (result != ISC_R_SUCCESS) - goto soa_cleanup; - result = dns_rdataset_first(&rdataset); - if (result != ISC_R_SUCCESS) - goto soa_cleanup; - dns_rdataset_current(&rdataset, &rdata); - dns_rdata_toregion(&rdata, &r); - result = isc_buffer_allocate(zone->mctx, &b, r.length); - if (result != ISC_R_SUCCESS) - goto soa_cleanup; - isc_buffer_putmem(b, r.base, r.length); - isc_buffer_usedregion(b, &r); - dns_rdata_init(temprdata); - dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r); - dns_message_takebuffer(message, &b); - result = dns_rdataset_next(&rdataset); - dns_rdataset_disassociate(&rdataset); - if (result != ISC_R_NOMORE) - goto soa_cleanup; - temprdatalist->rdclass = rdata.rdclass; - temprdatalist->type = rdata.type; - temprdatalist->covers = 0; - temprdatalist->ttl = rdataset.ttl; - ISC_LIST_INIT(temprdatalist->rdata); - ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link); + REQUIRE(DNS_ZONE_VALID(zone)); - dns_rdataset_init(temprdataset); - result = dns_rdatalist_tordataset(temprdatalist, temprdataset); - if (result != ISC_R_SUCCESS) - goto soa_cleanup; + zone->check_names = severity; +} - ISC_LIST_APPEND(tempname->list, temprdataset, link); - dns_message_addname(message, tempname, DNS_SECTION_ANSWER); - temprdatalist = NULL; - temprdataset = NULL; - temprdata = NULL; - tempname = NULL; +dns_severity_t +dns_zone_getchecknames(dns_zone_t *zone) { - soa_cleanup: - if (node != NULL) - dns_db_detachnode(zonedb, &node); - if (version != NULL) - dns_db_closeversion(zonedb, &version, ISC_FALSE); - if (zonedb != NULL) - dns_db_detach(&zonedb); - if (tempname != NULL) - dns_message_puttempname(message, &tempname); - if (temprdata != NULL) - dns_message_puttemprdata(message, &temprdata); - if (temprdataset != NULL) - dns_message_puttemprdataset(message, &temprdataset); - if (temprdatalist != NULL) - dns_message_puttemprdatalist(message, &temprdatalist); + REQUIRE(DNS_ZONE_VALID(zone)); - done: - *messagep = message; - return (ISC_R_SUCCESS); + return (zone->check_names); +} - cleanup: - if (tempname != NULL) - dns_message_puttempname(message, &tempname); - if (temprdataset != NULL) - dns_message_puttemprdataset(message, &temprdataset); - dns_message_destroy(&message); - return (result); +void +dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) { + + REQUIRE(DNS_ZONE_VALID(zone)); + + zone->journalsize = size; } -isc_result_t -dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from, - dns_message_t *msg) -{ - unsigned int i; - dns_rdata_soa_t soa; - dns_rdataset_t *rdataset = NULL; - dns_rdata_t rdata = DNS_RDATA_INIT; - isc_result_t result; - char fromtext[ISC_SOCKADDR_FORMATSIZE]; - int match = 0; - isc_netaddr_t netaddr; +isc_int32_t +dns_zone_getjournalsize(dns_zone_t *zone) { REQUIRE(DNS_ZONE_VALID(zone)); - /* - * If type != T_SOA return DNS_R_REFUSED. We don't yet support - * ROLLOVER. - * - * SOA: RFC1996 - * Check that 'from' is a valid notify source, (zone->masters). - * Return DNS_R_REFUSED if not. - * - * If the notify message contains a serial number check it - * against the zones serial and return if <= current serial - * - * If a refresh check is progress, if so just record the - * fact we received a NOTIFY and from where and return. - * We will perform a new refresh check when the current one - * completes. Return ISC_R_SUCCESS. - * - * Otherwise initiate a refresh check using 'from' as the - * first address to check. Return ISC_R_SUCCESS. - */ + return (zone->journalsize); +} - isc_sockaddr_format(from, fromtext, sizeof(fromtext)); +static void +zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) { + isc_result_t result = ISC_R_FAILURE; + isc_buffer_t buffer; - /* - * We only handle NOTIFY (SOA) at the present. - */ - LOCK_ZONE(zone); - if (isc_sockaddr_pf(from) == PF_INET) - inc_stats(zone, dns_zonestatscounter_notifyinv4); - else - inc_stats(zone, dns_zonestatscounter_notifyinv6); - if (msg->counts[DNS_SECTION_QUESTION] == 0 || - dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin, - dns_rdatatype_soa, dns_rdatatype_none, - NULL, NULL) != ISC_R_SUCCESS) { - UNLOCK_ZONE(zone); - if (msg->counts[DNS_SECTION_QUESTION] == 0) { - dns_zone_log(zone, ISC_LOG_NOTICE, - "NOTIFY with no " - "question section from: %s", fromtext); - return (DNS_R_FORMERR); - } - dns_zone_log(zone, ISC_LOG_NOTICE, - "NOTIFY zone does not match"); - return (DNS_R_NOTIMP); - } + REQUIRE(buf != NULL); + REQUIRE(length > 1U); /* - * If we are a master zone just succeed. + * Leave space for terminating '\0'. */ - if (zone->type == dns_zone_master) { - UNLOCK_ZONE(zone); - return (ISC_R_SUCCESS); - } + isc_buffer_init(&buffer, buf, length - 1); + if (dns_name_dynamic(&zone->origin)) + result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer); + if (result != ISC_R_SUCCESS && + isc_buffer_availablelength(&buffer) >= (sizeof("") - 1)) + isc_buffer_putstr(&buffer, ""); - isc_netaddr_fromsockaddr(&netaddr, from); - for (i = 0; i < zone->masterscnt; i++) { - if (isc_sockaddr_eqaddr(from, &zone->masters[i])) - break; - if (zone->view->aclenv.match_mapped && - IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) && - isc_sockaddr_pf(&zone->masters[i]) == AF_INET) { - isc_netaddr_t na1, na2; - isc_netaddr_fromv4mapped(&na1, &netaddr); - isc_netaddr_fromsockaddr(&na2, &zone->masters[i]); - if (isc_netaddr_equal(&na1, &na2)) - break; - } + if (isc_buffer_availablelength(&buffer) > 0) + isc_buffer_putstr(&buffer, "/"); + (void)dns_rdataclass_totext(zone->rdclass, &buffer); + + if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 && + strcmp(zone->view->name, "_default") != 0 && + strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) { + isc_buffer_putstr(&buffer, "/"); + isc_buffer_putstr(&buffer, zone->view->name); } + buf[isc_buffer_usedlength(&buffer)] = '\0'; +} + +static void +zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) { + isc_result_t result = ISC_R_FAILURE; + isc_buffer_t buffer; + + REQUIRE(buf != NULL); + REQUIRE(length > 1U); + /* - * Accept notify requests from non masters if they are on - * 'zone->notify_acl'. + * Leave space for terminating '\0'. */ - if (i >= zone->masterscnt && zone->notify_acl != NULL && - dns_acl_match(&netaddr, NULL, zone->notify_acl, - &zone->view->aclenv, - &match, NULL) == ISC_R_SUCCESS && - match > 0) - { - /* Accept notify. */ - } else if (i >= zone->masterscnt) { - UNLOCK_ZONE(zone); - dns_zone_log(zone, ISC_LOG_INFO, - "refused notify from non-master: %s", fromtext); - inc_stats(zone, dns_zonestatscounter_notifyrej); - return (DNS_R_REFUSED); - } + isc_buffer_init(&buffer, buf, length - 1); + if (dns_name_dynamic(&zone->origin)) + result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer); + if (result != ISC_R_SUCCESS && + isc_buffer_availablelength(&buffer) >= (sizeof("") - 1)) + isc_buffer_putstr(&buffer, ""); + + buf[isc_buffer_usedlength(&buffer)] = '\0'; +} + +static void +zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) { + isc_buffer_t buffer; + + REQUIRE(buf != NULL); + REQUIRE(length > 1U); /* - * If the zone is loaded and there are answers check the serial - * to see if we need to do a refresh. Do not worry about this - * check if we are a dialup zone as we use the notify request - * to trigger a refresh check. - */ - if (msg->counts[DNS_SECTION_ANSWER] > 0 && - DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) && - !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) { - result = dns_message_findname(msg, DNS_SECTION_ANSWER, - &zone->origin, - dns_rdatatype_soa, - dns_rdatatype_none, NULL, - &rdataset); - if (result == ISC_R_SUCCESS) - result = dns_rdataset_first(rdataset); - if (result == ISC_R_SUCCESS) { - isc_uint32_t serial = 0, oldserial; + * Leave space for terminating '\0'. + */ + isc_buffer_init(&buffer, buf, length - 1); + (void)dns_rdataclass_totext(zone->rdclass, &buffer); + + buf[isc_buffer_usedlength(&buffer)] = '\0'; +} + +static void +zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) { + isc_buffer_t buffer; + + REQUIRE(buf != NULL); + REQUIRE(length > 1U); - dns_rdataset_current(rdataset, &rdata); - result = dns_rdata_tostruct(&rdata, &soa, NULL); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - serial = soa.serial; - /* - * The following should safely be performed without DB - * lock and succeed in this context. - */ - result = zone_get_from_db(zone, zone->db, NULL, NULL, - &oldserial, NULL, NULL, NULL, - NULL, NULL); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - if (isc_serial_le(serial, oldserial)) { - dns_zone_log(zone, ISC_LOG_INFO, - "notify from %s: " - "zone is up to date", - fromtext); - UNLOCK_ZONE(zone); - return (ISC_R_SUCCESS); - } - } - } /* - * If we got this far and there was a refresh in progress just - * let it complete. Record where we got the notify from so we - * can perform a refresh check when the current one completes + * Leave space for terminating '\0'. */ - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) { - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH); - zone->notifyfrom = *from; - UNLOCK_ZONE(zone); - dns_zone_log(zone, ISC_LOG_INFO, - "notify from %s: refresh in progress, " - "refresh check queued", - fromtext); - return (ISC_R_SUCCESS); + isc_buffer_init(&buffer, buf, length - 1); + + if (zone->view == NULL) { + isc_buffer_putstr(&buffer, "_none"); + } else if (strlen(zone->view->name) + < isc_buffer_availablelength(&buffer)) { + isc_buffer_putstr(&buffer, zone->view->name); + } else { + isc_buffer_putstr(&buffer, "_toolong"); } - zone->notifyfrom = *from; - UNLOCK_ZONE(zone); - dns_zone_refresh(zone); - return (ISC_R_SUCCESS); + + buf[isc_buffer_usedlength(&buffer)] = '\0'; } void -dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) { - +dns_zone_name(dns_zone_t *zone, char *buf, size_t length) { REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(buf != NULL); + zone_namerd_tostr(zone, buf, length); +} - LOCK_ZONE(zone); - if (zone->notify_acl != NULL) - dns_acl_detach(&zone->notify_acl); - dns_acl_attach(acl, &zone->notify_acl); - UNLOCK_ZONE(zone); +static void +notify_log(dns_zone_t *zone, int level, const char *fmt, ...) { + va_list ap; + char message[4096]; + + if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE) + return; + + va_start(ap, fmt); + vsnprintf(message, sizeof(message), fmt, ap); + va_end(ap); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE, + level, "zone %s: %s", zone->strnamerd, message); } void -dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) { +dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category, + int level, const char *fmt, ...) { + va_list ap; + char message[4096]; - REQUIRE(DNS_ZONE_VALID(zone)); + if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE) + return; - LOCK_ZONE(zone); - if (zone->query_acl != NULL) - dns_acl_detach(&zone->query_acl); - dns_acl_attach(acl, &zone->query_acl); - UNLOCK_ZONE(zone); + va_start(ap, fmt); + vsnprintf(message, sizeof(message), fmt, ap); + va_end(ap); + isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE, + level, "%s %s: %s", (zone->type == dns_zone_key) ? + "managed-keys-zone" : "zone", zone->strnamerd, message); } void -dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) { +dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) { + va_list ap; + char message[4096]; - REQUIRE(DNS_ZONE_VALID(zone)); + if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE) + return; - LOCK_ZONE(zone); - if (zone->queryon_acl != NULL) - dns_acl_detach(&zone->queryon_acl); - dns_acl_attach(acl, &zone->queryon_acl); - UNLOCK_ZONE(zone); + va_start(ap, fmt); + vsnprintf(message, sizeof(message), fmt, ap); + va_end(ap); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE, + level, "%s %s: %s", (zone->type == dns_zone_key) ? + "managed-keys-zone" : "zone", zone->strnamerd, message); } -void -dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) { +static void +zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel, + const char *fmt, ...) +{ + va_list ap; + char message[4096]; + int level = ISC_LOG_DEBUG(debuglevel); - REQUIRE(DNS_ZONE_VALID(zone)); + if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE) + return; - LOCK_ZONE(zone); - if (zone->update_acl != NULL) - dns_acl_detach(&zone->update_acl); - dns_acl_attach(acl, &zone->update_acl); - UNLOCK_ZONE(zone); + va_start(ap, fmt); + vsnprintf(message, sizeof(message), fmt, ap); + va_end(ap); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE, + level, "%s: %s %s: %s", me, zone->type != dns_zone_key ? + "zone" : "managed-keys-zone", zone->strnamerd, message); } -void -dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) { +static int +message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type) +{ + isc_result_t result; + dns_name_t *name; + dns_rdataset_t *curr; + int count = 0; - REQUIRE(DNS_ZONE_VALID(zone)); + result = dns_message_firstname(msg, section); + while (result == ISC_R_SUCCESS) { + name = NULL; + dns_message_currentname(msg, section, &name); - LOCK_ZONE(zone); - if (zone->forward_acl != NULL) - dns_acl_detach(&zone->forward_acl); - dns_acl_attach(acl, &zone->forward_acl); - UNLOCK_ZONE(zone); + for (curr = ISC_LIST_TAIL(name->list); curr != NULL; + curr = ISC_LIST_PREV(curr, link)) { + if (curr->type == type) + count++; + } + result = dns_message_nextname(msg, section); + } + + return (count); } void -dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) { - +dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) { REQUIRE(DNS_ZONE_VALID(zone)); - LOCK_ZONE(zone); - if (zone->xfr_acl != NULL) - dns_acl_detach(&zone->xfr_acl); - dns_acl_attach(acl, &zone->xfr_acl); - UNLOCK_ZONE(zone); + zone->maxxfrin = maxxfrin; } -dns_acl_t * -dns_zone_getnotifyacl(dns_zone_t *zone) { - +isc_uint32_t +dns_zone_getmaxxfrin(dns_zone_t *zone) { REQUIRE(DNS_ZONE_VALID(zone)); - return (zone->notify_acl); + return (zone->maxxfrin); } -dns_acl_t * -dns_zone_getqueryacl(dns_zone_t *zone) { +void +dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) { + REQUIRE(DNS_ZONE_VALID(zone)); + zone->maxxfrout = maxxfrout; +} +isc_uint32_t +dns_zone_getmaxxfrout(dns_zone_t *zone) { REQUIRE(DNS_ZONE_VALID(zone)); - return (zone->query_acl); + return (zone->maxxfrout); } -dns_acl_t * -dns_zone_getqueryonacl(dns_zone_t *zone) { - +dns_zonetype_t +dns_zone_gettype(dns_zone_t *zone) { REQUIRE(DNS_ZONE_VALID(zone)); - return (zone->queryon_acl); + return (zone->type); } -dns_acl_t * -dns_zone_getupdateacl(dns_zone_t *zone) { +dns_name_t * +dns_zone_getorigin(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + return (&zone->origin); +} + +void +dns_zone_settask(dns_zone_t *zone, isc_task_t *task) { REQUIRE(DNS_ZONE_VALID(zone)); - return (zone->update_acl); + LOCK_ZONE(zone); + if (zone->task != NULL) + isc_task_detach(&zone->task); + isc_task_attach(task, &zone->task); + ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); + if (zone->db != NULL) + dns_db_settask(zone->db, zone->task); + ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); + UNLOCK_ZONE(zone); } -dns_acl_t * -dns_zone_getforwardacl(dns_zone_t *zone) { +void +dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) { + REQUIRE(DNS_ZONE_VALID(zone)); + isc_task_attach(zone->task, target); +} +void +dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) { REQUIRE(DNS_ZONE_VALID(zone)); - return (zone->forward_acl); + if (idlein == 0) + idlein = DNS_DEFAULT_IDLEIN; + zone->idlein = idlein; } -dns_acl_t * -dns_zone_getxfracl(dns_zone_t *zone) { - +isc_uint32_t +dns_zone_getidlein(dns_zone_t *zone) { REQUIRE(DNS_ZONE_VALID(zone)); - return (zone->xfr_acl); + return (zone->idlein); } void -dns_zone_clearupdateacl(dns_zone_t *zone) { +dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) { + REQUIRE(DNS_ZONE_VALID(zone)); + + zone->idleout = idleout; +} + +isc_uint32_t +dns_zone_getidleout(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + + return (zone->idleout); +} - REQUIRE(DNS_ZONE_VALID(zone)); +static void +notify_done(isc_task_t *task, isc_event_t *event) { + dns_requestevent_t *revent = (dns_requestevent_t *)event; + dns_notify_t *notify; + isc_result_t result; + dns_message_t *message = NULL; + isc_buffer_t buf; + char rcode[128]; + char addrbuf[ISC_SOCKADDR_FORMATSIZE]; - LOCK_ZONE(zone); - if (zone->update_acl != NULL) - dns_acl_detach(&zone->update_acl); - UNLOCK_ZONE(zone); -} + UNUSED(task); -void -dns_zone_clearforwardacl(dns_zone_t *zone) { + notify = event->ev_arg; + REQUIRE(DNS_NOTIFY_VALID(notify)); + INSIST(task == notify->zone->task); - REQUIRE(DNS_ZONE_VALID(zone)); + isc_buffer_init(&buf, rcode, sizeof(rcode)); + isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf)); - LOCK_ZONE(zone); - if (zone->forward_acl != NULL) - dns_acl_detach(&zone->forward_acl); - UNLOCK_ZONE(zone); + result = revent->result; + if (result == ISC_R_SUCCESS) + result = dns_message_create(notify->zone->mctx, + DNS_MESSAGE_INTENTPARSE, &message); + if (result == ISC_R_SUCCESS) + result = dns_request_getresponse(revent->request, message, + DNS_MESSAGEPARSE_PRESERVEORDER); + if (result == ISC_R_SUCCESS) + result = dns_rcode_totext(message->rcode, &buf); + if (result == ISC_R_SUCCESS) + notify_log(notify->zone, ISC_LOG_DEBUG(3), + "notify response from %s: %.*s", + addrbuf, (int)buf.used, rcode); + else + notify_log(notify->zone, ISC_LOG_DEBUG(2), + "notify to %s failed: %s", addrbuf, + dns_result_totext(result)); + + /* + * Old bind's return formerr if they see a soa record. Retry w/o + * the soa if we see a formerr and had sent a SOA. + */ + isc_event_free(&event); + if (message != NULL && message->rcode == dns_rcode_formerr && + (notify->flags & DNS_NOTIFY_NOSOA) == 0) { + notify->flags |= DNS_NOTIFY_NOSOA; + dns_request_destroy(¬ify->request); + result = notify_send_queue(notify); + if (result != ISC_R_SUCCESS) + notify_destroy(notify, ISC_FALSE); + } else { + if (result == ISC_R_TIMEDOUT) + notify_log(notify->zone, ISC_LOG_DEBUG(1), + "notify to %s: retries exceeded", addrbuf); + notify_destroy(notify, ISC_FALSE); + } + if (message != NULL) + dns_message_destroy(&message); } -void -dns_zone_clearnotifyacl(dns_zone_t *zone) { +isc_result_t +dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) { + isc_result_t result; REQUIRE(DNS_ZONE_VALID(zone)); - LOCK_ZONE(zone); - if (zone->notify_acl != NULL) - dns_acl_detach(&zone->notify_acl); + ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write); + result = zone_replacedb(zone, db, dump); + ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write); UNLOCK_ZONE(zone); + return (result); } -void -dns_zone_clearqueryacl(dns_zone_t *zone) { +static isc_result_t +zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) { + dns_dbversion_t *ver; + isc_result_t result; + unsigned int soacount = 0; + unsigned int nscount = 0; + /* + * 'zone' and 'zonedb' locked by caller. + */ REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(LOCKED_ZONE(zone)); - LOCK_ZONE(zone); - if (zone->query_acl != NULL) - dns_acl_detach(&zone->query_acl); - UNLOCK_ZONE(zone); -} + result = zone_get_from_db(zone, db, &nscount, &soacount, + NULL, NULL, NULL, NULL, NULL, NULL); + if (result == ISC_R_SUCCESS) { + if (soacount != 1) { + dns_zone_log(zone, ISC_LOG_ERROR, + "has %d SOA records", soacount); + result = DNS_R_BADZONE; + } + if (nscount == 0 && zone->type != dns_zone_key) { + dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records"); + result = DNS_R_BADZONE; + } + if (result != ISC_R_SUCCESS) + return (result); + } else { + dns_zone_log(zone, ISC_LOG_ERROR, + "retrieving SOA and NS records failed: %s", + dns_result_totext(result)); + return (result); + } -void -dns_zone_clearqueryonacl(dns_zone_t *zone) { + result = check_nsec3param(zone, db); + if (result != ISC_R_SUCCESS) + return (result); - REQUIRE(DNS_ZONE_VALID(zone)); + ver = NULL; + dns_db_currentversion(db, &ver); - LOCK_ZONE(zone); - if (zone->queryon_acl != NULL) - dns_acl_detach(&zone->queryon_acl); - UNLOCK_ZONE(zone); -} + /* + * The initial version of a slave zone is always dumped; + * subsequent versions may be journaled instead if this + * is enabled in the configuration. + */ + if (zone->db != NULL && zone->journal != NULL && + DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) && + !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) { + isc_uint32_t serial, oldserial; -void -dns_zone_clearxfracl(dns_zone_t *zone) { + dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs"); - REQUIRE(DNS_ZONE_VALID(zone)); + result = dns_db_getsoaserial(db, ver, &serial); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "ixfr-from-differences: unable to get " + "new serial"); + goto fail; + } - LOCK_ZONE(zone); - if (zone->xfr_acl != NULL) - dns_acl_detach(&zone->xfr_acl); - UNLOCK_ZONE(zone); -} + /* + * This is checked in zone_postload() for master zones. + */ + result = zone_get_from_db(zone, zone->db, NULL, NULL, + &oldserial, NULL, NULL, NULL, NULL, + NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + if (zone->type == dns_zone_slave && + !isc_serial_gt(serial, oldserial)) { + isc_uint32_t serialmin, serialmax; + serialmin = (oldserial + 1) & 0xffffffffU; + serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU; + dns_zone_log(zone, ISC_LOG_ERROR, + "ixfr-from-differences: failed: " + "new serial (%u) out of range [%u - %u]", + serial, serialmin, serialmax); + result = ISC_R_RANGE; + goto fail; + } -isc_boolean_t -dns_zone_getupdatedisabled(dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); - return (zone->update_disabled); + result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL, + zone->journal); + if (result != ISC_R_SUCCESS) + goto fail; + if (dump) + zone_needdump(zone, DNS_DUMP_DELAY); + else if (zone->journalsize != -1) { + result = dns_journal_compact(zone->mctx, zone->journal, + serial, zone->journalsize); + switch (result) { + case ISC_R_SUCCESS: + case ISC_R_NOSPACE: + case ISC_R_NOTFOUND: + dns_zone_log(zone, ISC_LOG_DEBUG(3), + "dns_journal_compact: %s", + dns_result_totext(result)); + break; + default: + dns_zone_log(zone, ISC_LOG_ERROR, + "dns_journal_compact failed: %s", + dns_result_totext(result)); + break; + } + } + } else { + if (dump && zone->masterfile != NULL) { + /* + * If DNS_ZONEFLG_FORCEXFER was set we don't want + * to keep the old masterfile. + */ + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) && + remove(zone->masterfile) < 0 && errno != ENOENT) { + char strbuf[ISC_STRERRORSIZE]; + isc__strerror(errno, strbuf, sizeof(strbuf)); + isc_log_write(dns_lctx, + DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_ZONE, + ISC_LOG_WARNING, + "unable to remove masterfile " + "'%s': '%s'", + zone->masterfile, strbuf); + } + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0) + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY); + else + zone_needdump(zone, 0); + } + if (dump && zone->journal != NULL) { + /* + * The in-memory database just changed, and + * because 'dump' is set, it didn't change by + * being loaded from disk. Also, we have not + * journaled diffs for this change. + * Therefore, the on-disk journal is missing + * the deltas for this change. Since it can + * no longer be used to bring the zone + * up-to-date, it is useless and should be + * removed. + */ + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3), + "removing journal file"); + if (remove(zone->journal) < 0 && errno != ENOENT) { + char strbuf[ISC_STRERRORSIZE]; + isc__strerror(errno, strbuf, sizeof(strbuf)); + isc_log_write(dns_lctx, + DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_ZONE, + ISC_LOG_WARNING, + "unable to remove journal " + "'%s': '%s'", + zone->journal, strbuf); + } + } + } -} + dns_db_closeversion(db, &ver, ISC_FALSE); -void -dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) { - REQUIRE(DNS_ZONE_VALID(zone)); - zone->update_disabled = state; -} + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3), + "replacing zone database"); -isc_boolean_t -dns_zone_getzeronosoattl(dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); - return (zone->zero_no_soa_ttl); + if (zone->db != NULL) + zone_detachdb(zone); + zone_attachdb(zone, db); + dns_db_settask(zone->db, zone->task); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY); + return (ISC_R_SUCCESS); + fail: + dns_db_closeversion(db, &ver, ISC_FALSE); + return (result); } -void -dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) { - REQUIRE(DNS_ZONE_VALID(zone)); - zone->zero_no_soa_ttl = state; -} +/* The caller must hold the dblock as a writer. */ +static inline void +zone_attachdb(dns_zone_t *zone, dns_db_t *db) { + REQUIRE(zone->db == NULL && db != NULL); -void -dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) { + dns_db_attach(db, &zone->db); + if (zone->acache != NULL) { + isc_result_t result; + result = dns_acache_setdb(zone->acache, db); + if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "dns_acache_setdb() failed: %s", + isc_result_totext(result)); + } + } +} - REQUIRE(DNS_ZONE_VALID(zone)); +/* The caller must hold the dblock as a writer. */ +static inline void +zone_detachdb(dns_zone_t *zone) { + REQUIRE(zone->db != NULL); - zone->check_names = severity; + if (zone->acache != NULL) + (void)dns_acache_putdb(zone->acache, zone->db); + dns_db_detach(&zone->db); } -dns_severity_t -dns_zone_getchecknames(dns_zone_t *zone) { +static void +zone_xfrdone(dns_zone_t *zone, isc_result_t result) { + isc_time_t now; + isc_boolean_t again = ISC_FALSE; + unsigned int soacount; + unsigned int nscount; + isc_uint32_t serial, refresh, retry, expire, minimum; + isc_result_t xfrresult = result; + isc_boolean_t free_needed; REQUIRE(DNS_ZONE_VALID(zone)); - return (zone->check_names); -} - -void -dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) { + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "zone transfer finished: %s", dns_result_totext(result)); - REQUIRE(DNS_ZONE_VALID(zone)); + LOCK_ZONE(zone); + INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0); + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH); + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR); - zone->journalsize = size; -} + TIME_NOW(&now); + switch (result) { + case ISC_R_SUCCESS: + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY); + /*FALLTHROUGH*/ + case DNS_R_UPTODATE: + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER); + /* + * Has the zone expired underneath us? + */ + ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); + if (zone->db == NULL) { + ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); + goto same_master; + } -isc_int32_t -dns_zone_getjournalsize(dns_zone_t *zone) { + /* + * Update the zone structure's data from the actual + * SOA received. + */ + nscount = 0; + soacount = 0; + INSIST(zone->db != NULL); + result = zone_get_from_db(zone, zone->db, &nscount, + &soacount, &serial, &refresh, + &retry, &expire, &minimum, NULL); + ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); + if (result == ISC_R_SUCCESS) { + if (soacount != 1) + dns_zone_log(zone, ISC_LOG_ERROR, + "transferred zone " + "has %d SOA record%s", soacount, + (soacount != 0) ? "s" : ""); + if (nscount == 0) { + dns_zone_log(zone, ISC_LOG_ERROR, + "transferred zone " + "has no NS records"); + if (DNS_ZONE_FLAG(zone, + DNS_ZONEFLG_HAVETIMERS)) { + zone->refresh = DNS_ZONE_DEFAULTREFRESH; + zone->retry = DNS_ZONE_DEFAULTRETRY; + } + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS); + zone_unload(zone); + goto next_master; + } + zone->refresh = RANGE(refresh, zone->minrefresh, + zone->maxrefresh); + zone->retry = RANGE(retry, zone->minretry, + zone->maxretry); + zone->expire = RANGE(expire, + zone->refresh + zone->retry, + DNS_MAX_EXPIRE); + zone->minimum = minimum; + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS); + } - REQUIRE(DNS_ZONE_VALID(zone)); + /* + * Set our next update/expire times. + */ + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) { + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH); + zone->refreshtime = now; + DNS_ZONE_TIME_ADD(&now, zone->expire, + &zone->expiretime); + } else { + DNS_ZONE_JITTER_ADD(&now, zone->refresh, + &zone->refreshtime); + DNS_ZONE_TIME_ADD(&now, zone->expire, + &zone->expiretime); + } + if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) { + char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")]; + if (zone->tsigkey != NULL) { + char namebuf[DNS_NAME_FORMATSIZE]; + dns_name_format(&zone->tsigkey->name, namebuf, + sizeof(namebuf)); + snprintf(buf, sizeof(buf), ": TSIG '%s'", + namebuf); + } else + buf[0] = '\0'; + dns_zone_log(zone, ISC_LOG_INFO, + "transferred serial %u%s", + serial, buf); + } - return (zone->journalsize); -} + /* + * This is not necessary if we just performed a AXFR + * however it is necessary for an IXFR / UPTODATE and + * won't hurt with an AXFR. + */ + if (zone->masterfile != NULL || zone->journal != NULL) { + result = ISC_R_FAILURE; + if (zone->journal != NULL) + result = isc_file_settime(zone->journal, &now); + if (result != ISC_R_SUCCESS && + zone->masterfile != NULL) + result = isc_file_settime(zone->masterfile, + &now); + /* Someone removed the file from underneath us! */ + if (result == ISC_R_FILENOTFOUND && + zone->masterfile != NULL) { + unsigned int delay = DNS_DUMP_DELAY; + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY)) + delay = 0; + zone_needdump(zone, delay); + } else if (result != ISC_R_SUCCESS) + dns_zone_log(zone, ISC_LOG_ERROR, + "transfer: could not set file " + "modification time of '%s': %s", + zone->masterfile, + dns_result_totext(result)); + } + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY); + inc_stats(zone, dns_zonestatscounter_xfrsuccess); + break; -static void -zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) { - isc_result_t result = ISC_R_FAILURE; - isc_buffer_t buffer; + case DNS_R_BADIXFR: + /* Force retry with AXFR. */ + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR); + goto same_master; - REQUIRE(buf != NULL); - REQUIRE(length > 1U); + default: + next_master: + /* + * Skip to next failed / untried master. + */ + do { + zone->curmaster++; + } while (zone->curmaster < zone->masterscnt && + zone->mastersok[zone->curmaster]); + /* FALLTHROUGH */ + same_master: + if (zone->curmaster >= zone->masterscnt) { + zone->curmaster = 0; + if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) && + !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) { + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC); + while (zone->curmaster < zone->masterscnt && + zone->mastersok[zone->curmaster]) + zone->curmaster++; + again = ISC_TRUE; + } else + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC); + } else { + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH); + again = ISC_TRUE; + } + inc_stats(zone, dns_zonestatscounter_xfrfail); + break; + } + zone_settimer(zone, &now); /* - * Leave space for terminating '\0'. + * If creating the transfer object failed, zone->xfr is NULL. + * Otherwise, we are called as the done callback of a zone + * transfer object that just entered its shutting-down + * state. Since we are no longer responsible for shutting + * it down, we can detach our reference. */ - isc_buffer_init(&buffer, buf, length - 1); - if (dns_name_dynamic(&zone->origin)) - result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer); - if (result != ISC_R_SUCCESS && - isc_buffer_availablelength(&buffer) >= (sizeof("") - 1)) - isc_buffer_putstr(&buffer, ""); + if (zone->xfr != NULL) + dns_xfrin_detach(&zone->xfr); - if (isc_buffer_availablelength(&buffer) > 0) - isc_buffer_putstr(&buffer, "/"); - (void)dns_rdataclass_totext(zone->rdclass, &buffer); + if (zone->tsigkey != NULL) + dns_tsigkey_detach(&zone->tsigkey); - if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 && - strcmp(zone->view->name, "_default") != 0 && - strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) { - isc_buffer_putstr(&buffer, "/"); - isc_buffer_putstr(&buffer, zone->view->name); + /* + * Handle any deferred journal compaction. + */ + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) { + result = dns_journal_compact(zone->mctx, zone->journal, + zone->compact_serial, + zone->journalsize); + switch (result) { + case ISC_R_SUCCESS: + case ISC_R_NOSPACE: + case ISC_R_NOTFOUND: + dns_zone_log(zone, ISC_LOG_DEBUG(3), + "dns_journal_compact: %s", + dns_result_totext(result)); + break; + default: + dns_zone_log(zone, ISC_LOG_ERROR, + "dns_journal_compact failed: %s", + dns_result_totext(result)); + break; + } + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT); } - buf[isc_buffer_usedlength(&buffer)] = '\0'; -} - -static void -zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) { - isc_result_t result = ISC_R_FAILURE; - isc_buffer_t buffer; - - REQUIRE(buf != NULL); - REQUIRE(length > 1U); - /* - * Leave space for terminating '\0'. + * This transfer finishing freed up a transfer quota slot. + * Let any other zones waiting for quota have it. */ - isc_buffer_init(&buffer, buf, length - 1); - if (dns_name_dynamic(&zone->origin)) - result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer); - if (result != ISC_R_SUCCESS && - isc_buffer_availablelength(&buffer) >= (sizeof("") - 1)) - isc_buffer_putstr(&buffer, ""); - - buf[isc_buffer_usedlength(&buffer)] = '\0'; -} - -static void -zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) { - isc_buffer_t buffer; - - REQUIRE(buf != NULL); - REQUIRE(length > 1U); + RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write); + ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink); + zone->statelist = NULL; + zmgr_resume_xfrs(zone->zmgr, ISC_FALSE); + RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write); /* - * Leave space for terminating '\0'. + * Retry with a different server if necessary. */ - isc_buffer_init(&buffer, buf, length - 1); - (void)dns_rdataclass_totext(zone->rdclass, &buffer); + if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) + queue_soa_query(zone); - buf[isc_buffer_usedlength(&buffer)] = '\0'; + INSIST(zone->irefs > 0); + zone->irefs--; + free_needed = exit_check(zone); + UNLOCK_ZONE(zone); + if (free_needed) + zone_free(zone); } static void -zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) { - isc_buffer_t buffer; +zone_loaddone(void *arg, isc_result_t result) { + static char me[] = "zone_loaddone"; + dns_load_t *load = arg; + dns_zone_t *zone; + isc_result_t tresult; - REQUIRE(buf != NULL); - REQUIRE(length > 1U); + REQUIRE(DNS_LOAD_VALID(load)); + zone = load->zone; + ENTER; + + tresult = dns_db_endload(load->db, &load->callbacks.add_private); + if (tresult != ISC_R_SUCCESS && + (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE)) + result = tresult; + LOCK_ZONE(load->zone); + (void)zone_postload(load->zone, load->db, load->loadtime, result); + zonemgr_putio(&load->zone->readio); + DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADING); /* - * Leave space for terminating '\0'. + * Leave the zone frozen if the reload fails. */ - isc_buffer_init(&buffer, buf, length - 1); - - if (zone->view == NULL) { - isc_buffer_putstr(&buffer, "_none"); - } else if (strlen(zone->view->name) - < isc_buffer_availablelength(&buffer)) { - isc_buffer_putstr(&buffer, zone->view->name); - } else { - isc_buffer_putstr(&buffer, "_toolong"); - } + if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) && + DNS_ZONE_FLAG(load->zone, DNS_ZONEFLG_THAW)) + zone->update_disabled = ISC_FALSE; + DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_THAW); + UNLOCK_ZONE(load->zone); - buf[isc_buffer_usedlength(&buffer)] = '\0'; + load->magic = 0; + dns_db_detach(&load->db); + if (load->zone->lctx != NULL) + dns_loadctx_detach(&load->zone->lctx); + dns_zone_idetach(&load->zone); + isc_mem_putanddetach(&load->mctx, load, sizeof(*load)); } void -dns_zone_name(dns_zone_t *zone, char *buf, size_t length) { +dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) { REQUIRE(DNS_ZONE_VALID(zone)); - REQUIRE(buf != NULL); - zone_namerd_tostr(zone, buf, length); -} - -static void -notify_log(dns_zone_t *zone, int level, const char *fmt, ...) { - va_list ap; - char message[4096]; - - if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE) - return; + REQUIRE(table != NULL); + REQUIRE(*table == NULL); - va_start(ap, fmt); - vsnprintf(message, sizeof(message), fmt, ap); - va_end(ap); - isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE, - level, "zone %s: %s", zone->strnamerd, message); + LOCK_ZONE(zone); + if (zone->ssutable != NULL) + dns_ssutable_attach(zone->ssutable, table); + UNLOCK_ZONE(zone); } void -dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category, - int level, const char *fmt, ...) { - va_list ap; - char message[4096]; - - if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE) - return; +dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) { + REQUIRE(DNS_ZONE_VALID(zone)); - va_start(ap, fmt); - vsnprintf(message, sizeof(message), fmt, ap); - va_end(ap); - isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE, - level, "zone %s: %s", zone->strnamerd, message); + LOCK_ZONE(zone); + if (zone->ssutable != NULL) + dns_ssutable_detach(&zone->ssutable); + if (table != NULL) + dns_ssutable_attach(table, &zone->ssutable); + UNLOCK_ZONE(zone); } void -dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) { - va_list ap; - char message[4096]; - - if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE) - return; - - va_start(ap, fmt); - vsnprintf(message, sizeof(message), fmt, ap); - va_end(ap); - isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE, - level, "zone %s: %s", zone->strnamerd, message); -} - -static void -zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel, - const char *fmt, ...) -{ - va_list ap; - char message[4096]; - int level = ISC_LOG_DEBUG(debuglevel); - - if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE) - return; +dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) { + REQUIRE(DNS_ZONE_VALID(zone)); - va_start(ap, fmt); - vsnprintf(message, sizeof(message), fmt, ap); - va_end(ap); - isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE, - level, "%s: zone %s: %s", me, zone->strnamerd, message); + zone->sigvalidityinterval = interval; } -static int -message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type) -{ - isc_result_t result; - dns_name_t *name; - dns_rdataset_t *curr; - int count = 0; - - result = dns_message_firstname(msg, section); - while (result == ISC_R_SUCCESS) { - name = NULL; - dns_message_currentname(msg, section, &name); - - for (curr = ISC_LIST_TAIL(name->list); curr != NULL; - curr = ISC_LIST_PREV(curr, link)) { - if (curr->type == type) - count++; - } - result = dns_message_nextname(msg, section); - } +isc_uint32_t +dns_zone_getsigvalidityinterval(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); - return (count); + return (zone->sigvalidityinterval); } void -dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) { +dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) { REQUIRE(DNS_ZONE_VALID(zone)); - zone->maxxfrin = maxxfrin; + zone->sigresigninginterval = interval; } isc_uint32_t -dns_zone_getmaxxfrin(dns_zone_t *zone) { +dns_zone_getsigresigninginterval(dns_zone_t *zone) { REQUIRE(DNS_ZONE_VALID(zone)); - return (zone->maxxfrin); + return (zone->sigresigninginterval); } -void -dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) { - REQUIRE(DNS_ZONE_VALID(zone)); - zone->maxxfrout = maxxfrout; -} +static void +queue_xfrin(dns_zone_t *zone) { + const char me[] = "queue_xfrin"; + isc_result_t result; + dns_zonemgr_t *zmgr = zone->zmgr; -isc_uint32_t -dns_zone_getmaxxfrout(dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); + ENTER; - return (zone->maxxfrout); + INSIST(zone->statelist == NULL); + + RWLOCK(&zmgr->rwlock, isc_rwlocktype_write); + ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink); + LOCK_ZONE(zone); + zone->irefs++; + UNLOCK_ZONE(zone); + zone->statelist = &zmgr->waiting_for_xfrin; + result = zmgr_start_xfrin_ifquota(zmgr, zone); + RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write); + + if (result == ISC_R_QUOTA) { + dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO, + "zone transfer deferred due to quota"); + } else if (result != ISC_R_SUCCESS) { + dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR, + "starting zone transfer: %s", + isc_result_totext(result)); + } } -dns_zonetype_t -dns_zone_gettype(dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); +/* + * This event callback is called when a zone has received + * any necessary zone transfer quota. This is the time + * to go ahead and start the transfer. + */ +static void +got_transfer_quota(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + dns_peer_t *peer = NULL; + char master[ISC_SOCKADDR_FORMATSIZE]; + char source[ISC_SOCKADDR_FORMATSIZE]; + dns_rdatatype_t xfrtype; + dns_zone_t *zone = event->ev_arg; + isc_netaddr_t masterip; + isc_sockaddr_t sourceaddr; + isc_sockaddr_t masteraddr; + isc_time_t now; + const char *soa_before = ""; + + UNUSED(task); - return (zone->type); -} + INSIST(task == zone->task); -dns_name_t * -dns_zone_getorigin(dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) { + result = ISC_R_CANCELED; + goto cleanup; + } - return (&zone->origin); -} + TIME_NOW(&now); -void -dns_zone_settask(dns_zone_t *zone, isc_task_t *task) { - REQUIRE(DNS_ZONE_VALID(zone)); + isc_sockaddr_format(&zone->masteraddr, master, sizeof(master)); + if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr, + &zone->sourceaddr, &now)) { + isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source)); + dns_zone_log(zone, ISC_LOG_INFO, + "got_transfer_quota: skipping zone transfer as " + "master %s (source %s) is unreachable (cached)", + master, source); + result = ISC_R_CANCELED; + goto cleanup; + } - LOCK_ZONE(zone); - if (zone->task != NULL) - isc_task_detach(&zone->task); - isc_task_attach(task, &zone->task); - ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); - if (zone->db != NULL) - dns_db_settask(zone->db, zone->task); - ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); - UNLOCK_ZONE(zone); -} + isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr); + (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer); -void -dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) { - REQUIRE(DNS_ZONE_VALID(zone)); - isc_task_attach(zone->task, target); -} + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) + soa_before = "SOA before "; + /* + * Decide whether we should request IXFR or AXFR. + */ + if (zone->db == NULL) { + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "no database exists yet, requesting AXFR of " + "initial version from %s", master); + xfrtype = dns_rdatatype_axfr; + } else if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) { + dns_zone_log(zone, ISC_LOG_DEBUG(1), "ixfr-from-differences " + "set, requesting %sAXFR from %s", soa_before, + master); + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) + xfrtype = dns_rdatatype_soa; + else + xfrtype = dns_rdatatype_axfr; + } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) { + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "forced reload, requesting AXFR of " + "initial version from %s", master); + xfrtype = dns_rdatatype_axfr; + } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) { + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "retrying with AXFR from %s due to " + "previous IXFR failure", master); + xfrtype = dns_rdatatype_axfr; + LOCK_ZONE(zone); + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR); + UNLOCK_ZONE(zone); + } else { + isc_boolean_t use_ixfr = ISC_TRUE; + if (peer != NULL && + dns_peer_getrequestixfr(peer, &use_ixfr) == + ISC_R_SUCCESS) { + ; /* Using peer setting */ + } else { + use_ixfr = zone->view->requestixfr; + } + if (use_ixfr == ISC_FALSE) { + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "IXFR disabled, requesting %sAXFR from %s", + soa_before, master); + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) + xfrtype = dns_rdatatype_soa; + else + xfrtype = dns_rdatatype_axfr; + } else { + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "requesting IXFR from %s", master); + xfrtype = dns_rdatatype_ixfr; + } + } -void -dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) { - REQUIRE(DNS_ZONE_VALID(zone)); + /* + * Determine if we should attempt to sign the request with TSIG. + */ + result = ISC_R_NOTFOUND; + /* + * First, look for a tsig key in the master statement, then + * try for a server key. + */ + if ((zone->masterkeynames != NULL) && + (zone->masterkeynames[zone->curmaster] != NULL)) { + dns_view_t *view = dns_zone_getview(zone); + dns_name_t *keyname = zone->masterkeynames[zone->curmaster]; + result = dns_view_gettsig(view, keyname, &zone->tsigkey); + } + if (zone->tsigkey == NULL) + result = dns_view_getpeertsig(zone->view, &masterip, + &zone->tsigkey); - if (idlein == 0) - idlein = DNS_DEFAULT_IDLEIN; - zone->idlein = idlein; -} + if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) { + dns_zone_log(zone, ISC_LOG_ERROR, + "could not get TSIG key for zone transfer: %s", + isc_result_totext(result)); + } -isc_uint32_t -dns_zone_getidlein(dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); + LOCK_ZONE(zone); + masteraddr = zone->masteraddr; + sourceaddr = zone->sourceaddr; + UNLOCK_ZONE(zone); + INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr)); + result = dns_xfrin_create2(zone, xfrtype, &masteraddr, &sourceaddr, + zone->tsigkey, zone->mctx, + zone->zmgr->timermgr, zone->zmgr->socketmgr, + zone->task, zone_xfrdone, &zone->xfr); + if (result == ISC_R_SUCCESS) { + LOCK_ZONE(zone); + if (xfrtype == dns_rdatatype_axfr) { + if (isc_sockaddr_pf(&masteraddr) == PF_INET) + inc_stats(zone, dns_zonestatscounter_axfrreqv4); + else + inc_stats(zone, dns_zonestatscounter_axfrreqv6); + } else if (xfrtype == dns_rdatatype_ixfr) { + if (isc_sockaddr_pf(&masteraddr) == PF_INET) + inc_stats(zone, dns_zonestatscounter_ixfrreqv4); + else + inc_stats(zone, dns_zonestatscounter_ixfrreqv6); + } + UNLOCK_ZONE(zone); + } + cleanup: + /* + * Any failure in this function is handled like a failed + * zone transfer. This ensures that we get removed from + * zmgr->xfrin_in_progress. + */ + if (result != ISC_R_SUCCESS) + zone_xfrdone(zone, result); - return (zone->idlein); + isc_event_free(&event); } -void -dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) { - REQUIRE(DNS_ZONE_VALID(zone)); - - zone->idleout = idleout; -} +/* + * Update forwarding support. + */ -isc_uint32_t -dns_zone_getidleout(dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); +static void +forward_destroy(dns_forward_t *forward) { - return (zone->idleout); + forward->magic = 0; + if (forward->request != NULL) + dns_request_destroy(&forward->request); + if (forward->msgbuf != NULL) + isc_buffer_free(&forward->msgbuf); + if (forward->zone != NULL) + dns_zone_idetach(&forward->zone); + isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward)); } -static void -notify_done(isc_task_t *task, isc_event_t *event) { - dns_requestevent_t *revent = (dns_requestevent_t *)event; - dns_notify_t *notify; +static isc_result_t +sendtomaster(dns_forward_t *forward) { isc_result_t result; - dns_message_t *message = NULL; - isc_buffer_t buf; - char rcode[128]; - char addrbuf[ISC_SOCKADDR_FORMATSIZE]; - - UNUSED(task); - - notify = event->ev_arg; - REQUIRE(DNS_NOTIFY_VALID(notify)); - INSIST(task == notify->zone->task); - - isc_buffer_init(&buf, rcode, sizeof(rcode)); - isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf)); + isc_sockaddr_t src; - result = revent->result; - if (result == ISC_R_SUCCESS) - result = dns_message_create(notify->zone->mctx, - DNS_MESSAGE_INTENTPARSE, &message); - if (result == ISC_R_SUCCESS) - result = dns_request_getresponse(revent->request, message, - DNS_MESSAGEPARSE_PRESERVEORDER); - if (result == ISC_R_SUCCESS) - result = dns_rcode_totext(message->rcode, &buf); - if (result == ISC_R_SUCCESS) - notify_log(notify->zone, ISC_LOG_DEBUG(3), - "notify response from %s: %.*s", - addrbuf, (int)buf.used, rcode); - else - notify_log(notify->zone, ISC_LOG_DEBUG(2), - "notify to %s failed: %s", addrbuf, - dns_result_totext(result)); + LOCK_ZONE(forward->zone); + if (forward->which >= forward->zone->masterscnt) { + UNLOCK_ZONE(forward->zone); + return (ISC_R_NOMORE); + } + forward->addr = forward->zone->masters[forward->which]; /* - * Old bind's return formerr if they see a soa record. Retry w/o - * the soa if we see a formerr and had sent a SOA. + * Always use TCP regardless of whether the original update + * used TCP. + * XXX The timeout may but a bit small if we are far down a + * transfer graph and the master has to try several masters. */ - isc_event_free(&event); - if (message != NULL && message->rcode == dns_rcode_formerr && - (notify->flags & DNS_NOTIFY_NOSOA) == 0) { - notify->flags |= DNS_NOTIFY_NOSOA; - dns_request_destroy(¬ify->request); - result = notify_send_queue(notify); - if (result != ISC_R_SUCCESS) - notify_destroy(notify, ISC_FALSE); - } else { - if (result == ISC_R_TIMEDOUT) - notify_log(notify->zone, ISC_LOG_DEBUG(1), - "notify to %s: retries exceeded", addrbuf); - notify_destroy(notify, ISC_FALSE); + switch (isc_sockaddr_pf(&forward->addr)) { + case PF_INET: + src = forward->zone->xfrsource4; + break; + case PF_INET6: + src = forward->zone->xfrsource6; + break; + default: + result = ISC_R_NOTIMPLEMENTED; + goto unlock; } - if (message != NULL) - dns_message_destroy(&message); + result = dns_request_createraw(forward->zone->view->requestmgr, + forward->msgbuf, + &src, &forward->addr, + DNS_REQUESTOPT_TCP, 15 /* XXX */, + forward->zone->task, + forward_callback, forward, + &forward->request); + unlock: + UNLOCK_ZONE(forward->zone); + return (result); } -isc_result_t -dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) { +static void +forward_callback(isc_task_t *task, isc_event_t *event) { + const char me[] = "forward_callback"; + dns_requestevent_t *revent = (dns_requestevent_t *)event; + dns_message_t *msg = NULL; + char master[ISC_SOCKADDR_FORMATSIZE]; isc_result_t result; + dns_forward_t *forward; + dns_zone_t *zone; - REQUIRE(DNS_ZONE_VALID(zone)); - LOCK_ZONE(zone); - ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write); - result = zone_replacedb(zone, db, dump); - ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write); - UNLOCK_ZONE(zone); - return (result); -} + UNUSED(task); -static isc_result_t -zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) { - dns_dbversion_t *ver; - isc_result_t result; - unsigned int soacount = 0; - unsigned int nscount = 0; + forward = revent->ev_arg; + INSIST(DNS_FORWARD_VALID(forward)); + zone = forward->zone; + INSIST(DNS_ZONE_VALID(zone)); - /* - * 'zone' and 'zonedb' locked by caller. - */ - REQUIRE(DNS_ZONE_VALID(zone)); - REQUIRE(LOCKED_ZONE(zone)); + ENTER; - result = zone_get_from_db(zone, db, &nscount, &soacount, - NULL, NULL, NULL, NULL, NULL, NULL); - if (result == ISC_R_SUCCESS) { - if (soacount != 1) { - dns_zone_log(zone, ISC_LOG_ERROR, - "has %d SOA records", soacount); - result = DNS_R_BADZONE; - } - if (nscount == 0) { - dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records"); - result = DNS_R_BADZONE; - } - if (result != ISC_R_SUCCESS) - return (result); - } else { - dns_zone_log(zone, ISC_LOG_ERROR, - "retrieving SOA and NS records failed: %s", - dns_result_totext(result)); - return (result); + isc_sockaddr_format(&forward->addr, master, sizeof(master)); + + if (revent->result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_INFO, + "could not forward dynamic update to %s: %s", + master, dns_result_totext(revent->result)); + goto next_master; } - result = check_nsec3param(zone, db); + result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg); if (result != ISC_R_SUCCESS) - return (result); + goto next_master; - ver = NULL; - dns_db_currentversion(db, &ver); + result = dns_request_getresponse(revent->request, msg, + DNS_MESSAGEPARSE_PRESERVEORDER | + DNS_MESSAGEPARSE_CLONEBUFFER); + if (result != ISC_R_SUCCESS) + goto next_master; + switch (msg->rcode) { /* - * The initial version of a slave zone is always dumped; - * subsequent versions may be journaled instead if this - * is enabled in the configuration. + * Pass these rcodes back to client. */ - if (zone->db != NULL && zone->journal != NULL && - DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) && - !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) { - isc_uint32_t serial, oldserial; - - dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs"); + case dns_rcode_noerror: + case dns_rcode_yxdomain: + case dns_rcode_yxrrset: + case dns_rcode_nxrrset: + case dns_rcode_refused: + case dns_rcode_nxdomain: + break; - result = dns_db_getsoaserial(db, ver, &serial); - if (result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_ERROR, - "ixfr-from-differences: unable to get " - "new serial"); - goto fail; - } + /* These should not occur if the masters/zone are valid. */ + case dns_rcode_notzone: + case dns_rcode_notauth: { + char rcode[128]; + isc_buffer_t rb; - /* - * This is checked in zone_postload() for master zones. - */ - result = zone_get_from_db(zone, zone->db, NULL, NULL, - &oldserial, NULL, NULL, NULL, NULL, - NULL); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - if (zone->type == dns_zone_slave && - !isc_serial_gt(serial, oldserial)) { - isc_uint32_t serialmin, serialmax; - serialmin = (oldserial + 1) & 0xffffffffU; - serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU; - dns_zone_log(zone, ISC_LOG_ERROR, - "ixfr-from-differences: failed: " - "new serial (%u) out of range [%u - %u]", - serial, serialmin, serialmax); - result = ISC_R_RANGE; - goto fail; - } + isc_buffer_init(&rb, rcode, sizeof(rcode)); + (void)dns_rcode_totext(msg->rcode, &rb); + dns_zone_log(zone, ISC_LOG_WARNING, + "forwarding dynamic update: " + "unexpected response: master %s returned: %.*s", + master, (int)rb.used, rcode); + goto next_master; + } - result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL, - zone->journal); - if (result != ISC_R_SUCCESS) - goto fail; - if (dump) - zone_needdump(zone, DNS_DUMP_DELAY); - else if (zone->journalsize != -1) { - result = dns_journal_compact(zone->mctx, zone->journal, - serial, zone->journalsize); - switch (result) { - case ISC_R_SUCCESS: - case ISC_R_NOSPACE: - case ISC_R_NOTFOUND: - dns_zone_log(zone, ISC_LOG_DEBUG(3), - "dns_journal_compact: %s", - dns_result_totext(result)); - break; - default: - dns_zone_log(zone, ISC_LOG_ERROR, - "dns_journal_compact failed: %s", - dns_result_totext(result)); - break; - } - } - } else { - if (dump && zone->masterfile != NULL) { - isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, - DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3), - "dumping new zone version"); - result = dns_db_dump2(db, ver, zone->masterfile, - zone->masterformat); - if (result != ISC_R_SUCCESS) - goto fail; + /* Try another server for these rcodes. */ + case dns_rcode_formerr: + case dns_rcode_servfail: + case dns_rcode_notimp: + case dns_rcode_badvers: + default: + goto next_master; + } - /* - * Update the time the zone was updated, so - * dns_zone_load can avoid loading it when - * the server is reloaded. If isc_time_now - * fails for some reason, all that happens is - * the timestamp is not updated. - */ - TIME_NOW(&zone->loadtime); - } + /* call callback */ + (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg); + msg = NULL; + dns_request_destroy(&forward->request); + forward_destroy(forward); + isc_event_free(&event); + return; - if (dump && zone->journal != NULL) { - /* - * The in-memory database just changed, and - * because 'dump' is set, it didn't change by - * being loaded from disk. Also, we have not - * journaled diffs for this change. - * Therefore, the on-disk journal is missing - * the deltas for this change. Since it can - * no longer be used to bring the zone - * up-to-date, it is useless and should be - * removed. - */ - isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, - DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3), - "removing journal file"); - if (remove(zone->journal) < 0 && errno != ENOENT) { - char strbuf[ISC_STRERRORSIZE]; - isc__strerror(errno, strbuf, sizeof(strbuf)); - isc_log_write(dns_lctx, - DNS_LOGCATEGORY_GENERAL, - DNS_LOGMODULE_ZONE, - ISC_LOG_WARNING, - "unable to remove journal " - "'%s': '%s'", - zone->journal, strbuf); - } - } + next_master: + if (msg != NULL) + dns_message_destroy(&msg); + isc_event_free(&event); + forward->which++; + dns_request_destroy(&forward->request); + result = sendtomaster(forward); + if (result != ISC_R_SUCCESS) { + /* call callback */ + dns_zone_log(zone, ISC_LOG_DEBUG(3), + "exhausted dynamic update forwarder list"); + (forward->callback)(forward->callback_arg, result, NULL); + forward_destroy(forward); } +} + +isc_result_t +dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg, + dns_updatecallback_t callback, void *callback_arg) +{ + dns_forward_t *forward; + isc_result_t result; + isc_region_t *mr; + + REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(msg != NULL); + REQUIRE(callback != NULL); + + forward = isc_mem_get(zone->mctx, sizeof(*forward)); + if (forward == NULL) + return (ISC_R_NOMEMORY); + + forward->request = NULL; + forward->zone = NULL; + forward->msgbuf = NULL; + forward->which = 0; + forward->mctx = 0; + forward->callback = callback; + forward->callback_arg = callback_arg; + forward->magic = FORWARD_MAGIC; - dns_db_closeversion(db, &ver, ISC_FALSE); + mr = dns_message_getrawmessage(msg); + if (mr == NULL) { + result = ISC_R_UNEXPECTEDEND; + goto cleanup; + } - isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, - DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3), - "replacing zone database"); + result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = isc_buffer_copyregion(forward->msgbuf, mr); + if (result != ISC_R_SUCCESS) + goto cleanup; - if (zone->db != NULL) - zone_detachdb(zone); - zone_attachdb(zone, db); - dns_db_settask(zone->db, zone->task); - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY); - return (ISC_R_SUCCESS); + isc_mem_attach(zone->mctx, &forward->mctx); + dns_zone_iattach(zone, &forward->zone); + result = sendtomaster(forward); - fail: - dns_db_closeversion(db, &ver, ISC_FALSE); + cleanup: + if (result != ISC_R_SUCCESS) { + forward_destroy(forward); + } return (result); } -/* The caller must hold the dblock as a writer. */ -static inline void -zone_attachdb(dns_zone_t *zone, dns_db_t *db) { - REQUIRE(zone->db == NULL && db != NULL); +isc_result_t +dns_zone_next(dns_zone_t *zone, dns_zone_t **next) { + REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(next != NULL && *next == NULL); - dns_db_attach(db, &zone->db); - if (zone->acache != NULL) { - isc_result_t result; - result = dns_acache_setdb(zone->acache, db); - if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "dns_acache_setdb() failed: %s", - isc_result_totext(result)); - } - } + *next = ISC_LIST_NEXT(zone, link); + if (*next == NULL) + return (ISC_R_NOMORE); + else + return (ISC_R_SUCCESS); } -/* The caller must hold the dblock as a writer. */ -static inline void -zone_detachdb(dns_zone_t *zone) { - REQUIRE(zone->db != NULL); +isc_result_t +dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) { + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); + REQUIRE(first != NULL && *first == NULL); - if (zone->acache != NULL) - (void)dns_acache_putdb(zone->acache, zone->db); - dns_db_detach(&zone->db); + *first = ISC_LIST_HEAD(zmgr->zones); + if (*first == NULL) + return (ISC_R_NOMORE); + else + return (ISC_R_SUCCESS); } -static void -zone_xfrdone(dns_zone_t *zone, isc_result_t result) { - isc_time_t now; - isc_boolean_t again = ISC_FALSE; - unsigned int soacount; - unsigned int nscount; - isc_uint32_t serial, refresh, retry, expire, minimum; - isc_result_t xfrresult = result; - isc_boolean_t free_needed; +/*** + *** Zone manager. + ***/ - REQUIRE(DNS_ZONE_VALID(zone)); +isc_result_t +dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, + isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr, + dns_zonemgr_t **zmgrp) +{ + dns_zonemgr_t *zmgr; + isc_result_t result; + isc_interval_t interval; - dns_zone_log(zone, ISC_LOG_DEBUG(1), - "zone transfer finished: %s", dns_result_totext(result)); + zmgr = isc_mem_get(mctx, sizeof(*zmgr)); + if (zmgr == NULL) + return (ISC_R_NOMEMORY); + zmgr->mctx = NULL; + zmgr->refs = 1; + isc_mem_attach(mctx, &zmgr->mctx); + zmgr->taskmgr = taskmgr; + zmgr->timermgr = timermgr; + zmgr->socketmgr = socketmgr; + zmgr->zonetasks = NULL; + zmgr->task = NULL; + zmgr->rl = NULL; + ISC_LIST_INIT(zmgr->zones); + ISC_LIST_INIT(zmgr->waiting_for_xfrin); + ISC_LIST_INIT(zmgr->xfrin_in_progress); + memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable)); + result = isc_rwlock_init(&zmgr->rwlock, 0, 0); + if (result != ISC_R_SUCCESS) + goto free_mem; - LOCK_ZONE(zone); - INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0); - DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH); - DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR); + zmgr->transfersin = 10; + zmgr->transfersperns = 2; - TIME_NOW(&now); - switch (result) { - case ISC_R_SUCCESS: - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY); - /*FALLTHROUGH*/ - case DNS_R_UPTODATE: - DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER); - /* - * Has the zone expired underneath us? - */ - ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); - if (zone->db == NULL) { - ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); - goto same_master; - } + /* Create the zone task pool. */ + result = isc_taskpool_create(taskmgr, mctx, + 8 /* XXX */, 2, &zmgr->zonetasks); + if (result != ISC_R_SUCCESS) + goto free_rwlock; - /* - * Update the zone structure's data from the actual - * SOA received. - */ - nscount = 0; - soacount = 0; - INSIST(zone->db != NULL); - result = zone_get_from_db(zone, zone->db, &nscount, - &soacount, &serial, &refresh, - &retry, &expire, &minimum, NULL); - ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); - if (result == ISC_R_SUCCESS) { - if (soacount != 1) - dns_zone_log(zone, ISC_LOG_ERROR, - "transferred zone " - "has %d SOA record%s", soacount, - (soacount != 0) ? "s" : ""); - if (nscount == 0) { - dns_zone_log(zone, ISC_LOG_ERROR, - "transferred zone " - "has no NS records"); - if (DNS_ZONE_FLAG(zone, - DNS_ZONEFLG_HAVETIMERS)) { - zone->refresh = DNS_ZONE_DEFAULTREFRESH; - zone->retry = DNS_ZONE_DEFAULTRETRY; - } - DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS); - zone_unload(zone); - goto next_master; - } - zone->refresh = RANGE(refresh, zone->minrefresh, - zone->maxrefresh); - zone->retry = RANGE(retry, zone->minretry, - zone->maxretry); - zone->expire = RANGE(expire, - zone->refresh + zone->retry, - DNS_MAX_EXPIRE); - zone->minimum = minimum; - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS); - } + /* Create a single task for queueing of SOA queries. */ + result = isc_task_create(taskmgr, 1, &zmgr->task); + if (result != ISC_R_SUCCESS) + goto free_taskpool; + isc_task_setname(zmgr->task, "zmgr", zmgr); + result = isc_ratelimiter_create(mctx, timermgr, zmgr->task, + &zmgr->rl); + if (result != ISC_R_SUCCESS) + goto free_task; + /* default to 20 refresh queries / notifies per second. */ + isc_interval_set(&interval, 0, 1000000000/2); + result = isc_ratelimiter_setinterval(zmgr->rl, &interval); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + isc_ratelimiter_setpertic(zmgr->rl, 10); - /* - * Set our next update/expire times. - */ - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) { - DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH); - zone->refreshtime = now; - DNS_ZONE_TIME_ADD(&now, zone->expire, - &zone->expiretime); - } else { - DNS_ZONE_JITTER_ADD(&now, zone->refresh, - &zone->refreshtime); - DNS_ZONE_TIME_ADD(&now, zone->expire, - &zone->expiretime); - } - if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) { - char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")]; - if (zone->tsigkey != NULL) { - char namebuf[DNS_NAME_FORMATSIZE]; - dns_name_format(&zone->tsigkey->name, namebuf, - sizeof(namebuf)); - snprintf(buf, sizeof(buf), ": TSIG '%s'", - namebuf); - } else - buf[0] = '\0'; - dns_zone_log(zone, ISC_LOG_INFO, - "transferred serial %u%s", - serial, buf); - } + zmgr->iolimit = 1; + zmgr->ioactive = 0; + ISC_LIST_INIT(zmgr->high); + ISC_LIST_INIT(zmgr->low); + + result = isc_mutex_init(&zmgr->iolock); + if (result != ISC_R_SUCCESS) + goto free_rl; + + zmgr->magic = ZONEMGR_MAGIC; + + *zmgrp = zmgr; + return (ISC_R_SUCCESS); + +#if 0 + free_iolock: + DESTROYLOCK(&zmgr->iolock); +#endif + free_rl: + isc_ratelimiter_detach(&zmgr->rl); + free_task: + isc_task_detach(&zmgr->task); + free_taskpool: + isc_taskpool_destroy(&zmgr->zonetasks); + free_rwlock: + isc_rwlock_destroy(&zmgr->rwlock); + free_mem: + isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr)); + isc_mem_detach(&mctx); + return (result); +} - /* - * This is not necessary if we just performed a AXFR - * however it is necessary for an IXFR / UPTODATE and - * won't hurt with an AXFR. - */ - if (zone->masterfile != NULL || zone->journal != NULL) { - result = ISC_R_FAILURE; - if (zone->journal != NULL) - result = isc_file_settime(zone->journal, &now); - if (result != ISC_R_SUCCESS && - zone->masterfile != NULL) - result = isc_file_settime(zone->masterfile, - &now); - /* Someone removed the file from underneath us! */ - if (result == ISC_R_FILENOTFOUND && - zone->masterfile != NULL) - zone_needdump(zone, DNS_DUMP_DELAY); - else if (result != ISC_R_SUCCESS) - dns_zone_log(zone, ISC_LOG_ERROR, - "transfer: could not set file " - "modification time of '%s': %s", - zone->masterfile, - dns_result_totext(result)); - } +isc_result_t +dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) { + isc_result_t result; - inc_stats(zone, dns_zonestatscounter_xfrsuccess); - break; + REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); - case DNS_R_BADIXFR: - /* Force retry with AXFR. */ - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR); - goto same_master; + RWLOCK(&zmgr->rwlock, isc_rwlocktype_write); + LOCK_ZONE(zone); + REQUIRE(zone->task == NULL); + REQUIRE(zone->timer == NULL); + REQUIRE(zone->zmgr == NULL); - default: - next_master: - /* - * Skip to next failed / untried master. - */ - do { - zone->curmaster++; - } while (zone->curmaster < zone->masterscnt && - zone->mastersok[zone->curmaster]); - /* FALLTHROUGH */ - same_master: - if (zone->curmaster >= zone->masterscnt) { - zone->curmaster = 0; - if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) && - !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) { - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH); - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC); - while (zone->curmaster < zone->masterscnt && - zone->mastersok[zone->curmaster]) - zone->curmaster++; - again = ISC_TRUE; - } else - DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC); - } else { - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH); - again = ISC_TRUE; - } - inc_stats(zone, dns_zonestatscounter_xfrfail); - break; - } - zone_settimer(zone, &now); + isc_taskpool_gettask(zmgr->zonetasks, + dns_name_hash(dns_zone_getorigin(zone), + ISC_FALSE), + &zone->task); /* - * If creating the transfer object failed, zone->xfr is NULL. - * Otherwise, we are called as the done callback of a zone - * transfer object that just entered its shutting-down - * state. Since we are no longer responsible for shutting - * it down, we can detach our reference. + * Set the task name. The tag will arbitrarily point to one + * of the zones sharing the task (in practice, the one + * to be managed last). */ - if (zone->xfr != NULL) - dns_xfrin_detach(&zone->xfr); + isc_task_setname(zone->task, "zone", zone); - if (zone->tsigkey != NULL) - dns_tsigkey_detach(&zone->tsigkey); + result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive, + NULL, NULL, + zone->task, zone_timer, zone, + &zone->timer); - /* - * Handle any deferred journal compaction. - */ - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) { - result = dns_journal_compact(zone->mctx, zone->journal, - zone->compact_serial, - zone->journalsize); - switch (result) { - case ISC_R_SUCCESS: - case ISC_R_NOSPACE: - case ISC_R_NOTFOUND: - dns_zone_log(zone, ISC_LOG_DEBUG(3), - "dns_journal_compact: %s", - dns_result_totext(result)); - break; - default: - dns_zone_log(zone, ISC_LOG_ERROR, - "dns_journal_compact failed: %s", - dns_result_totext(result)); - break; - } - DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT); - } + if (result != ISC_R_SUCCESS) + goto cleanup_task; /* - * This transfer finishing freed up a transfer quota slot. - * Let any other zones waiting for quota have it. + * The timer "holds" a iref. */ - RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write); - ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink); - zone->statelist = NULL; - zmgr_resume_xfrs(zone->zmgr, ISC_FALSE); - RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write); + zone->irefs++; + INSIST(zone->irefs != 0); - /* - * Retry with a different server if necessary. - */ - if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) - queue_soa_query(zone); + ISC_LIST_APPEND(zmgr->zones, zone, link); + zone->zmgr = zmgr; + zmgr->refs++; - INSIST(zone->irefs > 0); - zone->irefs--; - free_needed = exit_check(zone); + goto unlock; + + cleanup_task: + isc_task_detach(&zone->task); + + unlock: UNLOCK_ZONE(zone); - if (free_needed) - zone_free(zone); + RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write); + return (result); } -static void -zone_loaddone(void *arg, isc_result_t result) { - static char me[] = "zone_loaddone"; - dns_load_t *load = arg; - dns_zone_t *zone; - isc_result_t tresult; +void +dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) { + isc_boolean_t free_now = ISC_FALSE; - REQUIRE(DNS_LOAD_VALID(load)); - zone = load->zone; + REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); + REQUIRE(zone->zmgr == zmgr); - ENTER; + RWLOCK(&zmgr->rwlock, isc_rwlocktype_write); + LOCK_ZONE(zone); - tresult = dns_db_endload(load->db, &load->callbacks.add_private); - if (tresult != ISC_R_SUCCESS && - (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE)) - result = tresult; + ISC_LIST_UNLINK(zmgr->zones, zone, link); + zone->zmgr = NULL; + zmgr->refs--; + if (zmgr->refs == 0) + free_now = ISC_TRUE; + + UNLOCK_ZONE(zone); + RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write); + + if (free_now) + zonemgr_free(zmgr); + ENSURE(zone->zmgr == NULL); +} + +void +dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) { + REQUIRE(DNS_ZONEMGR_VALID(source)); + REQUIRE(target != NULL && *target == NULL); + + RWLOCK(&source->rwlock, isc_rwlocktype_write); + REQUIRE(source->refs > 0); + source->refs++; + INSIST(source->refs > 0); + RWUNLOCK(&source->rwlock, isc_rwlocktype_write); + *target = source; +} + +void +dns_zonemgr_detach(dns_zonemgr_t **zmgrp) { + dns_zonemgr_t *zmgr; + isc_boolean_t free_now = ISC_FALSE; + + REQUIRE(zmgrp != NULL); + zmgr = *zmgrp; + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); + + RWLOCK(&zmgr->rwlock, isc_rwlocktype_write); + zmgr->refs--; + if (zmgr->refs == 0) + free_now = ISC_TRUE; + RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write); + + if (free_now) + zonemgr_free(zmgr); +} + +isc_result_t +dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) { + dns_zone_t *p; + + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); + + RWLOCK(&zmgr->rwlock, isc_rwlocktype_read); + for (p = ISC_LIST_HEAD(zmgr->zones); + p != NULL; + p = ISC_LIST_NEXT(p, link)) + { + dns_zone_maintenance(p); + } + RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read); - LOCK_ZONE(load->zone); - (void)zone_postload(load->zone, load->db, load->loadtime, result); - zonemgr_putio(&load->zone->readio); - DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADING); /* - * Leave the zone frozen if the reload fails. + * Recent configuration changes may have increased the + * amount of available transfers quota. Make sure any + * transfers currently blocked on quota get started if + * possible. */ - if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) && - DNS_ZONE_FLAG(load->zone, DNS_ZONEFLG_THAW)) - zone->update_disabled = ISC_FALSE; - DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_THAW); - UNLOCK_ZONE(load->zone); + RWLOCK(&zmgr->rwlock, isc_rwlocktype_write); + zmgr_resume_xfrs(zmgr, ISC_TRUE); + RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write); + return (ISC_R_SUCCESS); +} - load->magic = 0; - dns_db_detach(&load->db); - if (load->zone->lctx != NULL) - dns_loadctx_detach(&load->zone->lctx); - dns_zone_idetach(&load->zone); - isc_mem_putanddetach(&load->mctx, load, sizeof(*load)); +void +dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) { + + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); + + RWLOCK(&zmgr->rwlock, isc_rwlocktype_write); + zmgr_resume_xfrs(zmgr, ISC_TRUE); + RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write); } void -dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) { - REQUIRE(DNS_ZONE_VALID(zone)); - REQUIRE(table != NULL); - REQUIRE(*table == NULL); +dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) { + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); - LOCK_ZONE(zone); - if (zone->ssutable != NULL) - dns_ssutable_attach(zone->ssutable, table); - UNLOCK_ZONE(zone); + isc_ratelimiter_shutdown(zmgr->rl); + + if (zmgr->task != NULL) + isc_task_destroy(&zmgr->task); + if (zmgr->zonetasks != NULL) + isc_taskpool_destroy(&zmgr->zonetasks); } -void -dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) { - REQUIRE(DNS_ZONE_VALID(zone)); +static void +zonemgr_free(dns_zonemgr_t *zmgr) { + isc_mem_t *mctx; - LOCK_ZONE(zone); - if (zone->ssutable != NULL) - dns_ssutable_detach(&zone->ssutable); - if (table != NULL) - dns_ssutable_attach(table, &zone->ssutable); - UNLOCK_ZONE(zone); + INSIST(zmgr->refs == 0); + INSIST(ISC_LIST_EMPTY(zmgr->zones)); + + zmgr->magic = 0; + + DESTROYLOCK(&zmgr->iolock); + isc_ratelimiter_detach(&zmgr->rl); + + isc_rwlock_destroy(&zmgr->rwlock); + mctx = zmgr->mctx; + isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr)); + isc_mem_detach(&mctx); } void -dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) { - REQUIRE(DNS_ZONE_VALID(zone)); +dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) { + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); - zone->sigvalidityinterval = interval; + zmgr->transfersin = value; } isc_uint32_t -dns_zone_getsigvalidityinterval(dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); +dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) { + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); - return (zone->sigvalidityinterval); + return (zmgr->transfersin); } void -dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) { - REQUIRE(DNS_ZONE_VALID(zone)); +dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) { + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); - zone->sigresigninginterval = interval; + zmgr->transfersperns = value; } isc_uint32_t -dns_zone_getsigresigninginterval(dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); +dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) { + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); - return (zone->sigresigninginterval); + return (zmgr->transfersperns); } +/* + * Try to start a new incoming zone transfer to fill a quota + * slot that was just vacated. + * + * Requires: + * The zone manager is locked by the caller. + */ static void -queue_xfrin(dns_zone_t *zone) { - const char me[] = "queue_xfrin"; - isc_result_t result; - dns_zonemgr_t *zmgr = zone->zmgr; - - ENTER; - - INSIST(zone->statelist == NULL); - - RWLOCK(&zmgr->rwlock, isc_rwlocktype_write); - ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink); - LOCK_ZONE(zone); - zone->irefs++; - UNLOCK_ZONE(zone); - zone->statelist = &zmgr->waiting_for_xfrin; - result = zmgr_start_xfrin_ifquota(zmgr, zone); - RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write); +zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) { + dns_zone_t *zone; + dns_zone_t *next; - if (result == ISC_R_QUOTA) { - dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO, - "zone transfer deferred due to quota"); - } else if (result != ISC_R_SUCCESS) { - dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR, - "starting zone transfer: %s", - isc_result_totext(result)); + for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin); + zone != NULL; + zone = next) + { + isc_result_t result; + next = ISC_LIST_NEXT(zone, statelink); + result = zmgr_start_xfrin_ifquota(zmgr, zone); + if (result == ISC_R_SUCCESS) { + if (multi) + continue; + /* + * We successfully filled the slot. We're done. + */ + break; + } else if (result == ISC_R_QUOTA) { + /* + * Not enough quota. This is probably the per-server + * quota, because we usually get called when a unit of + * global quota has just been freed. Try the next + * zone, it may succeed if it uses another master. + */ + continue; + } else { + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "starting zone transfer: %s", + isc_result_totext(result)); + break; + } } } /* - * This event callback is called when a zone has received - * any necessary zone transfer quota. This is the time - * to go ahead and start the transfer. + * Try to start an incoming zone transfer for 'zone', quota permitting. + * + * Requires: + * The zone manager is locked by the caller. + * + * Returns: + * ISC_R_SUCCESS There was enough quota and we attempted to + * start a transfer. zone_xfrdone() has been or will + * be called. + * ISC_R_QUOTA Not enough quota. + * Others Failure. */ -static void -got_transfer_quota(isc_task_t *task, isc_event_t *event) { - isc_result_t result; +static isc_result_t +zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) { dns_peer_t *peer = NULL; - char master[ISC_SOCKADDR_FORMATSIZE]; - char source[ISC_SOCKADDR_FORMATSIZE]; - dns_rdatatype_t xfrtype; - dns_zone_t *zone = event->ev_arg; isc_netaddr_t masterip; - isc_sockaddr_t sourceaddr; - isc_sockaddr_t masteraddr; - isc_time_t now; - const char *soa_before = ""; - - UNUSED(task); - - INSIST(task == zone->task); - - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) { - result = ISC_R_CANCELED; - goto cleanup; - } - - TIME_NOW(&now); - - isc_sockaddr_format(&zone->masteraddr, master, sizeof(master)); - if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr, - &zone->sourceaddr, &now)) { - isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source)); - dns_zone_log(zone, ISC_LOG_INFO, - "got_transfer_quota: skipping zone transfer as " - "master %s (source %s) is unreachable (cached)", - master, source); - result = ISC_R_CANCELED; - goto cleanup; - } - - isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr); - (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer); + isc_uint32_t nxfrsin, nxfrsperns; + dns_zone_t *x; + isc_uint32_t maxtransfersin, maxtransfersperns; + isc_event_t *e; - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) - soa_before = "SOA before "; /* - * Decide whether we should request IXFR or AXFR. + * Find any configured information about the server we'd + * like to transfer this zone from. */ - if (zone->db == NULL) { - dns_zone_log(zone, ISC_LOG_DEBUG(1), - "no database exists yet, requesting AXFR of " - "initial version from %s", master); - xfrtype = dns_rdatatype_axfr; - } else if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) { - dns_zone_log(zone, ISC_LOG_DEBUG(1), "ixfr-from-differences " - "set, requesting %sAXFR from %s", soa_before, - master); - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) - xfrtype = dns_rdatatype_soa; - else - xfrtype = dns_rdatatype_axfr; - } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) { - dns_zone_log(zone, ISC_LOG_DEBUG(1), - "forced reload, requesting AXFR of " - "initial version from %s", master); - xfrtype = dns_rdatatype_axfr; - } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) { - dns_zone_log(zone, ISC_LOG_DEBUG(1), - "retrying with AXFR from %s due to " - "previous IXFR failure", master); - xfrtype = dns_rdatatype_axfr; - LOCK_ZONE(zone); - DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR); - UNLOCK_ZONE(zone); - } else { - isc_boolean_t use_ixfr = ISC_TRUE; - if (peer != NULL && - dns_peer_getrequestixfr(peer, &use_ixfr) == - ISC_R_SUCCESS) { - ; /* Using peer setting */ - } else { - use_ixfr = zone->view->requestixfr; - } - if (use_ixfr == ISC_FALSE) { - dns_zone_log(zone, ISC_LOG_DEBUG(1), - "IXFR disabled, requesting %sAXFR from %s", - soa_before, master); - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) - xfrtype = dns_rdatatype_soa; - else - xfrtype = dns_rdatatype_axfr; - } else { - dns_zone_log(zone, ISC_LOG_DEBUG(1), - "requesting IXFR from %s", master); - xfrtype = dns_rdatatype_ixfr; - } - } + isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr); + (void)dns_peerlist_peerbyaddr(zone->view->peers, + &masterip, &peer); /* - * Determine if we should attempt to sign the request with TSIG. + * Determine the total maximum number of simultaneous + * transfers allowed, and the maximum for this specific + * master. */ - result = ISC_R_NOTFOUND; + maxtransfersin = zmgr->transfersin; + maxtransfersperns = zmgr->transfersperns; + if (peer != NULL) + (void)dns_peer_gettransfers(peer, &maxtransfersperns); + /* - * First, look for a tsig key in the master statement, then - * try for a server key. + * Count the total number of transfers that are in progress, + * and the number of transfers in progress from this master. + * We linearly scan a list of all transfers; if this turns + * out to be too slow, we could hash on the master address. */ - if ((zone->masterkeynames != NULL) && - (zone->masterkeynames[zone->curmaster] != NULL)) { - dns_view_t *view = dns_zone_getview(zone); - dns_name_t *keyname = zone->masterkeynames[zone->curmaster]; - result = dns_view_gettsig(view, keyname, &zone->tsigkey); + nxfrsin = nxfrsperns = 0; + for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress); + x != NULL; + x = ISC_LIST_NEXT(x, statelink)) + { + isc_netaddr_t xip; + isc_netaddr_fromsockaddr(&xip, &x->masteraddr); + nxfrsin++; + if (isc_netaddr_equal(&xip, &masterip)) + nxfrsperns++; } - if (zone->tsigkey == NULL) - result = dns_view_getpeertsig(zone->view, &masterip, - &zone->tsigkey); - if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) { - dns_zone_log(zone, ISC_LOG_ERROR, - "could not get TSIG key for zone transfer: %s", - isc_result_totext(result)); - } + /* Enforce quota. */ + if (nxfrsin >= maxtransfersin) + return (ISC_R_QUOTA); + + if (nxfrsperns >= maxtransfersperns) + return (ISC_R_QUOTA); - LOCK_ZONE(zone); - masteraddr = zone->masteraddr; - sourceaddr = zone->sourceaddr; - UNLOCK_ZONE(zone); - INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr)); - result = dns_xfrin_create2(zone, xfrtype, &masteraddr, &sourceaddr, - zone->tsigkey, zone->mctx, - zone->zmgr->timermgr, zone->zmgr->socketmgr, - zone->task, zone_xfrdone, &zone->xfr); - if (result == ISC_R_SUCCESS) { - LOCK_ZONE(zone); - if (xfrtype == dns_rdatatype_axfr) { - if (isc_sockaddr_pf(&masteraddr) == PF_INET) - inc_stats(zone, dns_zonestatscounter_axfrreqv4); - else - inc_stats(zone, dns_zonestatscounter_axfrreqv6); - } else if (xfrtype == dns_rdatatype_ixfr) { - if (isc_sockaddr_pf(&masteraddr) == PF_INET) - inc_stats(zone, dns_zonestatscounter_ixfrreqv4); - else - inc_stats(zone, dns_zonestatscounter_ixfrreqv6); - } - UNLOCK_ZONE(zone); - } - cleanup: /* - * Any failure in this function is handled like a failed - * zone transfer. This ensures that we get removed from - * zmgr->xfrin_in_progress. + * We have sufficient quota. Move the zone to the "xfrin_in_progress" + * list and send it an event to let it start the actual transfer in the + * context of its own task. */ - if (result != ISC_R_SUCCESS) - zone_xfrdone(zone, result); + e = isc_event_allocate(zmgr->mctx, zmgr, + DNS_EVENT_ZONESTARTXFRIN, + got_transfer_quota, zone, + sizeof(isc_event_t)); + if (e == NULL) + return (ISC_R_NOMEMORY); - isc_event_free(&event); + LOCK_ZONE(zone); + INSIST(zone->statelist == &zmgr->waiting_for_xfrin); + ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink); + ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink); + zone->statelist = &zmgr->xfrin_in_progress; + isc_task_send(zone->task, &e); + dns_zone_log(zone, ISC_LOG_INFO, "Transfer started."); + UNLOCK_ZONE(zone); + + return (ISC_R_SUCCESS); } -/* - * Update forwarding support. - */ +void +dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) { -static void -forward_destroy(dns_forward_t *forward) { + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); + REQUIRE(iolimit > 0); - forward->magic = 0; - if (forward->request != NULL) - dns_request_destroy(&forward->request); - if (forward->msgbuf != NULL) - isc_buffer_free(&forward->msgbuf); - if (forward->zone != NULL) - dns_zone_idetach(&forward->zone); - isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward)); + zmgr->iolimit = iolimit; +} + +isc_uint32_t +dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) { + + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); + + return (zmgr->iolimit); } +/* + * Get permission to request a file handle from the OS. + * An event will be sent to action when one is available. + * There are two queues available (high and low), the high + * queue will be serviced before the low one. + * + * zonemgr_putio() must be called after the event is delivered to + * 'action'. + */ + static isc_result_t -sendtomaster(dns_forward_t *forward) { - isc_result_t result; - isc_sockaddr_t src; +zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high, + isc_task_t *task, isc_taskaction_t action, void *arg, + dns_io_t **iop) +{ + dns_io_t *io; + isc_boolean_t queue; - LOCK_ZONE(forward->zone); - if (forward->which >= forward->zone->masterscnt) { - UNLOCK_ZONE(forward->zone); - return (ISC_R_NOMORE); + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); + REQUIRE(iop != NULL && *iop == NULL); + + io = isc_mem_get(zmgr->mctx, sizeof(*io)); + if (io == NULL) + return (ISC_R_NOMEMORY); + io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY, + action, arg, sizeof(*io->event)); + if (io->event == NULL) { + isc_mem_put(zmgr->mctx, io, sizeof(*io)); + return (ISC_R_NOMEMORY); } + io->zmgr = zmgr; + io->high = high; + io->task = NULL; + isc_task_attach(task, &io->task); + ISC_LINK_INIT(io, link); + io->magic = IO_MAGIC; - forward->addr = forward->zone->masters[forward->which]; - /* - * Always use TCP regardless of whether the original update - * used TCP. - * XXX The timeout may but a bit small if we are far down a - * transfer graph and the master has to try several masters. - */ - switch (isc_sockaddr_pf(&forward->addr)) { - case PF_INET: - src = forward->zone->xfrsource4; - break; - case PF_INET6: - src = forward->zone->xfrsource6; - break; - default: - result = ISC_R_NOTIMPLEMENTED; - goto unlock; + LOCK(&zmgr->iolock); + zmgr->ioactive++; + queue = ISC_TF(zmgr->ioactive > zmgr->iolimit); + if (queue) { + if (io->high) + ISC_LIST_APPEND(zmgr->high, io, link); + else + ISC_LIST_APPEND(zmgr->low, io, link); } - result = dns_request_createraw(forward->zone->view->requestmgr, - forward->msgbuf, - &src, &forward->addr, - DNS_REQUESTOPT_TCP, 15 /* XXX */, - forward->zone->task, - forward_callback, forward, - &forward->request); - unlock: - UNLOCK_ZONE(forward->zone); - return (result); + UNLOCK(&zmgr->iolock); + *iop = io; + + if (!queue) { + isc_task_send(io->task, &io->event); + } + return (ISC_R_SUCCESS); } static void -forward_callback(isc_task_t *task, isc_event_t *event) { - const char me[] = "forward_callback"; - dns_requestevent_t *revent = (dns_requestevent_t *)event; - dns_message_t *msg = NULL; - char master[ISC_SOCKADDR_FORMATSIZE]; - isc_result_t result; - dns_forward_t *forward; - dns_zone_t *zone; +zonemgr_putio(dns_io_t **iop) { + dns_io_t *io; + dns_io_t *next; + dns_zonemgr_t *zmgr; - UNUSED(task); + REQUIRE(iop != NULL); + io = *iop; + REQUIRE(DNS_IO_VALID(io)); - forward = revent->ev_arg; - INSIST(DNS_FORWARD_VALID(forward)); - zone = forward->zone; - INSIST(DNS_ZONE_VALID(zone)); + *iop = NULL; - ENTER; + INSIST(!ISC_LINK_LINKED(io, link)); + INSIST(io->event == NULL); - isc_sockaddr_format(&forward->addr, master, sizeof(master)); + zmgr = io->zmgr; + isc_task_detach(&io->task); + io->magic = 0; + isc_mem_put(zmgr->mctx, io, sizeof(*io)); - if (revent->result != ISC_R_SUCCESS) { - dns_zone_log(zone, ISC_LOG_INFO, - "could not forward dynamic update to %s: %s", - master, dns_result_totext(revent->result)); - goto next_master; + LOCK(&zmgr->iolock); + INSIST(zmgr->ioactive > 0); + zmgr->ioactive--; + next = HEAD(zmgr->high); + if (next == NULL) + next = HEAD(zmgr->low); + if (next != NULL) { + if (next->high) + ISC_LIST_UNLINK(zmgr->high, next, link); + else + ISC_LIST_UNLINK(zmgr->low, next, link); + INSIST(next->event != NULL); } + UNLOCK(&zmgr->iolock); + if (next != NULL) + isc_task_send(next->task, &next->event); +} - result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg); - if (result != ISC_R_SUCCESS) - goto next_master; +static void +zonemgr_cancelio(dns_io_t *io) { + isc_boolean_t send_event = ISC_FALSE; - result = dns_request_getresponse(revent->request, msg, - DNS_MESSAGEPARSE_PRESERVEORDER | - DNS_MESSAGEPARSE_CLONEBUFFER); - if (result != ISC_R_SUCCESS) - goto next_master; + REQUIRE(DNS_IO_VALID(io)); - switch (msg->rcode) { /* - * Pass these rcodes back to client. + * If we are queued to be run then dequeue. */ - case dns_rcode_noerror: - case dns_rcode_yxdomain: - case dns_rcode_yxrrset: - case dns_rcode_nxrrset: - case dns_rcode_refused: - case dns_rcode_nxdomain: - break; - - /* These should not occur if the masters/zone are valid. */ - case dns_rcode_notzone: - case dns_rcode_notauth: { - char rcode[128]; - isc_buffer_t rb; - - isc_buffer_init(&rb, rcode, sizeof(rcode)); - (void)dns_rcode_totext(msg->rcode, &rb); - dns_zone_log(zone, ISC_LOG_WARNING, - "forwarding dynamic update: " - "unexpected response: master %s returned: %.*s", - master, (int)rb.used, rcode); - goto next_master; - } + LOCK(&io->zmgr->iolock); + if (ISC_LINK_LINKED(io, link)) { + if (io->high) + ISC_LIST_UNLINK(io->zmgr->high, io, link); + else + ISC_LIST_UNLINK(io->zmgr->low, io, link); - /* Try another server for these rcodes. */ - case dns_rcode_formerr: - case dns_rcode_servfail: - case dns_rcode_notimp: - case dns_rcode_badvers: - default: - goto next_master; + send_event = ISC_TRUE; + INSIST(io->event != NULL); } - - /* call callback */ - (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg); - msg = NULL; - dns_request_destroy(&forward->request); - forward_destroy(forward); - isc_event_free(&event); - return; - - next_master: - if (msg != NULL) - dns_message_destroy(&msg); - isc_event_free(&event); - forward->which++; - dns_request_destroy(&forward->request); - result = sendtomaster(forward); - if (result != ISC_R_SUCCESS) { - /* call callback */ - dns_zone_log(zone, ISC_LOG_DEBUG(3), - "exhausted dynamic update forwarder list"); - (forward->callback)(forward->callback_arg, result, NULL); - forward_destroy(forward); + UNLOCK(&io->zmgr->iolock); + if (send_event) { + io->event->ev_attributes |= ISC_EVENTATTR_CANCELED; + isc_task_send(io->task, &io->event); } } -isc_result_t -dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg, - dns_updatecallback_t callback, void *callback_arg) -{ - dns_forward_t *forward; +static void +zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) { + char *buf; + int buflen; isc_result_t result; - isc_region_t *mr; - - REQUIRE(DNS_ZONE_VALID(zone)); - REQUIRE(msg != NULL); - REQUIRE(callback != NULL); - forward = isc_mem_get(zone->mctx, sizeof(*forward)); - if (forward == NULL) - return (ISC_R_NOMEMORY); - - forward->request = NULL; - forward->zone = NULL; - forward->msgbuf = NULL; - forward->which = 0; - forward->mctx = 0; - forward->callback = callback; - forward->callback_arg = callback_arg; - forward->magic = FORWARD_MAGIC; + buflen = strlen(path) + strlen(templat) + 2; - mr = dns_message_getrawmessage(msg); - if (mr == NULL) { - result = ISC_R_UNEXPECTEDEND; - goto cleanup; - } + buf = isc_mem_get(zone->mctx, buflen); + if (buf == NULL) + return; - result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length); + result = isc_file_template(path, templat, buf, buflen); if (result != ISC_R_SUCCESS) goto cleanup; - result = isc_buffer_copyregion(forward->msgbuf, mr); + + result = isc_file_renameunique(path, buf); if (result != ISC_R_SUCCESS) goto cleanup; - isc_mem_attach(zone->mctx, &forward->mctx); - dns_zone_iattach(zone, &forward->zone); - result = sendtomaster(forward); + dns_zone_log(zone, ISC_LOG_WARNING, "saved '%s' as '%s'", + path, buf); cleanup: - if (result != ISC_R_SUCCESS) { - forward_destroy(forward); - } - return (result); + isc_mem_put(zone->mctx, buf, buflen); } -isc_result_t -dns_zone_next(dns_zone_t *zone, dns_zone_t **next) { - REQUIRE(DNS_ZONE_VALID(zone)); - REQUIRE(next != NULL && *next == NULL); +#if 0 +/* Hook for ondestroy notification from a database. */ - *next = ISC_LIST_NEXT(zone, link); - if (*next == NULL) - return (ISC_R_NOMORE); - else - return (ISC_R_SUCCESS); -} +static void +dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) { + dns_db_t *db = event->sender; + UNUSED(task); -isc_result_t -dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) { - REQUIRE(DNS_ZONEMGR_VALID(zmgr)); - REQUIRE(first != NULL && *first == NULL); + isc_event_free(&event); - *first = ISC_LIST_HEAD(zmgr->zones); - if (*first == NULL) - return (ISC_R_NOMORE); - else - return (ISC_R_SUCCESS); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3), + "database (%p) destroyed", (void*) db); } +#endif -/*** - *** Zone manager. - ***/ - -isc_result_t -dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, - isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr, - dns_zonemgr_t **zmgrp) -{ - dns_zonemgr_t *zmgr; - isc_result_t result; +void +dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) { isc_interval_t interval; + isc_uint32_t s, ns; + isc_uint32_t pertic; + isc_result_t result; - zmgr = isc_mem_get(mctx, sizeof(*zmgr)); - if (zmgr == NULL) - return (ISC_R_NOMEMORY); - zmgr->mctx = NULL; - zmgr->refs = 1; - isc_mem_attach(mctx, &zmgr->mctx); - zmgr->taskmgr = taskmgr; - zmgr->timermgr = timermgr; - zmgr->socketmgr = socketmgr; - zmgr->zonetasks = NULL; - zmgr->task = NULL; - zmgr->rl = NULL; - ISC_LIST_INIT(zmgr->zones); - ISC_LIST_INIT(zmgr->waiting_for_xfrin); - ISC_LIST_INIT(zmgr->xfrin_in_progress); - memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable)); - result = isc_rwlock_init(&zmgr->rwlock, 0, 0); - if (result != ISC_R_SUCCESS) - goto free_mem; + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); - zmgr->transfersin = 10; - zmgr->transfersperns = 2; + if (value == 0) + value = 1; - /* Create the zone task pool. */ - result = isc_taskpool_create(taskmgr, mctx, - 8 /* XXX */, 2, &zmgr->zonetasks); - if (result != ISC_R_SUCCESS) - goto free_rwlock; + if (value == 1) { + s = 1; + ns = 0; + pertic = 1; + } else if (value <= 10) { + s = 0; + ns = 1000000000 / value; + pertic = 1; + } else { + s = 0; + ns = (1000000000 / value) * 10; + pertic = 10; + } - /* Create a single task for queueing of SOA queries. */ - result = isc_task_create(taskmgr, 1, &zmgr->task); - if (result != ISC_R_SUCCESS) - goto free_taskpool; - isc_task_setname(zmgr->task, "zmgr", zmgr); - result = isc_ratelimiter_create(mctx, timermgr, zmgr->task, - &zmgr->rl); - if (result != ISC_R_SUCCESS) - goto free_task; - /* default to 20 refresh queries / notifies per second. */ - isc_interval_set(&interval, 0, 1000000000/2); + isc_interval_set(&interval, s, ns); result = isc_ratelimiter_setinterval(zmgr->rl, &interval); RUNTIME_CHECK(result == ISC_R_SUCCESS); - isc_ratelimiter_setpertic(zmgr->rl, 10); + isc_ratelimiter_setpertic(zmgr->rl, pertic); - zmgr->iolimit = 1; - zmgr->ioactive = 0; - ISC_LIST_INIT(zmgr->high); - ISC_LIST_INIT(zmgr->low); + zmgr->serialqueryrate = value; +} - result = isc_mutex_init(&zmgr->iolock); - if (result != ISC_R_SUCCESS) - goto free_rl; +unsigned int +dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) { + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); + + return (zmgr->serialqueryrate); +} + +static isc_boolean_t +dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote, + isc_sockaddr_t *local, isc_time_t *now) +{ + unsigned int i; + isc_rwlocktype_t locktype; + isc_result_t result; + isc_uint32_t seconds = isc_time_seconds(now); + + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); + + locktype = isc_rwlocktype_read; + RWLOCK(&zmgr->rwlock, locktype); + for (i = 0; i < UNREACH_CHACHE_SIZE; i++) { + if (zmgr->unreachable[i].expire >= seconds && + isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) && + isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) { + result = isc_rwlock_tryupgrade(&zmgr->rwlock); + if (result == ISC_R_SUCCESS) { + locktype = isc_rwlocktype_write; + zmgr->unreachable[i].last = seconds; + } + break; + } + } + RWUNLOCK(&zmgr->rwlock, locktype); + return (ISC_TF(i < UNREACH_CHACHE_SIZE)); +} - zmgr->magic = ZONEMGR_MAGIC; +void +dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote, + isc_sockaddr_t *local, isc_time_t *now) +{ + isc_uint32_t seconds = isc_time_seconds(now); + isc_uint32_t last = seconds; + unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0; - *zmgrp = zmgr; - return (ISC_R_SUCCESS); + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); -#if 0 - free_iolock: - DESTROYLOCK(&zmgr->iolock); -#endif - free_rl: - isc_ratelimiter_detach(&zmgr->rl); - free_task: - isc_task_detach(&zmgr->task); - free_taskpool: - isc_taskpool_destroy(&zmgr->zonetasks); - free_rwlock: - isc_rwlock_destroy(&zmgr->rwlock); - free_mem: - isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr)); - isc_mem_detach(&mctx); - return (result); + RWLOCK(&zmgr->rwlock, isc_rwlocktype_write); + for (i = 0; i < UNREACH_CHACHE_SIZE; i++) { + /* Existing entry? */ + if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) && + isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) + break; + /* Empty slot? */ + if (zmgr->unreachable[i].expire < seconds) + slot = i; + /* Least recently used slot? */ + if (zmgr->unreachable[i].last < last) { + last = zmgr->unreachable[i].last; + oldest = i; + } + } + if (i < UNREACH_CHACHE_SIZE) { + /* + * Found a existing entry. Update the expire timer and + * last usage timestamps. + */ + zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME; + zmgr->unreachable[i].last = seconds; + } else if (slot != UNREACH_CHACHE_SIZE) { + /* + * Found a empty slot. Add a new entry to the cache. + */ + zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME; + zmgr->unreachable[slot].last = seconds; + zmgr->unreachable[slot].remote = *remote; + zmgr->unreachable[slot].local = *local; + } else { + /* + * Replace the least recently used entry in the cache. + */ + zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME; + zmgr->unreachable[oldest].last = seconds; + zmgr->unreachable[oldest].remote = *remote; + zmgr->unreachable[oldest].local = *local; + } + RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write); } -isc_result_t -dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) { - isc_result_t result; - +void +dns_zone_forcereload(dns_zone_t *zone) { REQUIRE(DNS_ZONE_VALID(zone)); - REQUIRE(DNS_ZONEMGR_VALID(zmgr)); - RWLOCK(&zmgr->rwlock, isc_rwlocktype_write); + if (zone->type == dns_zone_master) + return; + LOCK_ZONE(zone); - REQUIRE(zone->task == NULL); - REQUIRE(zone->timer == NULL); - REQUIRE(zone->zmgr == NULL); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER); + UNLOCK_ZONE(zone); + dns_zone_refresh(zone); +} - isc_taskpool_gettask(zmgr->zonetasks, - dns_name_hash(dns_zone_getorigin(zone), - ISC_FALSE), - &zone->task); +isc_boolean_t +dns_zone_isforced(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + + return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)); +} +isc_result_t +dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) { /* - * Set the task name. The tag will arbitrarily point to one - * of the zones sharing the task (in practice, the one - * to be managed last). + * This function is obsoleted. */ - isc_task_setname(zone->task, "zone", zone); - - result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive, - NULL, NULL, - zone->task, zone_timer, zone, - &zone->timer); - - if (result != ISC_R_SUCCESS) - goto cleanup_task; + UNUSED(zone); + UNUSED(on); + return (ISC_R_NOTIMPLEMENTED); +} +isc_uint64_t * +dns_zone_getstatscounters(dns_zone_t *zone) { /* - * The timer "holds" a iref. + * This function is obsoleted. */ - zone->irefs++; - INSIST(zone->irefs != 0); - - ISC_LIST_APPEND(zmgr->zones, zone, link); - zone->zmgr = zmgr; - zmgr->refs++; - - goto unlock; + UNUSED(zone); + return (NULL); +} - cleanup_task: - isc_task_detach(&zone->task); +void +dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) { + REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(zone->stats == NULL); - unlock: + LOCK_ZONE(zone); + zone->stats = NULL; + isc_stats_attach(stats, &zone->stats); UNLOCK_ZONE(zone); - RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write); - return (result); } void -dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) { - isc_boolean_t free_now = ISC_FALSE; - +dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) { REQUIRE(DNS_ZONE_VALID(zone)); - REQUIRE(DNS_ZONEMGR_VALID(zmgr)); - REQUIRE(zone->zmgr == zmgr); - RWLOCK(&zmgr->rwlock, isc_rwlocktype_write); LOCK_ZONE(zone); - - ISC_LIST_UNLINK(zmgr->zones, zone, link); - zone->zmgr = NULL; - zmgr->refs--; - if (zmgr->refs == 0) - free_now = ISC_TRUE; - + if (zone->requeststats_on && stats == NULL) + zone->requeststats_on = ISC_FALSE; + else if (!zone->requeststats_on && stats != NULL) { + if (zone->requeststats == NULL) { + isc_stats_attach(stats, &zone->requeststats); + zone->requeststats_on = ISC_TRUE; + } + } UNLOCK_ZONE(zone); - RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write); - if (free_now) - zonemgr_free(zmgr); - ENSURE(zone->zmgr == NULL); + return; } -void -dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) { - REQUIRE(DNS_ZONEMGR_VALID(source)); - REQUIRE(target != NULL && *target == NULL); - - RWLOCK(&source->rwlock, isc_rwlocktype_write); - REQUIRE(source->refs > 0); - source->refs++; - INSIST(source->refs > 0); - RWUNLOCK(&source->rwlock, isc_rwlocktype_write); - *target = source; +isc_stats_t * +dns_zone_getrequeststats(dns_zone_t *zone) { + /* + * We don't lock zone for efficiency reason. This is not catastrophic + * because requeststats must always be valid when requeststats_on is + * true. + * Some counters may be incremented while requeststats_on is becoming + * false, or some cannot be incremented just after the statistics are + * installed, but it shouldn't matter much in practice. + */ + if (zone->requeststats_on) + return (zone->requeststats); + else + return (NULL); } void -dns_zonemgr_detach(dns_zonemgr_t **zmgrp) { - dns_zonemgr_t *zmgr; - isc_boolean_t free_now = ISC_FALSE; +dns_zone_dialup(dns_zone_t *zone) { - REQUIRE(zmgrp != NULL); - zmgr = *zmgrp; - REQUIRE(DNS_ZONEMGR_VALID(zmgr)); + REQUIRE(DNS_ZONE_VALID(zone)); - RWLOCK(&zmgr->rwlock, isc_rwlocktype_write); - zmgr->refs--; - if (zmgr->refs == 0) - free_now = ISC_TRUE; - RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write); + zone_debuglog(zone, "dns_zone_dialup", 3, + "notify = %d, refresh = %d", + DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY), + DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)); - if (free_now) - zonemgr_free(zmgr); + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) + dns_zone_notify(zone); + if (zone->type != dns_zone_master && + DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) + dns_zone_refresh(zone); +} + +void +dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) { + REQUIRE(DNS_ZONE_VALID(zone)); + + LOCK_ZONE(zone); + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY | + DNS_ZONEFLG_DIALREFRESH | + DNS_ZONEFLG_NOREFRESH); + switch (dialup) { + case dns_dialuptype_no: + break; + case dns_dialuptype_yes: + DNS_ZONE_SETFLAG(zone, (DNS_ZONEFLG_DIALNOTIFY | + DNS_ZONEFLG_DIALREFRESH | + DNS_ZONEFLG_NOREFRESH)); + break; + case dns_dialuptype_notify: + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY); + break; + case dns_dialuptype_notifypassive: + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH); + break; + case dns_dialuptype_refresh: + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH); + break; + case dns_dialuptype_passive: + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH); + break; + default: + INSIST(0); + } + UNLOCK_ZONE(zone); } isc_result_t -dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) { - dns_zone_t *p; +dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) { + isc_result_t result = ISC_R_SUCCESS; - REQUIRE(DNS_ZONEMGR_VALID(zmgr)); + REQUIRE(DNS_ZONE_VALID(zone)); - RWLOCK(&zmgr->rwlock, isc_rwlocktype_read); - for (p = ISC_LIST_HEAD(zmgr->zones); - p != NULL; - p = ISC_LIST_NEXT(p, link)) - { - dns_zone_maintenance(p); - } - RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read); + LOCK_ZONE(zone); + result = dns_zone_setstring(zone, &zone->keydirectory, directory); + UNLOCK_ZONE(zone); - /* - * Recent configuration changes may have increased the - * amount of available transfers quota. Make sure any - * transfers currently blocked on quota get started if - * possible. - */ - RWLOCK(&zmgr->rwlock, isc_rwlocktype_write); - zmgr_resume_xfrs(zmgr, ISC_TRUE); - RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write); - return (ISC_R_SUCCESS); + return (result); } -void -dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) { - - REQUIRE(DNS_ZONEMGR_VALID(zmgr)); +const char * +dns_zone_getkeydirectory(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); - RWLOCK(&zmgr->rwlock, isc_rwlocktype_write); - zmgr_resume_xfrs(zmgr, ISC_TRUE); - RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write); + return (zone->keydirectory); } -void -dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) { +unsigned int +dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) { + dns_zone_t *zone; + unsigned int count = 0; + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); - isc_ratelimiter_shutdown(zmgr->rl); + RWLOCK(&zmgr->rwlock, isc_rwlocktype_read); + switch (state) { + case DNS_ZONESTATE_XFERRUNNING: + for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress); + zone != NULL; + zone = ISC_LIST_NEXT(zone, statelink)) + count++; + break; + case DNS_ZONESTATE_XFERDEFERRED: + for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin); + zone != NULL; + zone = ISC_LIST_NEXT(zone, statelink)) + count++; + break; + case DNS_ZONESTATE_SOAQUERY: + for (zone = ISC_LIST_HEAD(zmgr->zones); + zone != NULL; + zone = ISC_LIST_NEXT(zone, link)) + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) + count++; + break; + case DNS_ZONESTATE_ANY: + for (zone = ISC_LIST_HEAD(zmgr->zones); + zone != NULL; + zone = ISC_LIST_NEXT(zone, link)) { + dns_view_t *view = zone->view; + if (view != NULL && strcmp(view->name, "_bind") == 0) + continue; + count++; + } + break; + default: + INSIST(0); + } - if (zmgr->task != NULL) - isc_task_destroy(&zmgr->task); - if (zmgr->zonetasks != NULL) - isc_taskpool_destroy(&zmgr->zonetasks); + RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read); + + return (count); } -static void -zonemgr_free(dns_zonemgr_t *zmgr) { - isc_mem_t *mctx; +isc_result_t +dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) { + isc_boolean_t ok = ISC_TRUE; + isc_boolean_t fail = ISC_FALSE; + char namebuf[DNS_NAME_FORMATSIZE]; + char namebuf2[DNS_NAME_FORMATSIZE]; + char typebuf[DNS_RDATATYPE_FORMATSIZE]; + int level = ISC_LOG_WARNING; + dns_name_t bad; - INSIST(zmgr->refs == 0); - INSIST(ISC_LIST_EMPTY(zmgr->zones)); + REQUIRE(DNS_ZONE_VALID(zone)); - zmgr->magic = 0; + if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES)) + return (ISC_R_SUCCESS); - DESTROYLOCK(&zmgr->iolock); - isc_ratelimiter_detach(&zmgr->rl); + if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) { + level = ISC_LOG_ERROR; + fail = ISC_TRUE; + } - isc_rwlock_destroy(&zmgr->rwlock); - mctx = zmgr->mctx; - isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr)); - isc_mem_detach(&mctx); + ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE); + if (!ok) { + dns_name_format(name, namebuf, sizeof(namebuf)); + dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf)); + dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf, + dns_result_totext(DNS_R_BADOWNERNAME)); + if (fail) + return (DNS_R_BADOWNERNAME); + } + + dns_name_init(&bad, NULL); + ok = dns_rdata_checknames(rdata, name, &bad); + if (!ok) { + dns_name_format(name, namebuf, sizeof(namebuf)); + dns_name_format(&bad, namebuf2, sizeof(namebuf2)); + dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf)); + dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf, + namebuf2, dns_result_totext(DNS_R_BADNAME)); + if (fail) + return (DNS_R_BADNAME); + } + + return (ISC_R_SUCCESS); } void -dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) { - REQUIRE(DNS_ZONEMGR_VALID(zmgr)); - - zmgr->transfersin = value; +dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) { + REQUIRE(DNS_ZONE_VALID(zone)); + zone->checkmx = checkmx; } -isc_uint32_t -dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) { - REQUIRE(DNS_ZONEMGR_VALID(zmgr)); +void +dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) { + REQUIRE(DNS_ZONE_VALID(zone)); + zone->checksrv = checksrv; +} - return (zmgr->transfersin); +void +dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) { + REQUIRE(DNS_ZONE_VALID(zone)); + zone->checkns = checkns; } void -dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) { - REQUIRE(DNS_ZONEMGR_VALID(zmgr)); +dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) { + REQUIRE(DNS_ZONE_VALID(zone)); - zmgr->transfersperns = value; + LOCK_ZONE(zone); + zone->isself = isself; + zone->isselfarg = arg; + UNLOCK_ZONE(zone); } -isc_uint32_t -dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) { - REQUIRE(DNS_ZONEMGR_VALID(zmgr)); +void +dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) { + REQUIRE(DNS_ZONE_VALID(zone)); - return (zmgr->transfersperns); + LOCK_ZONE(zone); + zone->notifydelay = delay; + UNLOCK_ZONE(zone); } -/* - * Try to start a new incoming zone transfer to fill a quota - * slot that was just vacated. - * - * Requires: - * The zone manager is locked by the caller. - */ -static void -zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) { - dns_zone_t *zone; - dns_zone_t *next; +isc_uint32_t +dns_zone_getnotifydelay(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); - for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin); - zone != NULL; - zone = next) - { - isc_result_t result; - next = ISC_LIST_NEXT(zone, statelink); - result = zmgr_start_xfrin_ifquota(zmgr, zone); - if (result == ISC_R_SUCCESS) { - if (multi) - continue; - /* - * We successfully filled the slot. We're done. - */ - break; - } else if (result == ISC_R_QUOTA) { - /* - * Not enough quota. This is probably the per-server - * quota, because we usually get called when a unit of - * global quota has just been freed. Try the next - * zone, it may succeed if it uses another master. - */ - continue; - } else { - dns_zone_log(zone, ISC_LOG_DEBUG(1), - "starting zone transfer: %s", - isc_result_totext(result)); - break; - } - } + return (zone->notifydelay); } -/* - * Try to start an incoming zone transfer for 'zone', quota permitting. - * - * Requires: - * The zone manager is locked by the caller. - * - * Returns: - * ISC_R_SUCCESS There was enough quota and we attempted to - * start a transfer. zone_xfrdone() has been or will - * be called. - * ISC_R_QUOTA Not enough quota. - * Others Failure. - */ -static isc_result_t -zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) { - dns_peer_t *peer = NULL; - isc_netaddr_t masterip; - isc_uint32_t nxfrsin, nxfrsperns; - dns_zone_t *x; - isc_uint32_t maxtransfersin, maxtransfersperns; - isc_event_t *e; - - /* - * Find any configured information about the server we'd - * like to transfer this zone from. - */ - isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr); - (void)dns_peerlist_peerbyaddr(zone->view->peers, - &masterip, &peer); +isc_result_t +dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, + isc_uint16_t keyid, isc_boolean_t delete) +{ + isc_result_t result; + REQUIRE(DNS_ZONE_VALID(zone)); - /* - * Determine the total maximum number of simultaneous - * transfers allowed, and the maximum for this specific - * master. - */ - maxtransfersin = zmgr->transfersin; - maxtransfersperns = zmgr->transfersperns; - if (peer != NULL) - (void)dns_peer_gettransfers(peer, &maxtransfersperns); + dns_zone_log(zone, ISC_LOG_NOTICE, + "dns_zone_signwithkey(algorithm=%u, keyid=%u)", + algorithm, keyid); + LOCK_ZONE(zone); + result = zone_signwithkey(zone, algorithm, keyid, delete); + UNLOCK_ZONE(zone); - /* - * Count the total number of transfers that are in progress, - * and the number of transfers in progress from this master. - * We linearly scan a list of all transfers; if this turns - * out to be too slow, we could hash on the master address. - */ - nxfrsin = nxfrsperns = 0; - for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress); - x != NULL; - x = ISC_LIST_NEXT(x, statelink)) - { - isc_netaddr_t xip; - isc_netaddr_fromsockaddr(&xip, &x->masteraddr); - nxfrsin++; - if (isc_netaddr_equal(&xip, &masterip)) - nxfrsperns++; - } + return (result); +} - /* Enforce quota. */ - if (nxfrsin >= maxtransfersin) - return (ISC_R_QUOTA); +static const char *hex = "0123456789ABCDEF"; - if (nxfrsperns >= maxtransfersperns) - return (ISC_R_QUOTA); +isc_result_t +dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) { + isc_result_t result; + char salt[255*2+1]; + unsigned int i, j; - /* - * We have sufficient quota. Move the zone to the "xfrin_in_progress" - * list and send it an event to let it start the actual transfer in the - * context of its own task. - */ - e = isc_event_allocate(zmgr->mctx, zmgr, - DNS_EVENT_ZONESTARTXFRIN, - got_transfer_quota, zone, - sizeof(isc_event_t)); - if (e == NULL) - return (ISC_R_NOMEMORY); + REQUIRE(DNS_ZONE_VALID(zone)); + if (nsec3param->salt_length != 0) { + INSIST((nsec3param->salt_length * 2U) < sizeof(salt)); + for (i = 0, j = 0; i < nsec3param->salt_length; i++) { + salt[j++] = hex[(nsec3param->salt[i] >> 4) & 0xf]; + salt[j++] = hex[nsec3param->salt[i] & 0xf]; + } + salt[j] = '\0'; + } else + strcpy(salt, "-"); + dns_zone_log(zone, ISC_LOG_NOTICE, + "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)", + nsec3param->hash, nsec3param->iterations, + salt); LOCK_ZONE(zone); - INSIST(zone->statelist == &zmgr->waiting_for_xfrin); - ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink); - ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink); - zone->statelist = &zmgr->xfrin_in_progress; - isc_task_send(zone->task, &e); - dns_zone_log(zone, ISC_LOG_INFO, "Transfer started."); + result = zone_addnsec3chain(zone, nsec3param); UNLOCK_ZONE(zone); - return (ISC_R_SUCCESS); + return (result); } void -dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) { - - REQUIRE(DNS_ZONEMGR_VALID(zmgr)); - REQUIRE(iolimit > 0); +dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) { + REQUIRE(DNS_ZONE_VALID(zone)); - zmgr->iolimit = iolimit; + if (nodes == 0) + nodes = 1; + zone->nodes = nodes; } -isc_uint32_t -dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) { +void +dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) { + REQUIRE(DNS_ZONE_VALID(zone)); - REQUIRE(DNS_ZONEMGR_VALID(zmgr)); + /* + * We treat signatures as a signed value so explicitly + * limit its range here. + */ + if (signatures > ISC_INT32_MAX) + signatures = ISC_INT32_MAX; + else if (signatures == 0) + signatures = 1; + zone->signatures = signatures; +} - return (zmgr->iolimit); +void +dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) { + REQUIRE(DNS_ZONE_VALID(zone)); + zone->privatetype = type; } -/* - * Get permission to request a file handle from the OS. - * An event will be sent to action when one is available. - * There are two queues available (high and low), the high - * queue will be serviced before the low one. - * - * zonemgr_putio() must be called after the event is delivered to - * 'action'. - */ +dns_rdatatype_t +dns_zone_getprivatetype(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + return (zone->privatetype); +} static isc_result_t -zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high, - isc_task_t *task, isc_taskaction_t action, void *arg, - dns_io_t **iop) +zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid, + isc_boolean_t delete) { - dns_io_t *io; - isc_boolean_t queue; - - REQUIRE(DNS_ZONEMGR_VALID(zmgr)); - REQUIRE(iop != NULL && *iop == NULL); + dns_signing_t *signing; + dns_signing_t *current; + isc_result_t result = ISC_R_SUCCESS; + isc_time_t now; - io = isc_mem_get(zmgr->mctx, sizeof(*io)); - if (io == NULL) - return (ISC_R_NOMEMORY); - io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY, - action, arg, sizeof(*io->event)); - if (io->event == NULL) { - isc_mem_put(zmgr->mctx, io, sizeof(*io)); + signing = isc_mem_get(zone->mctx, sizeof *signing); + if (signing == NULL) return (ISC_R_NOMEMORY); - } - io->zmgr = zmgr; - io->high = high; - io->task = NULL; - isc_task_attach(task, &io->task); - ISC_LINK_INIT(io, link); - io->magic = IO_MAGIC; - - LOCK(&zmgr->iolock); - zmgr->ioactive++; - queue = ISC_TF(zmgr->ioactive > zmgr->iolimit); - if (queue) { - if (io->high) - ISC_LIST_APPEND(zmgr->high, io, link); - else - ISC_LIST_APPEND(zmgr->low, io, link); - } - UNLOCK(&zmgr->iolock); - *iop = io; - - if (!queue) { - isc_task_send(io->task, &io->event); - } - return (ISC_R_SUCCESS); -} -static void -zonemgr_putio(dns_io_t **iop) { - dns_io_t *io; - dns_io_t *next; - dns_zonemgr_t *zmgr; + signing->magic = 0; + signing->db = NULL; + signing->dbiterator = NULL; + signing->algorithm = algorithm; + signing->keyid = keyid; + signing->delete = delete; + signing->done = ISC_FALSE; - REQUIRE(iop != NULL); - io = *iop; - REQUIRE(DNS_IO_VALID(io)); + TIME_NOW(&now); - *iop = NULL; + for (current = ISC_LIST_HEAD(zone->signing); + current != NULL; + current = ISC_LIST_NEXT(current, link)) { + if (current->db == zone->db && + current->algorithm == signing->algorithm && + current->keyid == signing->keyid) { + if (current->delete != signing->delete) + current->done = ISC_TRUE; + else + goto cleanup; + } + } - INSIST(!ISC_LINK_LINKED(io, link)); - INSIST(io->event == NULL); + if (zone->db != NULL) { + dns_db_attach(zone->db, &signing->db); + result = dns_db_createiterator(signing->db, 0, + &signing->dbiterator); - zmgr = io->zmgr; - isc_task_detach(&io->task); - io->magic = 0; - isc_mem_put(zmgr->mctx, io, sizeof(*io)); + if (result == ISC_R_SUCCESS) + result = dns_dbiterator_first(signing->dbiterator); + if (result == ISC_R_SUCCESS) { + dns_dbiterator_pause(signing->dbiterator); + ISC_LIST_INITANDAPPEND(zone->signing, signing, link); + signing = NULL; + if (isc_time_isepoch(&zone->signingtime)) { + zone->signingtime = now; + if (zone->task != NULL) + zone_settimer(zone, &now); + } + } + } else + result = ISC_R_NOTFOUND; - LOCK(&zmgr->iolock); - INSIST(zmgr->ioactive > 0); - zmgr->ioactive--; - next = HEAD(zmgr->high); - if (next == NULL) - next = HEAD(zmgr->low); - if (next != NULL) { - if (next->high) - ISC_LIST_UNLINK(zmgr->high, next, link); - else - ISC_LIST_UNLINK(zmgr->low, next, link); - INSIST(next->event != NULL); + cleanup: + if (signing != NULL) { + if (signing->db != NULL) + dns_db_detach(&signing->db); + if (signing->dbiterator != NULL) + dns_dbiterator_destroy(&signing->dbiterator); + isc_mem_put(zone->mctx, signing, sizeof *signing); } - UNLOCK(&zmgr->iolock); - if (next != NULL) - isc_task_send(next->task, &next->event); + return (result); } static void -zonemgr_cancelio(dns_io_t *io) { - isc_boolean_t send_event = ISC_FALSE; +logmsg(const char *format, ...) { + va_list args; + va_start(args, format); + isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE, + ISC_LOG_DEBUG(1), format, args); + va_end(args); +} + +static void +clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) { + dns_dnsseckey_t *key; + while (!ISC_LIST_EMPTY(*list)) { + key = ISC_LIST_HEAD(*list); + ISC_LIST_UNLINK(*list, key, link); + dns_dnsseckey_destroy(mctx, &key); + } +} - REQUIRE(DNS_IO_VALID(io)); +/* Called once; *timep should be set to the current time. */ +static isc_result_t +next_keyevent(dst_key_t *key, isc_stdtime_t *timep) { + isc_result_t result; + isc_stdtime_t now, then = 0, event; + int i; - /* - * If we are queued to be run then dequeue. - */ - LOCK(&io->zmgr->iolock); - if (ISC_LINK_LINKED(io, link)) { - if (io->high) - ISC_LIST_UNLINK(io->zmgr->high, io, link); - else - ISC_LIST_UNLINK(io->zmgr->low, io, link); + now = *timep; - send_event = ISC_TRUE; - INSIST(io->event != NULL); + for (i = 0; i <= DST_MAX_TIMES; i++) { + result = dst_key_gettime(key, i, &event); + if (result == ISC_R_SUCCESS && event > now && + (then == 0 || event < then)) + then = event; } - UNLOCK(&io->zmgr->iolock); - if (send_event) { - io->event->ev_attributes |= ISC_EVENTATTR_CANCELED; - isc_task_send(io->task, &io->event); + + if (then != 0) { + *timep = then; + return (ISC_R_SUCCESS); } + + return (ISC_R_NOTFOUND); } -static void -zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) { - char *buf; - int buflen; +static isc_result_t +rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, + const dns_rdata_t *rdata, isc_boolean_t *flag) +{ + dns_rdataset_t rdataset; + dns_dbnode_t *node = NULL; isc_result_t result; - buflen = strlen(path) + strlen(templat) + 2; + dns_rdataset_init(&rdataset); + if (rdata->type == dns_rdatatype_nsec3) + CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node)); + else + CHECK(dns_db_findnode(db, name, ISC_FALSE, &node)); + result = dns_db_findrdataset(db, node, ver, rdata->type, 0, + (isc_stdtime_t) 0, &rdataset, NULL); + if (result == ISC_R_NOTFOUND) { + *flag = ISC_FALSE; + result = ISC_R_SUCCESS; + goto failure; + } - buf = isc_mem_get(zone->mctx, buflen); - if (buf == NULL) - return; + for (result = dns_rdataset_first(&rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&rdataset)) { + dns_rdata_t myrdata = DNS_RDATA_INIT; + dns_rdataset_current(&rdataset, &myrdata); + if (!dns_rdata_compare(&myrdata, rdata)) + break; + } + dns_rdataset_disassociate(&rdataset); + if (result == ISC_R_SUCCESS) { + *flag = ISC_TRUE; + } else if (result == ISC_R_NOMORE) { + *flag = ISC_FALSE; + result = ISC_R_SUCCESS; + } - result = isc_file_template(path, templat, buf, buflen); - if (result != ISC_R_SUCCESS) - goto cleanup; + failure: + if (node != NULL) + dns_db_detachnode(db, &node); + return (result); +} - result = isc_file_renameunique(path, buf); - if (result != ISC_R_SUCCESS) - goto cleanup; +/* + * Add records to signal the state of signing or of key removal. + */ +static isc_result_t +add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype, + dns_dbversion_t *ver, dns_diff_t *diff) +{ + dns_difftuple_t *tuple, *newtuple = NULL; + dns_rdata_dnskey_t dnskey; + dns_rdata_t rdata = DNS_RDATA_INIT; + isc_boolean_t flag; + isc_region_t r; + isc_result_t result = ISC_R_SUCCESS; + isc_uint16_t keyid; + unsigned char buf[5]; + dns_name_t *name = dns_db_origin(db); - dns_zone_log(zone, ISC_LOG_WARNING, "saved '%s' as '%s'", - path, buf); + for (tuple = ISC_LIST_HEAD(diff->tuples); + tuple != NULL; + tuple = ISC_LIST_NEXT(tuple, link)) { + if (tuple->rdata.type != dns_rdatatype_dnskey) + continue; - cleanup: - isc_mem_put(zone->mctx, buf, buflen); -} + result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + if ((dnskey.flags & + (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH)) + != DNS_KEYOWNER_ZONE) + continue; -#if 0 -/* Hook for ondestroy notification from a database. */ + dns_rdata_toregion(&tuple->rdata, &r); -static void -dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) { - dns_db_t *db = event->sender; - UNUSED(task); + keyid = dst_region_computeid(&r, dnskey.algorithm); - isc_event_free(&event); + buf[0] = dnskey.algorithm; + buf[1] = (keyid & 0xff00) >> 8; + buf[2] = (keyid & 0xff); + buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1; + buf[4] = 0; + rdata.data = buf; + rdata.length = sizeof(buf); + rdata.type = privatetype; + rdata.rdclass = tuple->rdata.rdclass; - isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, - DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3), - "database (%p) destroyed", (void*) db); + CHECK(rr_exists(db, ver, name, &rdata, &flag)); + if (flag) + continue; + CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, + name, 0, &rdata, &newtuple)); + CHECK(do_one_tuple(&newtuple, db, ver, diff)); + INSIST(newtuple == NULL); + /* + * Remove any record which says this operation has already + * completed. + */ + buf[4] = 1; + CHECK(rr_exists(db, ver, name, &rdata, &flag)); + if (flag) { + CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, + name, 0, &rdata, &newtuple)); + CHECK(do_one_tuple(&newtuple, db, ver, diff)); + INSIST(newtuple == NULL); + } + } + failure: + return (result); } -#endif -void -dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) { - isc_interval_t interval; - isc_uint32_t s, ns; - isc_uint32_t pertic; +static isc_result_t +sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, + dns_diff_t *diff, dns_diff_t *sig_diff) +{ isc_result_t result; + isc_stdtime_t now, inception, soaexpire; + isc_boolean_t check_ksk, keyset_kskonly; + dst_key_t *zone_keys[MAXZONEKEYS]; + unsigned int nkeys = 0, i; + dns_difftuple_t *tuple; - REQUIRE(DNS_ZONEMGR_VALID(zmgr)); + result = find_zone_keys(zone, db, ver, zone->mctx, MAXZONEKEYS, + zone_keys, &nkeys); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "sign_apex:find_zone_keys -> %s\n", + dns_result_totext(result)); + return (result); + } - if (value == 0) - value = 1; + isc_stdtime_get(&now); + inception = now - 3600; /* Allow for clock skew. */ + soaexpire = now + dns_zone_getsigvalidityinterval(zone); - if (value == 1) { - s = 1; - ns = 0; - pertic = 1; - } else if (value <= 10) { - s = 0; - ns = 1000000000 / value; - pertic = 1; - } else { - s = 0; - ns = (1000000000 / value) * 10; - pertic = 10; + check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK); + keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY); + + /* + * See if update_sigs will update DNSKEY signature and if not + * cause them to sign so that so that newly activated keys + * are used. + */ + for (tuple = ISC_LIST_HEAD(diff->tuples); + tuple != NULL; + tuple = ISC_LIST_NEXT(tuple, link)) { + if (tuple->rdata.type == dns_rdatatype_dnskey && + dns_name_equal(&tuple->name, &zone->origin)) + break; } - isc_interval_set(&interval, s, ns); - result = isc_ratelimiter_setinterval(zmgr->rl, &interval); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - isc_ratelimiter_setpertic(zmgr->rl, pertic); + if (tuple == NULL) { + result = del_sigs(zone, db, ver, &zone->origin, + dns_rdatatype_dnskey, sig_diff, + zone_keys, nkeys, now); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "sign_apex:del_sigs -> %s\n", + dns_result_totext(result)); + goto failure; + } + result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey, + sig_diff, zone_keys, nkeys, zone->mctx, + inception, soaexpire, check_ksk, + keyset_kskonly); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "sign_apex:add_sigs -> %s\n", + dns_result_totext(result)); + goto failure; + } + } - zmgr->serialqueryrate = value; -} + result = update_sigs(diff, db, ver, zone_keys, nkeys, zone, + inception, soaexpire, now, check_ksk, + keyset_kskonly, sig_diff); -unsigned int -dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) { - REQUIRE(DNS_ZONEMGR_VALID(zmgr)); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "sign_apex:update_sigs -> %s\n", + dns_result_totext(result)); + goto failure; + } - return (zmgr->serialqueryrate); + failure: + for (i = 0; i < nkeys; i++) + dst_key_free(&zone_keys[i]); + return (result); } +/* + * Prevent the zone entering a inconsistent state where + * NSEC only DNSKEYs are present with NSEC3 chains. + * See update.c:check_dnssec() + */ static isc_boolean_t -dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote, - isc_sockaddr_t *local, isc_time_t *now) +dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, + dns_diff_t *diff) { - unsigned int i; - isc_rwlocktype_t locktype; isc_result_t result; - isc_uint32_t seconds = isc_time_seconds(now); + dns_difftuple_t *tuple; + isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE; + dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); - REQUIRE(DNS_ZONEMGR_VALID(zmgr)); + /* Scan the tuples for an NSEC-only DNSKEY */ + for (tuple = ISC_LIST_HEAD(diff->tuples); + tuple != NULL; + tuple = ISC_LIST_NEXT(tuple, link)) { + isc_uint8_t alg; + if (tuple->rdata.type != dns_rdatatype_dnskey || + tuple->op != DNS_DIFFOP_ADD) + continue; - locktype = isc_rwlocktype_read; - RWLOCK(&zmgr->rwlock, locktype); - for (i = 0; i < UNREACH_CHACHE_SIZE; i++) { - if (zmgr->unreachable[i].expire >= seconds && - isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) && - isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) { - result = isc_rwlock_tryupgrade(&zmgr->rwlock); - if (result == ISC_R_SUCCESS) { - locktype = isc_rwlocktype_write; - zmgr->unreachable[i].last = seconds; - } + alg = tuple->rdata.data[3]; + if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 || + alg == DST_ALG_DSA || alg == DST_ALG_ECC) { + nseconly = ISC_TRUE; break; } } - RWUNLOCK(&zmgr->rwlock, locktype); - return (ISC_TF(i < UNREACH_CHACHE_SIZE)); -} -void -dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote, - isc_sockaddr_t *local, isc_time_t *now) -{ - isc_uint32_t seconds = isc_time_seconds(now); - isc_uint32_t last = seconds; - unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0; + /* Check existing DB for NSEC-only DNSKEY */ + if (!nseconly) + CHECK(dns_nsec_nseconly(db, ver, &nseconly)); - REQUIRE(DNS_ZONEMGR_VALID(zmgr)); + /* Check existing DB for NSEC3 */ + if (!nsec3) + CHECK(dns_nsec3_activex(db, ver, ISC_FALSE, + privatetype, &nsec3)); - RWLOCK(&zmgr->rwlock, isc_rwlocktype_write); - for (i = 0; i < UNREACH_CHACHE_SIZE; i++) { - /* Existing entry? */ - if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) && - isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) - break; - /* Empty slot? */ - if (zmgr->unreachable[i].expire < seconds) - slot = i; - /* Least recently used slot? */ - if (zmgr->unreachable[i].last < last) { - last = zmgr->unreachable[i].last; - oldest = i; - } - } - if (i < UNREACH_CHACHE_SIZE) { - /* - * Found a existing entry. Update the expire timer and - * last usage timestamps. - */ - zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME; - zmgr->unreachable[i].last = seconds; - } else if (slot != UNREACH_CHACHE_SIZE) { - /* - * Found a empty slot. Add a new entry to the cache. - */ - zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME; - zmgr->unreachable[slot].last = seconds; - zmgr->unreachable[slot].remote = *remote; - zmgr->unreachable[slot].local = *local; - } else { - /* - * Replace the least recently used entry in the cache. - */ - zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME; - zmgr->unreachable[oldest].last = seconds; - zmgr->unreachable[oldest].remote = *remote; - zmgr->unreachable[oldest].local = *local; + /* Refuse to allow NSEC3 with NSEC-only keys */ + if (nseconly && nsec3) { + dns_zone_log(zone, ISC_LOG_ERROR, + "NSEC only DNSKEYs and NSEC3 chains not allowed"); + goto failure; } - RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write); + + return (ISC_TRUE); + + failure: + return (ISC_FALSE); } -void -dns_zone_forcereload(dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); +static isc_result_t +clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, + dns_diff_t *diff) +{ + isc_result_t result; + dns_dbnode_t *node = NULL; + dns_rdataset_t rdataset; + + dns_rdataset_init(&rdataset); + CHECK(dns_db_getoriginnode(db, &node)); + + result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, + dns_rdatatype_none, 0, &rdataset, NULL); + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); + if (result != ISC_R_NOTFOUND) + goto failure; - if (zone->type == dns_zone_master) - return; + result = dns_nsec3param_deletechains(db, ver, zone, diff); - LOCK_ZONE(zone); - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER); - UNLOCK_ZONE(zone); - dns_zone_refresh(zone); + failure: + if (node != NULL) + dns_db_detachnode(db, &node); + return (result); } -isc_boolean_t -dns_zone_isforced(dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); +/* + * Given an RRSIG rdataset and an algorithm, determine whether there + * are any signatures using that algorithm. + */ +static isc_boolean_t +signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_rrsig_t rrsig; + isc_result_t result; - return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)); -} + REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig); + if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) { + return (ISC_FALSE); + } -isc_result_t -dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) { - /* - * This function is obsoleted. - */ - UNUSED(zone); - UNUSED(on); - return (ISC_R_NOTIMPLEMENTED); -} + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) + { + dns_rdataset_current(rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &rrsig, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + dns_rdata_reset(&rdata); + if (rrsig.algorithm == alg) + return (ISC_TRUE); + } -isc_uint64_t * -dns_zone_getstatscounters(dns_zone_t *zone) { - /* - * This function is obsoleted. - */ - UNUSED(zone); - return (NULL); + return (ISC_FALSE); } -void -dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) { - REQUIRE(DNS_ZONE_VALID(zone)); - REQUIRE(zone->stats == NULL); +static isc_result_t +add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, + dns_diff_t *diff) +{ + dns_name_t *origin; + isc_boolean_t build_nsec3; + isc_result_t result; - LOCK_ZONE(zone); - zone->stats = NULL; - isc_stats_attach(stats, &zone->stats); - UNLOCK_ZONE(zone); + origin = dns_db_origin(db); + CHECK(dns_private_chains(db, ver, zone->privatetype, NULL, + &build_nsec3)); + if (build_nsec3) + CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum, + ISC_FALSE, zone->privatetype, diff)); + CHECK(updatesecure(db, ver, origin, zone->minimum, ISC_TRUE, diff)); + + failure: + return (result); } -void -dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) { +static void +zone_rekey(dns_zone_t *zone) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbnode_t *node = NULL; + dns_dbversion_t *ver = NULL; + dns_rdataset_t soaset, soasigs, keyset, keysigs; + dns_dnsseckeylist_t dnskeys, keys, rmkeys; + dns_dnsseckey_t *key; + dns_diff_t diff, sig_diff; + isc_boolean_t commit = ISC_FALSE, newactive = ISC_FALSE; + isc_boolean_t fullsign; + dns_ttl_t ttl = 3600; + const char *dir; + isc_mem_t *mctx; + isc_stdtime_t now; + isc_time_t timenow; + isc_interval_t ival; + char timebuf[80]; + REQUIRE(DNS_ZONE_VALID(zone)); - LOCK_ZONE(zone); - if (zone->requeststats_on && stats == NULL) - zone->requeststats_on = ISC_FALSE; - else if (!zone->requeststats_on && stats != NULL) { - if (zone->requeststats == NULL) { - isc_stats_attach(stats, &zone->requeststats); - zone->requeststats_on = ISC_TRUE; - } - } - UNLOCK_ZONE(zone); + ISC_LIST_INIT(dnskeys); + ISC_LIST_INIT(keys); + ISC_LIST_INIT(rmkeys); + dns_rdataset_init(&soaset); + dns_rdataset_init(&soasigs); + dns_rdataset_init(&keyset); + dns_rdataset_init(&keysigs); + dir = dns_zone_getkeydirectory(zone); + mctx = zone->mctx; + dns_diff_init(mctx, &diff); + dns_diff_init(mctx, &sig_diff); - return; -} + CHECK(dns_zone_getdb(zone, &db)); + CHECK(dns_db_newversion(db, &ver)); + CHECK(dns_db_getoriginnode(db, &node)); + + dns_zone_log(zone, ISC_LOG_INFO, "reconfiguring zone keys"); + + /* Get the SOA record's TTL */ + CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa, + dns_rdatatype_none, 0, &soaset, &soasigs)); + ttl = soaset.ttl; + dns_rdataset_disassociate(&soaset); + + /* Get the DNSKEY rdataset */ + result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, + dns_rdatatype_none, 0, &keyset, &keysigs); + if (result == ISC_R_SUCCESS) { + ttl = keyset.ttl; + result = dns_dnssec_keylistfromrdataset(&zone->origin, dir, + mctx, &keyset, + &keysigs, &soasigs, + ISC_FALSE, ISC_FALSE, + &dnskeys); + /* Can't get keys for some reason; try again later. */ + if (result != ISC_R_SUCCESS) + goto trylater; + } else if (result != ISC_R_NOTFOUND) + goto failure; -isc_stats_t * -dns_zone_getrequeststats(dns_zone_t *zone) { /* - * We don't lock zone for efficiency reason. This is not catastrophic - * because requeststats must always be valid when requeststats_on is - * true. - * Some counters may be incremented while requeststats_on is becoming - * false, or some cannot be incremented just after the statistics are - * installed, but it shouldn't matter much in practice. + * True when called from "rndc sign". Indicates the zone should be + * fully signed now. */ - if (zone->requeststats_on) - return (zone->requeststats); - else - return (NULL); -} - -void -dns_zone_dialup(dns_zone_t *zone) { + fullsign = ISC_TF(DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN) != 0); - REQUIRE(DNS_ZONE_VALID(zone)); + result = dns_dnssec_findmatchingkeys(&zone->origin, dir, mctx, &keys); + if (result == ISC_R_SUCCESS) { + isc_boolean_t check_ksk; + check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK); - zone_debuglog(zone, "dns_zone_dialup", 3, - "notify = %d, refresh = %d", - DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY), - DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)); + result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys, + &zone->origin, ttl, &diff, + ISC_TF(!check_ksk), + mctx, logmsg); - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) - dns_zone_notify(zone); - if (zone->type != dns_zone_master && - DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) - dns_zone_refresh(zone); -} + /* Keys couldn't be updated for some reason; + * try again later. */ + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:" + "couldn't update zone keys: %s", + isc_result_totext(result)); + goto trylater; + } -void -dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) { - REQUIRE(DNS_ZONE_VALID(zone)); + /* See if any pre-existing keys have newly become active */ + for (key = ISC_LIST_HEAD(dnskeys); + key != NULL; + key = ISC_LIST_NEXT(key, link)) { + if (key->first_sign) { + newactive = ISC_TRUE; + break; + } + } - LOCK_ZONE(zone); - DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY | - DNS_ZONEFLG_DIALREFRESH | - DNS_ZONEFLG_NOREFRESH); - switch (dialup) { - case dns_dialuptype_no: - break; - case dns_dialuptype_yes: - DNS_ZONE_SETFLAG(zone, (DNS_ZONEFLG_DIALNOTIFY | - DNS_ZONEFLG_DIALREFRESH | - DNS_ZONEFLG_NOREFRESH)); - break; - case dns_dialuptype_notify: - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY); - break; - case dns_dialuptype_notifypassive: - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY); - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH); - break; - case dns_dialuptype_refresh: - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH); - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH); - break; - case dns_dialuptype_passive: - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH); - break; - default: - INSIST(0); + if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) && + dnskey_sane(zone, db, ver, &diff)) { + CHECK(dns_diff_apply(&diff, db, ver)); + CHECK(clean_nsec3param(zone, db, ver, &diff)); + CHECK(add_signing_records(db, zone->privatetype, ver, + &diff)); + CHECK(increment_soa_serial(db, ver, &diff, mctx)); + CHECK(add_chains(zone, db, ver, &diff)); + CHECK(sign_apex(zone, db, ver, &diff, &sig_diff)); + CHECK(zone_journal(zone, &sig_diff, "zone_rekey")); + commit = ISC_TRUE; + } } - UNLOCK_ZONE(zone); -} -isc_result_t -dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) { - isc_result_t result = ISC_R_SUCCESS; + dns_db_closeversion(db, &ver, commit); - REQUIRE(DNS_ZONE_VALID(zone)); + if (commit) { + isc_time_t timenow; + dns_difftuple_t *tuple; + isc_boolean_t newkey = ISC_FALSE; + isc_boolean_t newalg = ISC_FALSE; - LOCK_ZONE(zone); - result = dns_zone_setstring(zone, &zone->keydirectory, directory); - UNLOCK_ZONE(zone); + LOCK_ZONE(zone); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY); - return (result); -} + zone_needdump(zone, DNS_DUMP_DELAY); -const char * -dns_zone_getkeydirectory(dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); + TIME_NOW(&timenow); + zone_settimer(zone, &timenow); - return (zone->keydirectory); -} + /* + * Has a new key become active? If so, is it for + * a new algorithm? + */ + for (tuple = ISC_LIST_HEAD(sig_diff.tuples); + tuple != NULL; + tuple = ISC_LIST_NEXT(tuple, link)) { + dns_rdata_dnskey_t dnskey; -unsigned int -dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) { - dns_zone_t *zone; - unsigned int count = 0; + if (tuple->rdata.type != dns_rdatatype_dnskey) + continue; - REQUIRE(DNS_ZONEMGR_VALID(zmgr)); + newkey = ISC_TRUE; + if (!dns_rdataset_isassociated(&keysigs)) { + newalg = ISC_TRUE; + break; + } - RWLOCK(&zmgr->rwlock, isc_rwlocktype_read); - switch (state) { - case DNS_ZONESTATE_XFERRUNNING: - for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress); - zone != NULL; - zone = ISC_LIST_NEXT(zone, statelink)) - count++; - break; - case DNS_ZONESTATE_XFERDEFERRED: - for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin); - zone != NULL; - zone = ISC_LIST_NEXT(zone, statelink)) - count++; - break; - case DNS_ZONESTATE_SOAQUERY: - for (zone = ISC_LIST_HEAD(zmgr->zones); - zone != NULL; - zone = ISC_LIST_NEXT(zone, link)) - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) - count++; - break; - case DNS_ZONESTATE_ANY: - for (zone = ISC_LIST_HEAD(zmgr->zones); - zone != NULL; - zone = ISC_LIST_NEXT(zone, link)) { - dns_view_t *view = zone->view; - if (view != NULL && strcmp(view->name, "_bind") == 0) - continue; - count++; + result = dns_rdata_tostruct(&tuple->rdata, + &dnskey, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + if (!signed_with_alg(&keysigs, + dnskey.algorithm)) { + newalg = ISC_TRUE; + break; + } } - break; - default: - INSIST(0); - } - RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read); + /* + * If we found a new algorithm, we need to sign the + * zone fully. If there's a new key, but it's for an + * already-existing algorithm, then the zone signing + * can be handled incrementally. + */ + if (newkey && !newalg) + set_resigntime(zone); - return (count); -} + /* Remove any signatures from removed keys. */ + if (!ISC_LIST_EMPTY(rmkeys)) { + for (key = ISC_LIST_HEAD(rmkeys); + key != NULL; + key = ISC_LIST_NEXT(key, link)) { + result = zone_signwithkey(zone, + dst_key_alg(key->key), + dst_key_id(key->key), + ISC_TRUE); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "zone_signwithkey failed: %s", + dns_result_totext(result)); + } + } + } + + + if (fullsign) { + /* + * "rndc sign" was called, so we now sign the zone + * with all active keys, whether they're new or not. + */ + for (key = ISC_LIST_HEAD(dnskeys); + key != NULL; + key = ISC_LIST_NEXT(key, link)) { + if (!key->force_sign && !key->hint_sign) + continue; + + result = zone_signwithkey(zone, + dst_key_alg(key->key), + dst_key_id(key->key), + ISC_FALSE); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "zone_signwithkey failed: %s", + dns_result_totext(result)); + } + } + } else if (newalg) { + /* + * We haven't been told to sign fully, but a new + * algorithm was added to the DNSKEY. We sign + * the full zone, but only with the newly-added + * keys. + */ + for (tuple = ISC_LIST_HEAD(sig_diff.tuples); + tuple != NULL; + tuple = ISC_LIST_NEXT(tuple, link)) { + dns_rdata_dnskey_t dnskey; + dns_secalg_t algorithm; + isc_region_t r; + isc_uint16_t keyid; + + if (tuple->rdata.type != dns_rdatatype_dnskey || + tuple->op == DNS_DIFFOP_DEL) + continue; + + result = dns_rdata_tostruct(&tuple->rdata, + &dnskey, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + dns_rdata_toregion(&tuple->rdata, &r); + algorithm = dnskey.algorithm; + keyid = dst_region_computeid(&r, algorithm); + + result = zone_signwithkey(zone, algorithm, + keyid, ISC_FALSE); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "zone_signwithkey failed: %s", + dns_result_totext(result)); + } + } + } -isc_result_t -dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) { - isc_boolean_t ok = ISC_TRUE; - isc_boolean_t fail = ISC_FALSE; - char namebuf[DNS_NAME_FORMATSIZE]; - char namebuf2[DNS_NAME_FORMATSIZE]; - char typebuf[DNS_RDATATYPE_FORMATSIZE]; - int level = ISC_LOG_WARNING; - dns_name_t bad; + /* + * Clear fullsign flag, if it was set, so we don't do + * another full signing next time + */ + zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN; - REQUIRE(DNS_ZONE_VALID(zone)); + /* + * Cause the zone to add/delete NSEC3 chains for the + * deferred NSEC3PARAM changes. + */ + for (tuple = ISC_LIST_HEAD(sig_diff.tuples); + tuple != NULL; + tuple = ISC_LIST_NEXT(tuple, link)) { + unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_nsec3param_t nsec3param; - if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES)) - return (ISC_R_SUCCESS); + if (tuple->rdata.type != zone->privatetype || + tuple->op != DNS_DIFFOP_ADD) + continue; - if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) { - level = ISC_LOG_ERROR; - fail = ISC_TRUE; - } + if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata, + buf, sizeof(buf))) + continue; + result = dns_rdata_tostruct(&rdata, &nsec3param, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + if (nsec3param.flags == 0) + continue; - ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE); - if (!ok) { - dns_name_format(name, namebuf, sizeof(namebuf)); - dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf)); - dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf, - dns_result_totext(DNS_R_BADOWNERNAME)); - if (fail) - return (DNS_R_BADOWNERNAME); + result = zone_addnsec3chain(zone, &nsec3param); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "zone_addnsec3chain failed: %s", + dns_result_totext(result)); + } + } + UNLOCK_ZONE(zone); } - dns_name_init(&bad, NULL); - ok = dns_rdata_checknames(rdata, name, &bad); - if (!ok) { - dns_name_format(name, namebuf, sizeof(namebuf)); - dns_name_format(&bad, namebuf2, sizeof(namebuf2)); - dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf)); - dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf, - namebuf2, dns_result_totext(DNS_R_BADNAME)); - if (fail) - return (DNS_R_BADNAME); - } + isc_stdtime_get(&now); + TIME_NOW(&timenow); + isc_time_settoepoch(&zone->refreshkeytime); + for (key = ISC_LIST_HEAD(dnskeys); + key != NULL; + key = ISC_LIST_NEXT(key, link)) { + isc_stdtime_t then; + isc_time_t timethen; - return (ISC_R_SUCCESS); -} + /* + * If we are doing automatic key maintenance and the + * key metadata indicates there is a key change event + * scheduled in the future, set the key refresh timer. + */ + if (!DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) + break; -void -dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) { - REQUIRE(DNS_ZONE_VALID(zone)); - zone->checkmx = checkmx; -} + then = now; + result = next_keyevent(key->key, &then); + if (result != ISC_R_SUCCESS) + continue; -void -dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) { - REQUIRE(DNS_ZONE_VALID(zone)); - zone->checksrv = checksrv; -} + DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen); + LOCK_ZONE(zone); + if (isc_time_isepoch(&zone->refreshkeytime) || + isc_time_compare(&timethen, &zone->refreshkeytime) < 0) { + zone->refreshkeytime = timethen; + zone_settimer(zone, &timenow); + } + UNLOCK_ZONE(zone); + } -void -dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) { - REQUIRE(DNS_ZONE_VALID(zone)); - zone->checkns = checkns; -} + /* + * If no key event is scheduled, we should still check the key + * repository for updates every so often. (Currently this is + * hard-coded to 12 hours, but it could be configurable.) + */ + if (isc_time_isepoch(&zone->refreshkeytime)) + DNS_ZONE_TIME_ADD(&timenow, (3600 * 12), &zone->refreshkeytime); -void -dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) { - REQUIRE(DNS_ZONE_VALID(zone)); + isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80); + dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf); - LOCK_ZONE(zone); - zone->isself = isself; - zone->isselfarg = arg; - UNLOCK_ZONE(zone); -} + failure: + dns_diff_clear(&diff); + dns_diff_clear(&sig_diff); -void -dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) { - REQUIRE(DNS_ZONE_VALID(zone)); + clear_keylist(&dnskeys, mctx); + clear_keylist(&keys, mctx); + clear_keylist(&rmkeys, mctx); + + if (ver != NULL) + dns_db_closeversion(db, &ver, ISC_FALSE); + if (dns_rdataset_isassociated(&keyset)) + dns_rdataset_disassociate(&keyset); + if (dns_rdataset_isassociated(&keysigs)) + dns_rdataset_disassociate(&keysigs); + if (dns_rdataset_isassociated(&soasigs)) + dns_rdataset_disassociate(&soasigs); + if (node != NULL) + dns_db_detachnode(db, &node); + if (db != NULL) + dns_db_detach(&db); + return; - LOCK_ZONE(zone); - zone->notifydelay = delay; - UNLOCK_ZONE(zone); + trylater: + isc_interval_set(&ival, HOUR, 0); + isc_time_nowplusinterval(&zone->refreshkeytime, &ival); + goto failure; } -isc_uint32_t -dns_zone_getnotifydelay(dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); +void +dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign) { + isc_time_t now; - return (zone->notifydelay); -} + if (zone->type == dns_zone_master && zone->task != NULL) { + LOCK_ZONE(zone); -isc_result_t -dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, - isc_uint16_t keyid, isc_boolean_t delete) -{ - isc_result_t result; - REQUIRE(DNS_ZONE_VALID(zone)); + if (fullsign) + zone->keyopts |= DNS_ZONEKEY_FULLSIGN; - dns_zone_log(zone, ISC_LOG_NOTICE, - "dns_zone_signwithkey(algorithm=%u, keyid=%u)", - algorithm, keyid); - LOCK_ZONE(zone); - result = zone_signwithkey(zone, algorithm, keyid, delete); - UNLOCK_ZONE(zone); + TIME_NOW(&now); + zone->refreshkeytime = now; + zone_settimer(zone, &now); - return (result); + UNLOCK_ZONE(zone); + } } -static const char *hex = "0123456789ABCDEF"; - isc_result_t -dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) { +dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version, + unsigned int *errors) +{ isc_result_t result; - char salt[255*2+1]; - unsigned int i, j; + dns_dbnode_t *node = NULL; REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(errors != NULL); - if (nsec3param->salt_length != 0) { - INSIST((nsec3param->salt_length * 2U) < sizeof(salt)); - for (i = 0, j = 0; i < nsec3param->salt_length; i++) { - salt[j++] = hex[(nsec3param->salt[i] >> 4) & 0xf]; - salt[j++] = hex[nsec3param->salt[i] & 0xf]; - } - salt[j] = '\0'; - } else - strcpy(salt, "-"); - dns_zone_log(zone, ISC_LOG_NOTICE, - "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)", - nsec3param->hash, nsec3param->iterations, - salt); - LOCK_ZONE(zone); - result = zone_addnsec3chain(zone, nsec3param); - UNLOCK_ZONE(zone); - + result = dns_db_getoriginnode(db, &node); + if (result != ISC_R_SUCCESS) + return (result); + result = zone_count_ns_rr(zone, db, node, version, NULL, errors, + ISC_FALSE); + dns_db_detachnode(db, &node); return (result); } void -dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) { - REQUIRE(DNS_ZONE_VALID(zone)); - - if (nodes == 0) - nodes = 1; - zone->nodes = nodes; -} - -void -dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) { - REQUIRE(DNS_ZONE_VALID(zone)); - - /* - * We treat signatures as a signed value so explicitly - * limit its range here. - */ - if (signatures > ISC_INT32_MAX) - signatures = ISC_INT32_MAX; - else if (signatures == 0) - signatures = 1; - zone->signatures = signatures; -} - -void -dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) { +dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added) { REQUIRE(DNS_ZONE_VALID(zone)); - zone->privatetype = type; + LOCK_ZONE(zone); + zone->added = added; + UNLOCK_ZONE(zone); } -dns_rdatatype_t -dns_zone_getprivatetype(dns_zone_t *zone) { +isc_boolean_t +dns_zone_getadded(dns_zone_t *zone) { REQUIRE(DNS_ZONE_VALID(zone)); - return (zone->privatetype); + return (zone->added); } -static isc_result_t -zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid, - isc_boolean_t delete) +isc_result_t +dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db) { - dns_signing_t *signing; - dns_signing_t *current; - isc_result_t result = ISC_R_SUCCESS; - isc_time_t now; - - signing = isc_mem_get(zone->mctx, sizeof *signing); - if (signing == NULL) - return (ISC_R_NOMEMORY); - - signing->magic = 0; - signing->db = NULL; - signing->dbiterator = NULL; - signing->algorithm = algorithm; - signing->keyid = keyid; - signing->delete = delete; - signing->done = ISC_FALSE; - - TIME_NOW(&now); - - for (current = ISC_LIST_HEAD(zone->signing); - current != NULL; - current = ISC_LIST_NEXT(current, link)) { - if (current->db == zone->db && - current->algorithm == signing->algorithm && - current->keyid == signing->keyid) { - if (current->delete != signing->delete) - current->done = ISC_TRUE; - else - goto cleanup; - } - } - - if (zone->db != NULL) { - dns_db_attach(zone->db, &signing->db); - result = dns_db_createiterator(signing->db, 0, - &signing->dbiterator); - - if (result == ISC_R_SUCCESS) - result = dns_dbiterator_first(signing->dbiterator); - if (result == ISC_R_SUCCESS) { - dns_dbiterator_pause(signing->dbiterator); - ISC_LIST_INITANDAPPEND(zone->signing, signing, link); - signing = NULL; - if (isc_time_isepoch(&zone->signingtime)) { - zone->signingtime = now; - if (zone->task != NULL) - zone_settimer(zone, &now); - } - } - } else - result = ISC_R_NOTFOUND; + isc_time_t loadtime; + isc_result_t result; + TIME_NOW(&loadtime); - cleanup: - if (signing != NULL) { - if (signing->db != NULL) - dns_db_detach(&signing->db); - if (signing->dbiterator != NULL) - dns_dbiterator_destroy(&signing->dbiterator); - isc_mem_put(zone->mctx, signing, sizeof *signing); - } - return (result); + LOCK_ZONE(zone); + result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS); + UNLOCK_ZONE(zone); + return result; } diff --git a/lib/export/Makefile.in b/lib/export/Makefile.in new file mode 100644 index 0000000..5a9e633 --- /dev/null +++ b/lib/export/Makefile.in @@ -0,0 +1,27 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +# Note: the order of SUBDIRS is important. +# Attempt to disable parallel processing. +.NOTPARALLEL: +.NO_PARALLEL: +SUBDIRS = isc dns isccfg irs samples +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/export/dns/Makefile.in b/lib/export/dns/Makefile.in new file mode 100644 index 0000000..15b0d3f --- /dev/null +++ b/lib/export/dns/Makefile.in @@ -0,0 +1,179 @@ +# Copyright (C) 2009, 2010 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.8 2010-12-23 04:07:59 marka Exp $ + +top_srcdir = @top_srcdir@ +srcdir = @top_srcdir@/lib/dns +export_srcdir = @top_srcdir@/lib/export + +# Attempt to disable parallel processing. +.NOTPARALLEL: +.NO_PARALLEL: + +@BIND9_VERSION@ + +@LIBDNS_API@ + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I. -Iinclude ${DNS_INCLUDES} -I${export_srcdir}/isc/include \ + ${ISC_INCLUDES} @DST_OPENSSL_INC@ @DST_GSSAPI_INC@ + +CDEFINES = -DUSE_MD5 @USE_OPENSSL@ @USE_GSSAPI@ + +CWARNINGS = + +ISCLIBS = ../isc/libisc.@A@ + +ISCDEPLIBS = ../isc/libisc.@A@ + +LIBS = @LIBS@ + +# Alphabetically + +OPENSSLLINKOBJS = openssl_link.@O@ openssldh_link.@O@ openssldsa_link.@O@ \ + opensslgost_link.@O@ opensslrsa_link.@O@ + +DSTOBJS = @OPENSSLLINKOBJS@ \ + dst_api.@O@ dst_lib.@O@ dst_parse.@O@ dst_result.@O@ \ + gssapi_link.@O@ gssapictx.@O@ hmac_link.@O@ key.@O@ + +DNSOBJS = acl.@O@ adb.@O@ byaddr.@O@ \ + cache.@O@ callbacks.@O@ client.@O@ compress.@O@ \ + db.@O@ dbiterator.@O@ diff.@O@ dispatch.@O@ dlz.@O@ dnssec.@O@ \ + ds.@O@ \ + forward.@O@ iptable.@O@ \ + keytable.@O@ \ + lib.@O@ log.@O@ \ + master.@O@ masterdump.@O@ message.@O@ \ + name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ \ + peer.@O@ portlist.@O@ \ + rbt.@O@ rbtdb.@O@ rcode.@O@ rdata.@O@ \ + rdatalist.@O@ rdataset.@O@ rdatasetiter.@O@ rdataslab.@O@ \ + request.@O@ resolver.@O@ result.@O@ soa.@O@ stats.@O@ \ + tcpmsg.@O@ time.@O@ tsec.@O@ tsig.@O@ ttl.@O@ \ + validator.@O@ version.@O@ view.@O@ +PORTDNSOBJS = ecdb.@O@ + +OBJS= ${DNSOBJS} ${OTHEROBJS} ${DSTOBJS} ${PORTDNSOBJS} + +# Alphabetically + +OPENSSLLINKSRCS = openssl_link.c openssldh_link.c openssldsa_link.c \ + opensslgost_link.c opensslrsa_link.c + +DSTSRCS = @OPENSSLLINKSRCS@ \ + dst_api.c dst_lib.c dst_parse.c \ + dst_result.c gssapi_link.c gssapictx.c \ + hmac_link.c key.c + +DNSSRCS = acl.c adb.c byaddr.c \ + cache.c callbacks.c client.c compress.c \ + db.c dbiterator.c diff.c dispatch.c dlz.c dnssec.c ds.c \ + forward.c iptable.c \ + keytable.c \ + lib.c log.c \ + master.c masterdump.c message.c \ + name.c ncache.c nsec.c nsec3.c \ + peer.c portlist.c \ + rbt.c rbtdb.c rcode.c rdata.c \ + rdatalist.c rdataset.c rdatasetiter.c rdataslab.c \ + request.c res.c resolver.c result.c soa.c stats.c \ + tcpmsg.c time.c tsec.c tsig.c ttl.c \ + validator.c version.c view.c +PORTDNSSRCS = ecdb.c + +SRCS = ${DSTSRCS} ${DNSSRCS} ${PORTDNSSRCS} + +SUBDIRS = include +TARGETS = include/dns/enumtype.h include/dns/enumclass.h \ + include/dns/rdatastruct.h timestamp + +DEPENDEXTRA = ./gen -F include/dns/rdatastruct.h \ + -s ${srcdir} -d >> Makefile ; + +@BIND9_MAKE_RULES@ + +version.@O@: ${srcdir}/version.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ + -DVERSION=\"${VERSION}\" \ + -DLIBINTERFACE=${LIBINTERFACE} \ + -DLIBREVISION=${LIBREVISION} \ + -DLIBAGE=${LIBAGE} \ + -c ${srcdir}/version.c + +libdns.@SA@: ${OBJS} + ${AR} ${ARFLAGS} $@ ${OBJS} + ${RANLIB} $@ + +libdns.la: ${OBJS} + ${LIBTOOL_MODE_LINK} \ + ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libdns.la \ + -rpath ${export_libdir} \ + -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ + ${OBJS} ${ISCLIBS} @DNS_CRYPTO_LIBS@ ${LIBS} + +timestamp: libdns.@A@ + touch timestamp + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_libdir} + +install:: timestamp installdirs + ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libdns.@A@ \ + ${DESTDIR}${export_libdir} + +clean distclean:: + rm -f libdns.@A@ timestamp + rm -f gen code.h include/dns/enumtype.h include/dns/enumclass.h + rm -f include/dns/rdatastruct.h + +newrr:: + rm -f code.h include/dns/enumtype.h include/dns/enumclass.h + rm -f include/dns/rdatastruct.h + +include: include/dns/enumtype.h include/dns/enumclass.h \ + include/dns/rdatastruct.h + +rdata.@O@: code.h + +include/dns/enumtype.h: gen + ./gen -s ${srcdir} -t > $@ + +include/dns/enumclass.h: gen + ./gen -s ${srcdir} -c > $@ + +include/dns/rdatastruct.h: gen \ + ${srcdir}/rdata/rdatastructpre.h \ + ${srcdir}/rdata/rdatastructsuf.h + ./gen -s ${srcdir} -i \ + -P ${srcdir}/rdata/rdatastructpre.h \ + -S ${srcdir}/rdata/rdatastructsuf.h > $@ + +code.h: gen + ./gen -s ${srcdir} > code.h + +gen: ${srcdir}/gen.c + ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ ${srcdir}/gen.c ${LIBS} + +#We don't need rbtdb64 for this library +#rbtdb64.@O@: rbtdb.c + +depend: include/dns/enumtype.h include/dns/enumclass.h \ + include/dns/rdatastruct.h code.h +subdirs: include/dns/enumtype.h include/dns/enumclass.h \ + include/dns/rdatastruct.h code.h +${OBJS}: include/dns/enumtype.h include/dns/enumclass.h \ + include/dns/rdatastruct.h diff --git a/lib/export/dns/include/Makefile.in b/lib/export/dns/include/Makefile.in new file mode 100644 index 0000000..ecd9c8a --- /dev/null +++ b/lib/export/dns/include/Makefile.in @@ -0,0 +1,23 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +SUBDIRS = dns dst +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/export/dns/include/dns/Makefile.in b/lib/export/dns/include/dns/Makefile.in new file mode 100644 index 0000000..ccaae41 --- /dev/null +++ b/lib/export/dns/include/dns/Makefile.in @@ -0,0 +1,56 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.4 2009-09-18 07:18:04 jinmei Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +HEADERS = acl.h adb.h byaddr.h \ + cache.h callbacks.h cert.h client.h compress.h \ + db.h dbiterator.h diff.h dispatch.h dlz.h dnssec.h \ + ds.h events.h fixedname.h ecdb.h \ + forward.h iptable.h \ + keytable.h keyvalues.h \ + lib.h log.h \ + master.h masterdump.h message.h \ + name.h ncache.h nsec.h nsec3.h \ + peer.h portlist.h \ + rbt.h rcode.h rdata.h rdataclass.h \ + rdatalist.h rdataset.h rdatasetiter.h rdataslab.h rdatatype.h \ + request.h resolver.h result.h \ + secalg.h secproto.h soa.h stats.h \ + tcpmsg.h time.h tsec.h tsig.h ttl.h types.h \ + validator.h version.h view.h + +GENHEADERS = enumclass.h enumtype.h rdatastruct.h + +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_includedir}/dns + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} ${top_srcdir}/lib/dns/include/dns/$$i \ + ${DESTDIR}${export_includedir}/dns ; \ + done + for i in ${GENHEADERS}; do \ + ${INSTALL_DATA} $$i ${DESTDIR}${export_includedir}/dns ; \ + done diff --git a/lib/export/dns/include/dst/Makefile.in b/lib/export/dns/include/dst/Makefile.in new file mode 100644 index 0000000..cebc726 --- /dev/null +++ b/lib/export/dns/include/dst/Makefile.in @@ -0,0 +1,36 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +HEADERS = dst.h gssapi.h lib.h result.h + +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_includedir}/dst + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} ${top_srcdir}/lib/dns/include/dst/$$i \ + ${DESTDIR}${export_includedir}/dst ; \ + done diff --git a/lib/export/irs/Makefile.in b/lib/export/irs/Makefile.in new file mode 100644 index 0000000..aad9400 --- /dev/null +++ b/lib/export/irs/Makefile.in @@ -0,0 +1,86 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.4 2009-12-05 23:31:40 each Exp $ + +top_srcdir = @top_srcdir@ +srcdir = @top_srcdir@/lib/irs +export_srcdir = @top_srcdir@/lib/export + +@BIND9_VERSION@ + +@LIBIRS_API@ + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I. -I./include -I${srcdir}/include \ + ${ISCCFG_INCLUDES} -I../dns/include ${DNS_INCLUDES} \ + -I${export_srcdir}/isc/include ${ISC_INCLUDES} +CDEFINES = +CWARNINGS = + +# Alphabetically +OBJS = context.@O@ \ + dnsconf.@O@ \ + gai_strerror.@O@ getaddrinfo.@O@ getnameinfo.@O@ \ + resconf.@O@ + +# Alphabetically +SRCS = context.c \ + dnsconf.c \ + gai_sterror.c getaddrinfo.c getnameinfo.c \ + resconf.c + +ISCLIBS = ../isc/libisc.@A@ +DNSLIBS = ../dns/libdns.@A@ +ISCCFGLIBS = ../isccfg/libisccfg.@A@ + +LIBS = @LIBS@ + +SUBDIRS = include +TARGETS = timestamp + +@BIND9_MAKE_RULES@ + +version.@O@: ${srcdir}/version.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ + -DVERSION=\"${VERSION}\" \ + -DLIBINTERFACE=${LIBINTERFACE} \ + -DLIBREVISION=${LIBREVISION} \ + -DLIBAGE=${LIBAGE} \ + -c ${srcdir}/version.c + +libirs.@SA@: ${OBJS} version.@O@ + ${AR} ${ARFLAGS} $@ ${OBJS} version.@O@ + ${RANLIB} $@ + +libirs.la: ${OBJS} version.@O@ + ${LIBTOOL_MODE_LINK} \ + ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libirs.la \ + -rpath ${export_libdir} \ + -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ + ${OBJS} version.@O@ ${LIBS} ${ISCCFGLIBS} ${DNSLIBS} ${ISCLIBS} + +timestamp: libirs.@A@ + touch timestamp + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_libdir} + +install:: timestamp installdirs + ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libirs.@A@ \ + ${DESTDIR}${export_libdir} + +clean distclean:: + rm -f libirs.@A@ libirs.la timestamp diff --git a/lib/export/irs/include/Makefile.in b/lib/export/irs/include/Makefile.in new file mode 100644 index 0000000..e6d4eae --- /dev/null +++ b/lib/export/irs/include/Makefile.in @@ -0,0 +1,24 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.2 2009-09-01 00:22:27 jinmei Exp $ + +srcdir = @srdir@ +top_srcdir = @top_srcdir@ + + +SUBDIRS = irs +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/export/irs/include/irs/Makefile.in b/lib/export/irs/include/irs/Makefile.in new file mode 100644 index 0000000..93f4200 --- /dev/null +++ b/lib/export/irs/include/irs/Makefile.in @@ -0,0 +1,46 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +# +# Only list headers that are to be installed and are not +# machine generated. The latter are handled specially in the +# install target below. +# +HEADERS = context.h dnsconf.h resconf.h types.h version.h + +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_includedir}/irs + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} ${top_srcdir}/lib/irs/include/irs/$$i \ + ${DESTDIR}${export_includedir}/irs ; \ + done + ${INSTALL_DATA} ${top_srcdir}/lib/irs/include/irs/netdb.h \ + ${DESTDIR}${export_includedir}/irs + ${INSTALL_DATA} ${top_srcdir}/lib/irs/include/irs/platform.h \ + ${DESTDIR}${export_includedir}/irs + +distclean:: + rm -f netdb.h platform.h diff --git a/lib/export/isc/Makefile.in b/lib/export/isc/Makefile.in new file mode 100644 index 0000000..fa1c367 --- /dev/null +++ b/lib/export/isc/Makefile.in @@ -0,0 +1,139 @@ +# Copyright (C) 2009, 2010 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.8 2010-06-09 23:50:58 tbox Exp $ + +top_srcdir = @top_srcdir@ +srcdir = @top_srcdir@/lib/isc +export_srcdir = @top_srcdir@/lib/export + +@BIND9_VERSION@ + +@LIBISC_API@ + +CINCLUDES = -I${srcdir}/unix/include \ + -I${srcdir}/@ISC_THREAD_DIR@/include \ + -I${srcdir}/@ISC_ARCH_DIR@/include \ + -I${export_srcdir}/isc/include -I${srcdir}/include \ + @ISC_OPENSSL_INC@ +CDEFINES = @USE_OPENSSL@ -DUSE_APPIMPREGISTER -DUSE_MEMIMPREGISTER \ + -DUSE_SOCKETIMPREGISTER -DUSE_TASKIMPREGISTER \ + -DUSE_TIMERIMPREGISTER +CWARNINGS = + +# Alphabetically +# {file,dir}.c is necessary for isclog +# symtab.c is necessary for isccfg +APIOBJS = app_api.@O@ mem_api.@O@ socket_api.@O@ \ + task_api.@O@ timer_api.@O@ + +ISCDRIVEROBJS = mem.@O@ unix/socket.@O@ task.@O@ timer.@O@ lib.@O@ \ + heap.@O@ #timer module depends on this + +UNIXOBJS = @ISC_ISCIPV6_O@ \ + unix/app.@O@ \ + unix/dir.@O@ \ + unix/errno2result.@O@ \ + unix/file.@O@ \ + unix/fsaccess.@O@ \ + unix/stdio.@O@ \ + unix/stdtime.@O@ unix/strerror.@O@ unix/time.@O@ + +NLSOBJS = nls/msgcat.@O@ + +THREADOPTOBJS = @ISC_THREAD_DIR@/condition.@O@ @ISC_THREAD_DIR@/mutex.@O@ + +THREADOBJS = @THREADOPTOBJS@ @ISC_THREAD_DIR@/thread.@O@ + +WIN32OBJS = win32/condition.@O@ win32/dir.@O@ win32/file.@O@ \ + win32/fsaccess.@O@ win32/once.@O@ win32/stdtime.@O@ \ + win32/thread.@O@ win32/time.@O@ + +# Alphabetically +OBJS = @ISC_EXTRA_OBJS@ \ + assertions.@O@ backtrace.@O@ backtrace-emptytbl.@O@ base32.@O@ \ + base64.@O@ buffer.@O@ bufferlist.@O@ \ + error.@O@ event.@O@ \ + hash.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@ \ + inet_aton.@O@ iterated_hash.@O@ lex.@O@ lfsr.@O@ log.@O@ \ + md5.@O@ mutexblock.@O@ \ + netaddr.@O@ netscope.@O@ \ + ondestroy.@O@ \ + parseint.@O@ portset.@O@ radix.@O@ \ + random.@O@ refcount.@O@ region.@O@ result.@O@ rwlock.@O@ \ + serial.@O@ sha1.@O@ sha2.@O@ sockaddr.@O@ stats.@O@ string.@O@ \ + symtab.@O@ \ + version.@O@ \ + ${APIOBJS} ${ISCDRIVEROBJS} \ + ${UNIXOBJS} ${NLSOBJS} ${THREADOBJS} + +# Alphabetically +APISRCS = app_api.c mem_api.c socket_api.c \ + task_api.c timer_api.c + +ISCDRIVERSRCS = mem.c task.c lib.c timer.c heap.c + +SRCS = @ISC_EXTRA_SRCS@ \ + assertions.c backtrace.c backtrace-emptytbl.c base32.c \ + base64.c buffer.c bufferlist.c \ + error.c event.c \ + hash.c hex.c hmacmd5.c hmacsha.c \ + inet_aton.c iterated_hash.c lex.c log.c lfsr.c \ + md5.c mutexblock.c \ + netaddr.c netscope.c \ + ondestroy.c \ + parseint.c portset.c radix.c \ + random.c refcount.c region.c result.c rwlock.c \ + serial.c sha1.c sha2.c sockaddr.c stats.c string.c symtab.c \ + version.c \ + ${APISRCS} ${ISCDRIVERSRCS} + +LIBS = @LIBS@ + +SUBDIRS = include unix nls @ISC_THREAD_DIR@ +TARGETS = timestamp + +@BIND9_MAKE_RULES@ + +version.@O@: ${srcdir}/version.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ + -DVERSION=\"${VERSION}\" \ + -DLIBINTERFACE=${LIBINTERFACE} \ + -DLIBREVISION=${LIBREVISION} \ + -DLIBAGE=${LIBAGE} \ + -c ${srcdir}/version.c + +libisc.@SA@: ${OBJS} + ${AR} ${ARFLAGS} $@ ${OBJS} + ${RANLIB} $@ + +libisc.la: ${OBJS} + ${LIBTOOL_MODE_LINK} \ + ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc.la \ + -rpath ${export_libdir} \ + -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ + ${OBJS} ${LIBS} + +timestamp: libisc.@A@ + touch timestamp + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_libdir} + +install:: timestamp installdirs + ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libisc.@A@ \ + ${DESTDIR}${export_libdir} + +clean distclean:: + rm -f libisc.@A@ libisc.la timestamp diff --git a/lib/export/isc/include/Makefile.in b/lib/export/isc/include/Makefile.in new file mode 100644 index 0000000..f89628b --- /dev/null +++ b/lib/export/isc/include/Makefile.in @@ -0,0 +1,24 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.2 2009-09-01 00:22:27 jinmei Exp $ + +srcdir = @srdir@ +top_srcdir = @top_srcdir@ + + +SUBDIRS = isc +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/export/isc/include/isc/Makefile.in b/lib/export/isc/include/isc/Makefile.in new file mode 100644 index 0000000..0336ba2 --- /dev/null +++ b/lib/export/isc/include/isc/Makefile.in @@ -0,0 +1,66 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.3 2009-12-05 23:31:41 each Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +export_srcdir = @top_srcdir@/lib/export + +@BIND9_VERSION@ + +# +# Only list headers that are to be installed and are not +# machine generated. The latter are handled specially in the +# install target below. +# +HEADERS = app.h assertions.h base64.h bitstring.h boolean.h \ + buffer.h bufferlist.h commandline.h entropy.h error.h event.h \ + eventclass.h file.h formatcheck.h fsaccess.h \ + hash.h heap.h hex.h hmacmd5.h \ + httpd.h \ + interfaceiter.h @ISC_IPV6_H@ iterated_hash.h lang.h lex.h \ + lfsr.h lib.h list.h log.h \ + magic.h md5.h mem.h msgcat.h msgs.h \ + mutexblock.h namespace.h netaddr.h ondestroy.h os.h parseint.h \ + print.h quota.h radix.h random.h ratelimiter.h \ + refcount.h region.h resource.h \ + result.h resultclass.h rwlock.h serial.h sha1.h sha2.h \ + sockaddr.h socket.h stdio.h stdlib.h string.h \ + symtab.h \ + task.h taskpool.h timer.h types.h util.h version.h \ + xml.h + +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_includedir}/isc + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} ${top_srcdir}/lib/isc/include/isc/$$i \ + ${DESTDIR}${export_includedir}/isc ; \ + done + ${INSTALL_DATA} ${top_srcdir}/lib/isc/include/isc/platform.h \ + ${DESTDIR}${export_includedir}/isc + ${INSTALL_DATA} ${top_srcdir}/lib/isc/@ISC_ARCH_DIR@/include/isc/atomic.h \ + ${DESTDIR}${export_includedir}/isc + ${INSTALL_DATA} ${export_srcdir}/isc/include/isc/bind9.h \ + ${DESTDIR}${export_includedir}/isc + +distclean:: + rm -f platform.h diff --git a/lib/export/isc/include/isc/bind9.h b/lib/export/isc/include/isc/bind9.h new file mode 100644 index 0000000..380ca85 --- /dev/null +++ b/lib/export/isc/include/isc/bind9.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: bind9.h,v 1.2 2009-12-05 23:31:41 each Exp $ */ + +#ifndef ISC_BIND9_H +#define ISC_BIND9_H 1 + +/* + * This determines whether we are building BIND9 or using the exported + * libisc/libdns libraries. The version of this file included in the + * standard BIND9 build defines BIND9; the version included with the + * exportable libraries does not. + */ +#undef BIND9 + +#endif /* ISC_BIND9_H */ diff --git a/lib/export/isc/nls/Makefile.in b/lib/export/isc/nls/Makefile.in new file mode 100644 index 0000000..da2513f --- /dev/null +++ b/lib/export/isc/nls/Makefile.in @@ -0,0 +1,35 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $ + +top_srcdir = @top_srcdir@ +srcdir = @top_srcdir@/lib/isc/nls + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I${srcdir}/unix/include \ + ${ISC_INCLUDES} + +CDEFINES = +CWARNINGS = + +OBJS = msgcat.@O@ + +SRCS = msgcat.c + +SUBDIRS = +TARGETS = ${OBJS} + +@BIND9_MAKE_RULES@ diff --git a/lib/export/isc/nothreads/Makefile.in b/lib/export/isc/nothreads/Makefile.in new file mode 100644 index 0000000..3bffb4e --- /dev/null +++ b/lib/export/isc/nothreads/Makefile.in @@ -0,0 +1,40 @@ +# Copyright (C) 2009, 2010 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.5 2010-06-09 23:50:58 tbox Exp $ + +top_srcdir = @top_srcdir@ +srcdir = @top_srcdir@/lib/isc/nothreads + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I${srcdir}/include \ + -I${srcdir}/../unix/include \ + -I../include \ + -I${srcdir}/../include \ + -I${srcdir}/.. + +CDEFINES = +CWARNINGS = + +THREADOPTOBJS = condition.@O@ mutex.@O@ +OBJS = @THREADOPTOBJS@ thread.@O@ + +THREADOPTSRCS = condition.c mutex.c +SRCS = @THREADOPTSRCS@ thread.c + +SUBDIRS = include +TARGETS = ${OBJS} + +@BIND9_MAKE_RULES@ diff --git a/lib/export/isc/nothreads/include/Makefile.in b/lib/export/isc/nothreads/include/Makefile.in new file mode 100644 index 0000000..f89628b --- /dev/null +++ b/lib/export/isc/nothreads/include/Makefile.in @@ -0,0 +1,24 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.2 2009-09-01 00:22:27 jinmei Exp $ + +srcdir = @srdir@ +top_srcdir = @top_srcdir@ + + +SUBDIRS = isc +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/export/isc/nothreads/include/isc/Makefile.in b/lib/export/isc/nothreads/include/isc/Makefile.in new file mode 100644 index 0000000..423f10a --- /dev/null +++ b/lib/export/isc/nothreads/include/isc/Makefile.in @@ -0,0 +1,36 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.2 2009-09-01 00:22:27 jinmei Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +HEADERS = condition.h mutex.h once.h thread.h + +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_includedir}/isc + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} $(top_srcdir)/lib/isc/nothreads/include/isc/$$i \ + ${DESTDIR}${export_includedir}/isc ; \ + done diff --git a/lib/export/isc/pthreads/Makefile.in b/lib/export/isc/pthreads/Makefile.in new file mode 100644 index 0000000..5fac018 --- /dev/null +++ b/lib/export/isc/pthreads/Makefile.in @@ -0,0 +1,38 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $ + +top_srcdir = @top_srcdir@ +srcdir = @top_srcdir@/lib/isc/pthreads + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I${srcdir}/include \ + -I${srcdir}/../unix/include \ + -I../include \ + -I${srcdir}/../include \ + -I${srcdir}/.. + +CDEFINES = +CWARNINGS = + +OBJS = condition.@O@ mutex.@O@ thread.@O@ + +SRCS = condition.c mutex.c thread.c + +SUBDIRS = include +TARGETS = ${OBJS} + +@BIND9_MAKE_RULES@ diff --git a/lib/export/isc/pthreads/include/Makefile.in b/lib/export/isc/pthreads/include/Makefile.in new file mode 100644 index 0000000..f89628b --- /dev/null +++ b/lib/export/isc/pthreads/include/Makefile.in @@ -0,0 +1,24 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.2 2009-09-01 00:22:27 jinmei Exp $ + +srcdir = @srdir@ +top_srcdir = @top_srcdir@ + + +SUBDIRS = isc +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/export/isc/pthreads/include/isc/Makefile.in b/lib/export/isc/pthreads/include/isc/Makefile.in new file mode 100644 index 0000000..807de94 --- /dev/null +++ b/lib/export/isc/pthreads/include/isc/Makefile.in @@ -0,0 +1,36 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.2 2009-09-01 00:22:27 jinmei Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +HEADERS = condition.h mutex.h once.h thread.h + +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_includedir}/isc + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} $(top_srcdir)/lib/isc/pthreads/include/isc/$$i \ + ${DESTDIR}${export_includedir}/isc ; \ + done diff --git a/lib/export/isc/unix/Makefile.in b/lib/export/isc/unix/Makefile.in new file mode 100644 index 0000000..81746a4 --- /dev/null +++ b/lib/export/isc/unix/Makefile.in @@ -0,0 +1,57 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $ + +top_srcdir = @top_srcdir@ +srcdir = @top_srcdir@/lib/isc/unix + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I${srcdir}/include \ + -I${srcdir}/../@ISC_THREAD_DIR@/include \ + -I../include \ + -I${srcdir}/../include \ + -I${srcdir}/.. + +CDEFINES = -DUSE_SOCKETIMPREGISTER -DUSE_APPIMPREGISTER + +CWARNINGS = + +# Alphabetically +ISCDRIVEROBJS = app.@O@ socket.@O@ + +OBJS = @ISC_IPV6_O@ \ + dir.@O@ \ + errno2result.@O@ \ + file.@O@ fsaccess.@O@ \ + stdio.@O@ stdtime.@O@ strerror.@O@ \ + time.@O@ \ + ${ISCDRIVEROBJS} + +# Alphabetically +ISCDRIVERSRCS = app.c socket.c + +SRCS = @ISC_IPV6_C@ \ + dir.c \ + errno2result.c \ + file.c fsaccess.c \ + stdio.c stdtime.c strerror.c \ + time.c \ + ${ISCDRIVERSRCS} + +SUBDIRS = include +TARGETS = ${OBJS} + +@BIND9_MAKE_RULES@ diff --git a/lib/export/isc/unix/include/Makefile.in b/lib/export/isc/unix/include/Makefile.in new file mode 100644 index 0000000..f89628b --- /dev/null +++ b/lib/export/isc/unix/include/Makefile.in @@ -0,0 +1,24 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.2 2009-09-01 00:22:27 jinmei Exp $ + +srcdir = @srdir@ +top_srcdir = @top_srcdir@ + + +SUBDIRS = isc +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/export/isc/unix/include/isc/Makefile.in b/lib/export/isc/unix/include/isc/Makefile.in new file mode 100644 index 0000000..21ce049 --- /dev/null +++ b/lib/export/isc/unix/include/isc/Makefile.in @@ -0,0 +1,37 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.2 2009-09-01 00:22:27 jinmei Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +HEADERS = dir.h int.h net.h netdb.h offset.h stdtime.h \ + syslog.h time.h + +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_includedir}/isc + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} $(top_srcdir)/lib/isc/unix/include/isc/$$i \ + ${DESTDIR}${export_includedir}/isc ; \ + done diff --git a/lib/export/isccfg/Makefile.in b/lib/export/isccfg/Makefile.in new file mode 100644 index 0000000..ed2b2cf --- /dev/null +++ b/lib/export/isccfg/Makefile.in @@ -0,0 +1,83 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.4 2009-12-05 23:31:41 each Exp $ + +top_srcdir = @top_srcdir@ +srcdir = @top_srcdir@/lib/isccfg +export_srcdir = @top_srcdir@/lib/export + +@BIND9_VERSION@ + +@LIBISCCFG_API@ + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I. ${DNS_INCLUDES} -I${export_srcdir}/isc/include \ + ${ISC_INCLUDES} ${ISCCFG_INCLUDES} + +CDEFINES = +CWARNINGS = + +ISCLIBS = ../isc/libisc.@A@ +DNSLIBS = ../dns/libdns.@A@ + +ISCDEPLIBS = ../../lib/isc/libisc.@A@ +ISCCFGDEPLIBS = libisccfg.@A@ + +LIBS = @LIBS@ + +SUBDIRS = include + +# Alphabetically +OBJS = dnsconf.@O@ log.@O@ parser.@O@ version.@O@ + +# Alphabetically +SRCS = dnsconf.c log.c parser.c version.c + +TARGETS = timestamp + +@BIND9_MAKE_RULES@ + +version.@O@: ${srcdir}/version.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ + -DVERSION=\"${VERSION}\" \ + -DLIBINTERFACE=${LIBINTERFACE} \ + -DLIBREVISION=${LIBREVISION} \ + -DLIBAGE=${LIBAGE} \ + -c ${srcdir}/version.c + +libisccfg.@SA@: ${OBJS} + ${AR} ${ARFLAGS} $@ ${OBJS} + ${RANLIB} $@ + +libisccfg.la: ${OBJS} + ${LIBTOOL_MODE_LINK} \ + ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisccfg.la \ + -rpath ${export_libdir} \ + -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ + ${OBJS} ${LIBS} ${DNSLIBS} ${ISCLIBS} + +timestamp: libisccfg.@A@ + touch timestamp + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_libdir} + +install:: timestamp installdirs + ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libisccfg.@A@ \ + ${DESTDIR}${export_libdir} + +clean distclean:: + rm -f libisccfg.@A@ timestamp diff --git a/lib/export/isccfg/include/Makefile.in b/lib/export/isccfg/include/Makefile.in new file mode 100644 index 0000000..896c467 --- /dev/null +++ b/lib/export/isccfg/include/Makefile.in @@ -0,0 +1,24 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.2 2009-09-01 00:22:27 jinmei Exp $ + +srcdir = @srdir@ +top_srcdir = @top_srcdir@ + + +SUBDIRS = isccfg +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/export/isccfg/include/isccfg/Makefile.in b/lib/export/isccfg/include/isccfg/Makefile.in new file mode 100644 index 0000000..3f97894 --- /dev/null +++ b/lib/export/isccfg/include/isccfg/Makefile.in @@ -0,0 +1,42 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +# +# Only list headers that are to be installed and are not +# machine generated. The latter are handled specially in the +# install target below. +# +HEADERS = cfg.h grammar.h log.h dnsconf.h version.h + +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs \ + ${DESTDIR}${export_includedir}/isccfg + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} ${top_srcdir}/lib/isccfg/include/isccfg/$$i \ + ${DESTDIR}${export_includedir}/isccfg ; \ + done diff --git a/lib/export/samples/Makefile-postinstall.in b/lib/export/samples/Makefile-postinstall.in new file mode 100644 index 0000000..10a26f4 --- /dev/null +++ b/lib/export/samples/Makefile-postinstall.in @@ -0,0 +1,78 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile-postinstall.in,v 1.3 2009-09-02 23:48:02 tbox Exp $ + +srcdir = @srcdir@ +#prefix = @prefix@ +#exec_prefix = @exec_prefix@ + +CDEFINES = +CWARNINGS = + +DNSLIBS = -ldns @DNS_CRYPTO_LIBS@ +ISCLIBS = -lisc +ISCCFGLIBS = -lisccfg +IRSLIBS = -lirs + +LIBS = ${DNSLIBS} ${ISCCFGLIBS} ${ISCLIBS} @LIBS@ + +SUBDIRS = + +TARGETS = sample@EXEEXT@ sample-async@EXEEXT@ sample-gai@EXEEXT@ \ + sample-update@EXEEXT@ sample-request@EXEEXT@ nsprobe@EXEEXT@ \ + dlvchecks@EXEEXT@ + +OBJS = sample.@O@ sample-async.@O@ sample-gai.@O@ sample-update.@O@ \ + sample-request.@O@ nsprobe.@O@ dlvchecks.@O@ + +SRCS = sample.c sample-async.c sample-gai.c sample-update.c \ + sample-request.c nsprobe.c dlvchecks..c + +@BIND9_MAKE_RULES@ + +# The following two may depend on BIND9_MAKE_RULES +CINCLUDES = -I@export_includedir@ +LDFLAGS = -L@export_libdir@ + +sample@EXEEXT@: sample.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + sample.@O@ ${LIBS} + +sample-async@EXEEXT@: sample-async.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + sample-async.@O@ ${LIBS} + +sample-gai@EXEEXT@: sample-gai.@O@ ${IRSDEPLIBS} ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + sample-gai.@O@ ${IRSLIBS} ${LIBS} + +sample-update@EXEEXT@: sample-update.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + sample-update.@O@ ${LIBS} + +sample-request@EXEEXT@: sample-request.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + sample-request.@O@ ${LIBS} + +nsprobe@EXEEXT@: nsprobe.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + nsprobe.@O@ ${LIBS} + +dlvchecks@EXEEXT@: dlvchecks.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + dlvchecks.@O@ ${LIBS} + +clean distclean maintainer-clean:: + rm -f ${TARGETS} diff --git a/lib/export/samples/Makefile.in b/lib/export/samples/Makefile.in new file mode 100644 index 0000000..ff8e916 --- /dev/null +++ b/lib/export/samples/Makefile.in @@ -0,0 +1,98 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.4 2009-12-05 23:31:41 each Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +export_srcdir = @top_srcdir@/lib/export + +@BIND9_VERSION@ + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I${srcdir}/include -I../dns/include \ + -I${export_srcdir}/isc/include \ + ${DNS_INCLUDES} ${ISC_INCLUDES} \ + -I${top_srcdir}/lib/irs/include + +CDEFINES = +CWARNINGS = + +DNSLIBS = ../dns/libdns.@A@ @DNS_CRYPTO_LIBS@ +ISCLIBS = ../isc/libisc.@A@ +ISCCFGLIBS = ../isccfg/libisccfg.@A@ +IRSLIBS = ../irs/libirs.@A@ + +DNSDEPLIBS = ../dns/libdns.@A@ +ISCDEPLIBS = ../isc/libisc.@A@ +ISCCFGDEPLIBS = ../isccfg/libisccfg.@A@ +IRSDEPLIBS = ../irs/libirs.@A@ + +DEPLIBS = ${DNSDEPLIBS} ${ISCCFGDEPLIBS} ${ISCDEPLIBS} + +LIBS = ${DNSLIBS} ${ISCCFGLIBS} ${ISCLIBS} @LIBS@ + +SUBDIRS = + +TARGETS = sample@EXEEXT@ sample-async@EXEEXT@ sample-gai@EXEEXT@ \ + sample-update@EXEEXT@ sample-request@EXEEXT@ nsprobe@EXEEXT@ + +OBJS = sample.@O@ sample-async.@O@ sample-gai.@O@ sample-update.@O@ \ + sample-request.@O@ nsprobe.@O@ + +UOBJS = + +SRCS = sample.c sample-async.c sample-gai.c sample-update.c \ + sample-request.c nsprobe.c + +MANPAGES = + +HTMLPAGES = + +MANOBJS = ${MANPAGES} ${HTMLPAGES} + +@BIND9_MAKE_RULES@ + +sample@EXEEXT@: sample.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + sample.@O@ ${LIBS} + +sample-async@EXEEXT@: sample-async.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + sample-async.@O@ ${LIBS} + +sample-gai@EXEEXT@: sample-gai.@O@ ${IRSDEPLIBS} ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + sample-gai.@O@ ${IRSLIBS} ${LIBS} + +sample-update@EXEEXT@: sample-update.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + sample-update.@O@ ${LIBS} + +sample-request@EXEEXT@: sample-request.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + sample-request.@O@ ${LIBS} + +nsprobe@EXEEXT@: nsprobe.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + nsprobe.@O@ ${LIBS} + +doc man:: ${MANOBJS} + +docclean manclean maintainer-clean:: + rm -f ${MANOBJS} + +clean distclean maintainer-clean:: + rm -f ${TARGETS} diff --git a/lib/export/samples/nsprobe.c b/lib/export/samples/nsprobe.c new file mode 100644 index 0000000..85c572d --- /dev/null +++ b/lib/export/samples/nsprobe.c @@ -0,0 +1,1220 @@ +/* + * Copyright (C) 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: nsprobe.c,v 1.7 2010-01-07 23:48:54 tbox Exp $ */ + +#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 MAX_PROBES 1000 + +static dns_client_t *client = NULL; +static isc_task_t *probe_task = NULL; +static isc_appctx_t *actx = NULL; +static isc_mem_t *mctx = NULL; +static unsigned int outstanding_probes = 0; +const char *cacheserver = "127.0.0.1"; +static FILE *fp; + +typedef enum { + none, + exist, + nxdomain, + othererr, + multiplesoa, + multiplecname, + brokenanswer, + lame, + timedout, + notype, + unexpected +} query_result_t; + +struct server { + ISC_LINK(struct server) link; + + isc_sockaddr_t address; + query_result_t result_a; + query_result_t result_aaaa; +}; + +struct probe_ns { + ISC_LINK(struct probe_ns) link; + + dns_fixedname_t fixedname; + dns_name_t *name; + struct server *current_server; + ISC_LIST(struct server) servers; +}; + +struct probe_trans { + isc_boolean_t inuse; + char *domain; + dns_fixedname_t fixedname; + dns_name_t *qname; + const char **qlabel; + isc_boolean_t qname_found; + dns_clientrestrans_t *resid; + dns_message_t *qmessage; + dns_message_t *rmessage; + dns_clientreqtrans_t *reqid; + + /* NS list */ + struct probe_ns *current_ns; + ISC_LIST(struct probe_ns) nslist; +}; + +struct lcl_stat { + unsigned long valid; + unsigned long ignore; + unsigned long nxdomain; + unsigned long othererr; + unsigned long multiplesoa; + unsigned long multiplecname; + unsigned long brokenanswer; + unsigned long lame; + unsigned long unknown; +} server_stat, domain_stat; + +static unsigned long number_of_domains = 0; +static unsigned long number_of_servers = 0; +static unsigned long multiple_error_domains = 0; +static isc_boolean_t debug_mode = ISC_FALSE; +static int verbose_level = 0; +static const char *qlabels[] = {"www.", "ftp.", NULL}; +static struct probe_trans probes[MAX_PROBES]; + +static isc_result_t probe_domain(struct probe_trans *trans); +static void reset_probe(struct probe_trans *trans); +static isc_result_t fetch_nsaddress(struct probe_trans *trans); +static isc_result_t probe_name(struct probe_trans *trans, + dns_rdatatype_t type); + +/* Dump an rdataset for debug */ +static isc_result_t +print_rdataset(dns_rdataset_t *rdataset, dns_name_t *owner) { + isc_buffer_t target; + isc_result_t result; + isc_region_t r; + char t[4096]; + + if (!debug_mode) + return (ISC_R_SUCCESS); + + isc_buffer_init(&target, t, sizeof(t)); + + if (!dns_rdataset_isassociated(rdataset)) + return (ISC_R_SUCCESS); + result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE, + &target); + if (result != ISC_R_SUCCESS) + return (result); + isc_buffer_usedregion(&target, &r); + printf("%.*s", (int)r.length, (char *)r.base); + + return (ISC_R_SUCCESS); +} + +static isc_result_t +print_name(dns_name_t *name) { + isc_result_t result; + isc_buffer_t target; + isc_region_t r; + char t[4096]; + + isc_buffer_init(&target, t, sizeof(t)); + result = dns_name_totext(name, ISC_TRUE, &target); + if (result == ISC_R_SUCCESS) { + isc_buffer_usedregion(&target, &r); + printf("%.*s", (int)r.length, (char *)r.base); + } else + printf("(invalid name)"); + + return (result); +} + +static isc_result_t +print_address(FILE *fp, isc_sockaddr_t *addr) { + char buf[NI_MAXHOST]; + + if (getnameinfo(&addr->type.sa, addr->length, buf, sizeof(buf), + NULL, 0, NI_NUMERICHOST) == 0) { + fprintf(fp, "%s", buf); + } else { + fprintf(fp, "(invalid address)"); + } + + return (ISC_R_SUCCESS); +} + +static void +ctxs_destroy(isc_mem_t **mctxp, isc_appctx_t **actxp, + isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp, + isc_timermgr_t **timermgrp) +{ + if (*taskmgrp != NULL) + isc_taskmgr_destroy(taskmgrp); + + if (*timermgrp != NULL) + isc_timermgr_destroy(timermgrp); + + if (*socketmgrp != NULL) + isc_socketmgr_destroy(socketmgrp); + + if (*actxp != NULL) + isc_appctx_destroy(actxp); + + if (*mctxp != NULL) + isc_mem_destroy(mctxp); +} + +static isc_result_t +ctxs_init(isc_mem_t **mctxp, isc_appctx_t **actxp, + isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp, + isc_timermgr_t **timermgrp) +{ + isc_result_t result; + + result = isc_mem_create(0, 0, mctxp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_appctx_create(*mctxp, actxp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_taskmgr_createinctx(*mctxp, *actxp, 1, 0, taskmgrp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_socketmgr_createinctx(*mctxp, *actxp, socketmgrp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_timermgr_createinctx(*mctxp, *actxp, timermgrp); + if (result != ISC_R_SUCCESS) + goto fail; + + return (ISC_R_SUCCESS); + + fail: + ctxs_destroy(mctxp, actxp, taskmgrp, socketmgrp, timermgrp); + + return (result); +} + +/* + * Common routine to make query data + */ +static isc_result_t +make_querymessage(dns_message_t *message, dns_name_t *qname0, + dns_rdatatype_t rdtype) +{ + dns_name_t *qname = NULL; + dns_rdataset_t *qrdataset = NULL; + isc_result_t result; + + message->opcode = dns_opcode_query; + message->rdclass = dns_rdataclass_in; + + result = dns_message_gettempname(message, &qname); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = dns_message_gettemprdataset(message, &qrdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + + dns_name_init(qname, NULL); + dns_name_clone(qname0, qname); + dns_rdataset_init(qrdataset); + dns_rdataset_makequestion(qrdataset, message->rdclass, rdtype); + ISC_LIST_APPEND(qname->list, qrdataset, link); + dns_message_addname(message, qname, DNS_SECTION_QUESTION); + + return (ISC_R_SUCCESS); + + cleanup: + if (qname != NULL) + dns_message_puttempname(message, &qname); + if (qrdataset != NULL) + dns_message_puttemprdataset(message, &qrdataset); + if (message != NULL) + dns_message_destroy(&message); + return (result); +} + +/* + * Update statistics + */ +static inline void +increment_entry(unsigned long *entryp) { + (*entryp)++; + INSIST(*entryp != 0); /* check overflow */ +} + +static void +update_stat(struct probe_trans *trans) { + struct probe_ns *pns; + struct server *server; + struct lcl_stat local_stat; + unsigned int err_count = 0; + const char *stattype; + + increment_entry(&number_of_domains); + memset(&local_stat, 0, sizeof(local_stat)); + + /* Update per sever statistics */ + for (pns = ISC_LIST_HEAD(trans->nslist); pns != NULL; + pns = ISC_LIST_NEXT(pns, link)) { + for (server = ISC_LIST_HEAD(pns->servers); server != NULL; + server = ISC_LIST_NEXT(server, link)) { + increment_entry(&number_of_servers); + + if (server->result_aaaa == exist || + server->result_aaaa == notype) { + /* + * Don't care about the result of A query if + * the answer to AAAA query was expected. + */ + stattype = "valid"; + increment_entry(&server_stat.valid); + increment_entry(&local_stat.valid); + } else if (server->result_a == exist) { + switch (server->result_aaaa) { + case exist: + case notype: + stattype = "valid"; + increment_entry(&server_stat.valid); + increment_entry(&local_stat.valid); + break; + case timedout: + stattype = "ignore"; + increment_entry(&server_stat.ignore); + increment_entry(&local_stat.ignore); + break; + case nxdomain: + stattype = "nxdomain"; + increment_entry(&server_stat.nxdomain); + increment_entry(&local_stat.nxdomain); + break; + case othererr: + stattype = "othererr"; + increment_entry(&server_stat.othererr); + increment_entry(&local_stat.othererr); + break; + case multiplesoa: + stattype = "multiplesoa"; + increment_entry(&server_stat.multiplesoa); + increment_entry(&local_stat.multiplesoa); + break; + case multiplecname: + stattype = "multiplecname"; + increment_entry(&server_stat.multiplecname); + increment_entry(&local_stat.multiplecname); + break; + case brokenanswer: + stattype = "brokenanswer"; + increment_entry(&server_stat.brokenanswer); + increment_entry(&local_stat.brokenanswer); + break; + case lame: + stattype = "lame"; + increment_entry(&server_stat.lame); + increment_entry(&local_stat.lame); + break; + default: + stattype = "unknown"; + increment_entry(&server_stat.unknown); + increment_entry(&local_stat.unknown); + break; + } + } else { + stattype = "unknown"; + increment_entry(&server_stat.unknown); + increment_entry(&local_stat.unknown); + } + + if (verbose_level > 1 || + (verbose_level == 1 && + strcmp(stattype, "valid") != 0 && + strcmp(stattype, "unknown") != 0)) { + print_name(pns->name); + putchar('('); + print_address(stdout, &server->address); + printf(") for %s:%s\n", trans->domain, + stattype); + } + } + } + + /* Update per domain statistics */ + if (local_stat.ignore > 0) { + if (verbose_level > 0) + printf("%s:ignore\n", trans->domain); + increment_entry(&domain_stat.ignore); + err_count++; + } + if (local_stat.nxdomain > 0) { + if (verbose_level > 0) + printf("%s:nxdomain\n", trans->domain); + increment_entry(&domain_stat.nxdomain); + err_count++; + } + if (local_stat.othererr > 0) { + if (verbose_level > 0) + printf("%s:othererr\n", trans->domain); + increment_entry(&domain_stat.othererr); + err_count++; + } + if (local_stat.multiplesoa > 0) { + if (verbose_level > 0) + printf("%s:multiplesoa\n", trans->domain); + increment_entry(&domain_stat.multiplesoa); + err_count++; + } + if (local_stat.multiplecname > 0) { + if (verbose_level > 0) + printf("%s:multiplecname\n", trans->domain); + increment_entry(&domain_stat.multiplecname); + err_count++; + } + if (local_stat.brokenanswer > 0) { + if (verbose_level > 0) + printf("%s:brokenanswer\n", trans->domain); + increment_entry(&domain_stat.brokenanswer); + err_count++; + } + if (local_stat.lame > 0) { + if (verbose_level > 0) + printf("%s:lame\n", trans->domain); + increment_entry(&domain_stat.lame); + err_count++; + } + + if (err_count > 1) + increment_entry(&multiple_error_domains); + + /* + * We regard the domain as valid if and only if no authoritative server + * has a problem and at least one server is known to be valid. + */ + if (local_stat.valid > 0 && err_count == 0) { + if (verbose_level > 1) + printf("%s:valid\n", trans->domain); + increment_entry(&domain_stat.valid); + } + + /* + * If the domain has no available server or all servers have the + * 'unknown' result, the domain's result is also regarded as unknown. + */ + if (local_stat.valid == 0 && err_count == 0) { + if (verbose_level > 1) + printf("%s:unknown\n", trans->domain); + increment_entry(&domain_stat.unknown); + } +} + +/* + * Search for an existent name with an A RR + */ + +static isc_result_t +set_nextqname(struct probe_trans *trans) { + isc_result_t result; + size_t domainlen; + isc_buffer_t b; + char buf[4096]; /* XXX ad-hoc constant, but should be enough */ + + if (*trans->qlabel == NULL) + return (ISC_R_NOMORE); + + result = isc_string_copy(buf, sizeof(buf), *trans->qlabel); + if (result != ISC_R_SUCCESS) + return (result); + result = isc_string_append(buf, sizeof(buf), trans->domain); + if (result != ISC_R_SUCCESS) + return (result); + + domainlen = strlen(buf); + isc_buffer_init(&b, buf, domainlen); + isc_buffer_add(&b, domainlen); + dns_fixedname_init(&trans->fixedname); + trans->qname = dns_fixedname_name(&trans->fixedname); + result = dns_name_fromtext(trans->qname, &b, dns_rootname, + 0, NULL); + + trans->qlabel++; + + return (result); +} + +static void +request_done(isc_task_t *task, isc_event_t *event) { + struct probe_trans *trans = event->ev_arg; + dns_clientreqevent_t *rev = (dns_clientreqevent_t *)event; + dns_message_t *rmessage; + struct probe_ns *pns; + struct server *server; + isc_result_t result; + query_result_t *resultp; + dns_name_t *name; + dns_rdataset_t *rdataset; + dns_rdatatype_t type; + + REQUIRE(task == probe_task); + REQUIRE(trans != NULL && trans->inuse == ISC_TRUE); + rmessage = rev->rmessage; + REQUIRE(rmessage == trans->rmessage); + INSIST(outstanding_probes > 0); + + server = trans->current_ns->current_server; + INSIST(server != NULL); + + if (server->result_a == none) { + type = dns_rdatatype_a; + resultp = &server->result_a; + } else { + resultp = &server->result_aaaa; + type = dns_rdatatype_aaaa; + } + + if (rev->result == ISC_R_SUCCESS) { + if ((rmessage->flags & DNS_MESSAGEFLAG_AA) == 0) + *resultp = lame; + else if (rmessage->rcode == dns_rcode_nxdomain) + *resultp = nxdomain; + else if (rmessage->rcode != dns_rcode_noerror) + *resultp = othererr; + else if (rmessage->counts[DNS_SECTION_ANSWER] == 0) { + /* no error but empty answer */ + *resultp = notype; + } else { + result = dns_message_firstname(rmessage, + DNS_SECTION_ANSWER); + while (result == ISC_R_SUCCESS) { + name = NULL; + dns_message_currentname(rmessage, + DNS_SECTION_ANSWER, + &name); + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, + link)) { + (void)print_rdataset(rdataset, name); + + if (rdataset->type == + dns_rdatatype_cname || + rdataset->type == + dns_rdatatype_dname) { + /* Should chase the chain? */ + *resultp = exist; + goto found; + } else if (rdataset->type == type) { + *resultp = exist; + goto found; + } + } + result = dns_message_nextname(rmessage, + DNS_SECTION_ANSWER); + } + + /* + * Something unexpected happened: the response + * contained a non-empty authoritative answer, but we + * could not find an expected result. + */ + *resultp = unexpected; + } + } else if (rev->result == DNS_R_RECOVERABLE || + rev->result == DNS_R_BADLABELTYPE) { + /* Broken response. Try identifying known cases. */ + *resultp = brokenanswer; + + if (rmessage->counts[DNS_SECTION_ANSWER] > 0) { + result = dns_message_firstname(rmessage, + DNS_SECTION_ANSWER); + while (result == ISC_R_SUCCESS) { + /* + * Check to see if the response has multiple + * CNAME RRs. Update the result code if so. + */ + name = NULL; + dns_message_currentname(rmessage, + DNS_SECTION_ANSWER, + &name); + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, + link)) { + if (rdataset->type == + dns_rdatatype_cname && + dns_rdataset_count(rdataset) > 1) { + *resultp = multiplecname; + goto found; + } + } + result = dns_message_nextname(rmessage, + DNS_SECTION_ANSWER); + } + } + + if (rmessage->counts[DNS_SECTION_AUTHORITY] > 0) { + result = dns_message_firstname(rmessage, + DNS_SECTION_AUTHORITY); + while (result == ISC_R_SUCCESS) { + /* + * Check to see if the response has multiple + * SOA RRs. Update the result code if so. + */ + name = NULL; + dns_message_currentname(rmessage, + DNS_SECTION_AUTHORITY, + &name); + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, + link)) { + if (rdataset->type == + dns_rdatatype_soa && + dns_rdataset_count(rdataset) > 1) { + *resultp = multiplesoa; + goto found; + } + } + result = dns_message_nextname(rmessage, + DNS_SECTION_AUTHORITY); + } + } + } else if (rev->result == ISC_R_TIMEDOUT) + *resultp = timedout; + else { + fprintf(stderr, "unexpected result: %d (domain=%s, server=", + rev->result, trans->domain); + print_address(stderr, &server->address); + fputc('\n', stderr); + *resultp = unexpected; + } + + found: + INSIST(*resultp != none); + if (type == dns_rdatatype_a && *resultp == exist) + trans->qname_found = ISC_TRUE; + + dns_client_destroyreqtrans(&trans->reqid); + isc_event_free(&event); + dns_message_reset(trans->rmessage, DNS_MESSAGE_INTENTPARSE); + + result = probe_name(trans, type); + if (result == ISC_R_NOMORE) { + /* We've tried all addresses of all servers. */ + if (type == dns_rdatatype_a && trans->qname_found) { + /* + * If we've explored A RRs and found an existent + * record, we can move to AAAA. + */ + trans->current_ns = ISC_LIST_HEAD(trans->nslist); + probe_name(trans, dns_rdatatype_aaaa); + result = ISC_R_SUCCESS; + } else if (type == dns_rdatatype_a) { + /* + * No server provided an existent A RR of this name. + * Try next label. + */ + dns_fixedname_invalidate(&trans->fixedname); + trans->qname = NULL; + result = set_nextqname(trans); + if (result == ISC_R_SUCCESS) { + trans->current_ns = + ISC_LIST_HEAD(trans->nslist); + for (pns = trans->current_ns; pns != NULL; + pns = ISC_LIST_NEXT(pns, link)) { + for (server = ISC_LIST_HEAD(pns->servers); + server != NULL; + server = ISC_LIST_NEXT(server, + link)) { + INSIST(server->result_aaaa == + none); + server->result_a = none; + } + } + result = probe_name(trans, dns_rdatatype_a); + } + } + if (result != ISC_R_SUCCESS) { + /* + * We've explored AAAA RRs or failed to find a valid + * query label. Wrap up the result and move to the + * next domain. + */ + reset_probe(trans); + } + } else if (result != ISC_R_SUCCESS) + reset_probe(trans); /* XXX */ +} + +static isc_result_t +probe_name(struct probe_trans *trans, dns_rdatatype_t type) { + isc_result_t result; + struct probe_ns *pns; + struct server *server; + + REQUIRE(trans->reqid == NULL); + REQUIRE(type == dns_rdatatype_a || type == dns_rdatatype_aaaa); + + for (pns = trans->current_ns; pns != NULL; + pns = ISC_LIST_NEXT(pns, link)) { + for (server = ISC_LIST_HEAD(pns->servers); server != NULL; + server = ISC_LIST_NEXT(server, link)) { + if ((type == dns_rdatatype_a && + server->result_a == none) || + (type == dns_rdatatype_aaaa && + server->result_aaaa == none)) { + pns->current_server = server; + goto found; + } + } + } + + found: + trans->current_ns = pns; + if (pns == NULL) + return (ISC_R_NOMORE); + + INSIST(pns->current_server != NULL); + dns_message_reset(trans->qmessage, DNS_MESSAGE_INTENTRENDER); + result = make_querymessage(trans->qmessage, trans->qname, type); + if (result != ISC_R_SUCCESS) + return (result); + result = dns_client_startrequest(client, trans->qmessage, + trans->rmessage, + &pns->current_server->address, + 0, DNS_MESSAGEPARSE_BESTEFFORT, + NULL, 120, 0, 4, + probe_task, request_done, trans, + &trans->reqid); + + return (result); +} + +/* + * Get IP addresses of NSes + */ + +static void +resolve_nsaddress(isc_task_t *task, isc_event_t *event) { + struct probe_trans *trans = event->ev_arg; + dns_clientresevent_t *rev = (dns_clientresevent_t *)event; + dns_name_t *name; + dns_rdataset_t *rdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + struct probe_ns *pns = trans->current_ns; + isc_result_t result; + + REQUIRE(task == probe_task); + REQUIRE(trans->inuse == ISC_TRUE); + REQUIRE(pns != NULL); + INSIST(outstanding_probes > 0); + + for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL; + name = ISC_LIST_NEXT(name, link)) { + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + (void)print_rdataset(rdataset, name); + + if (rdataset->type != dns_rdatatype_a) + continue; + + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + dns_rdata_in_a_t rdata_a; + struct server *server; + + dns_rdataset_current(rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &rdata_a, + NULL); + if (result != ISC_R_SUCCESS) + continue; + + server = isc_mem_get(mctx, sizeof(*server)); + if (server == NULL) { + fprintf(stderr, "resolve_nsaddress: " + "mem_get failed"); + result = ISC_R_NOMEMORY; + goto cleanup; + } + isc_sockaddr_fromin(&server->address, + &rdata_a.in_addr, 53); + ISC_LINK_INIT(server, link); + server->result_a = none; + server->result_aaaa = none; + ISC_LIST_APPEND(pns->servers, server, link); + } + } + } + + cleanup: + dns_client_freeresanswer(client, &rev->answerlist); + dns_client_destroyrestrans(&trans->resid); + isc_event_free(&event); + + next_ns: + trans->current_ns = ISC_LIST_NEXT(pns, link); + if (trans->current_ns == NULL) { + trans->current_ns = ISC_LIST_HEAD(trans->nslist); + dns_fixedname_invalidate(&trans->fixedname); + trans->qname = NULL; + result = set_nextqname(trans); + if (result == ISC_R_SUCCESS) + result = probe_name(trans, dns_rdatatype_a); + } else { + result = fetch_nsaddress(trans); + if (result != ISC_R_SUCCESS) + goto next_ns; /* XXX: this is unlikely to succeed */ + } + + if (result != ISC_R_SUCCESS) + reset_probe(trans); +} + +static isc_result_t +fetch_nsaddress(struct probe_trans *trans) { + struct probe_ns *pns; + + pns = trans->current_ns; + REQUIRE(pns != NULL); + + return (dns_client_startresolve(client, pns->name, dns_rdataclass_in, + dns_rdatatype_a, 0, probe_task, + resolve_nsaddress, trans, + &trans->resid)); +} + +/* + * Get NS RRset for a given domain + */ + +static void +reset_probe(struct probe_trans *trans) { + struct probe_ns *pns; + struct server *server; + isc_result_t result; + + REQUIRE(trans->resid == NULL); + REQUIRE(trans->reqid == NULL); + + update_stat(trans); + + dns_message_reset(trans->qmessage, DNS_MESSAGE_INTENTRENDER); + dns_message_reset(trans->rmessage, DNS_MESSAGE_INTENTPARSE); + + trans->inuse = ISC_FALSE; + if (trans->domain != NULL) + isc_mem_free(mctx, trans->domain); + trans->domain = NULL; + if (trans->qname != NULL) + dns_fixedname_invalidate(&trans->fixedname); + trans->qname = NULL; + trans->qlabel = qlabels; + trans->qname_found = ISC_FALSE; + trans->current_ns = NULL; + + while ((pns = ISC_LIST_HEAD(trans->nslist)) != NULL) { + ISC_LIST_UNLINK(trans->nslist, pns, link); + while ((server = ISC_LIST_HEAD(pns->servers)) != NULL) { + ISC_LIST_UNLINK(pns->servers, server, link); + isc_mem_put(mctx, server, sizeof(*server)); + } + isc_mem_put(mctx, pns, sizeof(*pns)); + } + + outstanding_probes--; + + result = probe_domain(trans); + if (result == ISC_R_NOMORE && outstanding_probes == 0) + isc_app_ctxshutdown(actx); +} + +static void +resolve_ns(isc_task_t *task, isc_event_t *event) { + struct probe_trans *trans = event->ev_arg; + dns_clientresevent_t *rev = (dns_clientresevent_t *)event; + dns_name_t *name; + dns_rdataset_t *rdataset; + isc_result_t result = ISC_R_SUCCESS; + dns_rdata_t rdata = DNS_RDATA_INIT; + struct probe_ns *pns; + + REQUIRE(task == probe_task); + REQUIRE(trans->inuse == ISC_TRUE); + INSIST(outstanding_probes > 0); + + for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL; + name = ISC_LIST_NEXT(name, link)) { + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + (void)print_rdataset(rdataset, name); + + if (rdataset->type != dns_rdatatype_ns) + continue; + + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + dns_rdata_ns_t ns; + + dns_rdataset_current(rdataset, &rdata); + /* + * Extract the name from the NS record. + */ + result = dns_rdata_tostruct(&rdata, &ns, NULL); + if (result != ISC_R_SUCCESS) + continue; + + pns = isc_mem_get(mctx, sizeof(*pns)); + if (pns == NULL) { + fprintf(stderr, + "resolve_ns: mem_get failed"); + result = ISC_R_NOMEMORY; + /* + * XXX: should we continue with the + * available servers anyway? + */ + goto cleanup; + } + + dns_fixedname_init(&pns->fixedname); + pns->name = + dns_fixedname_name(&pns->fixedname); + ISC_LINK_INIT(pns, link); + ISC_LIST_APPEND(trans->nslist, pns, link); + ISC_LIST_INIT(pns->servers); + + dns_name_copy(&ns.name, pns->name, NULL); + dns_rdata_reset(&rdata); + dns_rdata_freestruct(&ns); + } + } + } + + cleanup: + dns_client_freeresanswer(client, &rev->answerlist); + dns_client_destroyrestrans(&trans->resid); + isc_event_free(&event); + + if (!ISC_LIST_EMPTY(trans->nslist)) { + /* Go get addresses of NSes */ + trans->current_ns = ISC_LIST_HEAD(trans->nslist); + result = fetch_nsaddress(trans); + } else + result = ISC_R_FAILURE; + + if (result == ISC_R_SUCCESS) + return; + + reset_probe(trans); +} + +static isc_result_t +probe_domain(struct probe_trans *trans) { + isc_result_t result; + size_t domainlen; + isc_buffer_t b; + char buf[4096]; /* XXX ad hoc constant, but should be enough */ + char *cp; + + REQUIRE(trans != NULL); + REQUIRE(trans->inuse == ISC_FALSE); + REQUIRE(outstanding_probes < MAX_PROBES); + + /* Construct domain */ + cp = fgets(buf, sizeof(buf), fp); + if (cp == NULL) + return (ISC_R_NOMORE); + if ((cp = strchr(buf, '\n')) != NULL) /* zap NL if any */ + *cp = '\0'; + trans->domain = isc_mem_strdup(mctx, buf); + if (trans->domain == NULL) { + fprintf(stderr, + "failed to allocate memory for domain: %s", cp); + return (ISC_R_NOMEMORY); + } + + /* Start getting NS for the domain */ + domainlen = strlen(buf); + isc_buffer_init(&b, buf, domainlen); + isc_buffer_add(&b, domainlen); + dns_fixedname_init(&trans->fixedname); + trans->qname = dns_fixedname_name(&trans->fixedname); + result = dns_name_fromtext(trans->qname, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = dns_client_startresolve(client, trans->qname, + dns_rdataclass_in, dns_rdatatype_ns, + 0, probe_task, resolve_ns, trans, + &trans->resid); + if (result != ISC_R_SUCCESS) + goto cleanup; + + trans->inuse = ISC_TRUE; + outstanding_probes++; + + return (ISC_R_SUCCESS); + + cleanup: + isc_mem_free(mctx, trans->domain); + dns_fixedname_invalidate(&trans->fixedname); + + return (result); +} + +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + +static void +usage(void) { + fprintf(stderr, "usage: nsprobe [-d] [-v [-v...]] [-c cache_address] " + "[input_file]\n"); + + exit(1); +} + +int +main(int argc, char *argv[]) { + int i, ch, error; + struct addrinfo hints, *res; + isc_result_t result; + isc_sockaddr_t sa; + isc_sockaddrlist_t servers; + isc_taskmgr_t *taskmgr = NULL; + isc_socketmgr_t *socketmgr = NULL; + isc_timermgr_t *timermgr = NULL; + + while ((ch = getopt(argc, argv, "c:dhv")) != -1) { + switch (ch) { + case 'c': + cacheserver = optarg; + break; + case 'd': + debug_mode = ISC_TRUE; + break; + case 'h': + usage(); + break; + case 'v': + verbose_level++; + break; + default: + usage(); + break; + } + } + + argc -= optind; + argv += optind; + + /* Common set up */ + isc_lib_register(); + result = dns_lib_init(); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_lib_init failed: %d\n", result); + exit(1); + } + + result = ctxs_init(&mctx, &actx, &taskmgr, &socketmgr, + &timermgr); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "ctx create failed: %d\n", result); + exit(1); + } + + isc_app_ctxstart(actx); + + result = dns_client_createx(mctx, actx, taskmgr, socketmgr, + timermgr, 0, &client); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_client_createx failed: %d\n", result); + exit(1); + } + + /* Set local cache server */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + error = getaddrinfo(cacheserver, "53", &hints, &res); + if (error != 0) { + fprintf(stderr, "failed to convert server name (%s): %s\n", + cacheserver, gai_strerror(error)); + exit(1); + } + + if (res->ai_addrlen > sizeof(sa.type)) { + fprintf(stderr, + "assumption failure: addrlen is too long: %d\n", + res->ai_addrlen); + exit(1); + } + memcpy(&sa.type.sa, res->ai_addr, res->ai_addrlen); + sa.length = res->ai_addrlen; + freeaddrinfo(res); + ISC_LINK_INIT(&sa, link); + ISC_LIST_INIT(servers); + ISC_LIST_APPEND(servers, &sa, link); + result = dns_client_setservers(client, dns_rdataclass_in, NULL, + &servers); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to set server: %d\n", result); + exit(1); + } + + /* Create the main task */ + probe_task = NULL; + result = isc_task_create(taskmgr, 0, &probe_task); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to create task: %d\n", result); + exit(1); + } + + /* Open input file */ + if (argc == 0) + fp = stdin; + else { + fp = fopen(argv[0], "r"); + if (fp == NULL) { + fprintf(stderr, "failed to open input file: %s\n", + argv[0]); + exit(1); + } + } + + /* Set up and start probe */ + for (i = 0; i < MAX_PROBES; i++) { + probes[i].inuse = ISC_FALSE; + probes[i].domain = NULL; + dns_fixedname_init(&probes[i].fixedname); + probes[i].qname = NULL; + probes[i].qlabel = qlabels; + probes[i].qname_found = ISC_FALSE; + probes[i].resid = NULL; + ISC_LIST_INIT(probes[i].nslist); + probes[i].reqid = NULL; + + probes[i].qmessage = NULL; + result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, + &probes[i].qmessage); + if (result == ISC_R_SUCCESS) { + result = dns_message_create(mctx, + DNS_MESSAGE_INTENTPARSE, + &probes[i].rmessage); + } + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "initialization failure\n"); + exit(1); + } + } + for (i = 0; i < MAX_PROBES; i++) { + result = probe_domain(&probes[i]); + if (result == ISC_R_NOMORE) + break; + else if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to issue an initial probe\n"); + exit(1); + } + } + + /* Start event loop */ + isc_app_ctxrun(actx); + + /* Dump results */ + printf("Per domain results (out of %lu domains):\n", + number_of_domains); + printf(" valid: %lu\n" + " ignore: %lu\n" + " nxdomain: %lu\n" + " othererr: %lu\n" + " multiplesoa: %lu\n" + " multiplecname: %lu\n" + " brokenanswer: %lu\n" + " lame: %lu\n" + " unknown: %lu\n" + " multiple errors: %lu\n", + domain_stat.valid, domain_stat.ignore, domain_stat.nxdomain, + domain_stat.othererr, domain_stat.multiplesoa, + domain_stat.multiplecname, domain_stat.brokenanswer, + domain_stat.lame, domain_stat.unknown, multiple_error_domains); + printf("Per server results (out of %lu servers):\n", + number_of_servers); + printf(" valid: %lu\n" + " ignore: %lu\n" + " nxdomain: %lu\n" + " othererr: %lu\n" + " multiplesoa: %lu\n" + " multiplecname: %lu\n" + " brokenanswer: %lu\n" + " lame: %lu\n" + " unknown: %lu\n", + server_stat.valid, server_stat.ignore, server_stat.nxdomain, + server_stat.othererr, server_stat.multiplesoa, + server_stat.multiplecname, server_stat.brokenanswer, + server_stat.lame, server_stat.unknown); + + /* Cleanup */ + for (i = 0; i < MAX_PROBES; i++) { + dns_message_destroy(&probes[i].qmessage); + dns_message_destroy(&probes[i].rmessage); + } + isc_task_detach(&probe_task); + dns_client_destroy(&client); + dns_lib_shutdown(); + isc_app_ctxfinish(actx); + ctxs_destroy(&mctx, &actx, &taskmgr, &socketmgr, &timermgr); + + exit(0); +} diff --git a/lib/export/samples/sample-async.c b/lib/export/samples/sample-async.c new file mode 100644 index 0000000..19c0bba --- /dev/null +++ b/lib/export/samples/sample-async.c @@ -0,0 +1,402 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: sample-async.c,v 1.5 2009-09-29 15:06:07 fdupont Exp $ */ + +#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 MAX_SERVERS 10 +#define MAX_QUERIES 100 + +static dns_client_t *client = NULL; +static isc_task_t *query_task = NULL; +static isc_appctx_t *query_actx = NULL; +static unsigned int outstanding_queries = 0; +static const char *def_server = "127.0.0.1"; +static FILE *fp; + +struct query_trans { + int id; + isc_boolean_t inuse; + dns_rdatatype_t type; + dns_fixedname_t fixedname; + dns_name_t *qname; + dns_namelist_t answerlist; + dns_clientrestrans_t *xid; +}; + +static struct query_trans query_array[MAX_QUERIES]; + +static isc_result_t dispatch_query(struct query_trans *trans); + +static void +ctxs_destroy(isc_mem_t **mctxp, isc_appctx_t **actxp, + isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp, + isc_timermgr_t **timermgrp) +{ + if (*taskmgrp != NULL) + isc_taskmgr_destroy(taskmgrp); + + if (*timermgrp != NULL) + isc_timermgr_destroy(timermgrp); + + if (*socketmgrp != NULL) + isc_socketmgr_destroy(socketmgrp); + + if (*actxp != NULL) + isc_appctx_destroy(actxp); + + if (*mctxp != NULL) + isc_mem_destroy(mctxp); +} + +static isc_result_t +ctxs_init(isc_mem_t **mctxp, isc_appctx_t **actxp, + isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp, + isc_timermgr_t **timermgrp) +{ + isc_result_t result; + + result = isc_mem_create(0, 0, mctxp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_appctx_create(*mctxp, actxp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_taskmgr_createinctx(*mctxp, *actxp, 1, 0, taskmgrp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_socketmgr_createinctx(*mctxp, *actxp, socketmgrp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_timermgr_createinctx(*mctxp, *actxp, timermgrp); + if (result != ISC_R_SUCCESS) + goto fail; + + return (ISC_R_SUCCESS); + + fail: + ctxs_destroy(mctxp, actxp, taskmgrp, socketmgrp, timermgrp); + + return (result); +} + +static isc_result_t +printdata(dns_rdataset_t *rdataset, dns_name_t *owner) { + isc_buffer_t target; + isc_result_t result; + isc_region_t r; + char t[4096]; + + isc_buffer_init(&target, t, sizeof(t)); + + if (!dns_rdataset_isassociated(rdataset)) + return (ISC_R_SUCCESS); + result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE, + &target); + if (result != ISC_R_SUCCESS) + return (result); + isc_buffer_usedregion(&target, &r); + printf(" %.*s", (int)r.length, (char *)r.base); + + return (ISC_R_SUCCESS); +} + +static void +process_answer(isc_task_t *task, isc_event_t *event) { + struct query_trans *trans = event->ev_arg; + dns_clientresevent_t *rev = (dns_clientresevent_t *)event; + dns_name_t *name; + dns_rdataset_t *rdataset; + isc_result_t result; + + REQUIRE(task == query_task); + REQUIRE(trans->inuse == ISC_TRUE); + REQUIRE(outstanding_queries > 0); + + printf("answer[%2d]\n", trans->id); + + if (rev->result != ISC_R_SUCCESS) + printf(" failed: %d(%s)\n", rev->result, + dns_result_totext(rev->result)); + + for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL; + name = ISC_LIST_NEXT(name, link)) { + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + (void)printdata(rdataset, name); + } + } + + dns_client_freeresanswer(client, &rev->answerlist); + dns_client_destroyrestrans(&trans->xid); + + isc_event_free(&event); + + trans->inuse = ISC_FALSE; + dns_fixedname_invalidate(&trans->fixedname); + trans->qname = NULL; + outstanding_queries--; + + result = dispatch_query(trans); +#if 0 /* for cancel test */ + if (result == ISC_R_SUCCESS) { + static int count = 0; + + if ((++count) % 10 == 0) + dns_client_cancelresolve(trans->xid); + } +#endif + if (result == ISC_R_NOMORE && outstanding_queries == 0) + isc_app_ctxshutdown(query_actx); +} + +static isc_result_t +dispatch_query(struct query_trans *trans) { + isc_result_t result; + size_t namelen; + isc_buffer_t b; + char buf[4096]; /* XXX ad hoc constant, but should be enough */ + char *cp; + + REQUIRE(trans != NULL); + REQUIRE(trans->inuse == ISC_FALSE); + REQUIRE(ISC_LIST_EMPTY(trans->answerlist)); + REQUIRE(outstanding_queries < MAX_QUERIES); + + /* Construct qname */ + cp = fgets(buf, sizeof(buf), fp); + if (cp == NULL) + return (ISC_R_NOMORE); + /* zap NL if any */ + if ((cp = strchr(buf, '\n')) != NULL) + *cp = '\0'; + namelen = strlen(buf); + isc_buffer_init(&b, buf, namelen); + isc_buffer_add(&b, namelen); + dns_fixedname_init(&trans->fixedname); + trans->qname = dns_fixedname_name(&trans->fixedname); + result = dns_name_fromtext(trans->qname, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) + goto cleanup; + + /* Start resolution */ + result = dns_client_startresolve(client, trans->qname, + dns_rdataclass_in, trans->type, 0, + query_task, process_answer, trans, + &trans->xid); + if (result != ISC_R_SUCCESS) + goto cleanup; + + trans->inuse = ISC_TRUE; + outstanding_queries++; + + return (ISC_R_SUCCESS); + + cleanup: + dns_fixedname_invalidate(&trans->fixedname); + + return (result); +} + +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + +static void +usage(void) { + fprintf(stderr, "usage: sample-async [-s server_address] [-t RR type] " + "input_file\n"); + + exit(1); +} + +int +main(int argc, char *argv[]) { + int ch; + isc_textregion_t tr; + isc_mem_t *mctx = NULL; + isc_taskmgr_t *taskmgr = NULL; + isc_socketmgr_t *socketmgr = NULL; + isc_timermgr_t *timermgr = NULL; + int nservers = 0; + const char *serveraddr[MAX_SERVERS]; + isc_sockaddr_t sa[MAX_SERVERS]; + isc_sockaddrlist_t servers; + dns_rdatatype_t type = dns_rdatatype_a; + struct in_addr inaddr; + isc_result_t result; + int i; + + while ((ch = getopt(argc, argv, "s:t:")) != -1) { + switch (ch) { + case 't': + tr.base = optarg; + tr.length = strlen(optarg); + result = dns_rdatatype_fromtext(&type, &tr); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, + "invalid RRtype: %s\n", optarg); + exit(1); + } + break; + case 's': + if (nservers == MAX_SERVERS) { + fprintf(stderr, + "too many servers (up to %d)\n", + MAX_SERVERS); + exit(1); + } + serveraddr[nservers++] = (const char *)optarg; + break; + default: + usage(); + } + } + + argc -= optind; + argv += optind; + if (argc < 1) + usage(); + + if (nservers == 0) { + nservers = 1; + serveraddr[0] = def_server; + } + + for (i = 0; i < MAX_QUERIES; i++) { + query_array[i].id = i; + query_array[i].inuse = ISC_FALSE; + query_array[i].type = type; + dns_fixedname_init(&query_array[i].fixedname); + query_array[i].qname = NULL; + ISC_LIST_INIT(query_array[i].answerlist); + query_array[i].xid = NULL; + } + + isc_lib_register(); + result = dns_lib_init(); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_lib_init failed: %d\n", result); + exit(1); + } + + result = ctxs_init(&mctx, &query_actx, &taskmgr, &socketmgr, + &timermgr); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "ctx create failed: %d\n", result); + exit(1); + } + + isc_app_ctxstart(query_actx); + + result = dns_client_createx(mctx, query_actx, taskmgr, socketmgr, + timermgr, 0, &client); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_client_createx failed: %d\n", result); + exit(1); + } + + /* Set nameservers */ + ISC_LIST_INIT(servers); + for (i = 0; i < nservers; i++) { + if (inet_pton(AF_INET, serveraddr[i], &inaddr) != 1) { + fprintf(stderr, "failed to parse IPv4 address %s\n", + serveraddr[i]); + exit(1); + } + isc_sockaddr_fromin(&sa[i], &inaddr, 53); + ISC_LIST_APPEND(servers, &sa[i], link); + } + result = dns_client_setservers(client, dns_rdataclass_in, NULL, + &servers); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "set server failed: %d\n", result); + exit(1); + } + + /* Create the main task */ + query_task = NULL; + result = isc_task_create(taskmgr, 0, &query_task); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to create task: %d\n", result); + exit(1); + } + + /* Open input file */ + fp = fopen(argv[0], "r"); + if (fp == NULL) { + fprintf(stderr, "failed to open input file: %s\n", argv[1]); + exit(1); + } + + /* Dispatch initial queries */ + for (i = 0; i < MAX_QUERIES; i++) { + result = dispatch_query(&query_array[i]); + if (result == ISC_R_NOMORE) + break; + } + + /* Start event loop */ + isc_app_ctxrun(query_actx); + + /* Sanity check */ + for (i = 0; i < MAX_QUERIES; i++) + INSIST(query_array[i].inuse == ISC_FALSE); + + /* Cleanup */ + isc_task_detach(&query_task); + dns_client_destroy(&client); + dns_lib_shutdown(); + isc_app_ctxfinish(query_actx); + ctxs_destroy(&mctx, &query_actx, &taskmgr, &socketmgr, &timermgr); + + exit(0); +} diff --git a/lib/export/samples/sample-gai.c b/lib/export/samples/sample-gai.c new file mode 100644 index 0000000..7c07f1b --- /dev/null +++ b/lib/export/samples/sample-gai.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: sample-gai.c,v 1.4 2009-09-02 23:48:02 tbox Exp $ */ + +#include + +#include +#include + +#include + +#include +#include +#include + +static void +do_gai(int family, char *hostname) { + struct addrinfo hints, *res, *res0; + int error; + char namebuf[1024], addrbuf[1024], servbuf[1024]; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = family; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_CANONNAME; + error = getaddrinfo(hostname, "http", &hints, &res0); + if (error) { + fprintf(stderr, "getaddrinfo failed for %s,family=%d: %s\n", + hostname, family, gai_strerror(error)); + return; + } + + for (res = res0; res; res = res->ai_next) { + error = getnameinfo(res->ai_addr, res->ai_addrlen, + addrbuf, sizeof(addrbuf), + NULL, 0, NI_NUMERICHOST); + if (error == 0) + error = getnameinfo(res->ai_addr, res->ai_addrlen, + namebuf, sizeof(namebuf), + servbuf, sizeof(servbuf), 0); + if (error != 0) { + fprintf(stderr, "getnameinfo failed: %s\n", + gai_strerror(error)); + } else { + printf("%s(%s/%s)=%s:%s\n", hostname, + res->ai_canonname, addrbuf, namebuf, servbuf); + } + } + + freeaddrinfo(res); +} + +int +main(int argc, char *argv[]) { + if (argc < 2) + exit(1); + + do_gai(AF_INET, argv[1]); + do_gai(AF_INET6, argv[1]); + do_gai(AF_UNSPEC, argv[1]); + + exit(0); +} diff --git a/lib/export/samples/sample-request.c b/lib/export/samples/sample-request.c new file mode 100644 index 0000000..4331498 --- /dev/null +++ b/lib/export/samples/sample-request.c @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: sample-request.c,v 1.5 2009-09-29 15:06:07 fdupont Exp $ */ + +#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 + +static isc_mem_t *mctx; +static dns_fixedname_t fixedqname; + +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + +static void +usage(void) { + fprintf(stderr, "sample-request [-t RRtype] server_address hostname\n"); + + exit(1); +} + +static isc_result_t +make_querymessage(dns_message_t *message, const char *namestr, + dns_rdatatype_t rdtype) +{ + dns_name_t *qname = NULL, *qname0; + dns_rdataset_t *qrdataset = NULL; + isc_result_t result; + isc_buffer_t b; + size_t namelen; + + /* Construct qname */ + namelen = strlen(namestr); + isc_buffer_init(&b, namestr, namelen); + isc_buffer_add(&b, namelen); + dns_fixedname_init(&fixedqname); + qname0 = dns_fixedname_name(&fixedqname); + result = dns_name_fromtext(qname0, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to convert qname: %d\n", result); + return (result); + } + + /* Construct query message */ + message->opcode = dns_opcode_query; + message->rdclass = dns_rdataclass_in; + + result = dns_message_gettempname(message, &qname); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = dns_message_gettemprdataset(message, &qrdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + + dns_name_init(qname, NULL); + dns_name_clone(qname0, qname); + dns_rdataset_init(qrdataset); + dns_rdataset_makequestion(qrdataset, message->rdclass, rdtype); + ISC_LIST_APPEND(qname->list, qrdataset, link); + dns_message_addname(message, qname, DNS_SECTION_QUESTION); + + return (ISC_R_SUCCESS); + + cleanup: + if (qname != NULL) + dns_message_puttempname(message, &qname); + if (qrdataset != NULL) + dns_message_puttemprdataset(message, &qrdataset); + if (message != NULL) + dns_message_destroy(&message); + return (result); +} + +static void +print_section(dns_message_t *message, int section, isc_buffer_t *buf) { + isc_result_t result; + isc_region_t r; + + result = dns_message_sectiontotext(message, section, + &dns_master_style_full, 0, buf); + if (result != ISC_R_SUCCESS) + goto fail; + + isc_buffer_usedregion(buf, &r); + printf("%.*s", (int)r.length, (char *)r.base); + + return; + + fail: + fprintf(stderr, "failed to convert a section\n"); +} + +int +main(int argc, char *argv[]) { + int ch, i, gai_error; + struct addrinfo hints, *res; + isc_textregion_t tr; + dns_client_t *client = NULL; + isc_result_t result; + isc_sockaddr_t sa; + dns_message_t *qmessage, *rmessage; + dns_rdatatype_t type = dns_rdatatype_a; + isc_buffer_t *outputbuf; + + while ((ch = getopt(argc, argv, "t:")) != -1) { + switch (ch) { + case 't': + tr.base = optarg; + tr.length = strlen(optarg); + result = dns_rdatatype_fromtext(&type, &tr); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, + "invalid RRtype: %s\n", optarg); + exit(1); + } + break; + default: + usage(); + } + } + + argc -= optind; + argv += optind; + if (argc < 2) + usage(); + + isc_lib_register(); + result = dns_lib_init(); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_lib_init failed: %d\n", result); + exit(1); + } + + result = dns_client_create(&client, 0); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_client_create failed: %d\n", result); + exit(1); + } + + /* Prepare message structures */ + mctx = NULL; + qmessage = NULL; + rmessage = NULL; + + result = isc_mem_create(0, 0, &mctx); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to create a memory context\n"); + exit(1); + } + result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &qmessage); + if (result == ISC_R_SUCCESS) { + result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, + &rmessage); + } + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to create messages\n"); + exit(1); + } + + /* Initialize the nameserver address */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_flags = AI_NUMERICHOST; + gai_error = getaddrinfo(argv[0], "53", &hints, &res); + if (gai_error != 0) { + fprintf(stderr, "getaddrinfo failed: %s\n", + gai_strerror(gai_error)); + exit(1); + } + INSIST(res->ai_addrlen <= sizeof(sa.type)); + memcpy(&sa.type, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + sa.length = res->ai_addrlen; + ISC_LINK_INIT(&sa, link); + + /* Construct qname */ + result = make_querymessage(qmessage, argv[1], type); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to create a query\n"); + exit(1); + } + + /* Send request and wait for a response */ + result = dns_client_request(client, qmessage, rmessage, &sa, 0, 0, + NULL, 60, 0, 3); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to get a response: %s\n", + dns_result_totext(result)); + } + + /* Dump the response */ + outputbuf = NULL; + result = isc_buffer_allocate(mctx, &outputbuf, 65535); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to allocate a result buffer\n"); + exit(1); + } + for (i = 0; i < DNS_SECTION_MAX; i++) { + print_section(rmessage, i, outputbuf); + isc_buffer_clear(outputbuf); + } + isc_buffer_free(&outputbuf); + + /* Cleanup */ + dns_message_destroy(&qmessage); + dns_message_destroy(&rmessage); + isc_mem_destroy(&mctx); + dns_client_destroy(&client); + dns_lib_shutdown(); + + exit(0); +} diff --git a/lib/export/samples/sample-update.c b/lib/export/samples/sample-update.c new file mode 100644 index 0000000..eef0a58 --- /dev/null +++ b/lib/export/samples/sample-update.c @@ -0,0 +1,755 @@ +/* + * Copyright (C) 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: sample-update.c,v 1.10 2010-12-09 00:54:34 marka Exp $ */ + +#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 +#include + +#include + +static dns_tsec_t *tsec = NULL; +static const dns_rdataclass_t default_rdataclass = dns_rdataclass_in; +static isc_bufferlist_t usedbuffers; +static ISC_LIST(dns_rdatalist_t) usedrdatalists; + +static void setup_tsec(char *keyfile, isc_mem_t *mctx); +static void update_addordelete(isc_mem_t *mctx, char *cmdline, + isc_boolean_t isdelete, dns_name_t *name); +static void evaluate_prereq(isc_mem_t *mctx, char *cmdline, dns_name_t *name); + +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + +static void +usage(void) { + fprintf(stderr, "sample-update " + "[-a auth_server] " + "[-k keyfile] " + "[-p prerequisite] " + "[-r recursive_server] " + "[-z zonename] " + "(add|delete) \"name TTL RRtype RDATA\"\n"); + exit(1); +} + +int +main(int argc, char *argv[]) { + int ch; + struct addrinfo hints, *res; + int gai_error; + dns_client_t *client = NULL; + char *zonenamestr = NULL; + char *keyfilename = NULL; + char *prereqstr = NULL; + isc_sockaddrlist_t auth_servers; + char *auth_server = NULL; + char *recursive_server = NULL; + isc_sockaddr_t sa_auth, sa_recursive; + isc_sockaddrlist_t rec_servers; + isc_result_t result; + isc_boolean_t isdelete; + isc_buffer_t b, *buf; + dns_fixedname_t zname0, pname0, uname0; + size_t namelen; + dns_name_t *zname = NULL, *uname, *pname; + dns_rdataset_t *rdataset; + dns_rdatalist_t *rdatalist; + dns_rdata_t *rdata; + dns_namelist_t updatelist, prereqlist, *prereqlistp = NULL; + isc_mem_t *umctx = NULL; + + while ((ch = getopt(argc, argv, "a:k:p:r:z:")) != -1) { + switch (ch) { + case 'k': + keyfilename = optarg; + break; + case 'a': + auth_server = optarg; + break; + case 'p': + prereqstr = optarg; + break; + case 'r': + recursive_server = optarg; + break; + case 'z': + zonenamestr = optarg; + break; + default: + usage(); + } + } + + argc -= optind; + argv += optind; + if (argc < 2) + usage(); + + /* command line argument validation */ + if (strcmp(argv[0], "delete") == 0) + isdelete = ISC_TRUE; + else if (strcmp(argv[0], "add") == 0) + isdelete = ISC_FALSE; + else { + fprintf(stderr, "invalid update command: %s\n", argv[0]); + exit(1); + } + + if (auth_server == NULL && recursive_server == NULL) { + fprintf(stderr, "authoritative or recursive server " + "must be specified\n"); + usage(); + } + + /* Initialization */ + ISC_LIST_INIT(usedbuffers); + ISC_LIST_INIT(usedrdatalists); + ISC_LIST_INIT(prereqlist); + ISC_LIST_INIT(auth_servers); + isc_lib_register(); + result = dns_lib_init(); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_lib_init failed: %d\n", result); + exit(1); + } + result = isc_mem_create(0, 0, &umctx); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to crate mctx\n"); + exit(1); + } + + result = dns_client_create(&client, 0); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_client_create failed: %d\n", result); + exit(1); + } + + /* Set the authoritative server */ + if (auth_server != NULL) { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_flags = AI_NUMERICHOST; + gai_error = getaddrinfo(auth_server, "53", &hints, &res); + if (gai_error != 0) { + fprintf(stderr, "getaddrinfo failed: %s\n", + gai_strerror(gai_error)); + exit(1); + } + INSIST(res->ai_addrlen <= sizeof(sa_auth.type)); + memcpy(&sa_auth.type, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + sa_auth.length = res->ai_addrlen; + ISC_LINK_INIT(&sa_auth, link); + + ISC_LIST_APPEND(auth_servers, &sa_auth, link); + } + + /* Set the recursive server */ + if (recursive_server != NULL) { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_flags = AI_NUMERICHOST; + gai_error = getaddrinfo(recursive_server, "53", &hints, &res); + if (gai_error != 0) { + fprintf(stderr, "getaddrinfo failed: %s\n", + gai_strerror(gai_error)); + exit(1); + } + INSIST(res->ai_addrlen <= sizeof(sa_recursive.type)); + memcpy(&sa_recursive.type, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + sa_recursive.length = res->ai_addrlen; + ISC_LINK_INIT(&sa_recursive, link); + ISC_LIST_INIT(rec_servers); + ISC_LIST_APPEND(rec_servers, &sa_recursive, link); + result = dns_client_setservers(client, dns_rdataclass_in, + NULL, &rec_servers); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "set server failed: %d\n", result); + exit(1); + } + } + + /* Construct zone name */ + zname = NULL; + if (zonenamestr != NULL) { + namelen = strlen(zonenamestr); + isc_buffer_init(&b, zonenamestr, namelen); + isc_buffer_add(&b, namelen); + dns_fixedname_init(&zname0); + zname = dns_fixedname_name(&zname0); + result = dns_name_fromtext(zname, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) + fprintf(stderr, "failed to convert zone name: %d\n", + result); + } + + /* Construct prerequisite name (if given) */ + if (prereqstr != NULL) { + dns_fixedname_init(&pname0); + pname = dns_fixedname_name(&pname0); + evaluate_prereq(umctx, prereqstr, pname); + ISC_LIST_APPEND(prereqlist, pname, link); + prereqlistp = &prereqlist; + } + + /* Construct update name */ + ISC_LIST_INIT(updatelist); + dns_fixedname_init(&uname0); + uname = dns_fixedname_name(&uname0); + update_addordelete(umctx, argv[1], isdelete, uname); + ISC_LIST_APPEND(updatelist, uname, link); + + /* Set up TSIG/SIG(0) key (if given) */ + if (keyfilename != NULL) + setup_tsec(keyfilename, umctx); + + /* Perform update */ + result = dns_client_update(client, + default_rdataclass, /* XXX: fixed */ + zname, prereqlistp, &updatelist, + (auth_server == NULL) ? NULL : + &auth_servers, tsec, 0); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, + "update failed: %s\n", dns_result_totext(result)); + } else + fprintf(stderr, "update succeeded\n"); + + /* Cleanup */ + while ((pname = ISC_LIST_HEAD(prereqlist)) != NULL) { + while ((rdataset = ISC_LIST_HEAD(pname->list)) != NULL) { + ISC_LIST_UNLINK(pname->list, rdataset, link); + dns_rdataset_disassociate(rdataset); + isc_mem_put(umctx, rdataset, sizeof(*rdataset)); + } + ISC_LIST_UNLINK(prereqlist, pname, link); + } + while ((uname = ISC_LIST_HEAD(updatelist)) != NULL) { + while ((rdataset = ISC_LIST_HEAD(uname->list)) != NULL) { + ISC_LIST_UNLINK(uname->list, rdataset, link); + dns_rdataset_disassociate(rdataset); + isc_mem_put(umctx, rdataset, sizeof(*rdataset)); + } + ISC_LIST_UNLINK(updatelist, uname, link); + } + while ((rdatalist = ISC_LIST_HEAD(usedrdatalists)) != NULL) { + while ((rdata = ISC_LIST_HEAD(rdatalist->rdata)) != NULL) { + ISC_LIST_UNLINK(rdatalist->rdata, rdata, link); + isc_mem_put(umctx, rdata, sizeof(*rdata)); + } + ISC_LIST_UNLINK(usedrdatalists, rdatalist, link); + isc_mem_put(umctx, rdatalist, sizeof(*rdatalist)); + } + while ((buf = ISC_LIST_HEAD(usedbuffers)) != NULL) { + ISC_LIST_UNLINK(usedbuffers, buf, link); + isc_buffer_free(&buf); + } + if (tsec != NULL) + dns_tsec_destroy(&tsec); + isc_mem_destroy(&umctx); + dns_client_destroy(&client); + dns_lib_shutdown(); + + exit(0); +} + +/* + * Subroutines borrowed from nsupdate.c + */ +#define MAXWIRE (64 * 1024) +#define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */ + +static char * +nsu_strsep(char **stringp, const char *delim) { + char *string = *stringp; + char *s; + const char *d; + char sc, dc; + + if (string == NULL) + return (NULL); + + for (; *string != '\0'; string++) { + sc = *string; + for (d = delim; (dc = *d) != '\0'; d++) { + if (sc == dc) + break; + } + if (dc == 0) + break; + } + + for (s = string; *s != '\0'; s++) { + sc = *s; + for (d = delim; (dc = *d) != '\0'; d++) { + if (sc == dc) { + *s++ = '\0'; + *stringp = s; + return (string); + } + } + } + *stringp = NULL; + return (string); +} + +static void +fatal(const char *format, ...) { + va_list args; + + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + exit(1); +} + +static inline void +check_result(isc_result_t result, const char *msg) { + if (result != ISC_R_SUCCESS) + fatal("%s: %s", msg, isc_result_totext(result)); +} + +static void +parse_name(char **cmdlinep, dns_name_t *name) { + isc_result_t result; + char *word; + isc_buffer_t source; + + word = nsu_strsep(cmdlinep, " \t\r\n"); + if (*word == 0) { + fprintf(stderr, "could not read owner name\n"); + exit(1); + } + + isc_buffer_init(&source, word, strlen(word)); + isc_buffer_add(&source, strlen(word)); + result = dns_name_fromtext(name, &source, dns_rootname, 0, NULL); + check_result(result, "dns_name_fromtext"); + isc_buffer_invalidate(&source); +} + +static void +parse_rdata(isc_mem_t *mctx, char **cmdlinep, dns_rdataclass_t rdataclass, + dns_rdatatype_t rdatatype, dns_rdata_t *rdata) +{ + char *cmdline = *cmdlinep; + isc_buffer_t source, *buf = NULL, *newbuf = NULL; + isc_region_t r; + isc_lex_t *lex = NULL; + dns_rdatacallbacks_t callbacks; + isc_result_t result; + + while (cmdline != NULL && *cmdline != 0 && + isspace((unsigned char)*cmdline)) + cmdline++; + + if (cmdline != NULL && *cmdline != 0) { + dns_rdatacallbacks_init(&callbacks); + result = isc_lex_create(mctx, strlen(cmdline), &lex); + check_result(result, "isc_lex_create"); + isc_buffer_init(&source, cmdline, strlen(cmdline)); + isc_buffer_add(&source, strlen(cmdline)); + result = isc_lex_openbuffer(lex, &source); + check_result(result, "isc_lex_openbuffer"); + result = isc_buffer_allocate(mctx, &buf, MAXWIRE); + check_result(result, "isc_buffer_allocate"); + result = dns_rdata_fromtext(rdata, rdataclass, rdatatype, lex, + dns_rootname, 0, mctx, buf, + &callbacks); + isc_lex_destroy(&lex); + if (result == ISC_R_SUCCESS) { + isc_buffer_usedregion(buf, &r); + result = isc_buffer_allocate(mctx, &newbuf, r.length); + check_result(result, "isc_buffer_allocate"); + isc_buffer_putmem(newbuf, r.base, r.length); + isc_buffer_usedregion(newbuf, &r); + dns_rdata_reset(rdata); + dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r); + isc_buffer_free(&buf); + ISC_LIST_APPEND(usedbuffers, newbuf, link); + } else { + fprintf(stderr, "invalid rdata format: %s\n", + isc_result_totext(result)); + isc_buffer_free(&buf); + exit(1); + } + } else { + rdata->flags = DNS_RDATA_UPDATE; + } + *cmdlinep = cmdline; +} + +static void +update_addordelete(isc_mem_t *mctx, char *cmdline, isc_boolean_t isdelete, + dns_name_t *name) +{ + isc_result_t result; + isc_uint32_t ttl; + char *word; + dns_rdataclass_t rdataclass; + dns_rdatatype_t rdatatype; + dns_rdata_t *rdata = NULL; + dns_rdatalist_t *rdatalist = NULL; + dns_rdataset_t *rdataset = NULL; + isc_textregion_t region; + + /* + * Read the owner name. + */ + parse_name(&cmdline, name); + + rdata = isc_mem_get(mctx, sizeof(*rdata)); + if (rdata == NULL) { + fprintf(stderr, "memory allocation for rdata failed\n"); + exit(1); + } + dns_rdata_init(rdata); + + /* + * If this is an add, read the TTL and verify that it's in range. + * If it's a delete, ignore a TTL if present (for compatibility). + */ + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + if (!isdelete) { + fprintf(stderr, "could not read owner ttl\n"); + exit(1); + } + else { + ttl = 0; + rdataclass = dns_rdataclass_any; + rdatatype = dns_rdatatype_any; + rdata->flags = DNS_RDATA_UPDATE; + goto doneparsing; + } + } + result = isc_parse_uint32(&ttl, word, 10); + if (result != ISC_R_SUCCESS) { + if (isdelete) { + ttl = 0; + goto parseclass; + } else { + fprintf(stderr, "ttl '%s': %s\n", word, + isc_result_totext(result)); + exit(1); + } + } + + if (isdelete) + ttl = 0; + else if (ttl > TTL_MAX) { + fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", + word, TTL_MAX); + exit(1); + } + + /* + * Read the class or type. + */ + word = nsu_strsep(&cmdline, " \t\r\n"); + parseclass: + if (word == NULL || *word == 0) { + if (isdelete) { + rdataclass = dns_rdataclass_any; + rdatatype = dns_rdatatype_any; + rdata->flags = DNS_RDATA_UPDATE; + goto doneparsing; + } else { + fprintf(stderr, "could not read class or type\n"); + exit(1); + } + } + region.base = word; + region.length = strlen(word); + result = dns_rdataclass_fromtext(&rdataclass, ®ion); + if (result == ISC_R_SUCCESS) { + /* + * Now read the type. + */ + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + if (isdelete) { + rdataclass = dns_rdataclass_any; + rdatatype = dns_rdatatype_any; + rdata->flags = DNS_RDATA_UPDATE; + goto doneparsing; + } else { + fprintf(stderr, "could not read type\n"); + exit(1); + } + } + region.base = word; + region.length = strlen(word); + result = dns_rdatatype_fromtext(&rdatatype, ®ion); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "'%s' is not a valid type: %s\n", + word, isc_result_totext(result)); + exit(1); + } + } else { + rdataclass = default_rdataclass; + result = dns_rdatatype_fromtext(&rdatatype, ®ion); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "'%s' is not a valid class or type: " + "%s\n", word, isc_result_totext(result)); + exit(1); + } + } + + parse_rdata(mctx, &cmdline, rdataclass, rdatatype, rdata); + + if (isdelete) { + if ((rdata->flags & DNS_RDATA_UPDATE) != 0) + rdataclass = dns_rdataclass_any; + else + rdataclass = dns_rdataclass_none; + } else { + if ((rdata->flags & DNS_RDATA_UPDATE) != 0) { + fprintf(stderr, "could not read rdata\n"); + exit(1); + } + } + + doneparsing: + + rdatalist = isc_mem_get(mctx, sizeof(*rdatalist)); + if (rdatalist == NULL) { + fprintf(stderr, "memory allocation for rdatalist failed\n"); + exit(1); + } + dns_rdatalist_init(rdatalist); + rdatalist->type = rdatatype; + rdatalist->rdclass = rdataclass; + rdatalist->covers = rdatatype; + rdatalist->ttl = (dns_ttl_t)ttl; + ISC_LIST_INIT(rdatalist->rdata); + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + ISC_LIST_APPEND(usedrdatalists, rdatalist, link); + + rdataset = isc_mem_get(mctx, sizeof(*rdataset)); + if (rdataset == NULL) { + fprintf(stderr, "memory allocation for rdataset failed\n"); + exit(1); + } + dns_rdataset_init(rdataset); + dns_rdatalist_tordataset(rdatalist, rdataset); + ISC_LIST_INIT(name->list); + ISC_LIST_APPEND(name->list, rdataset, link); +} + +static void +make_prereq(isc_mem_t *mctx, char *cmdline, isc_boolean_t ispositive, + isc_boolean_t isrrset, dns_name_t *name) +{ + isc_result_t result; + char *word; + isc_textregion_t region; + dns_rdataset_t *rdataset = NULL; + dns_rdatalist_t *rdatalist = NULL; + dns_rdataclass_t rdataclass; + dns_rdatatype_t rdatatype; + dns_rdata_t *rdata = NULL; + + /* + * Read the owner name + */ + parse_name(&cmdline, name); + + /* + * If this is an rrset prereq, read the class or type. + */ + if (isrrset) { + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + fprintf(stderr, "could not read class or type\n"); + exit(1); + } + region.base = word; + region.length = strlen(word); + result = dns_rdataclass_fromtext(&rdataclass, ®ion); + if (result == ISC_R_SUCCESS) { + /* + * Now read the type. + */ + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + fprintf(stderr, "could not read type\n"); + exit(1); + } + region.base = word; + region.length = strlen(word); + result = dns_rdatatype_fromtext(&rdatatype, ®ion); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "invalid type: %s\n", word); + exit(1); + } + } else { + rdataclass = default_rdataclass; + result = dns_rdatatype_fromtext(&rdatatype, ®ion); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "invalid type: %s\n", word); + exit(1); + } + } + } else + rdatatype = dns_rdatatype_any; + + rdata = isc_mem_get(mctx, sizeof(*rdata)); + if (rdata == NULL) { + fprintf(stderr, "memory allocation for rdata failed\n"); + exit(1); + } + dns_rdata_init(rdata); + + if (isrrset && ispositive) + parse_rdata(mctx, &cmdline, rdataclass, rdatatype, rdata); + else + rdata->flags = DNS_RDATA_UPDATE; + + rdatalist = isc_mem_get(mctx, sizeof(*rdatalist)); + if (rdatalist == NULL) { + fprintf(stderr, "memory allocation for rdatalist failed\n"); + exit(1); + } + dns_rdatalist_init(rdatalist); + rdatalist->type = rdatatype; + if (ispositive) { + if (isrrset && rdata->data != NULL) + rdatalist->rdclass = rdataclass; + else + rdatalist->rdclass = dns_rdataclass_any; + } else + rdatalist->rdclass = dns_rdataclass_none; + rdatalist->covers = 0; + rdatalist->ttl = 0; + rdata->rdclass = rdatalist->rdclass; + rdata->type = rdatatype; + ISC_LIST_INIT(rdatalist->rdata); + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + ISC_LIST_APPEND(usedrdatalists, rdatalist, link); + + rdataset = isc_mem_get(mctx, sizeof(*rdataset)); + if (rdataset == NULL) { + fprintf(stderr, "memory allocation for rdataset failed\n"); + exit(1); + } + dns_rdataset_init(rdataset); + dns_rdatalist_tordataset(rdatalist, rdataset); + ISC_LIST_INIT(name->list); + ISC_LIST_APPEND(name->list, rdataset, link); +} + +static void +evaluate_prereq(isc_mem_t *mctx, char *cmdline, dns_name_t *name) { + char *word; + isc_boolean_t ispositive, isrrset; + + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + fprintf(stderr, "could not read operation code\n"); + exit(1); + } + if (strcasecmp(word, "nxdomain") == 0) { + ispositive = ISC_FALSE; + isrrset = ISC_FALSE; + } else if (strcasecmp(word, "yxdomain") == 0) { + ispositive = ISC_TRUE; + isrrset = ISC_FALSE; + } else if (strcasecmp(word, "nxrrset") == 0) { + ispositive = ISC_FALSE; + isrrset = ISC_TRUE; + } else if (strcasecmp(word, "yxrrset") == 0) { + ispositive = ISC_TRUE; + isrrset = ISC_TRUE; + } else { + fprintf(stderr, "incorrect operation code: %s\n", word); + exit(1); + } + + make_prereq(mctx, cmdline, ispositive, isrrset, name); +} + +static void +setup_tsec(char *keyfile, isc_mem_t *mctx) { + dst_key_t *dstkey = NULL; + isc_result_t result; + dns_tsectype_t tsectype; + + result = dst_key_fromnamedfile(keyfile, NULL, + DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, + &dstkey); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "could not read key from %s: %s\n", + keyfile, isc_result_totext(result)); + exit(1); + } + + if (dst_key_alg(dstkey) == DST_ALG_HMACMD5) + tsectype = dns_tsectype_tsig; + else + tsectype = dns_tsectype_sig0; + + result = dns_tsec_create(mctx, tsectype, dstkey, &tsec); + dst_key_free(&dstkey); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "could not create tsec: %s\n", + isc_result_totext(result)); + exit(1); + } +} diff --git a/lib/export/samples/sample.c b/lib/export/samples/sample.c new file mode 100644 index 0000000..6564f0e --- /dev/null +++ b/lib/export/samples/sample.c @@ -0,0 +1,378 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: sample.c,v 1.5 2009-09-29 15:06:07 fdupont Exp $ */ + +#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 + +static char *algname; + +static isc_result_t +printdata(dns_rdataset_t *rdataset, dns_name_t *owner) { + isc_buffer_t target; + isc_result_t result; + isc_region_t r; + char t[4096]; + + if (!dns_rdataset_isassociated(rdataset)) { + printf("[WARN: empty]\n"); + return (ISC_R_SUCCESS); + } + + isc_buffer_init(&target, t, sizeof(t)); + + result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE, + &target); + if (result != ISC_R_SUCCESS) + return (result); + isc_buffer_usedregion(&target, &r); + printf("%.*s", (int)r.length, (char *)r.base); + + return (ISC_R_SUCCESS); +} + +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + +static void +usage(void) { + fprintf(stderr, "sample [-t RRtype] " + "[[-a algorithm] [-e] -k keyname -K keystring] " + "[-s domain:serveraddr_for_domain ] " + "server_address hostname\n"); + + exit(1); +} + +static void +set_key(dns_client_t *client, char *keynamestr, char *keystr, + isc_boolean_t is_sep, isc_mem_t **mctxp) +{ + isc_result_t result; + dns_fixedname_t fkeyname; + size_t namelen; + dns_name_t *keyname; + dns_rdata_dnskey_t keystruct; + unsigned char keydata[4096]; + isc_buffer_t keydatabuf; + unsigned char rrdata[4096]; + isc_buffer_t rrdatabuf; + isc_buffer_t b; + isc_textregion_t tr; + isc_region_t r; + dns_secalg_t alg; + + result = isc_mem_create(0, 0, mctxp); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to crate mctx\n"); + exit(1); + } + + if (algname != NULL) { + tr.base = algname; + tr.length = strlen(algname); + result = dns_secalg_fromtext(&alg, &tr); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to identify the algorithm\n"); + exit(1); + } + } else + alg = DNS_KEYALG_RSASHA1; + + keystruct.common.rdclass = dns_rdataclass_in; + keystruct.common.rdtype = dns_rdatatype_dnskey; + keystruct.flags = DNS_KEYOWNER_ZONE; /* fixed */ + if (is_sep) + keystruct.flags |= DNS_KEYFLAG_KSK; + keystruct.protocol = DNS_KEYPROTO_DNSSEC; /* fixed */ + keystruct.algorithm = alg; + + isc_buffer_init(&keydatabuf, keydata, sizeof(keydata)); + isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); + result = isc_base64_decodestring(keystr, &keydatabuf); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "base64 decode failed\n"); + exit(1); + } + isc_buffer_usedregion(&keydatabuf, &r); + keystruct.datalen = r.length; + keystruct.data = r.base; + + result = dns_rdata_fromstruct(NULL, keystruct.common.rdclass, + keystruct.common.rdtype, + &keystruct, &rrdatabuf); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to construct key rdata\n"); + exit(1); + } + namelen = strlen(keynamestr); + isc_buffer_init(&b, keynamestr, namelen); + isc_buffer_add(&b, namelen); + dns_fixedname_init(&fkeyname); + keyname = dns_fixedname_name(&fkeyname); + result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to construct key name\n"); + exit(1); + } + result = dns_client_addtrustedkey(client, dns_rdataclass_in, + keyname, &rrdatabuf); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to add key for %s\n", + keynamestr); + exit(1); + } +} + +static void +addserver(dns_client_t *client, const char *addrstr, const char *namespace) { + struct addrinfo hints, *res; + int gai_error; + isc_sockaddr_t sa; + isc_sockaddrlist_t servers; + isc_result_t result; + size_t namelen; + isc_buffer_t b; + dns_fixedname_t fname; + dns_name_t *name = NULL; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_flags = AI_NUMERICHOST; + gai_error = getaddrinfo(addrstr, "53", &hints, &res); + if (gai_error != 0) { + fprintf(stderr, "getaddrinfo failed: %s\n", + gai_strerror(gai_error)); + exit(1); + } + INSIST(res->ai_addrlen <= sizeof(sa.type)); + memcpy(&sa.type, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + sa.length = res->ai_addrlen; + ISC_LINK_INIT(&sa, link); + ISC_LIST_INIT(servers); + ISC_LIST_APPEND(servers, &sa, link); + + if (namespace != NULL) { + namelen = strlen(namespace); + isc_buffer_init(&b, namespace, namelen); + isc_buffer_add(&b, namelen); + dns_fixedname_init(&fname); + name = dns_fixedname_name(&fname); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to convert qname: %d\n", + result); + exit(1); + } + } + + result = dns_client_setservers(client, dns_rdataclass_in, name, + &servers); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "set server failed: %d\n", result); + exit(1); + } +} + +int +main(int argc, char *argv[]) { + int ch; + isc_textregion_t tr; + char *altserver = NULL; + char *altserveraddr = NULL; + char *altservername = NULL; + dns_client_t *client = NULL; + char *keynamestr = NULL; + char *keystr = NULL; + isc_result_t result; + isc_buffer_t b; + dns_fixedname_t qname0; + size_t namelen; + dns_name_t *qname, *name; + dns_rdatatype_t type = dns_rdatatype_a; + dns_rdataset_t *rdataset; + dns_namelist_t namelist; + isc_mem_t *keymctx = NULL; + unsigned int clientopt, resopt; + isc_boolean_t is_sep = ISC_FALSE; + + while ((ch = getopt(argc, argv, "a:es:t:k:K:")) != -1) { + switch (ch) { + case 't': + tr.base = optarg; + tr.length = strlen(optarg); + result = dns_rdatatype_fromtext(&type, &tr); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, + "invalid RRtype: %s\n", optarg); + exit(1); + } + break; + case 'a': + algname = optarg; + break; + case 'e': + is_sep = ISC_TRUE; + break; + case 's': + if (altserver != NULL) { + fprintf(stderr, "alternate server " + "already defined: %s\n", + altserver); + exit(1); + } + altserver = optarg; + break; + case 'k': + keynamestr = optarg; + break; + case 'K': + keystr = optarg; + break; + default: + usage(); + } + } + + argc -= optind; + argv += optind; + if (argc < 2) + usage(); + + if (altserver != NULL) { + char *cp; + + cp = strchr(altserver, ':'); + if (cp == NULL) { + fprintf(stderr, "invalid alternate server: %s\n", + altserver); + exit(1); + } + *cp = '\0'; + altservername = altserver; + altserveraddr = cp + 1; + } + + isc_lib_register(); + result = dns_lib_init(); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_lib_init failed: %d\n", result); + exit(1); + } + + clientopt = 0; + result = dns_client_create(&client, clientopt); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_client_create failed: %d\n", result); + exit(1); + } + + /* Set the nameserver */ + addserver(client, argv[0], NULL); + + /* Set the alternate nameserver (when specified) */ + if (altserver != NULL) + addserver(client, altserveraddr, altservername); + + /* Install DNSSEC key (if given) */ + if (keynamestr != NULL) { + if (keystr == NULL) { + fprintf(stderr, + "key string is missing " + "while key name is provided\n"); + exit(1); + } + set_key(client, keynamestr, keystr, is_sep, &keymctx); + } + + /* Construct qname */ + namelen = strlen(argv[1]); + isc_buffer_init(&b, argv[1], namelen); + isc_buffer_add(&b, namelen); + dns_fixedname_init(&qname0); + qname = dns_fixedname_name(&qname0); + result = dns_name_fromtext(qname, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) + fprintf(stderr, "failed to convert qname: %d\n", result); + + /* Perform resolution */ + resopt = 0; + if (keynamestr == NULL) + resopt |= DNS_CLIENTRESOPT_NODNSSEC; + ISC_LIST_INIT(namelist); + result = dns_client_resolve(client, qname, dns_rdataclass_in, type, + resopt, &namelist); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, + "resolution failed: %s\n", dns_result_totext(result)); + } + for (name = ISC_LIST_HEAD(namelist); name != NULL; + name = ISC_LIST_NEXT(name, link)) { + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + if (printdata(rdataset, name) != ISC_R_SUCCESS) + fprintf(stderr, "print data failed\n"); + } + } + + dns_client_freeresanswer(client, &namelist); + + /* Cleanup */ + dns_client_destroy(&client); + if (keynamestr != NULL) + isc_mem_destroy(&keymctx); + dns_lib_shutdown(); + + exit(0); +} diff --git a/lib/irs/Makefile.in b/lib/irs/Makefile.in new file mode 100644 index 0000000..3f9bfb3 --- /dev/null +++ b/lib/irs/Makefile.in @@ -0,0 +1,80 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $ + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +@LIBIRS_API@ + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I. -I./include -I${srcdir}/include \ + ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCFG_INCLUDES} + +CDEFINES = +CWARNINGS = + +# Alphabetically +OBJS = context.@O@ \ + dnsconf.@O@ \ + gai_strerror.@O@ getaddrinfo.@O@ getnameinfo.@O@ \ + resconf.@O@ + +# Alphabetically +SRCS = context.c \ + dnsconf.c \ + gai_sterror.c getaddrinfo.c getnameinfo.c \ + resconf.c + +LIBS = @LIBS@ + +SUBDIRS = include +TARGETS = timestamp + +@BIND9_MAKE_RULES@ + +version.@O@: version.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ + -DVERSION=\"${VERSION}\" \ + -DLIBINTERFACE=${LIBINTERFACE} \ + -DLIBREVISION=${LIBREVISION} \ + -DLIBAGE=${LIBAGE} \ + -c ${srcdir}/version.c + +libirs.@SA@: ${OBJS} version.@O@ + ${AR} ${ARFLAGS} $@ ${OBJS} version.@O@ + ${RANLIB} $@ + +libirs.la: ${OBJS} version.@O@ + ${LIBTOOL_MODE_LINK} \ + ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libirs.la -rpath ${libdir} \ + -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ + ${OBJS} version.@O@ ${LIBS} + +timestamp: libirs.@A@ + touch timestamp + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir} + +install:: timestamp installdirs + ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libirs.@A@ ${DESTDIR}${libdir} + +clean distclean:: + rm -f libirs.@A@ libirs.la timestamp diff --git a/lib/irs/api b/lib/irs/api new file mode 100644 index 0000000..94575eb --- /dev/null +++ b/lib/irs/api @@ -0,0 +1,3 @@ +LIBINTERFACE = 80 +LIBREVISION = 0 +LIBAGE = 0 diff --git a/lib/irs/context.c b/lib/irs/context.c new file mode 100644 index 0000000..0c6d856 --- /dev/null +++ b/lib/irs/context.c @@ -0,0 +1,396 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: context.c,v 1.3 2009-09-02 23:48:02 tbox Exp $ */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#define IRS_CONTEXT_MAGIC ISC_MAGIC('I', 'R', 'S', 'c') +#define IRS_CONTEXT_VALID(c) ISC_MAGIC_VALID(c, IRS_CONTEXT_MAGIC) + +#ifndef RESOLV_CONF +/*% location of resolve.conf */ +#define RESOLV_CONF "/etc/resolv.conf" +#endif + +#ifndef DNS_CONF +/*% location of dns.conf */ +#define DNS_CONF "/etc/dns.conf" +#endif + +#ifndef ISC_PLATFORM_USETHREADS +irs_context_t *irs_g_context = NULL; +#else +static isc_boolean_t thread_key_initialized = ISC_FALSE; +static isc_mutex_t thread_key_mutex; +static isc_thread_key_t irs_context_key; +static isc_once_t once = ISC_ONCE_INIT; +#endif + + +struct irs_context { + /* + * An IRS context is a thread-specific object, and does not need to + * be locked. + */ + unsigned int magic; + isc_mem_t *mctx; + isc_appctx_t *actx; + isc_taskmgr_t *taskmgr; + isc_task_t *task; + isc_socketmgr_t *socketmgr; + isc_timermgr_t *timermgr; + dns_client_t *dnsclient; + irs_resconf_t *resconf; + irs_dnsconf_t *dnsconf; +}; + +static void +ctxs_destroy(isc_mem_t **mctxp, isc_appctx_t **actxp, + isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp, + isc_timermgr_t **timermgrp) +{ + if (taskmgrp != NULL) + isc_taskmgr_destroy(taskmgrp); + + if (timermgrp != NULL) + isc_timermgr_destroy(timermgrp); + + if (socketmgrp != NULL) + isc_socketmgr_destroy(socketmgrp); + + if (actxp != NULL) + isc_appctx_destroy(actxp); + + if (mctxp != NULL) + isc_mem_destroy(mctxp); +} + +static isc_result_t +ctxs_init(isc_mem_t **mctxp, isc_appctx_t **actxp, + isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp, + isc_timermgr_t **timermgrp) +{ + isc_result_t result; + + result = isc_mem_create(0, 0, mctxp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_appctx_create(*mctxp, actxp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_taskmgr_createinctx(*mctxp, *actxp, 1, 0, taskmgrp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_socketmgr_createinctx(*mctxp, *actxp, socketmgrp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_timermgr_createinctx(*mctxp, *actxp, timermgrp); + if (result != ISC_R_SUCCESS) + goto fail; + + return (ISC_R_SUCCESS); + + fail: + ctxs_destroy(mctxp, actxp, taskmgrp, socketmgrp, timermgrp); + + return (result); +} + +#ifdef ISC_PLATFORM_USETHREADS +static void +free_specific_context(void *arg) { + irs_context_t *context = arg; + + irs_context_destroy(&context); + + isc_thread_key_setspecific(irs_context_key, NULL); +} + +static void +thread_key_mutex_init(void) { + RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS); +} + +static isc_result_t +thread_key_init() { + isc_result_t result; + + result = isc_once_do(&once, thread_key_mutex_init); + if (result != ISC_R_SUCCESS) + return (result); + + if (!thread_key_initialized) { + LOCK(&thread_key_mutex); + + if (!thread_key_initialized && + isc_thread_key_create(&irs_context_key, + free_specific_context) != 0) { + result = ISC_R_FAILURE; + } else + thread_key_initialized = ISC_TRUE; + + UNLOCK(&thread_key_mutex); + } + + return (result); +} +#endif /* ISC_PLATFORM_USETHREADS */ + +isc_result_t +irs_context_get(irs_context_t **contextp) { + irs_context_t *context; + isc_result_t result; + + REQUIRE(contextp != NULL && *contextp == NULL); + +#ifndef ISC_PLATFORM_USETHREADS + if (irs_g_context == NULL) { + result = irs_context_create(&irs_g_context); + if (result != ISC_R_SUCCESS) + return (result); + } + + context = irs_g_context; +#else + result = thread_key_init(); + if (result != ISC_R_SUCCESS) + return (result); + + context = isc_thread_key_getspecific(irs_context_key); + if (context == NULL) { + result = irs_context_create(&context); + if (result != ISC_R_SUCCESS) + return (result); + result = isc_thread_key_setspecific(irs_context_key, context); + if (result != ISC_R_SUCCESS) { + irs_context_destroy(&context); + return (result); + } + } +#endif /* ISC_PLATFORM_USETHREADS */ + + *contextp = context; + + return (ISC_R_SUCCESS); +} + +isc_result_t +irs_context_create(irs_context_t **contextp) { + isc_result_t result; + irs_context_t *context; + isc_appctx_t *actx = NULL; + isc_mem_t *mctx = NULL; + isc_taskmgr_t *taskmgr = NULL; + isc_socketmgr_t *socketmgr = NULL; + isc_timermgr_t *timermgr = NULL; + dns_client_t *client = NULL; + isc_sockaddrlist_t *nameservers; + irs_dnsconf_dnskeylist_t *trustedkeys; + irs_dnsconf_dnskey_t *trustedkey; + + isc_lib_register(); + result = dns_lib_init(); + if (result != ISC_R_SUCCESS) + return (result); + + result = ctxs_init(&mctx, &actx, &taskmgr, &socketmgr, &timermgr); + if (result != ISC_R_SUCCESS) + return (result); + + result = isc_app_ctxstart(actx); + if (result != ISC_R_SUCCESS) { + ctxs_destroy(&mctx, &actx, &taskmgr, &socketmgr, &timermgr); + return (result); + } + + context = isc_mem_get(mctx, sizeof(*context)); + if (context == NULL) { + ctxs_destroy(&mctx, &actx, &taskmgr, &socketmgr, &timermgr); + return (ISC_R_NOMEMORY); + } + + context->mctx = mctx; + context->actx = actx; + context->taskmgr = taskmgr; + context->socketmgr = socketmgr; + context->timermgr = timermgr; + context->resconf = NULL; + context->dnsconf = NULL; + context->task = NULL; + result = isc_task_create(taskmgr, 0, &context->task); + if (result != ISC_R_SUCCESS) + goto fail; + + /* Create a DNS client object */ + result = dns_client_createx(mctx, actx, taskmgr, socketmgr, timermgr, + 0, &client); + if (result != ISC_R_SUCCESS) + goto fail; + context->dnsclient = client; + + /* Read resolver configuration file */ + result = irs_resconf_load(mctx, RESOLV_CONF, &context->resconf); + if (result != ISC_R_SUCCESS) + goto fail; + /* Set nameservers */ + nameservers = irs_resconf_getnameservers(context->resconf); + result = dns_client_setservers(client, dns_rdataclass_in, NULL, + nameservers); + if (result != ISC_R_SUCCESS) + goto fail; + + /* Read advanced DNS configuration (if any) */ + result = irs_dnsconf_load(mctx, DNS_CONF, &context->dnsconf); + if (result != ISC_R_SUCCESS) + goto fail; + trustedkeys = irs_dnsconf_gettrustedkeys(context->dnsconf); + for (trustedkey = ISC_LIST_HEAD(*trustedkeys); + trustedkey != NULL; + trustedkey = ISC_LIST_NEXT(trustedkey, link)) { + result = dns_client_addtrustedkey(client, dns_rdataclass_in, + trustedkey->keyname, + trustedkey->keydatabuf); + if (result != ISC_R_SUCCESS) + goto fail; + } + + context->magic = IRS_CONTEXT_MAGIC; + *contextp = context; + + return (ISC_R_SUCCESS); + + fail: + if (context->task != NULL) + isc_task_detach(&context->task); + if (context->resconf != NULL) + irs_resconf_destroy(&context->resconf); + if (context->dnsconf != NULL) + irs_dnsconf_destroy(&context->dnsconf); + if (client != NULL) + dns_client_destroy(&client); + ctxs_destroy(NULL, &actx, &taskmgr, &socketmgr, &timermgr); + isc_mem_putanddetach(&mctx, context, sizeof(*context)); + + return (result); +} + +void +irs_context_destroy(irs_context_t **contextp) { + irs_context_t *context; + + REQUIRE(contextp != NULL); + context = *contextp; + REQUIRE(IRS_CONTEXT_VALID(context)); + + isc_task_detach(&context->task); + irs_dnsconf_destroy(&context->dnsconf); + irs_resconf_destroy(&context->resconf); + dns_client_destroy(&context->dnsclient); + + ctxs_destroy(NULL, &context->actx, &context->taskmgr, + &context->socketmgr, &context->timermgr); + + context->magic = 0; + + isc_mem_putanddetach(&context->mctx, context, sizeof(*context)); + + *contextp = NULL; + +#ifndef ISC_PLATFORM_USETHREADS + irs_g_context = NULL; +#else + (void)isc_thread_key_setspecific(irs_context_key, NULL); +#endif +} + +isc_mem_t * +irs_context_getmctx(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->mctx); +} + +isc_appctx_t * +irs_context_getappctx(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->actx); +} + +isc_taskmgr_t * +irs_context_gettaskmgr(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->taskmgr); +} + +isc_timermgr_t * +irs_context_gettimermgr(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->timermgr); +} + +isc_task_t * +irs_context_gettask(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->task); +} + +dns_client_t * +irs_context_getdnsclient(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->dnsclient); +} + +irs_resconf_t * +irs_context_getresconf(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->resconf); +} + +irs_dnsconf_t * +irs_context_getdnsconf(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->dnsconf); +} diff --git a/lib/irs/dnsconf.c b/lib/irs/dnsconf.c new file mode 100644 index 0000000..8464d6d --- /dev/null +++ b/lib/irs/dnsconf.c @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: dnsconf.c,v 1.3 2009-09-02 23:48:02 tbox Exp $ */ + +/*! \file */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#define IRS_DNSCONF_MAGIC ISC_MAGIC('D', 'c', 'f', 'g') +#define IRS_DNSCONF_VALID(c) ISC_MAGIC_VALID(c, IRS_DNSCONF_MAGIC) + +/*! + * configuration data structure + */ + +struct irs_dnsconf { + unsigned int magic; + isc_mem_t *mctx; + irs_dnsconf_dnskeylist_t trusted_keylist; +}; + +static isc_result_t +configure_dnsseckeys(irs_dnsconf_t *conf, cfg_obj_t *cfgobj, + dns_rdataclass_t rdclass) +{ + isc_mem_t *mctx = conf->mctx; + const cfg_obj_t *keys = NULL; + const cfg_obj_t *key, *keylist; + dns_fixedname_t fkeyname; + dns_name_t *keyname_base, *keyname; + const cfg_listelt_t *element, *element2; + isc_result_t result; + isc_uint32_t flags, proto, alg; + const char *keystr, *keynamestr; + unsigned char keydata[4096]; + isc_buffer_t keydatabuf_base, *keydatabuf; + dns_rdata_dnskey_t keystruct; + unsigned char rrdata[4096]; + isc_buffer_t rrdatabuf; + isc_region_t r; + isc_buffer_t namebuf; + irs_dnsconf_dnskey_t *keyent; + + cfg_map_get(cfgobj, "trusted-keys", &keys); + if (keys == NULL) + return (ISC_R_SUCCESS); + + for (element = cfg_list_first(keys); + element != NULL; + element = cfg_list_next(element)) { + keylist = cfg_listelt_value(element); + for (element2 = cfg_list_first(keylist); + element2 != NULL; + element2 = cfg_list_next(element2)) + { + keydatabuf = NULL; + keyname = NULL; + + key = cfg_listelt_value(element2); + + flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags")); + proto = cfg_obj_asuint32(cfg_tuple_get(key, + "protocol")); + alg = cfg_obj_asuint32(cfg_tuple_get(key, + "algorithm")); + keynamestr = cfg_obj_asstring(cfg_tuple_get(key, + "name")); + + keystruct.common.rdclass = rdclass; + keystruct.common.rdtype = dns_rdatatype_dnskey; + keystruct.mctx = NULL; + ISC_LINK_INIT(&keystruct.common, link); + + if (flags > 0xffff) + return (ISC_R_RANGE); + if (proto > 0xff) + return (ISC_R_RANGE); + if (alg > 0xff) + return (ISC_R_RANGE); + keystruct.flags = (isc_uint16_t)flags; + keystruct.protocol = (isc_uint8_t)proto; + keystruct.algorithm = (isc_uint8_t)alg; + + isc_buffer_init(&keydatabuf_base, keydata, + sizeof(keydata)); + isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); + + /* Configure key value */ + keystr = cfg_obj_asstring(cfg_tuple_get(key, "key")); + result = isc_base64_decodestring(keystr, + &keydatabuf_base); + if (result != ISC_R_SUCCESS) + return (result); + isc_buffer_usedregion(&keydatabuf_base, &r); + keystruct.datalen = r.length; + keystruct.data = r.base; + + result = dns_rdata_fromstruct(NULL, + keystruct.common.rdclass, + keystruct.common.rdtype, + &keystruct, &rrdatabuf); + if (result != ISC_R_SUCCESS) + return (result); + isc_buffer_usedregion(&rrdatabuf, &r); + result = isc_buffer_allocate(mctx, &keydatabuf, + r.length); + if (result != ISC_R_SUCCESS) + return (result); + result = isc_buffer_copyregion(keydatabuf, &r); + if (result != ISC_R_SUCCESS) + goto cleanup; + + /* Configure key name */ + dns_fixedname_init(&fkeyname); + keyname_base = dns_fixedname_name(&fkeyname); + isc_buffer_init(&namebuf, keynamestr, + strlen(keynamestr)); + isc_buffer_add(&namebuf, strlen(keynamestr)); + result = dns_name_fromtext(keyname_base, &namebuf, + dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) + return (result); + keyname = isc_mem_get(mctx, sizeof(*keyname)); + if (keyname == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + dns_name_init(keyname, NULL); + result = dns_name_dup(keyname_base, mctx, keyname); + if (result != ISC_R_SUCCESS) + goto cleanup; + + /* Add the key data to the list */ + keyent = isc_mem_get(mctx, sizeof(*keyent)); + if (keyent == NULL) { + dns_name_free(keyname, mctx); + result = ISC_R_NOMEMORY; + goto cleanup; + } + keyent->keyname = keyname; + keyent->keydatabuf = keydatabuf; + + ISC_LIST_APPEND(conf->trusted_keylist, keyent, link); + } + } + + return (ISC_R_SUCCESS); + + cleanup: + if (keydatabuf != NULL) + isc_buffer_free(&keydatabuf); + if (keyname != NULL) + isc_mem_put(mctx, keyname, sizeof(*keyname)); + + return (result); +} + +isc_result_t +irs_dnsconf_load(isc_mem_t *mctx, const char *filename, irs_dnsconf_t **confp) +{ + irs_dnsconf_t *conf; + cfg_parser_t *parser = NULL; + cfg_obj_t *cfgobj = NULL; + isc_result_t result = ISC_R_SUCCESS; + + REQUIRE(confp != NULL && *confp == NULL); + + conf = isc_mem_get(mctx, sizeof(*conf)); + if (conf == NULL) + return (ISC_R_NOMEMORY); + + conf->mctx = mctx; + ISC_LIST_INIT(conf->trusted_keylist); + + /* + * If the specified file does not exist, we'll simply with an empty + * configuration. + */ + if (!isc_file_exists(filename)) + goto cleanup; + + result = cfg_parser_create(mctx, NULL, &parser); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = cfg_parse_file(parser, filename, &cfg_type_dnsconf, + &cfgobj); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = configure_dnsseckeys(conf, cfgobj, dns_rdataclass_in); + + cleanup: + if (parser != NULL) { + if (cfgobj != NULL) + cfg_obj_destroy(parser, &cfgobj); + cfg_parser_destroy(&parser); + } + + conf->magic = IRS_DNSCONF_MAGIC; + + if (result == ISC_R_SUCCESS) + *confp = conf; + else + irs_dnsconf_destroy(&conf); + + return (result); +} + +void +irs_dnsconf_destroy(irs_dnsconf_t **confp) { + irs_dnsconf_t *conf; + irs_dnsconf_dnskey_t *keyent; + + REQUIRE(confp != NULL); + conf = *confp; + REQUIRE(IRS_DNSCONF_VALID(conf)); + + while ((keyent = ISC_LIST_HEAD(conf->trusted_keylist)) != NULL) { + ISC_LIST_UNLINK(conf->trusted_keylist, keyent, link); + + isc_buffer_free(&keyent->keydatabuf); + dns_name_free(keyent->keyname, conf->mctx); + isc_mem_put(conf->mctx, keyent->keyname, sizeof(dns_name_t)); + isc_mem_put(conf->mctx, keyent, sizeof(*keyent)); + } + + isc_mem_put(conf->mctx, conf, sizeof(*conf)); + + *confp = NULL; +} + +irs_dnsconf_dnskeylist_t * +irs_dnsconf_gettrustedkeys(irs_dnsconf_t *conf) { + REQUIRE(IRS_DNSCONF_VALID(conf)); + + return (&conf->trusted_keylist); +} diff --git a/lib/irs/gai_strerror.c b/lib/irs/gai_strerror.c new file mode 100644 index 0000000..aa021ef --- /dev/null +++ b/lib/irs/gai_strerror.c @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: gai_strerror.c,v 1.5 2009-09-02 23:48:02 tbox Exp $ */ + +/*! \file gai_strerror.c + * gai_strerror() returns an error message corresponding to an + * error code returned by getaddrinfo() and getnameinfo(). The following error + * codes and their meaning are defined in + * \link netdb.h include/irs/netdb.h.\endlink + * This implementation is almost an exact copy of lwres/gai_sterror.c except + * that it catches up the latest API standard, RFC3493. + * + * \li #EAI_ADDRFAMILY address family for hostname not supported + * \li #EAI_AGAIN temporary failure in name resolution + * \li #EAI_BADFLAGS invalid value for ai_flags + * \li #EAI_FAIL non-recoverable failure in name resolution + * \li #EAI_FAMILY ai_family not supported + * \li #EAI_MEMORY memory allocation failure + * \li #EAI_NODATA no address associated with hostname (obsoleted in RFC3493) + * \li #EAI_NONAME hostname nor servname provided, or not known + * \li #EAI_SERVICE servname not supported for ai_socktype + * \li #EAI_SOCKTYPE ai_socktype not supported + * \li #EAI_SYSTEM system error returned in errno + * \li #EAI_BADHINTS Invalid value for hints (non-standard) + * \li #EAI_PROTOCOL Resolved protocol is unknown (non-standard) + * \li #EAI_OVERFLOW Argument buffer overflow + * \li #EAI_INSECUREDATA Insecure Data (experimental) + * + * The message invalid error code is returned if ecode is out of range. + * + * ai_flags, ai_family and ai_socktype are elements of the struct + * addrinfo used by lwres_getaddrinfo(). + * + * \section gai_strerror_see See Also + * + * strerror(), getaddrinfo(), getnameinfo(), RFC3493. + */ +#include + +#include + +/*% Text of error messages. */ +static const char *gai_messages[] = { + "no error", + "address family for hostname not supported", + "temporary failure in name resolution", + "invalid value for ai_flags", + "non-recoverable failure in name resolution", + "ai_family not supported", + "memory allocation failure", + "no address associated with hostname", + "hostname nor servname provided, or not known", + "servname not supported for ai_socktype", + "ai_socktype not supported", + "system error returned in errno", + "bad hints", + "bad protocol", + "argument buffer overflow", + "insecure data provided" +}; + +/*% + * Returns an error message corresponding to an error code returned by + * getaddrinfo() and getnameinfo() + */ +IRS_GAISTRERROR_RETURN_T +gai_strerror(int ecode) { + union { + const char *const_ptr; + char *deconst_ptr; + } ptr; + + if ((ecode < 0) || + (ecode >= (int)(sizeof(gai_messages)/sizeof(*gai_messages)))) + ptr.const_ptr = "invalid error code"; + else + ptr.const_ptr = gai_messages[ecode]; + return (ptr.deconst_ptr); +} diff --git a/lib/irs/getaddrinfo.c b/lib/irs/getaddrinfo.c new file mode 100644 index 0000000..e7075da --- /dev/null +++ b/lib/irs/getaddrinfo.c @@ -0,0 +1,1295 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: getaddrinfo.c,v 1.3 2009-09-02 23:48:02 tbox Exp $ */ + +/*! \file */ + +/** + * getaddrinfo() is used to get a list of IP addresses and port + * numbers for host hostname and service servname as defined in RFC3493. + * hostname and servname are pointers to null-terminated strings + * or NULL. hostname is either a host name or a numeric host address + * string: a dotted decimal IPv4 address or an IPv6 address. servname is + * either a decimal port number or a service name as listed in + * /etc/services. + * + * If the operating system does not provide a struct addrinfo, the + * following structure is used: + * + * \code + * 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 + * }; + * \endcode + * + * + * hints is an optional pointer to a struct addrinfo. This structure can + * be used to provide hints concerning the type of socket that the caller + * supports or wishes to use. The caller can supply the following + * structure elements in *hints: + * + *
      + *
    • ai_family: + * The protocol family that should be used. When ai_family is set + * to PF_UNSPEC, it means the caller will accept any protocol + * family supported by the operating system.
    • + * + *
    • ai_socktype: + * denotes the type of socket -- SOCK_STREAM, SOCK_DGRAM or + * SOCK_RAW -- that is wanted. When ai_socktype is zero the caller + * will accept any socket type.
    • + * + *
    • ai_protocol: + * indicates which transport protocol is wanted: IPPROTO_UDP or + * IPPROTO_TCP. If ai_protocol is zero the caller will accept any + * protocol.
    • + * + *
    • ai_flags: + * Flag bits. If the AI_CANONNAME bit is set, a successful call to + * getaddrinfo() will return a null-terminated string + * containing the canonical name of the specified hostname in + * ai_canonname of the first addrinfo structure returned. Setting + * the AI_PASSIVE bit indicates that the returned socket address + * structure is intended for used in a call to bind(2). In this + * case, if the hostname argument is a NULL pointer, then the IP + * address portion of the socket address structure will be set to + * INADDR_ANY for an IPv4 address or IN6ADDR_ANY_INIT for an IPv6 + * address.

      + * + * When ai_flags does not set the AI_PASSIVE bit, the returned + * socket address structure will be ready for use in a call to + * connect(2) for a connection-oriented protocol or connect(2), + * sendto(2), or sendmsg(2) if a connectionless protocol was + * chosen. The IP address portion of the socket address structure + * will be set to the loopback address if hostname is a NULL + * pointer and AI_PASSIVE is not set in ai_flags.

      + * + * If ai_flags is set to AI_NUMERICHOST it indicates that hostname + * should be treated as a numeric string defining an IPv4 or IPv6 + * address and no name resolution should be attempted. + *
    + * + * All other elements of the struct addrinfo passed via hints must be + * zero. + * + * A hints of NULL is treated as if the caller provided a struct addrinfo + * initialized to zero with ai_familyset to PF_UNSPEC. + * + * After a successful call to getaddrinfo(), *res is a pointer to a + * linked list of one or more addrinfo structures. Each struct addrinfo + * in this list cn be processed by following the ai_next pointer, until a + * NULL pointer is encountered. The three members ai_family, ai_socktype, + * and ai_protocol in each returned addrinfo structure contain the + * corresponding arguments for a call to socket(2). For each addrinfo + * structure in the list, the ai_addr member points to a filled-in socket + * address structure of length ai_addrlen. + * + * All of the information returned by getaddrinfo() is dynamically + * allocated: the addrinfo structures, and the socket address structures + * and canonical host name strings pointed to by the addrinfostructures. + * Memory allocated for the dynamically allocated structures created by a + * successful call to getaddrinfo() is released by freeaddrinfo(). + * ai is a pointer to a struct addrinfo created by a call to getaddrinfo(). + * + * \section irsreturn RETURN VALUES + * + * getaddrinfo() returns zero on success or one of the error codes + * listed in gai_strerror() if an error occurs. If both hostname and + * servname are NULL getaddrinfo() returns #EAI_NONAME. + * + * \section irssee SEE ALSO + * + * getaddrinfo(), freeaddrinfo(), + * gai_strerror(), RFC3493, getservbyname(3), connect(2), + * sendto(2), sendmsg(2), socket(2). + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define SA(addr) ((struct sockaddr *)(addr)) +#define SIN(addr) ((struct sockaddr_in *)(addr)) +#define SIN6(addr) ((struct sockaddr_in6 *)(addr)) +#define SLOCAL(addr) ((struct sockaddr_un *)(addr)) + +/*! \struct addrinfo + */ +static struct addrinfo + *ai_concat(struct addrinfo *ai1, struct addrinfo *ai2), + *ai_reverse(struct addrinfo *oai), + *ai_clone(struct addrinfo *oai, int family), + *ai_alloc(int family, int addrlen); +#ifdef AF_LOCAL +static int get_local(const char *name, int socktype, struct addrinfo **res); +#endif + +static int +resolve_name(int family, const char *hostname, int flags, + struct addrinfo **aip, int socktype, int port); + +static int add_ipv4(const char *hostname, int flags, struct addrinfo **aip, + int socktype, int port); +static int add_ipv6(const char *hostname, int flags, struct addrinfo **aip, + int socktype, int port); +static void set_order(int, int (**)(const char *, int, struct addrinfo **, + int, int)); + +#define FOUND_IPV4 0x1 +#define FOUND_IPV6 0x2 +#define FOUND_MAX 2 + +#define ISC_AI_MASK (AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST) +/*% + * Get a list of IP addresses and port numbers for host hostname and + * service servname. + */ +int +getaddrinfo(const char *hostname, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + struct servent *sp; + const char *proto; + int family, socktype, flags, protocol; + struct addrinfo *ai, *ai_list; + int err = 0; + int port, i; + int (*net_order[FOUND_MAX+1])(const char *, int, struct addrinfo **, + int, int); + + if (hostname == NULL && servname == NULL) + return (EAI_NONAME); + + proto = NULL; + if (hints != NULL) { + if ((hints->ai_flags & ~(ISC_AI_MASK)) != 0) + return (EAI_BADFLAGS); + if (hints->ai_addrlen || hints->ai_canonname || + hints->ai_addr || hints->ai_next) { + errno = EINVAL; + return (EAI_SYSTEM); + } + family = hints->ai_family; + socktype = hints->ai_socktype; + protocol = hints->ai_protocol; + flags = hints->ai_flags; + switch (family) { + case AF_UNSPEC: + switch (hints->ai_socktype) { + case SOCK_STREAM: + proto = "tcp"; + break; + case SOCK_DGRAM: + proto = "udp"; + break; + } + break; + case AF_INET: + case AF_INET6: + switch (hints->ai_socktype) { + case 0: + break; + case SOCK_STREAM: + proto = "tcp"; + break; + case SOCK_DGRAM: + proto = "udp"; + break; + case SOCK_RAW: + break; + default: + return (EAI_SOCKTYPE); + } + break; +#ifdef AF_LOCAL + case AF_LOCAL: + switch (hints->ai_socktype) { + case 0: + break; + case SOCK_STREAM: + break; + case SOCK_DGRAM: + break; + default: + return (EAI_SOCKTYPE); + } + break; +#endif + default: + return (EAI_FAMILY); + } + } else { + protocol = 0; + family = 0; + socktype = 0; + flags = 0; + } + +#ifdef AF_LOCAL + /*! + * First, deal with AF_LOCAL. If the family was not set, + * then assume AF_LOCAL if the first character of the + * hostname/servname is '/'. + */ + + if (hostname != NULL && + (family == AF_LOCAL || (family == 0 && *hostname == '/'))) + return (get_local(hostname, socktype, res)); + + if (servname != NULL && + (family == AF_LOCAL || (family == 0 && *servname == '/'))) + return (get_local(servname, socktype, res)); +#endif + + /* + * Ok, only AF_INET and AF_INET6 left. + */ + ai_list = NULL; + + /* + * First, look up the service name (port) if it was + * requested. If the socket type wasn't specified, then + * try and figure it out. + */ + if (servname != NULL) { + char *e; + + port = strtol(servname, &e, 10); + if (*e == '\0') { + if (socktype == 0) + return (EAI_SOCKTYPE); + if (port < 0 || port > 65535) + return (EAI_SERVICE); + port = htons((unsigned short) port); + } else { + sp = getservbyname(servname, proto); + if (sp == NULL) + return (EAI_SERVICE); + port = sp->s_port; + if (socktype == 0) { + if (strcmp(sp->s_proto, "tcp") == 0) + socktype = SOCK_STREAM; + else if (strcmp(sp->s_proto, "udp") == 0) + socktype = SOCK_DGRAM; + } + } + } else + port = 0; + + /* + * Next, deal with just a service name, and no hostname. + * (we verified that one of them was non-null up above). + */ + if (hostname == NULL && (flags & AI_PASSIVE) != 0) { + if (family == AF_INET || family == 0) { + ai = ai_alloc(AF_INET, sizeof(struct sockaddr_in)); + if (ai == NULL) + return (EAI_MEMORY); + ai->ai_socktype = socktype; + ai->ai_protocol = protocol; + SIN(ai->ai_addr)->sin_port = port; + ai->ai_next = ai_list; + ai_list = ai; + } + + if (family == AF_INET6 || family == 0) { + ai = ai_alloc(AF_INET6, sizeof(struct sockaddr_in6)); + if (ai == NULL) { + freeaddrinfo(ai_list); + return (EAI_MEMORY); + } + ai->ai_socktype = socktype; + ai->ai_protocol = protocol; + SIN6(ai->ai_addr)->sin6_port = port; + ai->ai_next = ai_list; + ai_list = ai; + } + + *res = ai_list; + return (0); + } + + /* + * If the family isn't specified or AI_NUMERICHOST specified, check + * first to see if it is a numeric address. + * Though the gethostbyname2() routine will recognize numeric addresses, + * it will only recognize the format that it is being called for. Thus, + * a numeric AF_INET address will be treated by the AF_INET6 call as + * a domain name, and vice versa. Checking for both numerics here + * avoids that. + */ + if (hostname != NULL && + (family == 0 || (flags & AI_NUMERICHOST) != 0)) { + char abuf[sizeof(struct in6_addr)]; + char nbuf[NI_MAXHOST]; + int addrsize, addroff; +#ifdef IRS_HAVE_SIN6_SCOPE_ID + char *p, *ep; + char ntmp[NI_MAXHOST]; + isc_uint32_t scopeid; +#endif + +#ifdef IRS_HAVE_SIN6_SCOPE_ID + /* + * Scope identifier portion. + */ + ntmp[0] = '\0'; + if (strchr(hostname, '%') != NULL) { + strncpy(ntmp, hostname, sizeof(ntmp) - 1); + ntmp[sizeof(ntmp) - 1] = '\0'; + p = strchr(ntmp, '%'); + ep = NULL; + + /* + * Vendors may want to support non-numeric + * scopeid around here. + */ + + if (p != NULL) + scopeid = (isc_uint32_t)strtoul(p + 1, + &ep, 10); + if (p != NULL && ep != NULL && ep[0] == '\0') + *p = '\0'; + else { + ntmp[0] = '\0'; + scopeid = 0; + } + } else + scopeid = 0; +#endif + + if (inet_pton(AF_INET, hostname, (struct in_addr *)abuf) + == 1) { + if (family == AF_INET6) { + /* + * Convert to a V4 mapped address. + */ + struct in6_addr *a6 = (struct in6_addr *)abuf; + memcpy(&a6->s6_addr[12], &a6->s6_addr[0], 4); + memset(&a6->s6_addr[10], 0xff, 2); + memset(&a6->s6_addr[0], 0, 10); + goto inet6_addr; + } + addrsize = sizeof(struct in_addr); + addroff = (char *)(&SIN(0)->sin_addr) - (char *)0; + family = AF_INET; + goto common; +#ifdef IRS_HAVE_SIN6_SCOPE_ID + } else if (ntmp[0] != '\0' && + inet_pton(AF_INET6, ntmp, abuf) == 1) { + if (family && family != AF_INET6) + return (EAI_NONAME); + addrsize = sizeof(struct in6_addr); + addroff = (char *)(&SIN6(0)->sin6_addr) - (char *)0; + family = AF_INET6; + goto common; +#endif + } else if (inet_pton(AF_INET6, hostname, abuf) == 1) { + if (family != 0 && family != AF_INET6) + return (EAI_NONAME); + inet6_addr: + addrsize = sizeof(struct in6_addr); + addroff = (char *)(&SIN6(0)->sin6_addr) - (char *)0; + family = AF_INET6; + + common: + ai = ai_alloc(family, + ((family == AF_INET6) ? + sizeof(struct sockaddr_in6) : + sizeof(struct sockaddr_in))); + if (ai == NULL) + return (EAI_MEMORY); + ai_list = ai; + ai->ai_socktype = socktype; + SIN(ai->ai_addr)->sin_port = port; + memcpy((char *)ai->ai_addr + addroff, abuf, addrsize); + if ((flags & AI_CANONNAME) != 0) { +#ifdef IRS_HAVE_SIN6_SCOPE_ID + if (ai->ai_family == AF_INET6) + SIN6(ai->ai_addr)->sin6_scope_id = + scopeid; +#endif + if (getnameinfo(ai->ai_addr, ai->ai_addrlen, + nbuf, sizeof(nbuf), NULL, 0, + NI_NUMERICHOST) == 0) { + ai->ai_canonname = strdup(nbuf); + if (ai->ai_canonname == NULL) { + freeaddrinfo(ai); + return (EAI_MEMORY); + } + } else { + /* XXX raise error? */ + ai->ai_canonname = NULL; + } + } + goto done; + } else if ((flags & AI_NUMERICHOST) != 0) { + return (EAI_NONAME); + } + } + + if (hostname == NULL && (flags & AI_PASSIVE) == 0) { + set_order(family, net_order); + for (i = 0; i < FOUND_MAX; i++) { + if (net_order[i] == NULL) + break; + err = (net_order[i])(hostname, flags, &ai_list, + socktype, port); + if (err != 0) { + if (ai_list != NULL) + freeaddrinfo(ai_list); + break; + } + } + } else + err = resolve_name(family, hostname, flags, &ai_list, + socktype, port); + + if (ai_list == NULL) { + if (err == 0) + err = EAI_NONAME; + return (err); + } + +done: + ai_list = ai_reverse(ai_list); + + *res = ai_list; + return (0); +} + +typedef struct gai_restrans { + dns_clientrestrans_t *xid; + isc_boolean_t is_inprogress; + int error; + struct addrinfo ai_sentinel; + struct gai_resstate *resstate; +} gai_restrans_t; + +typedef struct gai_resstate { + isc_mem_t *mctx; + struct gai_statehead *head; + dns_fixedname_t fixedname; + dns_name_t *qname; + gai_restrans_t *trans4; + gai_restrans_t *trans6; + ISC_LINK(struct gai_resstate) link; +} gai_resstate_t; + +typedef struct gai_statehead { + int ai_family; + int ai_flags; + int ai_socktype; + int ai_port; + isc_appctx_t *actx; + dns_client_t *dnsclient; + ISC_LIST(struct gai_resstate) resstates; + unsigned int activestates; +} gai_statehead_t; + +static isc_result_t +make_resstate(isc_mem_t *mctx, gai_statehead_t *head, const char *hostname, + const char *domain, gai_resstate_t **statep) +{ + isc_result_t result; + gai_resstate_t *state; + dns_fixedname_t fixeddomain; + dns_name_t *qdomain; + size_t namelen; + isc_buffer_t b; + isc_boolean_t need_v4 = ISC_FALSE; + isc_boolean_t need_v6 = ISC_FALSE; + + state = isc_mem_get(mctx, sizeof(*state)); + if (state == NULL) + return (ISC_R_NOMEMORY); + + /* Construct base domain name */ + namelen = strlen(domain); + isc_buffer_init(&b, domain, namelen); + isc_buffer_add(&b, namelen); + dns_fixedname_init(&fixeddomain); + qdomain = dns_fixedname_name(&fixeddomain); + result = dns_name_fromtext(qdomain, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + isc_mem_put(mctx, state, sizeof(*state)); + return (result); + } + + /* Construct query name */ + namelen = strlen(hostname); + isc_buffer_init(&b, hostname, namelen); + isc_buffer_add(&b, namelen); + dns_fixedname_init(&state->fixedname); + state->qname = dns_fixedname_name(&state->fixedname); + result = dns_name_fromtext(state->qname, &b, qdomain, 0, NULL); + if (result != ISC_R_SUCCESS) { + isc_mem_put(mctx, state, sizeof(*state)); + return (result); + } + + if (head->ai_family == AF_UNSPEC || head->ai_family == AF_INET) + need_v4 = ISC_TRUE; + if (head->ai_family == AF_UNSPEC || head->ai_family == AF_INET6) + need_v6 = ISC_TRUE; + + state->trans6 = NULL; + state->trans4 = NULL; + if (need_v4) { + state->trans4 = isc_mem_get(mctx, sizeof(gai_restrans_t)); + if (state->trans4 == NULL) { + isc_mem_put(mctx, state, sizeof(*state)); + return (ISC_R_NOMEMORY); + } + state->trans4->error = 0; + state->trans4->xid = NULL; + state->trans4->resstate = state; + state->trans4->is_inprogress = ISC_TRUE; + state->trans4->ai_sentinel.ai_next = NULL; + } + if (need_v6) { + state->trans6 = isc_mem_get(mctx, sizeof(gai_restrans_t)); + if (state->trans6 == NULL) { + if (state->trans4 != NULL) + isc_mem_put(mctx, state->trans4, + sizeof(*state->trans4)); + isc_mem_put(mctx, state, sizeof(*state)); + return (ISC_R_NOMEMORY); + } + state->trans6->error = 0; + state->trans6->xid = NULL; + state->trans6->resstate = state; + state->trans6->is_inprogress = ISC_TRUE; + state->trans6->ai_sentinel.ai_next = NULL; + } + + state->mctx = mctx; + state->head = head; + ISC_LINK_INIT(state, link); + + *statep = state; + + return (ISC_R_SUCCESS); +} + +static isc_result_t +make_resstates(isc_mem_t *mctx, const char *hostname, gai_statehead_t *head, + irs_resconf_t *resconf) +{ + isc_result_t result; + irs_resconf_searchlist_t *searchlist; + irs_resconf_search_t *searchent; + gai_resstate_t *resstate, *resstate0; + + resstate0 = NULL; + result = make_resstate(mctx, head, hostname, ".", &resstate0); + if (result != ISC_R_SUCCESS) + return (result); + + searchlist = irs_resconf_getsearchlist(resconf); + for (searchent = ISC_LIST_HEAD(*searchlist); searchent != NULL; + searchent = ISC_LIST_NEXT(searchent, link)) { + resstate = NULL; + result = make_resstate(mctx, head, hostname, + (const char *)searchent->domain, + &resstate); + if (result != ISC_R_SUCCESS) + break; + + ISC_LIST_APPEND(head->resstates, resstate, link); + head->activestates++; + } + + /* + * Insert the original hostname either at the head or the tail of the + * state list, depending on the number of labels contained in the + * original name and the 'ndots' configuration parameter. + */ + if (dns_name_countlabels(resstate0->qname) > + irs_resconf_getndots(resconf) + 1) { + ISC_LIST_PREPEND(head->resstates, resstate0, link); + } else + ISC_LIST_APPEND(head->resstates, resstate0, link); + head->activestates++; + + if (result != ISC_R_SUCCESS) { + while ((resstate = ISC_LIST_HEAD(head->resstates)) != NULL) { + ISC_LIST_UNLINK(head->resstates, resstate, link); + if (resstate->trans4 != NULL) { + isc_mem_put(mctx, resstate->trans4, + sizeof(*resstate->trans4)); + } + if (resstate->trans6 != NULL) { + isc_mem_put(mctx, resstate->trans6, + sizeof(*resstate->trans6)); + } + + isc_mem_put(mctx, resstate, sizeof(*resstate)); + } + } + + return (result); +} + +static void +process_answer(isc_task_t *task, isc_event_t *event) { + int error = 0, family; + gai_restrans_t *trans = event->ev_arg; + gai_resstate_t *resstate; + dns_clientresevent_t *rev = (dns_clientresevent_t *)event; + dns_rdatatype_t qtype; + dns_name_t *name; + + REQUIRE(trans != NULL); + resstate = trans->resstate; + REQUIRE(resstate != NULL); + REQUIRE(task != NULL); + + if (trans == resstate->trans4) { + family = AF_INET; + qtype = dns_rdatatype_a; + } else { + INSIST(trans == resstate->trans6); + family = AF_INET6; + qtype = dns_rdatatype_aaaa; + } + + INSIST(trans->is_inprogress); + trans->is_inprogress = ISC_FALSE; + + switch (rev->result) { + case ISC_R_SUCCESS: + case DNS_R_NCACHENXDOMAIN: /* treat this as a fatal error? */ + case DNS_R_NCACHENXRRSET: + break; + default: + switch (rev->vresult) { + case DNS_R_SIGINVALID: + case DNS_R_SIGEXPIRED: + case DNS_R_SIGFUTURE: + case DNS_R_KEYUNAUTHORIZED: + case DNS_R_MUSTBESECURE: + case DNS_R_COVERINGNSEC: + case DNS_R_NOTAUTHORITATIVE: + case DNS_R_NOVALIDKEY: + case DNS_R_NOVALIDDS: + case DNS_R_NOVALIDSIG: + error = EAI_INSECUREDATA; + break; + default: + error = EAI_FAIL; + } + goto done; + } + + /* Parse the response and construct the addrinfo chain */ + for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL; + name = ISC_LIST_NEXT(name, link)) { + isc_result_t result; + dns_rdataset_t *rdataset; + isc_buffer_t b; + isc_region_t r; + char t[1024]; + + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + if (!dns_rdataset_isassociated(rdataset)) + continue; + if (rdataset->type != qtype) + continue; + + if ((resstate->head->ai_flags & AI_CANONNAME) != 0) { + isc_buffer_init(&b, t, sizeof(t)); + result = dns_name_totext(name, ISC_TRUE, &b); + if (result != ISC_R_SUCCESS) { + error = EAI_FAIL; + goto done; + } + isc_buffer_putuint8(&b, '\0'); + isc_buffer_usedregion(&b, &r); + } + + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + struct addrinfo *ai; + dns_rdata_t rdata; + dns_rdata_in_a_t rdata_a; + dns_rdata_in_aaaa_t rdata_aaaa; + + ai = ai_alloc(family, + ((family == AF_INET6) ? + sizeof(struct sockaddr_in6) : + sizeof(struct sockaddr_in))); + if (ai == NULL) { + error = EAI_MEMORY; + goto done; + } + ai->ai_socktype = resstate->head->ai_socktype; + ai->ai_next = trans->ai_sentinel.ai_next; + trans->ai_sentinel.ai_next = ai; + + /* + * Set AF-specific parameters + * (IPv4/v6 address/port) + */ + dns_rdata_init(&rdata); + switch (family) { + case AF_INET: + dns_rdataset_current(rdataset, &rdata); + dns_rdata_tostruct(&rdata, &rdata_a, + NULL); + + SIN(ai->ai_addr)->sin_port = + resstate->head->ai_port; + memcpy(&SIN(ai->ai_addr)->sin_addr, + &rdata_a.in_addr, 4); + dns_rdata_freestruct(&rdata_a); + break; + case AF_INET6: + dns_rdataset_current(rdataset, &rdata); + dns_rdata_tostruct(&rdata, &rdata_aaaa, + NULL); + SIN6(ai->ai_addr)->sin6_port = + resstate->head->ai_port; + memcpy(&SIN6(ai->ai_addr)->sin6_addr, + &rdata_aaaa.in6_addr, 16); + dns_rdata_freestruct(&rdata_aaaa); + break; + } + + if ((resstate->head->ai_flags & AI_CANONNAME) + != 0) { + ai->ai_canonname = + strdup((const char *)r.base); + if (ai->ai_canonname == NULL) { + error = EAI_MEMORY; + goto done; + } + } + } + } + } + + done: + dns_client_freeresanswer(resstate->head->dnsclient, &rev->answerlist); + dns_client_destroyrestrans(&trans->xid); + + isc_event_free(&event); + + /* Make sure that error == 0 iff we have a non-empty list */ + if (error == 0) { + if (trans->ai_sentinel.ai_next == NULL) + error = EAI_NONAME; + } else { + if (trans->ai_sentinel.ai_next != NULL) { + freeaddrinfo(trans->ai_sentinel.ai_next); + trans->ai_sentinel.ai_next = NULL; + } + } + trans->error = error; + + /* Check whether we are done */ + if ((resstate->trans4 == NULL || !resstate->trans4->is_inprogress) && + (resstate->trans6 == NULL || !resstate->trans6->is_inprogress)) { + /* + * We're done for this state. If there is no other outstanding + * state, we can exit. + */ + resstate->head->activestates--; + if (resstate->head->activestates == 0) { + isc_app_ctxsuspend(resstate->head->actx); + return; + } + + /* + * There are outstanding states, but if we are at the head + * of the state list (i.e., at the highest search priority) + * and have any answer, we can stop now by canceling the + * others. + */ + if (resstate == ISC_LIST_HEAD(resstate->head->resstates)) { + if ((resstate->trans4 != NULL && + resstate->trans4->ai_sentinel.ai_next != NULL) || + (resstate->trans6 != NULL && + resstate->trans6->ai_sentinel.ai_next != NULL)) { + gai_resstate_t *rest; + + for (rest = ISC_LIST_NEXT(resstate, link); + rest != NULL; + rest = ISC_LIST_NEXT(rest, link)) { + if (rest->trans4 != NULL && + rest->trans4->xid != NULL) + dns_client_cancelresolve( + rest->trans4->xid); + if (rest->trans6 != NULL && + rest->trans6->xid != NULL) + dns_client_cancelresolve( + rest->trans6->xid); + } + } else { + /* + * This search fails, so we move to the tail + * of the list so that the next entry will + * have the highest priority. + */ + ISC_LIST_UNLINK(resstate->head->resstates, + resstate, link); + ISC_LIST_APPEND(resstate->head->resstates, + resstate, link); + } + } + } +} + +static int +resolve_name(int family, const char *hostname, int flags, + struct addrinfo **aip, int socktype, int port) +{ + isc_result_t result; + irs_context_t *irsctx; + irs_resconf_t *conf; + isc_mem_t *mctx; + isc_appctx_t *actx; + isc_task_t *task; + int terror = 0; + int error = 0; + dns_client_t *client; + gai_resstate_t *resstate; + gai_statehead_t head; + isc_boolean_t all_fail = ISC_TRUE; + + /* get IRS context and the associated parameters */ + irsctx = NULL; + result = irs_context_get(&irsctx); + if (result != ISC_R_SUCCESS) + return (EAI_FAIL); + actx = irs_context_getappctx(irsctx); + + mctx = irs_context_getmctx(irsctx); + task = irs_context_gettask(irsctx); + conf = irs_context_getresconf(irsctx); + client = irs_context_getdnsclient(irsctx); + + /* construct resolution states */ + head.activestates = 0; + head.ai_family = family; + head.ai_socktype = socktype; + head.ai_flags = flags; + head.ai_port = port; + head.actx = actx; + head.dnsclient = client; + ISC_LIST_INIT(head.resstates); + result = make_resstates(mctx, hostname, &head, conf); + if (result != ISC_R_SUCCESS) + return (EAI_FAIL); + + for (resstate = ISC_LIST_HEAD(head.resstates); + resstate != NULL; resstate = ISC_LIST_NEXT(resstate, link)) { + if (resstate->trans4 != NULL) { + result = dns_client_startresolve(client, + resstate->qname, + dns_rdataclass_in, + dns_rdatatype_a, + 0, task, + process_answer, + resstate->trans4, + &resstate->trans4->xid); + if (result == ISC_R_SUCCESS) { + resstate->trans4->is_inprogress = ISC_TRUE; + all_fail = ISC_FALSE; + } else + resstate->trans4->is_inprogress = ISC_FALSE; + } + if (resstate->trans6 != NULL) { + result = dns_client_startresolve(client, + resstate->qname, + dns_rdataclass_in, + dns_rdatatype_aaaa, + 0, task, + process_answer, + resstate->trans6, + &resstate->trans6->xid); + if (result == ISC_R_SUCCESS) { + resstate->trans6->is_inprogress = ISC_TRUE; + all_fail = ISC_FALSE; + } else + resstate->trans6->is_inprogress= ISC_FALSE; + } + } + if (!all_fail) { + /* Start all the events */ + isc_app_ctxrun(actx); + } else + error = EAI_FAIL; + + /* Cleanup */ + while ((resstate = ISC_LIST_HEAD(head.resstates)) != NULL) { + int terror4 = 0, terror6 = 0; + + ISC_LIST_UNLINK(head.resstates, resstate, link); + + if (*aip == NULL) { + struct addrinfo *sentinel4 = NULL; + struct addrinfo *sentinel6 = NULL; + + if (resstate->trans4 != NULL) { + sentinel4 = + resstate->trans4->ai_sentinel.ai_next; + resstate->trans4->ai_sentinel.ai_next = NULL; + } + if (resstate->trans6 != NULL) { + sentinel6 = + resstate->trans6->ai_sentinel.ai_next; + resstate->trans6->ai_sentinel.ai_next = NULL; + } + *aip = ai_concat(sentinel4, sentinel6); + } + + if (resstate->trans4 != NULL) { + INSIST(resstate->trans4->xid == NULL); + terror4 = resstate->trans4->error; + isc_mem_put(mctx, resstate->trans4, + sizeof(*resstate->trans4)); + } + if (resstate->trans6 != NULL) { + INSIST(resstate->trans6->xid == NULL); + terror6 = resstate->trans6->error; + isc_mem_put(mctx, resstate->trans6, + sizeof(*resstate->trans6)); + } + + /* + * If the entire lookup fails, we need to choose an appropriate + * error code from individual codes. We'll try to provide as + * specific a code as possible. In general, we are going to + * find an error code other than EAI_NONAME (which is too + * generic and may actually not be problematic in some cases). + * EAI_NONAME will be set below if no better code is found. + */ + if (terror == 0 || terror == EAI_NONAME) { + if (terror4 != 0 && terror4 != EAI_NONAME) + terror = terror4; + else if (terror6 != 0 && terror6 != EAI_NONAME) + terror = terror6; + } + + isc_mem_put(mctx, resstate, sizeof(*resstate)); + } + + if (*aip == NULL) { + error = terror; + if (error == 0) + error = EAI_NONAME; + } + +#if 1 /* XXX: enabled for finding leaks. should be cleaned up later. */ + isc_app_ctxfinish(actx); + irs_context_destroy(&irsctx); +#endif + + return (error); +} + +static char * +irs_strsep(char **stringp, const char *delim) { + char *string = *stringp; + char *s; + const char *d; + char sc, dc; + + if (string == NULL) + return (NULL); + + for (s = string; *s != '\0'; s++) { + sc = *s; + for (d = delim; (dc = *d) != '\0'; d++) + if (sc == dc) { + *s++ = '\0'; + *stringp = s; + return (string); + } + } + *stringp = NULL; + return (string); +} + +static void +set_order(int family, int (**net_order)(const char *, int, struct addrinfo **, + int, int)) +{ + char *order, *tok; + int found; + + if (family) { + switch (family) { + case AF_INET: + *net_order++ = add_ipv4; + break; + case AF_INET6: + *net_order++ = add_ipv6; + break; + } + } else { + order = getenv("NET_ORDER"); + found = 0; + while (order != NULL) { + /* + * We ignore any unknown names. + */ + tok = irs_strsep(&order, ":"); + if (strcasecmp(tok, "inet6") == 0) { + if ((found & FOUND_IPV6) == 0) + *net_order++ = add_ipv6; + found |= FOUND_IPV6; + } else if (strcasecmp(tok, "inet") == 0 || + strcasecmp(tok, "inet4") == 0) { + if ((found & FOUND_IPV4) == 0) + *net_order++ = add_ipv4; + found |= FOUND_IPV4; + } + } + + /* + * Add in anything that we didn't find. + */ + if ((found & FOUND_IPV4) == 0) + *net_order++ = add_ipv4; + if ((found & FOUND_IPV6) == 0) + *net_order++ = add_ipv6; + } + *net_order = NULL; + return; +} + +static char v4_loop[4] = { 127, 0, 0, 1 }; + +static int +add_ipv4(const char *hostname, int flags, struct addrinfo **aip, + int socktype, int port) +{ + struct addrinfo *ai; + + UNUSED(hostname); + UNUSED(flags); + + ai = ai_clone(*aip, AF_INET); /* don't use ai_clone() */ + if (ai == NULL) { + freeaddrinfo(*aip); + return (EAI_MEMORY); + } + + *aip = ai; + ai->ai_socktype = socktype; + SIN(ai->ai_addr)->sin_port = port; + memcpy(&SIN(ai->ai_addr)->sin_addr, v4_loop, 4); + + return (0); +} + +static char v6_loop[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; + +static int +add_ipv6(const char *hostname, int flags, struct addrinfo **aip, + int socktype, int port) +{ + struct addrinfo *ai; + + UNUSED(hostname); + UNUSED(flags); + + ai = ai_clone(*aip, AF_INET6); /* don't use ai_clone() */ + if (ai == NULL) { + freeaddrinfo(*aip); + return (EAI_MEMORY); + } + + *aip = ai; + ai->ai_socktype = socktype; + SIN6(ai->ai_addr)->sin6_port = port; + memcpy(&SIN6(ai->ai_addr)->sin6_addr, v6_loop, 16); + + return (0); +} + +/*% Free address info. */ +void +freeaddrinfo(struct addrinfo *ai) { + struct addrinfo *ai_next; + + while (ai != NULL) { + ai_next = ai->ai_next; + if (ai->ai_addr != NULL) + free(ai->ai_addr); + if (ai->ai_canonname) + free(ai->ai_canonname); + free(ai); + ai = ai_next; + } +} + +#ifdef AF_LOCAL +static int +get_local(const char *name, int socktype, struct addrinfo **res) { + struct addrinfo *ai; + struct sockaddr_un *slocal; + + if (socktype == 0) + return (EAI_SOCKTYPE); + + ai = ai_alloc(AF_LOCAL, sizeof(*slocal)); + if (ai == NULL) + return (EAI_MEMORY); + + slocal = SLOCAL(ai->ai_addr); + strncpy(slocal->sun_path, name, sizeof(slocal->sun_path)); + + ai->ai_socktype = socktype; + /* + * ai->ai_flags, ai->ai_protocol, ai->ai_canonname, + * and ai->ai_next were initialized to zero. + */ + + *res = ai; + return (0); +} +#endif + +/*! + * Allocate an addrinfo structure, and a sockaddr structure + * of the specificed length. We initialize: + * ai_addrlen + * ai_family + * ai_addr + * ai_addr->sa_family + * ai_addr->sa_len (IRS_PLATFORM_HAVESALEN) + * and everything else is initialized to zero. + */ +static struct addrinfo * +ai_alloc(int family, int addrlen) { + struct addrinfo *ai; + + ai = (struct addrinfo *)calloc(1, sizeof(*ai)); + if (ai == NULL) + return (NULL); + + ai->ai_addr = SA(calloc(1, addrlen)); + if (ai->ai_addr == NULL) { + free(ai); + return (NULL); + } + ai->ai_addrlen = addrlen; + ai->ai_family = family; + ai->ai_addr->sa_family = family; +#ifdef IRS_PLATFORM_HAVESALEN + ai->ai_addr->sa_len = addrlen; +#endif + return (ai); +} + +static struct addrinfo * +ai_clone(struct addrinfo *oai, int family) { + struct addrinfo *ai; + + ai = ai_alloc(family, ((family == AF_INET6) ? + sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))); + + if (ai == NULL) { + if (oai != NULL) + freeaddrinfo(oai); + return (NULL); + } + if (oai == NULL) + return (ai); + + ai->ai_flags = oai->ai_flags; + ai->ai_socktype = oai->ai_socktype; + ai->ai_protocol = oai->ai_protocol; + ai->ai_canonname = NULL; + ai->ai_next = oai; + return (ai); +} + +static struct addrinfo * +ai_reverse(struct addrinfo *oai) { + struct addrinfo *nai, *tai; + + nai = NULL; + + while (oai != NULL) { + /* + * Grab one off the old list. + */ + tai = oai; + oai = oai->ai_next; + /* + * Put it on the front of the new list. + */ + tai->ai_next = nai; + nai = tai; + } + return (nai); +} + + +static struct addrinfo * +ai_concat(struct addrinfo *ai1, struct addrinfo *ai2) { + struct addrinfo *ai_tmp; + + if (ai1 == NULL) + return (ai2); + else if (ai2 == NULL) + return (ai1); + + for (ai_tmp = ai1; ai_tmp != NULL && ai_tmp->ai_next != NULL; + ai_tmp = ai_tmp->ai_next) + ; + + ai_tmp->ai_next = ai2; + + return (ai1); +} diff --git a/lib/irs/getnameinfo.c b/lib/irs/getnameinfo.c new file mode 100644 index 0000000..fadd8d8 --- /dev/null +++ b/lib/irs/getnameinfo.c @@ -0,0 +1,410 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: getnameinfo.c,v 1.4 2009-09-02 23:48:02 tbox Exp $ */ + +/*! \file */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * getnameinfo() returns the hostname for the struct sockaddr sa which is + * salen bytes long. The hostname is of length hostlen and is returned via + * *host. The maximum length of the hostname is 1025 bytes: #NI_MAXHOST. + * + * The name of the service associated with the port number in sa is + * returned in *serv. It is servlen bytes long. The maximum length of the + * service name is #NI_MAXSERV - 32 bytes. + * + * The flags argument sets the following bits: + * + * \li #NI_NOFQDN: + * A fully qualified domain name is not required for local hosts. + * The local part of the fully qualified domain name is returned + * instead. + * + * \li #NI_NUMERICHOST + * Return the address in numeric form, as if calling inet_ntop(), + * instead of a host name. + * + * \li #NI_NAMEREQD + * A name is required. If the hostname cannot be found in the DNS + * and this flag is set, a non-zero error code is returned. If the + * hostname is not found and the flag is not set, the address is + * returned in numeric form. + * + * \li #NI_NUMERICSERV + * The service name is returned as a digit string representing the + * port number. + * + * \li #NI_DGRAM + * Specifies that the service being looked up is a datagram + * service, and causes getservbyport() to be called with a second + * argument of "udp" instead of its default of "tcp". This is + * required for the few ports (512-514) that have different + * services for UDP and TCP. + * + * \section getnameinfo_return Return Values + * + * getnameinfo() returns 0 on success or a non-zero error code if + * an error occurs. + * + * \section getname_see See Also + * + * RFC3493, getservbyport(), + * getnamebyaddr(). inet_ntop(). + */ + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define SUCCESS 0 + +/*% afd structure definition */ +static struct afd { + int a_af; + size_t a_addrlen; + size_t a_socklen; +} afdl [] = { + /*! + * First entry is linked last... + */ + { AF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in) }, + { AF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6) }, + {0, 0, 0}, +}; + +/*! + * The test against 0 is there to keep the Solaris compiler + * from complaining about "end-of-loop code not reached". + */ +#define ERR(code) \ + do { result = (code); \ + if (result != 0) goto cleanup; \ + } while (0) + +int +getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, + IRS_GETNAMEINFO_BUFLEN_T hostlen, char *serv, + IRS_GETNAMEINFO_BUFLEN_T servlen, IRS_GETNAMEINFO_FLAGS_T flags) +{ + struct afd *afd; + struct servent *sp; + unsigned short port; +#ifdef IRS_PLATFORM_HAVESALEN + size_t len; +#endif + int family, i; + const void *addr; + char *p; +#if 0 + unsigned long v4a; + unsigned char pfx; +#endif + char numserv[sizeof("65000")]; + char numaddr[sizeof("abcd:abcd:abcd:abcd:abcd:abcd:255.255.255.255") + + 1 + sizeof("4294967295")]; + const char *proto; + int result = SUCCESS; + + if (sa == NULL) + ERR(EAI_FAIL); + +#ifdef IRS_PLATFORM_HAVESALEN + len = sa->sa_len; + if (len != salen) + ERR(EAI_FAIL); +#endif + + family = sa->sa_family; + for (i = 0; afdl[i].a_af; i++) + if (afdl[i].a_af == family) { + afd = &afdl[i]; + goto found; + } + ERR(EAI_FAMILY); + + found: + if (salen != afd->a_socklen) + ERR(EAI_FAIL); + + switch (family) { + case AF_INET: + port = ((const struct sockaddr_in *)sa)->sin_port; + addr = &((const struct sockaddr_in *)sa)->sin_addr.s_addr; + break; + + case AF_INET6: + port = ((const struct sockaddr_in6 *)sa)->sin6_port; + addr = ((const struct sockaddr_in6 *)sa)->sin6_addr.s6_addr; + break; + + default: + port = 0; + addr = NULL; + INSIST(0); + } + proto = (flags & NI_DGRAM) ? "udp" : "tcp"; + + if (serv == NULL || servlen == 0U) { + /* + * Caller does not want service. + */ + } else if ((flags & NI_NUMERICSERV) != 0 || + (sp = getservbyport(port, proto)) == NULL) { + snprintf(numserv, sizeof(numserv), "%d", ntohs(port)); + if ((strlen(numserv) + 1) > servlen) + ERR(EAI_OVERFLOW); + strcpy(serv, numserv); + } else { + if ((strlen(sp->s_name) + 1) > servlen) + ERR(EAI_OVERFLOW); + strcpy(serv, sp->s_name); + } + +#if 0 + switch (sa->sa_family) { + case AF_INET: + v4a = ((struct sockaddr_in *)sa)->sin_addr.s_addr; + if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a)) + flags |= NI_NUMERICHOST; + v4a >>= IN_CLASSA_NSHIFT; + if (v4a == 0 || v4a == IN_LOOPBACKNET) + flags |= NI_NUMERICHOST; + break; + + case AF_INET6: + pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[0]; + if (pfx == 0 || pfx == 0xfe || pfx == 0xff) + flags |= NI_NUMERICHOST; + break; + } +#endif + + if (host == NULL || hostlen == 0U) { + /* + * do nothing in this case. + * in case you are wondering if "&&" is more correct than + * "||" here: RFC3493 says that host == NULL or hostlen == 0 + * means that the caller does not want the result. + */ + } else if ((flags & NI_NUMERICHOST) != 0) { + if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) + == NULL) + ERR(EAI_SYSTEM); +#if defined(IRS_HAVE_SIN6_SCOPE_ID) + if (afd->a_af == AF_INET6 && + ((const struct sockaddr_in6 *)sa)->sin6_scope_id) { + char *p = numaddr + strlen(numaddr); + const char *stringscope = NULL; +#ifdef VENDOR_SPECIFIC + /* + * Vendors may want to add support for + * non-numeric scope identifier. + */ + stringscope = foo; +#endif + if (stringscope == NULL) { + snprintf(p, sizeof(numaddr) - (p - numaddr), + "%%%u", + ((const struct sockaddr_in6 *)sa)->sin6_scope_id); + } else { + snprintf(p, sizeof(numaddr) - (p - numaddr), + "%%%s", stringscope); + } + } +#endif + if (strlen(numaddr) + 1 > hostlen) + ERR(EAI_OVERFLOW); + strcpy(host, numaddr); + } else { + isc_netaddr_t netaddr; + dns_fixedname_t ptrfname; + dns_name_t *ptrname; + irs_context_t *irsctx = NULL; + dns_client_t *client; + isc_boolean_t found = ISC_FALSE; + dns_namelist_t answerlist; + dns_rdataset_t *rdataset; + isc_region_t hostregion; + char hoststr[1024]; /* is this enough? */ + isc_result_t iresult; + + /* Get IRS context and the associated DNS client object */ + iresult = irs_context_get(&irsctx); + if (iresult != ISC_R_SUCCESS) + ERR(EAI_FAIL); + client = irs_context_getdnsclient(irsctx); + + /* Make query name */ + isc_netaddr_fromsockaddr(&netaddr, (const isc_sockaddr_t *)sa); + dns_fixedname_init(&ptrfname); + ptrname = dns_fixedname_name(&ptrfname); + iresult = dns_byaddr_createptrname2(&netaddr, 0, ptrname); + if (iresult != ISC_R_SUCCESS) + ERR(EAI_FAIL); + + /* Get the PTR RRset */ + ISC_LIST_INIT(answerlist); + iresult = dns_client_resolve(client, ptrname, + dns_rdataclass_in, + dns_rdatatype_ptr, + DNS_CLIENTRESOPT_ALLOWRUN, + &answerlist); + switch (iresult) { + case ISC_R_SUCCESS: + /* + * a 'non-existent' error is not necessarily fatal for + * getnameinfo(). + */ + case DNS_R_NCACHENXDOMAIN: + case DNS_R_NCACHENXRRSET: + break; + case DNS_R_SIGINVALID: + case DNS_R_SIGEXPIRED: + case DNS_R_SIGFUTURE: + case DNS_R_KEYUNAUTHORIZED: + case DNS_R_MUSTBESECURE: + case DNS_R_COVERINGNSEC: + case DNS_R_NOTAUTHORITATIVE: + case DNS_R_NOVALIDKEY: + case DNS_R_NOVALIDDS: + case DNS_R_NOVALIDSIG: + ERR(EAI_INSECUREDATA); + default: + ERR(EAI_FAIL); + } + + /* Parse the answer for the hostname */ + for (ptrname = ISC_LIST_HEAD(answerlist); ptrname != NULL; + ptrname = ISC_LIST_NEXT(ptrname, link)) { + for (rdataset = ISC_LIST_HEAD(ptrname->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + if (!dns_rdataset_isassociated(rdataset)) + continue; + if (rdataset->type != dns_rdatatype_ptr) + continue; + + for (iresult = dns_rdataset_first(rdataset); + iresult == ISC_R_SUCCESS; + iresult = dns_rdataset_next(rdataset)) { + dns_rdata_t rdata; + dns_rdata_ptr_t rdata_ptr; + isc_buffer_t b; + + dns_rdata_init(&rdata); + dns_rdataset_current(rdataset, &rdata); + dns_rdata_tostruct(&rdata, &rdata_ptr, + NULL); + + isc_buffer_init(&b, hoststr, + sizeof(hoststr)); + iresult = + dns_name_totext(&rdata_ptr.ptr, + ISC_TRUE, &b); + dns_rdata_freestruct(&rdata_ptr); + if (iresult == ISC_R_SUCCESS) { + /* + * We ignore the rest of the + * answer. After all, + * getnameinfo() can return + * at most one hostname. + */ + found = ISC_TRUE; + isc_buffer_usedregion( + &b, &hostregion); + goto ptrfound; + } + + } + } + } + ptrfound: + dns_client_freeresanswer(client, &answerlist); + if (found) { + if ((flags & NI_NOFQDN) != 0) { + p = strchr(hoststr, '.'); + if (p) + *p = '\0'; + } + if (hostregion.length + 1 > hostlen) + ERR(EAI_OVERFLOW); + snprintf(host, hostlen, "%.*s", + (int)hostregion.length, + (char *)hostregion.base); + } else { + if ((flags & NI_NAMEREQD) != 0) + ERR(EAI_NONAME); + if (inet_ntop(afd->a_af, addr, numaddr, + sizeof(numaddr)) == NULL) + ERR(EAI_SYSTEM); + if ((strlen(numaddr) + 1) > hostlen) + ERR(EAI_OVERFLOW); + strcpy(host, numaddr); + } + } + result = SUCCESS; + + cleanup: + return (result); +} diff --git a/lib/irs/include/Makefile.in b/lib/irs/include/Makefile.in new file mode 100644 index 0000000..22a63ee --- /dev/null +++ b/lib/irs/include/Makefile.in @@ -0,0 +1,24 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $ + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +SUBDIRS = irs +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/irs/include/irs/Makefile.in b/lib/irs/include/irs/Makefile.in new file mode 100644 index 0000000..7d50995 --- /dev/null +++ b/lib/irs/include/irs/Makefile.in @@ -0,0 +1,44 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# 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 ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC 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. + +# $Id: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $ + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +# +# Only list headers that are to be installed and are not +# machine generated. The latter are handled specially in the +# install target below. +# +HEADERS = version.h + +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/irs + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} ${srcdir}/$$i ${DESTDIR}${includedir}/irs ; \ + done + ${INSTALL_DATA} netdb.h ${DESTDIR}${includedir}/irs + ${INSTALL_DATA} platform.h ${DESTDIR}${includedir}/irs + +distclean:: + rm -f netdb.h platform.h diff --git a/lib/irs/include/irs/context.h b/lib/irs/include/irs/context.h new file mode 100644 index 0000000..c49cfcf --- /dev/null +++ b/lib/irs/include/irs/context.h @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: context.h,v 1.3 2009-09-02 23:48:02 tbox Exp $ */ + +#ifndef IRS_CONTEXT_H +#define IRS_CONTEXT_H 1 + +/*! \file + * + * \brief + * The IRS context module provides an abstract interface to the DNS library + * with an application. An IRS context object initializes and holds various + * resources used in the DNS library. + */ + +#include +#include + +ISC_LANG_BEGINDECLS + +isc_result_t +irs_context_create(irs_context_t **contextp); +/*%< + * Create an IRS context. It internally initializes the ISC and DNS libraries + * (if not yet), creates a DNS client object and initializes the client using + * the configuration files parsed via the 'resconf' and 'dnsconf' IRS modules. + * Some of the internally initialized objects can be used by the application + * via irs_context_getxxx() functions (see below). + * + * Requires: + * + *\li contextp != NULL && *contextp == NULL. + */ + +isc_result_t +irs_context_get(irs_context_t **contextp); +/*%< + * Return an IRS context for the calling thread. If no IRS context is + * associated to the thread, this function creates a new one by calling + * irs_context_create(), and associates it with the thread as a thread specific + * data value. This function is provided for standard libraries that are + * expected to be thread-safe but do not accept an appropriate IRS context + * as a library parameter, e.g., getaddrinfo(). + * + * Requires: + * + *\li contextp != NULL && *contextp == NULL. + */ + +void +irs_context_destroy(irs_context_t **contextp); +/*%< + * Destroy an IRS context. + * + * Requires: + * + *\li '*contextp' is a valid IRS context. + * + * Ensures: + *\li '*contextp' == NULL. + */ + +isc_mem_t * +irs_context_getmctx(irs_context_t *context); +/*%< + * Return the memory context held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +isc_appctx_t * +irs_context_getappctx(irs_context_t *context); +/*%< + * Return the application context held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +isc_taskmgr_t * +irs_context_gettaskmgr(irs_context_t *context); +/*%< + * Return the task manager held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +isc_timermgr_t * +irs_context_gettimermgr(irs_context_t *context); +/*%< + * Return the timer manager held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +isc_task_t * +irs_context_gettask(irs_context_t *context); +/*%< + * Return the task object held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +dns_client_t * +irs_context_getdnsclient(irs_context_t *context); +/*%< + * Return the DNS client object held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +irs_resconf_t * +irs_context_getresconf(irs_context_t *context); +/*%< + * Return the resolver configuration object held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +irs_dnsconf_t * +irs_context_getdnsconf(irs_context_t *context); +/*%< + * Return the advanced DNS configuration object held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +ISC_LANG_ENDDECLS + +#endif /* IRS_CONTEXT_H */ diff --git a/lib/irs/include/irs/dnsconf.h b/lib/irs/include/irs/dnsconf.h new file mode 100644 index 0000000..0041c16 --- /dev/null +++ b/lib/irs/include/irs/dnsconf.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: dnsconf.h,v 1.3 2009-09-02 23:48:02 tbox Exp $ */ + +#ifndef IRS_DNSCONF_H +#define IRS_DNSCONF_H 1 + +/*! \file + * + * \brief + * The IRS dnsconf module parses an "advanced" configuration file related to + * the DNS library, such as trusted keys for DNSSEC validation, and creates + * the corresponding configuration objects for the DNS library modules. + * + * Notes: + * This module is very experimental and the configuration syntax or library + * interfaces may change in future versions. Currently, only the + * 'trusted-keys' statement is supported, whose syntax is the same as the + * same name of statement for named.conf. + */ + +#include + +/*% + * A compound structure storing DNS key information mainly for DNSSEC + * validation. A dns_key_t object will be created using the 'keyname' and + * 'keydatabuf' members with the dst_key_fromdns() function. + */ +typedef struct irs_dnsconf_dnskey { + dns_name_t *keyname; + isc_buffer_t *keydatabuf; + ISC_LINK(struct irs_dnsconf_dnskey) link; +} irs_dnsconf_dnskey_t; + +typedef ISC_LIST(irs_dnsconf_dnskey_t) irs_dnsconf_dnskeylist_t; + +ISC_LANG_BEGINDECLS + +isc_result_t +irs_dnsconf_load(isc_mem_t *mctx, const char *filename, irs_dnsconf_t **confp); +/*%< + * Load the "advanced" DNS configuration file 'filename' in the "dns.conf" + * format, and create a new irs_dnsconf_t object from the configuration. + * + * Requires: + * + *\li 'mctx' is a valid memory context. + * + *\li 'filename' != NULL + * + *\li 'confp' != NULL && '*confp' == NULL + */ + +void +irs_dnsconf_destroy(irs_dnsconf_t **confp); +/*%< + * Destroy the dnsconf object. + * + * Requires: + * + *\li '*confp' is a valid dnsconf object. + * + * Ensures: + * + *\li *confp == NULL + */ + +irs_dnsconf_dnskeylist_t * +irs_dnsconf_gettrustedkeys(irs_dnsconf_t *conf); +/*%< + * Return a list of key information stored in 'conf'. + * + * Requires: + * + *\li 'conf' is a valid dnsconf object. + */ + +ISC_LANG_ENDDECLS + +#endif /* IRS_DNSCONF_H */ diff --git a/lib/irs/include/irs/netdb.h.in b/lib/irs/include/irs/netdb.h.in new file mode 100644 index 0000000..9dda413 --- /dev/null +++ b/lib/irs/include/irs/netdb.h.in @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: netdb.h.in,v 1.3 2009-09-02 23:48:02 tbox Exp $ */ + +/*! \file */ + +#ifndef IRS_NETDB_H +#define IRS_NETDB_H 1 + +#include /* Required on FreeBSD (and others?) for size_t. */ +#include /* Contractual provision. */ + +/* + * Define if does not declare struct addrinfo. + */ +@ISC_IRS_NEEDADDRINFO@ + +#ifdef ISC_IRS_NEEDADDRINFO +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 + +/* + * Undefine all #defines we are interested in as may or may not have + * defined them. + */ + +/* + * Error return codes from gethostbyname() and gethostbyaddr() + * (left in extern int h_errno). + */ + +#undef NETDB_INTERNAL +#undef NETDB_SUCCESS +#undef HOST_NOT_FOUND +#undef TRY_AGAIN +#undef NO_RECOVERY +#undef NO_DATA +#undef NO_ADDRESS + +#define NETDB_INTERNAL -1 /* see errno */ +#define NETDB_SUCCESS 0 /* no problem */ +#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */ +#define TRY_AGAIN 2 /* Non-Authoritive Host not found, or SERVERFAIL */ +#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ +#define NO_DATA 4 /* Valid name, no data record of requested type */ +#define NO_ADDRESS NO_DATA /* no address, look for MX record */ + +/* + * Error return codes from getaddrinfo(). EAI_INSECUREDATA is our own extension + * and it's very unlikely to be already defined, but undef it just in case; it + * at least doesn't do any harm. + */ + +#undef EAI_ADDRFAMILY +#undef EAI_AGAIN +#undef EAI_BADFLAGS +#undef EAI_FAIL +#undef EAI_FAMILY +#undef EAI_MEMORY +#undef EAI_NODATA +#undef EAI_NONAME +#undef EAI_SERVICE +#undef EAI_SOCKTYPE +#undef EAI_SYSTEM +#undef EAI_BADHINTS +#undef EAI_PROTOCOL +#undef EAI_OVERFLOW +#undef EAI_INSECUREDATA +#undef EAI_MAX + +#define EAI_ADDRFAMILY 1 /* address family for hostname not supported */ +#define EAI_AGAIN 2 /* temporary failure in name resolution */ +#define EAI_BADFLAGS 3 /* invalid value for ai_flags */ +#define EAI_FAIL 4 /* non-recoverable failure in name resolution */ +#define EAI_FAMILY 5 /* ai_family not supported */ +#define EAI_MEMORY 6 /* memory allocation failure */ +#define EAI_NODATA 7 /* no address associated with hostname */ +#define EAI_NONAME 8 /* hostname nor servname provided, or not known */ +#define EAI_SERVICE 9 /* servname not supported for ai_socktype */ +#define EAI_SOCKTYPE 10 /* ai_socktype not supported */ +#define EAI_SYSTEM 11 /* system error returned in errno */ +#define EAI_BADHINTS 12 +#define EAI_PROTOCOL 13 +#define EAI_OVERFLOW 14 +#define EAI_INSECUREDATA 15 +#define EAI_MAX 16 + +/* + * Flag values for getaddrinfo() + */ +#undef AI_PASSIVE +#undef AI_CANONNAME +#undef AI_NUMERICHOST + +#define AI_PASSIVE 0x00000001 +#define AI_CANONNAME 0x00000002 +#define AI_NUMERICHOST 0x00000004 + +/* + * Flag values for getipnodebyname() + */ +#undef AI_V4MAPPED +#undef AI_ALL +#undef AI_ADDRCONFIG +#undef AI_DEFAULT + +#define AI_V4MAPPED 0x00000008 +#define AI_ALL 0x00000010 +#define AI_ADDRCONFIG 0x00000020 +#define AI_DEFAULT (AI_V4MAPPED|AI_ADDRCONFIG) + +/* + * Constants for lwres_getnameinfo() + */ +#undef NI_MAXHOST +#undef NI_MAXSERV + +#define NI_MAXHOST 1025 +#define NI_MAXSERV 32 + +/* + * Flag values for lwres_getnameinfo() + */ +#undef NI_NOFQDN +#undef NI_NUMERICHOST +#undef NI_NAMEREQD +#undef NI_NUMERICSERV +#undef NI_DGRAM +#undef NI_NUMERICSCOPE + +#define NI_NOFQDN 0x00000001 +#define NI_NUMERICHOST 0x00000002 +#define NI_NAMEREQD 0x00000004 +#define NI_NUMERICSERV 0x00000008 +#define NI_DGRAM 0x00000010 + +/* + * Tell Emacs to use C mode on this file. + * Local variables: + * mode: c + * End: + */ + +#endif /* IRS_NETDB_H */ diff --git a/lib/irs/include/irs/platform.h.in b/lib/irs/include/irs/platform.h.in new file mode 100644 index 0000000..f61f671 --- /dev/null +++ b/lib/irs/include/irs/platform.h.in @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: platform.h.in,v 1.3 2009-09-02 23:48:02 tbox Exp $ */ + +/*! \file */ + +#ifndef IRS_PLATFORM_H +#define IRS_PLATFORM_H 1 + +/***** + ***** Platform-dependent defines. + *****/ + +#ifndef IRS_PLATFORM_USEDECLSPEC +#define LIBIRS_EXTERNAL_DATA +#else +#ifdef LIBIRS_EXPORTS +#define LIBIRS_EXTERNAL_DATA __declspec(dllexport) +#else +#define LIBIRS_EXTERNAL_DATA __declspec(dllimport) +#endif +#endif + +/* + * Tell Emacs to use C mode on this file. + * Local Variables: + * mode: c + * End: + */ + +#endif /* IRS_PLATFORM_H */ diff --git a/lib/irs/include/irs/resconf.h b/lib/irs/include/irs/resconf.h new file mode 100644 index 0000000..8249c7b --- /dev/null +++ b/lib/irs/include/irs/resconf.h @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: resconf.h,v 1.3 2009-09-02 23:48:02 tbox Exp $ */ + +#ifndef IRS_RESCONF_H +#define IRS_RESCONF_H 1 + +/*! \file + * + * \brief + * The IRS resconf module parses the legacy "/etc/resolv.conf" file and + * creates the corresponding configuration objects for the DNS library + * modules. + */ + +#include + +/*% + * A DNS search list specified in the 'domain' or 'search' statements + * in the "resolv.conf" file. + */ +typedef struct irs_resconf_search { + char *domain; + ISC_LINK(struct irs_resconf_search) link; +} irs_resconf_search_t; + +typedef ISC_LIST(irs_resconf_search_t) irs_resconf_searchlist_t; + +ISC_LANG_BEGINDECLS + +isc_result_t +irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp); +/*%< + * Load the resolver configuration file 'filename' in the "resolv.conf" format, + * and create a new irs_resconf_t object from the configuration. + * + * Notes: + * + *\li Currently, only the following options are supported: + * nameserver, domain, search, sortlist, ndots, and options. + * In addition, 'sortlist' is not actually effective; it's parsed, but + * the application cannot use the configuration. + * + * Requires: + * + *\li 'mctx' is a valid memory context. + * + *\li 'filename' != NULL + * + *\li 'confp' != NULL && '*confp' == NULL + */ + +void +irs_resconf_destroy(irs_resconf_t **confp); +/*%< + * Destroy the resconf object. + * + * Requires: + * + *\li '*confp' is a valid resconf object. + * + * Ensures: + * + *\li *confp == NULL + */ + +isc_sockaddrlist_t * +irs_resconf_getnameservers(irs_resconf_t *conf); +/*%< + * Return a list of name server addresses stored in 'conf'. + * + * Requires: + * + *\li 'conf' is a valid resconf object. + */ + +irs_resconf_searchlist_t * +irs_resconf_getsearchlist(irs_resconf_t *conf); +/*%< + * Return the search list stored in 'conf'. + * + * Requires: + * + *\li 'conf' is a valid resconf object. + */ + +unsigned int +irs_resconf_getndots(irs_resconf_t *conf); +/*%< + * Return the 'ndots' value stored in 'conf'. + * + * Requires: + * + *\li 'conf' is a valid resconf object. + */ + +ISC_LANG_ENDDECLS + +#endif /* IRS_RESCONF_H */ diff --git a/lib/irs/include/irs/types.h b/lib/irs/include/irs/types.h new file mode 100644 index 0000000..4b8a804 --- /dev/null +++ b/lib/irs/include/irs/types.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: types.h,v 1.3 2009-09-02 23:48:02 tbox Exp $ */ + +#ifndef IRS_TYPES_H +#define IRS_TYPES_H 1 + +/* Core Types. Alphabetized by defined type. */ + +/*%< per-thread IRS context */ +typedef struct irs_context irs_context_t; +/*%< resolv.conf configuration information */ +typedef struct irs_resconf irs_resconf_t; +/*%< advanced DNS-related configuration information */ +typedef struct irs_dnsconf irs_dnsconf_t; + +#endif /* IRS_TYPES_H */ diff --git a/lib/irs/include/irs/version.h b/lib/irs/include/irs/version.h new file mode 100644 index 0000000..f43aa14 --- /dev/null +++ b/lib/irs/include/irs/version.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: version.h,v 1.3 2009-09-02 23:48:02 tbox Exp $ */ + +/*! \file */ + +#include + +LIBIRS_EXTERNAL_DATA extern const char irs_version[]; + +LIBIRS_EXTERNAL_DATA extern const unsigned int irs_libinterface; +LIBIRS_EXTERNAL_DATA extern const unsigned int irs_librevision; +LIBIRS_EXTERNAL_DATA extern const unsigned int irs_libage; diff --git a/lib/irs/resconf.c b/lib/irs/resconf.c new file mode 100644 index 0000000..af1413b --- /dev/null +++ b/lib/irs/resconf.c @@ -0,0 +1,636 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: resconf.c,v 1.3 2009-09-02 23:48:02 tbox Exp $ */ + +/*! \file resconf.c */ + +/** + * Module for parsing resolv.conf files (largely derived from lwconfig.c). + * + * irs_resconf_load() opens the file filename and parses it to initialize + * the configuration structure. + * + * \section lwconfig_return Return Values + * + * irs_resconf_load() returns #IRS_R_SUCCESS if it successfully read and + * parsed filename. It returns a non-0 error code if filename could not be + * opened or contained incorrect resolver statements. + * + * \section lwconfig_see See Also + * + * stdio(3), \link resolver resolver \endlink + * + * \section files Files + * + * /etc/resolv.conf + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#define IRS_RESCONF_MAGIC ISC_MAGIC('R', 'E', 'S', 'c') +#define IRS_RESCONF_VALID(c) ISC_MAGIC_VALID(c, IRS_RESCONF_MAGIC) + +/*! + * protocol constants + */ + +#if ! defined(NS_INADDRSZ) +#define NS_INADDRSZ 4 +#endif + +#if ! defined(NS_IN6ADDRSZ) +#define NS_IN6ADDRSZ 16 +#endif + +/*! + * resolv.conf parameters + */ + +#define RESCONFMAXNAMESERVERS 3 /*%< max 3 "nameserver" entries */ +#define RESCONFMAXSEARCH 8 /*%< max 8 domains in "search" entry */ +#define RESCONFMAXLINELEN 256 /*%< max size of a line */ +#define RESCONFMAXSORTLIST 10 /*%< max 10 */ + +/*! + * configuration data structure + */ + +struct irs_resconf { + /* + * The configuration data is a thread-specific object, and does not + * need to be locked. + */ + unsigned int magic; + isc_mem_t *mctx; + + isc_sockaddrlist_t nameservers; + unsigned int numns; /*%< number of configured servers */ + + char *domainname; + char *search[RESCONFMAXSEARCH]; + isc_uint8_t searchnxt; /*%< index for next free slot */ + + irs_resconf_searchlist_t searchlist; + + struct { + isc_netaddr_t addr; + /*% mask has a non-zero 'family' if set */ + isc_netaddr_t mask; + } sortlist[RESCONFMAXSORTLIST]; + isc_uint8_t sortlistnxt; + + /*%< non-zero if 'options debug' set */ + isc_uint8_t resdebug; + /*%< set to n in 'options ndots:n' */ + isc_uint8_t ndots; +}; + +static isc_result_t +resconf_parsenameserver(irs_resconf_t *conf, FILE *fp); +static isc_result_t +resconf_parsedomain(irs_resconf_t *conf, FILE *fp); +static isc_result_t +resconf_parsesearch(irs_resconf_t *conf, FILE *fp); +static isc_result_t +resconf_parsesortlist(irs_resconf_t *conf, FILE *fp); +static isc_result_t +resconf_parseoption(irs_resconf_t *ctx, FILE *fp); + +/*! + * Eat characters from FP until EOL or EOF. Returns EOF or '\n' + */ +static int +eatline(FILE *fp) { + int ch; + + ch = fgetc(fp); + while (ch != '\n' && ch != EOF) + ch = fgetc(fp); + + return (ch); +} + +/*! + * Eats white space up to next newline or non-whitespace character (of + * EOF). Returns the last character read. Comments are considered white + * space. + */ +static int +eatwhite(FILE *fp) { + int ch; + + ch = fgetc(fp); + while (ch != '\n' && ch != EOF && isspace((unsigned char)ch)) + ch = fgetc(fp); + + if (ch == ';' || ch == '#') + ch = eatline(fp); + + return (ch); +} + +/*! + * Skip over any leading whitespace and then read in the next sequence of + * non-whitespace characters. In this context newline is not considered + * whitespace. Returns EOF on end-of-file, or the character + * that caused the reading to stop. + */ +static int +getword(FILE *fp, char *buffer, size_t size) { + int ch; + char *p = buffer; + + REQUIRE(buffer != NULL); + REQUIRE(size > 0U); + + *p = '\0'; + + ch = eatwhite(fp); + + if (ch == EOF) + return (EOF); + + do { + *p = '\0'; + + if (ch == EOF || isspace((unsigned char)ch)) + break; + else if ((size_t) (p - buffer) == size - 1) + return (EOF); /* Not enough space. */ + + *p++ = (char)ch; + ch = fgetc(fp); + } while (1); + + return (ch); +} + +static isc_result_t +add_server(isc_mem_t *mctx, const char *address_str, + isc_sockaddrlist_t *nameservers) +{ + int error; + isc_sockaddr_t *address = NULL; + struct addrinfo hints, *res; + isc_result_t result = ISC_R_SUCCESS; + + res = NULL; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_flags = AI_NUMERICHOST; + error = getaddrinfo(address_str, "53", &hints, &res); + if (error != 0) + return (ISC_R_BADADDRESSFORM); + + /* XXX: special case: treat all-0 IPv4 address as loopback */ + if (res->ai_family == AF_INET) { + struct in_addr *v4; + unsigned char zeroaddress[] = {0, 0, 0, 0}; + unsigned char loopaddress[] = {127, 0, 0, 1}; + + v4 = &((struct sockaddr_in *)res->ai_addr)->sin_addr; + if (memcmp(v4, zeroaddress, 4) == 0) + memcpy(v4, loopaddress, 4); + } + + address = isc_mem_get(mctx, sizeof(*address)); + if (address == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + if (res->ai_addrlen > sizeof(address->type)) { + isc_mem_put(mctx, address, sizeof(*address)); + result = ISC_R_RANGE; + goto cleanup; + } + address->length = res->ai_addrlen; + memcpy(&address->type.sa, res->ai_addr, res->ai_addrlen); + ISC_LINK_INIT(address, link); + ISC_LIST_APPEND(*nameservers, address, link); + + cleanup: + freeaddrinfo(res); + + return (result); +} + +static isc_result_t +create_addr(const char *buffer, isc_netaddr_t *addr, int convert_zero) { + struct in_addr v4; + struct in6_addr v6; + + if (inet_aton(buffer, &v4) == 1) { + if (convert_zero) { + unsigned char zeroaddress[] = {0, 0, 0, 0}; + unsigned char loopaddress[] = {127, 0, 0, 1}; + if (memcmp(&v4, zeroaddress, 4) == 0) + memcpy(&v4, loopaddress, 4); + } + addr->family = AF_INET; + memcpy(&addr->type.in, &v4, NS_INADDRSZ); + addr->zone = 0; + } else if (inet_pton(AF_INET6, buffer, &v6) == 1) { + addr->family = AF_INET6; + memcpy(&addr->type.in6, &v6, NS_IN6ADDRSZ); + addr->zone = 0; + } else + return (ISC_R_BADADDRESSFORM); /* Unrecognised format. */ + + return (ISC_R_SUCCESS); +} + +static isc_result_t +resconf_parsenameserver(irs_resconf_t *conf, FILE *fp) { + char word[RESCONFMAXLINELEN]; + int cp; + isc_result_t result; + + if (conf->numns == RESCONFMAXNAMESERVERS) + return (ISC_R_SUCCESS); + + cp = getword(fp, word, sizeof(word)); + if (strlen(word) == 0U) + return (ISC_R_UNEXPECTEDEND); /* Nothing on line. */ + else if (cp == ' ' || cp == '\t') + cp = eatwhite(fp); + + if (cp != EOF && cp != '\n') + return (ISC_R_UNEXPECTEDTOKEN); /* Extra junk on line. */ + + result = add_server(conf->mctx, word, &conf->nameservers); + if (result != ISC_R_SUCCESS) + return (result); + conf->numns++; + + return (ISC_R_SUCCESS); +} + +static isc_result_t +resconf_parsedomain(irs_resconf_t *conf, FILE *fp) { + char word[RESCONFMAXLINELEN]; + int res, i; + + res = getword(fp, word, sizeof(word)); + if (strlen(word) == 0U) + return (ISC_R_UNEXPECTEDEND); /* Nothing else on line. */ + else if (res == ' ' || res == '\t') + res = eatwhite(fp); + + if (res != EOF && res != '\n') + return (ISC_R_UNEXPECTEDTOKEN); /* Extra junk on line. */ + + if (conf->domainname != NULL) + isc_mem_free(conf->mctx, conf->domainname); + + /* + * Search and domain are mutually exclusive. + */ + for (i = 0; i < RESCONFMAXSEARCH; i++) { + if (conf->search[i] != NULL) { + isc_mem_free(conf->mctx, conf->search[i]); + conf->search[i] = NULL; + } + } + conf->searchnxt = 0; + + conf->domainname = isc_mem_strdup(conf->mctx, word); + if (conf->domainname == NULL) + return (ISC_R_NOMEMORY); + + return (ISC_R_SUCCESS); +} + +static isc_result_t +resconf_parsesearch(irs_resconf_t *conf, FILE *fp) { + int idx, delim; + char word[RESCONFMAXLINELEN]; + + if (conf->domainname != NULL) { + /* + * Search and domain are mutually exclusive. + */ + isc_mem_free(conf->mctx, conf->domainname); + conf->domainname = NULL; + } + + /* + * Remove any previous search definitions. + */ + for (idx = 0; idx < RESCONFMAXSEARCH; idx++) { + if (conf->search[idx] != NULL) { + isc_mem_free(conf->mctx, conf->search[idx]); + conf->search[idx] = NULL; + } + } + conf->searchnxt = 0; + + delim = getword(fp, word, sizeof(word)); + if (strlen(word) == 0U) + return (ISC_R_UNEXPECTEDEND); /* Nothing else on line. */ + + idx = 0; + while (strlen(word) > 0U) { + if (conf->searchnxt == RESCONFMAXSEARCH) + goto ignore; /* Too many domains. */ + + conf->search[idx] = isc_mem_strdup(conf->mctx, word); + if (conf->search[idx] == NULL) + return (ISC_R_NOMEMORY); + idx++; + conf->searchnxt++; + + ignore: + if (delim == EOF || delim == '\n') + break; + else + delim = getword(fp, word, sizeof(word)); + } + + return (ISC_R_SUCCESS); +} + +static isc_result_t +resconf_parsesortlist(irs_resconf_t *conf, FILE *fp) { + int delim, res, idx; + char word[RESCONFMAXLINELEN]; + char *p; + + delim = getword(fp, word, sizeof(word)); + if (strlen(word) == 0U) + return (ISC_R_UNEXPECTEDEND); /* Empty line after keyword. */ + + while (strlen(word) > 0U) { + if (conf->sortlistnxt == RESCONFMAXSORTLIST) + return (ISC_R_QUOTA); /* Too many values. */ + + p = strchr(word, '/'); + if (p != NULL) + *p++ = '\0'; + + idx = conf->sortlistnxt; + res = create_addr(word, &conf->sortlist[idx].addr, 1); + if (res != ISC_R_SUCCESS) + return (res); + + if (p != NULL) { + res = create_addr(p, &conf->sortlist[idx].mask, 0); + if (res != ISC_R_SUCCESS) + return (res); + } else { + /* + * Make up a mask. (XXX: is this correct?) + */ + conf->sortlist[idx].mask = conf->sortlist[idx].addr; + memset(&conf->sortlist[idx].mask.type, 0xff, + sizeof(conf->sortlist[idx].mask.type)); + } + + conf->sortlistnxt++; + + if (delim == EOF || delim == '\n') + break; + else + delim = getword(fp, word, sizeof(word)); + } + + return (ISC_R_SUCCESS); +} + +static isc_result_t +resconf_parseoption(irs_resconf_t *conf, FILE *fp) { + int delim; + long ndots; + char *p; + char word[RESCONFMAXLINELEN]; + + delim = getword(fp, word, sizeof(word)); + if (strlen(word) == 0U) + return (ISC_R_UNEXPECTEDEND); /* Empty line after keyword. */ + + while (strlen(word) > 0U) { + if (strcmp("debug", word) == 0) { + conf->resdebug = 1; + } else if (strncmp("ndots:", word, 6) == 0) { + ndots = strtol(word + 6, &p, 10); + if (*p != '\0') /* Bad string. */ + return (ISC_R_UNEXPECTEDTOKEN); + if (ndots < 0 || ndots > 0xff) /* Out of range. */ + return (ISC_R_RANGE); + conf->ndots = (isc_uint8_t)ndots; + } + + if (delim == EOF || delim == '\n') + break; + else + delim = getword(fp, word, sizeof(word)); + } + + return (ISC_R_SUCCESS); +} + +static isc_result_t +add_search(irs_resconf_t *conf, char *domain) { + irs_resconf_search_t *entry; + + entry = isc_mem_get(conf->mctx, sizeof(*entry)); + if (entry == NULL) + return (ISC_R_NOMEMORY); + + entry->domain = domain; + ISC_LINK_INIT(entry, link); + ISC_LIST_APPEND(conf->searchlist, entry, link); + + return (ISC_R_SUCCESS); +} + +/*% parses a file and fills in the data structure. */ +isc_result_t +irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp) +{ + FILE *fp = NULL; + char word[256]; + isc_result_t rval, ret; + irs_resconf_t *conf; + int i, stopchar; + + REQUIRE(mctx != NULL); + REQUIRE(filename != NULL); + REQUIRE(strlen(filename) > 0U); + REQUIRE(confp != NULL && *confp == NULL); + + conf = isc_mem_get(mctx, sizeof(*conf)); + if (conf == NULL) + return (ISC_R_NOMEMORY); + + conf->mctx = mctx; + ISC_LIST_INIT(conf->nameservers); + conf->numns = 0; + conf->domainname = NULL; + conf->searchnxt = 0; + conf->resdebug = 0; + conf->ndots = 1; + for (i = 0; i < RESCONFMAXSEARCH; i++) + conf->search[i] = NULL; + + errno = 0; + if ((fp = fopen(filename, "r")) == NULL) { + isc_mem_put(mctx, conf, sizeof(*conf)); + return (ISC_R_INVALIDFILE); + } + + ret = ISC_R_SUCCESS; + do { + stopchar = getword(fp, word, sizeof(word)); + if (stopchar == EOF) { + rval = ISC_R_SUCCESS; + break; + } + + if (strlen(word) == 0U) + rval = ISC_R_SUCCESS; + else if (strcmp(word, "nameserver") == 0) + rval = resconf_parsenameserver(conf, fp); + else if (strcmp(word, "domain") == 0) + rval = resconf_parsedomain(conf, fp); + else if (strcmp(word, "search") == 0) + rval = resconf_parsesearch(conf, fp); + else if (strcmp(word, "sortlist") == 0) + rval = resconf_parsesortlist(conf, fp); + else if (strcmp(word, "options") == 0) + rval = resconf_parseoption(conf, fp); + else { + /* unrecognised word. Ignore entire line */ + rval = ISC_R_SUCCESS; + stopchar = eatline(fp); + if (stopchar == EOF) { + break; + } + } + if (ret == ISC_R_SUCCESS && rval != ISC_R_SUCCESS) + ret = rval; + } while (1); + + fclose(fp); + + /* If we don't find a nameserver fall back to localhost */ + if (conf->numns == 0) { + INSIST(ISC_LIST_EMPTY(conf->nameservers)); + + /* XXX: should we catch errors? */ + (void)add_server(conf->mctx, "127.0.0.1", &conf->nameservers); + (void)add_server(conf->mctx, "::1", &conf->nameservers); + } + + /* + * Construct unified search list from domain or configured + * search list + */ + ISC_LIST_INIT(conf->searchlist); + if (conf->domainname != NULL) { + ret = add_search(conf, conf->domainname); + } else if (conf->searchnxt > 0) { + for (i = 0; i < conf->searchnxt; i++) { + ret = add_search(conf, conf->search[i]); + if (ret != ISC_R_SUCCESS) + break; + } + } + + conf->magic = IRS_RESCONF_MAGIC; + + if (ret != ISC_R_SUCCESS) + irs_resconf_destroy(&conf); + else + *confp = conf; + + return (ret); +} + +void +irs_resconf_destroy(irs_resconf_t **confp) { + irs_resconf_t *conf; + isc_sockaddr_t *address; + irs_resconf_search_t *searchentry; + int i; + + REQUIRE(confp != NULL); + conf = *confp; + REQUIRE(IRS_RESCONF_VALID(conf)); + + while ((searchentry = ISC_LIST_HEAD(conf->searchlist)) != NULL) { + ISC_LIST_UNLINK(conf->searchlist, searchentry, link); + isc_mem_put(conf->mctx, searchentry, sizeof(*searchentry)); + } + + while ((address = ISC_LIST_HEAD(conf->nameservers)) != NULL) { + ISC_LIST_UNLINK(conf->nameservers, address, link); + isc_mem_put(conf->mctx, address, sizeof(*address)); + } + + if (conf->domainname != NULL) + isc_mem_free(conf->mctx, conf->domainname); + + for (i = 0; i < RESCONFMAXSEARCH; i++) { + if (conf->search[i] != NULL) + isc_mem_free(conf->mctx, conf->search[i]); + } + + isc_mem_put(conf->mctx, conf, sizeof(*conf)); + + *confp = NULL; +} + +isc_sockaddrlist_t * +irs_resconf_getnameservers(irs_resconf_t *conf) { + REQUIRE(IRS_RESCONF_VALID(conf)); + + return (&conf->nameservers); +} + +irs_resconf_searchlist_t * +irs_resconf_getsearchlist(irs_resconf_t *conf) { + REQUIRE(IRS_RESCONF_VALID(conf)); + + return (&conf->searchlist); +} + +unsigned int +irs_resconf_getndots(irs_resconf_t *conf) { + REQUIRE(IRS_RESCONF_VALID(conf)); + + return ((unsigned int)conf->ndots); +} diff --git a/lib/irs/version.c b/lib/irs/version.c new file mode 100644 index 0000000..b27de99 --- /dev/null +++ b/lib/irs/version.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: version.c,v 1.3 2009-09-02 23:48:02 tbox Exp $ */ + +/*! \file */ + +#include + +const char irs_version[] = VERSION; + +const unsigned int irs_libinterface = LIBINTERFACE; +const unsigned int irs_librevision = LIBREVISION; +const unsigned int irs_libage = LIBAGE; diff --git a/lib/isc/Makefile.in b/lib/isc/Makefile.in index d831fcf..d92c0b8 100644 --- a/lib/isc/Makefile.in +++ b/lib/isc/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.96.50.6 2010-06-09 01:52:54 marka Exp $ +# $Id: Makefile.in,v 1.109 2010-06-09 01:43:09 marka Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -27,8 +27,8 @@ CINCLUDES = -I${srcdir}/unix/include \ -I${srcdir}/@ISC_THREAD_DIR@/include \ -I${srcdir}/@ISC_ARCH_DIR@/include \ -I./include \ - -I${srcdir}/include -CDEFINES = + -I${srcdir}/include @ISC_OPENSSL_INC@ +CDEFINES = @USE_OPENSSL@ CWARNINGS = # Alphabetically @@ -39,7 +39,6 @@ UNIXOBJS = @ISC_ISCIPV6_O@ \ unix/os.@O@ unix/resource.@O@ unix/socket.@O@ unix/stdio.@O@ \ unix/stdtime.@O@ unix/strerror.@O@ unix/syslog.@O@ unix/time.@O@ - NLSOBJS = nls/msgcat.@O@ THREADOPTOBJS = @ISC_THREAD_DIR@/condition.@O@ @ISC_THREAD_DIR@/mutex.@O@ @@ -52,8 +51,9 @@ WIN32OBJS = win32/condition.@O@ win32/dir.@O@ win32/file.@O@ \ # Alphabetically OBJS = @ISC_EXTRA_OBJS@ \ - assertions.@O@ base32.@O@ base64.@O@ bitstring.@O@ buffer.@O@ \ - bufferlist.@O@ commandline.@O@ error.@O@ event.@O@ \ + assertions.@O@ backtrace.@O@ base32.@O@ base64.@O@ \ + bitstring.@O@ buffer.@O@ bufferlist.@O@ commandline.@O@ \ + error.@O@ event.@O@ \ hash.@O@ heap.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@ \ httpd.@O@ inet_aton.@O@ iterated_hash.@O@ \ lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \ @@ -64,11 +64,12 @@ OBJS = @ISC_EXTRA_OBJS@ \ serial.@O@ sha1.@O@ sha2.@O@ sockaddr.@O@ stats.@O@ \ string.@O@ strtoul.@O@ symtab.@O@ task.@O@ taskpool.@O@ \ timer.@O@ version.@O@ ${UNIXOBJS} ${NLSOBJS} ${THREADOBJS} +SYMTBLOBJS = backtrace-emptytbl.@O@ # Alphabetically SRCS = @ISC_EXTRA_SRCS@ \ - assertions.c base32.c base64.c bitstring.c buffer.c \ - bufferlist.c commandline.c error.c event.c \ + assertions.c backtrace.c base32.c base64.c bitstring.c \ + buffer.c bufferlist.c commandline.c error.c event.c \ heap.c hex.c hmacmd5.c hmacsha.c \ httpd.c inet_aton.c iterated_hash.c \ lex.c lfsr.c lib.c log.c \ @@ -77,7 +78,7 @@ SRCS = @ISC_EXTRA_SRCS@ \ parseint.c portset.c quota.c radix.c random.c \ ratelimiter.c refcount.c region.c result.c rwlock.c \ serial.c sha1.c sha2.c sockaddr.c stats.c string.c strtoul.c \ - symtab.c task.c taskpool.c timer.c version.c + symtab.c symtbl-empty.c task.c taskpool.c timer.c version.c LIBS = @LIBS@ @@ -98,17 +99,27 @@ version.@O@: version.c -DLIBAGE=${LIBAGE} \ -c ${srcdir}/version.c -libisc.@SA@: ${OBJS} +libisc.@SA@: ${OBJS} ${SYMTBLOBJS} + ${AR} ${ARFLAGS} $@ ${OBJS} ${SYMTBLOBJS} + ${RANLIB} $@ + +libisc-nosymtbl.@SA@: ${OBJS} ${AR} ${ARFLAGS} $@ ${OBJS} ${RANLIB} $@ -libisc.la: ${OBJS} +libisc.la: ${OBJS} ${SYMTBLOBJS} ${LIBTOOL_MODE_LINK} \ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc.la -rpath ${libdir} \ -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ + ${OBJS} ${SYMTBLOBJS} ${LIBS} + +libisc-nosymtbl.la: ${OBJS} + ${LIBTOOL_MODE_LINK} \ + ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc-nosymtbl.la -rpath ${libdir} \ + -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ ${OBJS} ${LIBS} -timestamp: libisc.@A@ +timestamp: libisc.@A@ libisc-nosymtbl.@A@ touch timestamp installdirs: @@ -118,4 +129,5 @@ install:: timestamp installdirs ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libisc.@A@ ${DESTDIR}${libdir} clean distclean:: - rm -f libisc.@A@ libisc.la timestamp + rm -f libisc.@A@ libisc-nosymtbl.@A@ libisc.la \ + libisc-nosymtbl.la timestamp diff --git a/lib/isc/alpha/include/isc/atomic.h b/lib/isc/alpha/include/isc/atomic.h index bb4f1ad..012c955 100644 --- a/lib/isc/alpha/include/isc/atomic.h +++ b/lib/isc/alpha/include/isc/atomic.h @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: atomic.h,v 1.5.332.2 2009-04-08 06:47:32 tbox Exp $ */ +/* $Id: atomic.h,v 1.7 2009-04-08 06:48:23 tbox Exp $ */ /* * This code was written based on FreeBSD's kernel source whose copyright diff --git a/lib/isc/api b/lib/isc/api index e1f7b71..b91b130 100644 --- a/lib/isc/api +++ b/lib/isc/api @@ -1,3 +1,3 @@ -LIBINTERFACE = 54 -LIBREVISION = 1 -LIBAGE = 4 +LIBINTERFACE = 81 +LIBREVISION = 2 +LIBAGE = 0 diff --git a/lib/isc/app_api.c b/lib/isc/app_api.c new file mode 100644 index 0000000..b2a2f14 --- /dev/null +++ b/lib/isc/app_api.c @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: app_api.c,v 1.5 2009-09-02 23:48:02 tbox Exp $ */ + +#include + +#include + +#include +#include +#include +#include +#include + +static isc_mutex_t createlock; +static isc_once_t once = ISC_ONCE_INIT; +static isc_appctxcreatefunc_t appctx_createfunc = NULL; + +#define ISCAPI_APPMETHODS_VALID(m) ISC_MAGIC_VALID(m, ISCAPI_APPMETHODS_MAGIC) + +static void +initialize(void) { + RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS); +} + +isc_result_t +isc_app_register(isc_appctxcreatefunc_t createfunc) { + isc_result_t result = ISC_R_SUCCESS; + + RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); + + LOCK(&createlock); + if (appctx_createfunc == NULL) + appctx_createfunc = createfunc; + else + result = ISC_R_EXISTS; + UNLOCK(&createlock); + + return (result); +} + +isc_result_t +isc_appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp) { + isc_result_t result; + + LOCK(&createlock); + + REQUIRE(appctx_createfunc != NULL); + result = (*appctx_createfunc)(mctx, ctxp); + + UNLOCK(&createlock); + + return (result); +} + +void +isc_appctx_destroy(isc_appctx_t **ctxp) { + REQUIRE(ctxp != NULL && ISCAPI_APPCTX_VALID(*ctxp)); + + (*ctxp)->methods->ctxdestroy(ctxp); + + ENSURE(*ctxp == NULL); +} + +isc_result_t +isc_app_ctxstart(isc_appctx_t *ctx) { + REQUIRE(ISCAPI_APPCTX_VALID(ctx)); + + return (ctx->methods->ctxstart(ctx)); +} + +isc_result_t +isc_app_ctxrun(isc_appctx_t *ctx) { + REQUIRE(ISCAPI_APPCTX_VALID(ctx)); + + return (ctx->methods->ctxrun(ctx)); +} + +isc_result_t +isc_app_ctxsuspend(isc_appctx_t *ctx) { + REQUIRE(ISCAPI_APPCTX_VALID(ctx)); + + return (ctx->methods->ctxsuspend(ctx)); +} + +isc_result_t +isc_app_ctxshutdown(isc_appctx_t *ctx) { + REQUIRE(ISCAPI_APPCTX_VALID(ctx)); + + return (ctx->methods->ctxshutdown(ctx)); +} + +void +isc_app_ctxfinish(isc_appctx_t *ctx) { + REQUIRE(ISCAPI_APPCTX_VALID(ctx)); + + ctx->methods->ctxfinish(ctx); +} + +void +isc_appctx_settaskmgr(isc_appctx_t *ctx, isc_taskmgr_t *taskmgr) { + REQUIRE(ISCAPI_APPCTX_VALID(ctx)); + REQUIRE(taskmgr != NULL); + + ctx->methods->settaskmgr(ctx, taskmgr); +} + +void +isc_appctx_setsocketmgr(isc_appctx_t *ctx, isc_socketmgr_t *socketmgr) { + REQUIRE(ISCAPI_APPCTX_VALID(ctx)); + REQUIRE(socketmgr != NULL); + + ctx->methods->setsocketmgr(ctx, socketmgr); +} + +void +isc_appctx_settimermgr(isc_appctx_t *ctx, isc_timermgr_t *timermgr) { + REQUIRE(ISCAPI_APPCTX_VALID(ctx)); + REQUIRE(timermgr != NULL); + + ctx->methods->settimermgr(ctx, timermgr); +} diff --git a/lib/isc/assertions.c b/lib/isc/assertions.c index b98d61d..fe082b7 100644 --- a/lib/isc/assertions.c +++ b/lib/isc/assertions.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1997-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: assertions.c,v 1.23 2008-10-15 23:47:31 tbox Exp $ */ +/* $Id: assertions.c,v 1.26 2009-09-29 15:06:07 fdupont Exp $ */ /*! \file */ @@ -25,29 +25,47 @@ #include #include +#include #include +#include + +/* + * The maximum number of stack frames to dump on assertion failure. + */ +#ifndef BACKTRACE_MAXFRAME +#define BACKTRACE_MAXFRAME 128 +#endif /*% * Forward. */ -/* coverity[+kill] */ static void default_callback(const char *, int, isc_assertiontype_t, const char *); +static isc_assertioncallback_t isc_assertion_failed_cb = default_callback; + /*% * Public. */ -LIBISC_EXTERNAL_DATA isc_assertioncallback_t isc_assertion_failed = - default_callback; +/*% assertion failed handler */ +/* coverity[+kill] */ +void +isc_assertion_failed(const char *file, int line, isc_assertiontype_t type, + const char *cond) +{ + isc_assertion_failed_cb(file, line, type, cond); + abort(); + /* NOTREACHED */ +} /*% Set callback. */ void isc_assertion_setcallback(isc_assertioncallback_t cb) { if (cb == NULL) - isc_assertion_failed = default_callback; + isc_assertion_failed_cb = default_callback; else - isc_assertion_failed = cb; + isc_assertion_failed_cb = cb; } /*% Type to Text */ @@ -87,11 +105,35 @@ static void default_callback(const char *file, int line, isc_assertiontype_t type, const char *cond) { - fprintf(stderr, "%s:%d: %s(%s) %s.\n", + void *tracebuf[BACKTRACE_MAXFRAME]; + int i, nframes; + const char *logsuffix = "."; + const char *fname; + isc_result_t result; + + result = isc_backtrace_gettrace(tracebuf, BACKTRACE_MAXFRAME, &nframes); + if (result == ISC_R_SUCCESS && nframes > 0) + logsuffix = ", back trace"; + + fprintf(stderr, "%s:%d: %s(%s) %s%s\n", file, line, isc_assertion_typetotext(type), cond, isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, "failed")); + ISC_MSG_FAILED, "failed"), logsuffix); + if (result == ISC_R_SUCCESS) { + for (i = 0; i < nframes; i++) { + unsigned long offset; + + fname = NULL; + result = isc_backtrace_getsymbol(tracebuf[i], &fname, + &offset); + if (result == ISC_R_SUCCESS) { + fprintf(stderr, "#%d %p in %s()+0x%lx\n", i, + tracebuf[i], fname, offset); + } else { + fprintf(stderr, "#%d %p in ??\n", i, + tracebuf[i]); + } + } + } fflush(stderr); - abort(); - /* NOTREACHED */ } diff --git a/lib/isc/backtrace-emptytbl.c b/lib/isc/backtrace-emptytbl.c new file mode 100644 index 0000000..2743030 --- /dev/null +++ b/lib/isc/backtrace-emptytbl.c @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: backtrace-emptytbl.c,v 1.3 2009-09-01 20:13:44 each Exp $ */ + +/*! \file */ + +/* + * This file defines an empty (default) symbol table used in backtrace.c + * If the application wants to have a complete symbol table, it should redefine + * isc__backtrace_symtable with the complete table in some way, and link the + * version of the library not including this definition + * (e.g. libisc-nosymbol.a). + */ + +#include + +#include + +const int isc__backtrace_nsymbols = 0; +const isc_backtrace_symmap_t isc__backtrace_symtable[] = { { NULL, "" } }; diff --git a/lib/isc/backtrace.c b/lib/isc/backtrace.c new file mode 100644 index 0000000..7b5ddfe --- /dev/null +++ b/lib/isc/backtrace.c @@ -0,0 +1,285 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: backtrace.c,v 1.3 2009-09-02 23:48:02 tbox Exp $ */ + +/*! \file */ + +#include "config.h" + +#include +#include +#ifdef HAVE_LIBCTRACE +#include +#endif + +#include +#include +#include + +#ifdef ISC_PLATFORM_USEBACKTRACE +/* + * Getting a back trace of a running process is tricky and highly platform + * dependent. Our current approach is as follows: + * 1. If the system library supports the "backtrace()" function, use it. + * 2. Otherwise, if the compiler is gcc and the architecture is x86_64 or IA64, + * then use gcc's (hidden) Unwind_Backtrace() function. Note that this + * function doesn't work for C programs on many other architectures. + * 3. Otherwise, if the architecture x86 or x86_64, try to unwind the stack + * frame following frame pointers. This assumes the executable binary + * compiled with frame pointers; this is not always true for x86_64 (rather, + * compiler optimizations often disable frame pointers). The validation + * checks in getnextframeptr() hopefully rejects bogus values stored in + * the RBP register in such a case. If the backtrace function itself crashes + * due to this problem, the whole package should be rebuilt with + * --disable-backtrace. + */ +#ifdef HAVE_LIBCTRACE +#define BACKTRACE_LIBC +#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__ia64__)) +#define BACKTRACE_GCC +#elif defined(__x86_64__) || defined(__i386__) +#define BACKTRACE_X86STACK +#else +#define BACKTRACE_DISABLED +#endif /* HAVE_LIBCTRACE */ +#else /* !ISC_PLATFORM_USEBACKTRACE */ +#define BACKTRACE_DISABLED +#endif /* ISC_PLATFORM_USEBACKTRACE */ + +#ifdef BACKTRACE_LIBC +isc_result_t +isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes) { + int n; + + /* + * Validate the arguments: intentionally avoid using REQUIRE(). + * See notes in backtrace.h. + */ + if (addrs == NULL || nframes == NULL) + return (ISC_R_FAILURE); + + /* + * backtrace(3) includes this function itself in the address array, + * which should be eliminated from the returned sequence. + */ + n = backtrace(addrs, maxaddrs); + if (n < 2) + return (ISC_R_NOTFOUND); + n--; + memmove(addrs, &addrs[1], sizeof(void *) * n); + *nframes = n; + return (ISC_R_SUCCESS); +} +#elif defined(BACKTRACE_GCC) +extern int _Unwind_Backtrace(void* fn, void* a); +extern void* _Unwind_GetIP(void* ctx); + +typedef struct { + void **result; + int max_depth; + int skip_count; + int count; +} trace_arg_t; + +static int +btcallback(void *uc, void *opq) { + trace_arg_t *arg = (trace_arg_t *)opq; + + if (arg->skip_count > 0) + arg->skip_count--; + else + arg->result[arg->count++] = (void *)_Unwind_GetIP(uc); + if (arg->count == arg->max_depth) + return (5); /* _URC_END_OF_STACK */ + + return (0); /* _URC_NO_REASON */ +} + +isc_result_t +isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes) { + trace_arg_t arg; + + /* Argument validation: see above. */ + if (addrs == NULL || nframes == NULL) + return (ISC_R_FAILURE); + + arg.skip_count = 1; + arg.result = addrs; + arg.max_depth = maxaddrs; + arg.count = 0; + _Unwind_Backtrace(btcallback, &arg); + + *nframes = arg.count; + + return (ISC_R_SUCCESS); +} +#elif defined(BACKTRACE_X86STACK) +#ifdef __x86_64__ +static unsigned long +getrbp() { + __asm("movq %rbp, %rax\n"); +} +#endif + +static void ** +getnextframeptr(void **sp) { + void **newsp = (void **)*sp; + + /* + * Perform sanity check for the new frame pointer, derived from + * google glog. This can actually be bogus depending on compiler. + */ + + /* prohibit the stack frames from growing downwards */ + if (newsp <= sp) + return (NULL); + + /* A heuristics to reject "too large" frame: this actually happened. */ + if ((char *)newsp - (char *)sp > 100000) + return (NULL); + + /* + * Not sure if other checks used in glog are needed at this moment. + * For our purposes we don't have to consider non-contiguous frames, + * for example. + */ + + return (newsp); +} + +isc_result_t +isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes) { + int i = 0; + void **sp; + + /* Argument validation: see above. */ + if (addrs == NULL || nframes == NULL) + return (ISC_R_FAILURE); + +#ifdef __x86_64__ + sp = (void **)getrbp(); + if (sp == NULL) + return (ISC_R_NOTFOUND); + /* + * sp is the frame ptr of this function itself due to the call to + * getrbp(), so need to unwind one frame for consistency. + */ + sp = getnextframeptr(sp); +#else + /* + * i386: the frame pointer is stored 2 words below the address for the + * first argument. Note that the body of this function cannot be + * inlined since it depends on the address of the function argument. + */ + sp = (void **)&addrs - 2; +#endif + + while (sp != NULL && i < maxaddrs) { + addrs[i++] = *(sp + 1); + sp = getnextframeptr(sp); + } + + *nframes = i; + + return (ISC_R_SUCCESS); +} +#elif defined(BACKTRACE_DISABLED) +isc_result_t +isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes) { + /* Argument validation: see above. */ + if (addrs == NULL || nframes == NULL) + return (ISC_R_FAILURE); + + UNUSED(maxaddrs); + + return (ISC_R_NOTIMPLEMENTED); +} +#endif + +isc_result_t +isc_backtrace_getsymbolfromindex(int index, const void **addrp, + const char **symbolp) +{ + REQUIRE(addrp != NULL && *addrp == NULL); + REQUIRE(symbolp != NULL && *symbolp == NULL); + + if (index < 0 || index >= isc__backtrace_nsymbols) + return (ISC_R_RANGE); + + *addrp = isc__backtrace_symtable[index].addr; + *symbolp = isc__backtrace_symtable[index].symbol; + return (ISC_R_SUCCESS); +} + +static int +symtbl_compare(const void *addr, const void *entryarg) { + const isc_backtrace_symmap_t *entry = entryarg; + const isc_backtrace_symmap_t *end = + &isc__backtrace_symtable[isc__backtrace_nsymbols - 1]; + + if (isc__backtrace_nsymbols == 1 || entry == end) { + if (addr >= entry->addr) { + /* + * If addr is equal to or larger than that of the last + * entry of the table, we cannot be sure if this is + * within a valid range so we consider it valid. + */ + return (0); + } + return (-1); + } + + /* entry + 1 is a valid entry from now on. */ + if (addr < entry->addr) + return (-1); + else if (addr >= (entry + 1)->addr) + return (1); + return (0); +} + +isc_result_t +isc_backtrace_getsymbol(const void *addr, const char **symbolp, + unsigned long *offsetp) +{ + isc_result_t result = ISC_R_SUCCESS; + isc_backtrace_symmap_t *found; + + /* + * Validate the arguments: intentionally avoid using REQUIRE(). + * See notes in backtrace.h. + */ + if (symbolp == NULL || *symbolp != NULL || offsetp == NULL) + return (ISC_R_FAILURE); + + if (isc__backtrace_nsymbols < 1) + return (ISC_R_NOTFOUND); + + /* + * Search the table for the entry that meets: + * entry.addr <= addr < next_entry.addr. + */ + found = bsearch(addr, isc__backtrace_symtable, isc__backtrace_nsymbols, + sizeof(isc__backtrace_symtable[0]), symtbl_compare); + if (found == NULL) + result = ISC_R_NOTFOUND; + else { + *symbolp = found->symbol; + *offsetp = (const char *)addr - (char *)found->addr; + } + + return (result); +} diff --git a/lib/isc/base32.c b/lib/isc/base32.c index 5e5cbd9..7621920 100644 --- a/lib/isc/base32.c +++ b/lib/isc/base32.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: base32.c,v 1.3.116.3 2009-10-21 01:22:47 each Exp $ */ +/* $Id: base32.c,v 1.6 2009-10-21 01:22:29 each Exp $ */ /*! \file */ diff --git a/lib/isc/base64.c b/lib/isc/base64.c index 858525f..ee34c3c 100644 --- a/lib/isc/base64.c +++ b/lib/isc/base64.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: base64.c,v 1.32.332.2 2009-10-21 23:47:20 tbox Exp $ */ +/* $Id: base64.c,v 1.34 2009-10-21 23:48:05 tbox Exp $ */ /*! \file */ diff --git a/lib/isc/entropy.c b/lib/isc/entropy.c index af8757f..8d273d2 100644 --- a/lib/isc/entropy.c +++ b/lib/isc/entropy.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: entropy.c,v 1.18.332.4 2010-08-10 23:46:54 tbox Exp $ */ +/* $Id: entropy.c,v 1.22 2010-08-10 23:48:19 tbox Exp $ */ /*! \file * \brief diff --git a/lib/isc/hash.c b/lib/isc/hash.c index 7c0fcea..44975e7 100644 --- a/lib/isc/hash.c +++ b/lib/isc/hash.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: hash.c,v 1.13.332.3 2009-05-07 23:47:12 tbox Exp $ */ +/* $Id: hash.c,v 1.16 2009-09-01 00:22:28 jinmei Exp $ */ /*! \file * Some portion of this code was derived from universal hash function @@ -194,8 +194,12 @@ isc_hash_ctxcreate(isc_mem_t *mctx, isc_entropy_t *entropy, hctx->vectorlen = vlen; hctx->rndvector = rv; +#ifdef BIND9 if (entropy != NULL) isc_entropy_attach(entropy, &hctx->entropy); +#else + UNUSED(entropy); +#endif *hctxp = hctx; return (ISC_R_SUCCESS); @@ -236,18 +240,22 @@ isc_hash_create(isc_mem_t *mctx, isc_entropy_t *entropy, size_t limit) { void isc_hash_ctxinit(isc_hash_t *hctx) { - isc_result_t result; - LOCK(&hctx->lock); if (hctx->initialized == ISC_TRUE) goto out; if (hctx->entropy) { +#ifdef BIND9 + isc_result_t result; + result = isc_entropy_getdata(hctx->entropy, hctx->rndvector, hctx->vectorlen, NULL, 0); INSIST(result == ISC_R_SUCCESS); +#else + INSIST(0); +#endif } else { isc_uint32_t pr; unsigned int i, copylen; @@ -293,6 +301,7 @@ static void destroy(isc_hash_t **hctxp) { isc_hash_t *hctx; isc_mem_t *mctx; + unsigned char canary0[4], canary1[4]; REQUIRE(hctxp != NULL && *hctxp != NULL); hctx = *hctxp; @@ -303,8 +312,10 @@ destroy(isc_hash_t **hctxp) { isc_refcount_destroy(&hctx->refcnt); mctx = hctx->mctx; +#ifdef BIND9 if (hctx->entropy != NULL) isc_entropy_detach(&hctx->entropy); +#endif if (hctx->rndvector != NULL) isc_mem_put(mctx, hctx->rndvector, hctx->vectorlen); @@ -312,7 +323,10 @@ destroy(isc_hash_t **hctxp) { DESTROYLOCK(&hctx->lock); + memcpy(canary0, hctx + 1, sizeof(canary0)); memset(hctx, 0, sizeof(isc_hash_t)); + memcpy(canary1, hctx + 1, sizeof(canary1)); + INSIST(memcmp(canary0, canary1, sizeof(canary0)) == 0); isc_mem_put(mctx, hctx, sizeof(isc_hash_t)); isc_mem_detach(&mctx); } diff --git a/lib/isc/heap.c b/lib/isc/heap.c index 68f8ba8..4dead3f 100644 --- a/lib/isc/heap.c +++ b/lib/isc/heap.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: heap.c,v 1.37.240.3 2010-02-04 23:47:46 tbox Exp $ */ +/* $Id: heap.c,v 1.39 2010-02-04 23:49:13 tbox Exp $ */ /*! \file * Heap implementation of priority queues adapted from the following: diff --git a/lib/isc/hmacmd5.c b/lib/isc/hmacmd5.c index b1d5906..10e87c9 100644 --- a/lib/isc/hmacmd5.c +++ b/lib/isc/hmacmd5.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: hmacmd5.c,v 1.14 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: hmacmd5.c,v 1.16 2009-02-06 23:47:42 tbox Exp $ */ /*! \file * This code implements the HMAC-MD5 keyed hash algorithm @@ -27,10 +27,40 @@ #include #include #include +#include #include #include #include +#ifdef ISC_PLATFORM_OPENSSLHASH + +void +isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key, + unsigned int len) +{ + HMAC_Init(ctx, (const void *) key, (int) len, EVP_md5()); +} + +void +isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) { + HMAC_CTX_cleanup(ctx); +} + +void +isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf, + unsigned int len) +{ + HMAC_Update(ctx, buf, (int) len); +} + +void +isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) { + HMAC_Final(ctx, digest, NULL); + HMAC_CTX_cleanup(ctx); +} + +#else + #define PADLEN 64 #define IPAD 0x36 #define OPAD 0x5C @@ -98,6 +128,7 @@ isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) { isc_md5_final(&ctx->md5ctx, digest); isc_hmacmd5_invalidate(ctx); } +#endif /* !ISC_PLATFORM_OPENSSLHASH */ /*! * Verify signature - finalize MD5 operation and reapply MD5, then diff --git a/lib/isc/hmacsha.c b/lib/isc/hmacsha.c index 9f27163..125672d 100644 --- a/lib/isc/hmacsha.c +++ b/lib/isc/hmacsha.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2005-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: hmacsha.c,v 1.8 2007-08-27 03:27:53 marka Exp $ */ +/* $Id: hmacsha.c,v 1.10 2009-02-06 23:47:42 tbox Exp $ */ /* * This code implements the HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, HMAC-SHA384 @@ -26,12 +26,172 @@ #include #include +#include #include #include #include #include #include +#ifdef ISC_PLATFORM_OPENSSLHASH + +void +isc_hmacsha1_init(isc_hmacsha1_t *ctx, const unsigned char *key, + unsigned int len) +{ + HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha1()); +} + +void +isc_hmacsha1_invalidate(isc_hmacsha1_t *ctx) { + HMAC_CTX_cleanup(ctx); +} + +void +isc_hmacsha1_update(isc_hmacsha1_t *ctx, const unsigned char *buf, + unsigned int len) +{ + HMAC_Update(ctx, buf, (int) len); +} + +void +isc_hmacsha1_sign(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) { + unsigned char newdigest[ISC_SHA1_DIGESTLENGTH]; + + REQUIRE(len <= ISC_SHA1_DIGESTLENGTH); + + HMAC_Final(ctx, newdigest, NULL); + HMAC_CTX_cleanup(ctx); + memcpy(digest, newdigest, len); + memset(newdigest, 0, sizeof(newdigest)); +} + +void +isc_hmacsha224_init(isc_hmacsha224_t *ctx, const unsigned char *key, + unsigned int len) +{ + HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha224()); +} + +void +isc_hmacsha224_invalidate(isc_hmacsha224_t *ctx) { + HMAC_CTX_cleanup(ctx); +} + +void +isc_hmacsha224_update(isc_hmacsha224_t *ctx, const unsigned char *buf, + unsigned int len) +{ + HMAC_Update(ctx, buf, (int) len); +} + +void +isc_hmacsha224_sign(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) { + unsigned char newdigest[ISC_SHA224_DIGESTLENGTH]; + + REQUIRE(len <= ISC_SHA224_DIGESTLENGTH); + + HMAC_Final(ctx, newdigest, NULL); + HMAC_CTX_cleanup(ctx); + memcpy(digest, newdigest, len); + memset(newdigest, 0, sizeof(newdigest)); +} + +void +isc_hmacsha256_init(isc_hmacsha256_t *ctx, const unsigned char *key, + unsigned int len) +{ + HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha256()); +} + +void +isc_hmacsha256_invalidate(isc_hmacsha256_t *ctx) { + HMAC_CTX_cleanup(ctx); +} + +void +isc_hmacsha256_update(isc_hmacsha256_t *ctx, const unsigned char *buf, + unsigned int len) +{ + HMAC_Update(ctx, buf, (int) len); +} + +void +isc_hmacsha256_sign(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) { + unsigned char newdigest[ISC_SHA256_DIGESTLENGTH]; + + REQUIRE(len <= ISC_SHA256_DIGESTLENGTH); + + HMAC_Final(ctx, newdigest, NULL); + HMAC_CTX_cleanup(ctx); + memcpy(digest, newdigest, len); + memset(newdigest, 0, sizeof(newdigest)); +} + +void +isc_hmacsha384_init(isc_hmacsha384_t *ctx, const unsigned char *key, + unsigned int len) +{ + HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha384()); +} + +void +isc_hmacsha384_invalidate(isc_hmacsha384_t *ctx) { + HMAC_CTX_cleanup(ctx); +} + +void +isc_hmacsha384_update(isc_hmacsha384_t *ctx, const unsigned char *buf, + unsigned int len) +{ + HMAC_Update(ctx, buf, (int) len); +} + +void +isc_hmacsha384_sign(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) { + unsigned char newdigest[ISC_SHA384_DIGESTLENGTH]; + + REQUIRE(len <= ISC_SHA384_DIGESTLENGTH); + + HMAC_Final(ctx, newdigest, NULL); + HMAC_CTX_cleanup(ctx); + memcpy(digest, newdigest, len); + memset(newdigest, 0, sizeof(newdigest)); +} + +void +isc_hmacsha512_init(isc_hmacsha512_t *ctx, const unsigned char *key, + unsigned int len) +{ + HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha512()); +} + +void +isc_hmacsha512_invalidate(isc_hmacsha512_t *ctx) { + HMAC_CTX_cleanup(ctx); +} + +void +isc_hmacsha512_update(isc_hmacsha512_t *ctx, const unsigned char *buf, + unsigned int len) +{ + HMAC_Update(ctx, buf, (int) len); +} + +void +isc_hmacsha512_sign(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) { + unsigned char newdigest[ISC_SHA512_DIGESTLENGTH]; + + REQUIRE(len <= ISC_SHA512_DIGESTLENGTH); + + HMAC_Final(ctx, newdigest, NULL); + HMAC_CTX_cleanup(ctx); + memcpy(digest, newdigest, len); + memset(newdigest, 0, sizeof(newdigest)); +} + +#else + #define IPAD 0x36 #define OPAD 0x5C @@ -105,19 +265,6 @@ isc_hmacsha1_sign(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) { } /* - * Verify signature - finalize SHA1 operation and reapply SHA1, then - * compare to the supplied digest. - */ -isc_boolean_t -isc_hmacsha1_verify(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) { - unsigned char newdigest[ISC_SHA1_DIGESTLENGTH]; - - REQUIRE(len <= ISC_SHA1_DIGESTLENGTH); - isc_hmacsha1_sign(ctx, newdigest, ISC_SHA1_DIGESTLENGTH); - return (ISC_TF(memcmp(digest, newdigest, len) == 0)); -} - -/* * Start HMAC-SHA224 process. Initialize an sha224 context and digest the key. */ void @@ -185,19 +332,6 @@ isc_hmacsha224_sign(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) { } /* - * Verify signature - finalize SHA224 operation and reapply SHA224, then - * compare to the supplied digest. - */ -isc_boolean_t -isc_hmacsha224_verify(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) { - unsigned char newdigest[ISC_SHA224_DIGESTLENGTH]; - - REQUIRE(len <= ISC_SHA224_DIGESTLENGTH); - isc_hmacsha224_sign(ctx, newdigest, ISC_SHA224_DIGESTLENGTH); - return (ISC_TF(memcmp(digest, newdigest, len) == 0)); -} - -/* * Start HMAC-SHA256 process. Initialize an sha256 context and digest the key. */ void @@ -265,19 +399,6 @@ isc_hmacsha256_sign(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) { } /* - * Verify signature - finalize SHA256 operation and reapply SHA256, then - * compare to the supplied digest. - */ -isc_boolean_t -isc_hmacsha256_verify(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) { - unsigned char newdigest[ISC_SHA256_DIGESTLENGTH]; - - REQUIRE(len <= ISC_SHA256_DIGESTLENGTH); - isc_hmacsha256_sign(ctx, newdigest, ISC_SHA256_DIGESTLENGTH); - return (ISC_TF(memcmp(digest, newdigest, len) == 0)); -} - -/* * Start HMAC-SHA384 process. Initialize an sha384 context and digest the key. */ void @@ -345,19 +466,6 @@ isc_hmacsha384_sign(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) { } /* - * Verify signature - finalize SHA384 operation and reapply SHA384, then - * compare to the supplied digest. - */ -isc_boolean_t -isc_hmacsha384_verify(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) { - unsigned char newdigest[ISC_SHA384_DIGESTLENGTH]; - - REQUIRE(len <= ISC_SHA384_DIGESTLENGTH); - isc_hmacsha384_sign(ctx, newdigest, ISC_SHA384_DIGESTLENGTH); - return (ISC_TF(memcmp(digest, newdigest, len) == 0)); -} - -/* * Start HMAC-SHA512 process. Initialize an sha512 context and digest the key. */ void @@ -423,6 +531,59 @@ isc_hmacsha512_sign(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) { memcpy(digest, newdigest, len); memset(newdigest, 0, sizeof(newdigest)); } +#endif /* !ISC_PLATFORM_OPENSSLHASH */ + +/* + * Verify signature - finalize SHA1 operation and reapply SHA1, then + * compare to the supplied digest. + */ +isc_boolean_t +isc_hmacsha1_verify(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) { + unsigned char newdigest[ISC_SHA1_DIGESTLENGTH]; + + REQUIRE(len <= ISC_SHA1_DIGESTLENGTH); + isc_hmacsha1_sign(ctx, newdigest, ISC_SHA1_DIGESTLENGTH); + return (ISC_TF(memcmp(digest, newdigest, len) == 0)); +} + +/* + * Verify signature - finalize SHA224 operation and reapply SHA224, then + * compare to the supplied digest. + */ +isc_boolean_t +isc_hmacsha224_verify(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) { + unsigned char newdigest[ISC_SHA224_DIGESTLENGTH]; + + REQUIRE(len <= ISC_SHA224_DIGESTLENGTH); + isc_hmacsha224_sign(ctx, newdigest, ISC_SHA224_DIGESTLENGTH); + return (ISC_TF(memcmp(digest, newdigest, len) == 0)); +} + +/* + * Verify signature - finalize SHA256 operation and reapply SHA256, then + * compare to the supplied digest. + */ +isc_boolean_t +isc_hmacsha256_verify(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) { + unsigned char newdigest[ISC_SHA256_DIGESTLENGTH]; + + REQUIRE(len <= ISC_SHA256_DIGESTLENGTH); + isc_hmacsha256_sign(ctx, newdigest, ISC_SHA256_DIGESTLENGTH); + return (ISC_TF(memcmp(digest, newdigest, len) == 0)); +} + +/* + * Verify signature - finalize SHA384 operation and reapply SHA384, then + * compare to the supplied digest. + */ +isc_boolean_t +isc_hmacsha384_verify(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) { + unsigned char newdigest[ISC_SHA384_DIGESTLENGTH]; + + REQUIRE(len <= ISC_SHA384_DIGESTLENGTH); + isc_hmacsha384_sign(ctx, newdigest, ISC_SHA384_DIGESTLENGTH); + return (ISC_TF(memcmp(digest, newdigest, len) == 0)); +} /* * Verify signature - finalize SHA512 operation and reapply SHA512, then diff --git a/lib/isc/httpd.c b/lib/isc/httpd.c index b653f79..81f118e 100644 --- a/lib/isc/httpd.c +++ b/lib/isc/httpd.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: httpd.c,v 1.16.64.2 2010-02-04 23:47:46 tbox Exp $ */ +/* $Id: httpd.c,v 1.20 2010-11-16 05:38:31 marka Exp $ */ /*! \file */ diff --git a/lib/isc/ia64/include/isc/atomic.h b/lib/isc/ia64/include/isc/atomic.h index 466cddb..11c9706 100644 --- a/lib/isc/ia64/include/isc/atomic.h +++ b/lib/isc/ia64/include/isc/atomic.h @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: atomic.h,v 1.4.326.3 2009-06-24 02:21:28 marka Exp $ */ +/* $Id: atomic.h,v 1.7 2009-06-24 02:22:50 marka Exp $ */ #ifndef ISC_ATOMIC_H #define ISC_ATOMIC_H 1 diff --git a/lib/isc/include/isc/Makefile.in b/lib/isc/include/isc/Makefile.in index c1d71f4..12c09cd 100644 --- a/lib/isc/include/isc/Makefile.in +++ b/lib/isc/include/isc/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.64.12.2 2009-02-12 23:47:22 tbox Exp $ +# $Id: Makefile.in,v 1.68 2009-12-05 23:31:41 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -26,15 +26,15 @@ top_srcdir = @top_srcdir@ # machine generated. The latter are handled specially in the # install target below. # -HEADERS = app.h assertions.h base64.h bitstring.h boolean.h buffer.h \ - bufferlist.h commandline.h entropy.h error.h event.h \ +HEADERS = app.h assertions.h base64.h bind9.h bitstring.h boolean.h \ + buffer.h bufferlist.h commandline.h entropy.h error.h event.h \ eventclass.h file.h formatcheck.h fsaccess.h \ hash.h heap.h hex.h hmacmd5.h \ httpd.h \ interfaceiter.h @ISC_IPV6_H@ iterated_hash.h lang.h lex.h \ lfsr.h lib.h list.h log.h \ - magic.h md5.h mem.h msgcat.h msgs.h \ - mutexblock.h netaddr.h ondestroy.h os.h parseint.h \ + magic.h md5.h mem.h msgcat.h msgs.h mutexblock.h \ + namespace.h netaddr.h ondestroy.h os.h parseint.h \ print.h quota.h radix.h random.h ratelimiter.h \ refcount.h region.h resource.h \ result.h resultclass.h rwlock.h serial.h sha1.h sha2.h \ diff --git a/lib/isc/include/isc/app.h b/lib/isc/include/isc/app.h index 0552758..ac8669f 100644 --- a/lib/isc/include/isc/app.h +++ b/lib/isc/include/isc/app.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: app.h,v 1.8 2007-06-19 23:47:18 tbox Exp $ */ +/* $Id: app.h,v 1.11 2009-09-02 23:48:03 tbox Exp $ */ #ifndef ISC_APP_H #define ISC_APP_H 1 @@ -54,12 +54,23 @@ * Use of this module is not required. In particular, isc_app_start() is * NOT an ISC library initialization routine. * + * This module also supports per-thread 'application contexts'. With this + * mode, a thread-based application will have a separate context, in which + * it uses other ISC library services such as tasks or timers. Signals are + * not caught in this mode, so that the application can handle the signals + * in its preferred way. + * * \li MP: * Clients must ensure that isc_app_start(), isc_app_run(), and * isc_app_finish() are called at most once. isc_app_shutdown() * is safe to use by any thread (provided isc_app_start() has been * called previously). * + * The same note applies to isc_app_ctxXXX() functions, but in this case + * it's a per-thread restriction. For example, a thread with an + * application context must ensure that isc_app_ctxstart() with the + * context is called at most once. + * * \li Reliability: * No anticipated impact. * @@ -75,17 +86,64 @@ #include #include +#include #include +/*** + *** Types + ***/ + typedef isc_event_t isc_appevent_t; #define ISC_APPEVENT_FIRSTEVENT (ISC_EVENTCLASS_APP + 0) #define ISC_APPEVENT_SHUTDOWN (ISC_EVENTCLASS_APP + 1) #define ISC_APPEVENT_LASTEVENT (ISC_EVENTCLASS_APP + 65535) +/*% + * app module methods. Only app driver implementations use this structure. + * Other clients should use the top-level interfaces (i.e., isc_app_xxx + * functions). magic must be ISCAPI_APPMETHODS_MAGIC. + */ +typedef struct isc_appmethods { + void (*ctxdestroy)(isc_appctx_t **ctxp); + isc_result_t (*ctxstart)(isc_appctx_t *ctx); + isc_result_t (*ctxrun)(isc_appctx_t *ctx); + isc_result_t (*ctxsuspend)(isc_appctx_t *ctx); + isc_result_t (*ctxshutdown)(isc_appctx_t *ctx); + void (*ctxfinish)(isc_appctx_t *ctx); + void (*settaskmgr)(isc_appctx_t *ctx, + isc_taskmgr_t *timermgr); + void (*setsocketmgr)(isc_appctx_t *ctx, + isc_socketmgr_t *timermgr); + void (*settimermgr)(isc_appctx_t *ctx, + isc_timermgr_t *timermgr); +} isc_appmethods_t; + +/*% + * This structure is actually just the common prefix of an application context + * implementation's version of an isc_appctx_t. + * \brief + * Direct use of this structure by clients is forbidden. app implementations + * may change the structure. 'magic' must be ISCAPI_APPCTX_MAGIC for any + * of the isc_app_ routines to work. app implementations must maintain + * all app context invariants. + */ +struct isc_appctx { + unsigned int impmagic; + unsigned int magic; + isc_appmethods_t *methods; +}; + +#define ISCAPI_APPCTX_MAGIC ISC_MAGIC('A','a','p','c') +#define ISCAPI_APPCTX_VALID(c) ((c) != NULL && \ + (c)->magic == ISCAPI_APPCTX_MAGIC) + ISC_LANG_BEGINDECLS isc_result_t +isc_app_ctxstart(isc_appctx_t *ctx); + +isc_result_t isc_app_start(void); /*!< * \brief Start an ISC library application. @@ -93,6 +151,9 @@ isc_app_start(void); * Notes: * This call should be made before any other ISC library call, and as * close to the beginning of the application as possible. + * + * Requires: + * 'ctx' is a valid application context (for app_ctxstart()). */ isc_result_t @@ -102,7 +163,7 @@ isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, * \brief Request delivery of an event when the application is run. * * Requires: - * isc_app_start() has been called. + *\li isc_app_start() has been called. * * Returns: * ISC_R_SUCCESS @@ -110,6 +171,9 @@ isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, */ isc_result_t +isc_app_ctxrun(isc_appctx_t *ctx); + +isc_result_t isc_app_run(void); /*!< * \brief Run an ISC library application. @@ -120,11 +184,12 @@ isc_app_run(void); * caller should start shutting down the application. * * Requires: - *\li isc_app_start() has been called. + *\li isc_app_[ctx]start() has been called. * * Ensures: *\li Any events requested via isc_app_onrun() will have been posted (in * FIFO order) before isc_app_run() blocks. + *\li 'ctx' is a valid application context (for app_ctxrun()). * * Returns: *\li ISC_R_SUCCESS Shutdown has been requested. @@ -132,6 +197,9 @@ isc_app_run(void); */ isc_result_t +isc_app_ctxshutdown(isc_appctx_t *ctx); + +isc_result_t isc_app_shutdown(void); /*!< * \brief Request application shutdown. @@ -141,7 +209,8 @@ isc_app_shutdown(void); * only be triggered once. * * Requires: - *\li isc_app_run() has been called. + *\li isc_app_[ctx]run() has been called. + *\li 'ctx' is a valid application context (for app_ctxshutdown()). * * Returns: *\li ISC_R_SUCCESS @@ -149,6 +218,12 @@ isc_app_shutdown(void); */ isc_result_t +isc_app_ctxsuspend(isc_appctx_t *ctx); +/*!< + * \brief This has the same behavior as isc_app_ctxsuspend(). + */ + +isc_result_t isc_app_reload(void); /*!< * \brief Request application reload. @@ -162,6 +237,9 @@ isc_app_reload(void); */ void +isc_app_ctxfinish(isc_appctx_t *ctx); + +void isc_app_finish(void); /*!< * \brief Finish an ISC library application. @@ -171,6 +249,7 @@ isc_app_finish(void); * * Requires: *\li isc_app_start() has been called. + *\li 'ctx' is a valid application context (for app_ctxfinish()). * * Ensures: *\li Any resources allocated by isc_app_start() have been released. @@ -206,6 +285,90 @@ isc_app_unblock(void); * \li isc_app_block() has been called by the same thread. */ +isc_result_t +isc_appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp); +/*!< + * \brief Create an application context. + * + * Requires: + *\li 'mctx' is a valid memory context. + *\li 'ctxp' != NULL && *ctxp == NULL. + */ + +void +isc_appctx_destroy(isc_appctx_t **ctxp); +/*!< + * \brief Destroy an application context. + * + * Requires: + *\li '*ctxp' is a valid application context. + * + * Ensures: + *\li *ctxp == NULL. + */ + +void +isc_appctx_settaskmgr(isc_appctx_t *ctx, isc_taskmgr_t *taskmgr); +/*!< + * \brief Associate a task manager with an application context. + * + * This must be done before running tasks within the application context. + * + * Requires: + *\li 'ctx' is a valid application context. + *\li 'taskmgr' is a valid task manager. + */ + +void +isc_appctx_setsocketmgr(isc_appctx_t *ctx, isc_socketmgr_t *socketmgr); +/*!< + * \brief Associate a socket manager with an application context. + * + * This must be done before handling socket events within the application + * context. + * + * Requires: + *\li 'ctx' is a valid application context. + *\li 'socketmgr' is a valid socket manager. + */ + +void +isc_appctx_settimermgr(isc_appctx_t *ctx, isc_timermgr_t *timermgr); +/*!< + * \brief Associate a socket timer with an application context. + * + * This must be done before handling timer events within the application + * context. + * + * Requires: + *\li 'ctx' is a valid application context. + *\li 'timermgr' is a valid timer manager. + */ + +#ifdef USE_APPIMPREGISTER +/*%< + * See isc_appctx_create() above. + */ +typedef isc_result_t +(*isc_appctxcreatefunc_t)(isc_mem_t *mctx, isc_appctx_t **ctxp); + +isc_result_t +isc_app_register(isc_appctxcreatefunc_t createfunc); +/*%< + * Register a new application implementation and add it to the list of + * supported implementations. This function must be called when a different + * event library is used than the one contained in the ISC library. + */ + +isc_result_t +isc__app_register(void); +/*%< + * A short cut function that specifies the application module in the ISC + * library for isc_app_register(). An application that uses the ISC library + * usually do not have to care about this function: it would call + * isc_lib_register(), which internally calls this function. + */ +#endif /* USE_APPIMPREGISTER */ ISC_LANG_ENDDECLS diff --git a/lib/isc/include/isc/assertions.h b/lib/isc/include/isc/assertions.h index 8a2ba7e..91217b8 100644 --- a/lib/isc/include/isc/assertions.h +++ b/lib/isc/include/isc/assertions.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1997-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -16,7 +16,7 @@ */ /* - * $Id: assertions.h,v 1.26 2008-10-15 23:47:31 tbox Exp $ + * $Id: assertions.h,v 1.28 2009-09-29 23:48:04 tbox Exp $ */ /*! \file isc/assertions.h */ @@ -41,7 +41,9 @@ typedef void (*isc_assertioncallback_t)(const char *, int, isc_assertiontype_t, const char *); /* coverity[+kill] */ -LIBISC_EXTERNAL_DATA extern isc_assertioncallback_t isc_assertion_failed; +ISC_PLATFORM_NORETURN_PRE +void isc_assertion_failed(const char *, int, isc_assertiontype_t, + const char *) ISC_PLATFORM_NORETURN_POST; void isc_assertion_setcallback(isc_assertioncallback_t); diff --git a/lib/isc/include/isc/backtrace.h b/lib/isc/include/isc/backtrace.h new file mode 100644 index 0000000..94fee61 --- /dev/null +++ b/lib/isc/include/isc/backtrace.h @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: backtrace.h,v 1.2 2009-09-01 18:40:25 jinmei Exp $ */ + +/*! \file isc/backtrace.h + * \brief provide a back trace of the running process to help debug problems. + * + * This module tries to get a back trace of the process using some platform + * dependent way when available. It also manages an internal symbol table + * that maps function addresses used in the process to their textual symbols. + * This module is expected to be used to help debug when some fatal error + * happens. + * + * IMPORTANT NOTE: since the (major) intended use case of this module is + * dumping a back trace on a fatal error, normally followed by self termination, + * functions defined in this module generally doesn't employ assertion checks + * (if it did, a program bug could cause infinite recursive calls to a + * backtrace function). These functions still perform minimal checks and return + * ISC_R_FAILURE if they detect an error, but the caller should therefore be + * very careful about the use of these functions, and generally discouraged to + * use them except in an exit path. The exception is + * isc_backtrace_getsymbolfromindex(), which is expected to be used in a + * non-error-handling context and validates arguments with assertion checks. + */ + +#ifndef ISC_BACKTRACE_H +#define ISC_BACKTRACE_H 1 + +/*** + *** Imports + ***/ + +#include + +/*** + *** Types + ***/ +struct isc_backtrace_symmap { + void *addr; + const char *symbol; +}; + +extern const int isc__backtrace_nsymbols; +extern const isc_backtrace_symmap_t isc__backtrace_symtable[]; + +/*** + *** Functions + ***/ + +ISC_LANG_BEGINDECLS +isc_result_t +isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes); +/*%< + * Get a back trace of the running process above this function itself. On + * success, addrs[i] will store the address of the call point of the i-th + * stack frame (addrs[0] is the caller of this function). *nframes will store + * the total number of frames. + * + * Requires (note that these are not ensured by assertion checks, see above): + * + *\li 'addrs' is a valid array containing at least 'maxaddrs' void * entries. + * + *\li 'nframes' must be non NULL. + * + * Returns: + * + *\li #ISC_R_SUCCESS + *\li #ISC_R_FAILURE + *\li #ISC_R_NOTFOUND + *\li #ISC_R_NOTIMPLEMENTED + */ + +isc_result_t +isc_backtrace_getsymbolfromindex(int index, const void **addrp, + const char **symbolp); +/*%< + * Returns the content of the internal symbol table of the given index. + * On success, *addrsp and *symbolp point to the address and the symbol of + * the 'index'th entry of the table, respectively. If 'index' is not in the + * range of the symbol table, ISC_R_RANGE will be returned. + * + * Requires + * + *\li 'addrp' must be non NULL && '*addrp' == NULL. + * + *\li 'symbolp' must be non NULL && '*symbolp' == NULL. + * + * Returns: + * + *\li #ISC_R_SUCCESS + *\li #ISC_R_RANGE + */ + +isc_result_t +isc_backtrace_getsymbol(const void *addr, const char **symbolp, + unsigned long *offsetp); +/*%< + * Searches the internal symbol table for the symbol that most matches the + * given 'addr'. On success, '*symbolp' will point to the name of function + * to which the address 'addr' belong, and '*offsetp' will store the offset + * from the function's entry address to 'addr'. + * + * Requires (note that these are not ensured by assertion checks, see above): + * + *\li 'symbolp' must be non NULL && '*symbolp' == NULL. + * + *\li 'offsetp' must be non NULL. + * + * Returns: + * + *\li #ISC_R_SUCCESS + *\li #ISC_R_FAILURE + *\li #ISC_R_NOTFOUND + */ +ISC_LANG_ENDDECLS + +#endif /* ISC_BACKTRACE_H */ diff --git a/lib/isc/include/isc/bind9.h b/lib/isc/include/isc/bind9.h new file mode 100644 index 0000000..dd75e91 --- /dev/null +++ b/lib/isc/include/isc/bind9.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: bind9.h,v 1.2 2009-12-05 23:31:41 each Exp $ */ + +#ifndef ISC_BIND9_H +#define ISC_BIND9_H 1 + +/* + * This determines whether we are building BIND9 or using the exported + * libisc/libdns libraries. The version of this file included in the + * standard BIND9 build defines BIND9; the version included with the + * exportable libraries does not. + */ +#define BIND9 1 + +#endif /* ISC_BIND9_H */ diff --git a/lib/isc/include/isc/buffer.h b/lib/isc/include/isc/buffer.h index e55c5b0..30a6e39 100644 --- a/lib/isc/include/isc/buffer.h +++ b/lib/isc/include/isc/buffer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: buffer.h,v 1.53 2008-09-25 04:02:39 tbox Exp $ */ +/* $Id: buffer.h,v 1.55 2010-12-20 23:47:21 tbox Exp $ */ #ifndef ISC_BUFFER_H #define ISC_BUFFER_H 1 diff --git a/lib/isc/include/isc/entropy.h b/lib/isc/include/isc/entropy.h index 1eb8fd1..e115906 100644 --- a/lib/isc/include/isc/entropy.h +++ b/lib/isc/include/isc/entropy.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: entropy.h,v 1.32.332.3 2009-10-19 02:46:07 marka Exp $ */ +/* $Id: entropy.h,v 1.35 2009-10-19 02:37:08 marka Exp $ */ #ifndef ISC_ENTROPY_H #define ISC_ENTROPY_H 1 diff --git a/lib/isc/include/isc/error.h b/lib/isc/include/isc/error.h index a0025e0..d3dcc8b 100644 --- a/lib/isc/include/isc/error.h +++ b/lib/isc/include/isc/error.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: error.h,v 1.20 2007-06-19 23:47:18 tbox Exp $ */ +/* $Id: error.h,v 1.22 2009-09-29 23:48:04 tbox Exp $ */ #ifndef ISC_ERROR_H #define ISC_ERROR_H 1 @@ -26,6 +26,7 @@ #include #include +#include ISC_LANG_BEGINDECLS @@ -45,9 +46,9 @@ isc_error_unexpected(const char *, int, const char *, ...) ISC_FORMAT_PRINTF(3, 4); /*% fatal error */ -void +ISC_PLATFORM_NORETURN_PRE void isc_error_fatal(const char *, int, const char *, ...) - ISC_FORMAT_PRINTF(3, 4); +ISC_FORMAT_PRINTF(3, 4) ISC_PLATFORM_NORETURN_POST; /*% runtimecheck error */ void diff --git a/lib/isc/include/isc/file.h b/lib/isc/include/isc/file.h index 6629a3e..be40825 100644 --- a/lib/isc/include/isc/file.h +++ b/lib/isc/include/isc/file.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: file.h,v 1.33.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: file.h,v 1.39 2011-01-11 23:47:14 tbox Exp $ */ #ifndef ISC_FILE_H #define ISC_FILE_H 1 @@ -100,6 +100,10 @@ isc_file_mktemplate(const char *path, char *buf, size_t buflen); isc_result_t isc_file_openunique(char *templet, FILE **fp); +isc_result_t +isc_file_openuniqueprivate(char *templet, FILE **fp); +isc_result_t +isc_file_openuniquemode(char *templet, int mode, FILE **fp); /*!< * \brief Create and open a file with a unique name based on 'templet'. * @@ -251,6 +255,29 @@ isc_file_truncate(const char *filename, isc_offset_t size); * Truncate/extend the file specified to 'size' bytes. */ +isc_result_t +isc_file_safecreate(const char *filename, FILE **fp); +/*%< + * Open 'filename' for writing, truncating if necessary. Ensure that + * if it existed it was a normal file. If creating the file, ensure + * that only the owner can read/write it. + */ + +isc_result_t +isc_file_splitpath(isc_mem_t *mctx, char *path, + char **dirname, char **basename); +/*%< + * Split a path into dirname and basename. If 'path' contains no slash + * (or, on windows, backslash), then '*dirname' is set to ".". + * + * Allocates memory for '*dirname', which can be freed with isc_mem_free(). + * + * Returns: + * - ISC_R_SUCCESS on success + * - ISC_R_INVALIDFILE if 'path' is empty or ends with '/' + * - ISC_R_NOMEMORY if unable to allocate memory + */ + ISC_LANG_ENDDECLS #endif /* ISC_FILE_H */ diff --git a/lib/isc/include/isc/fsaccess.h b/lib/isc/include/isc/fsaccess.h index 88469dd..9758242 100644 --- a/lib/isc/include/isc/fsaccess.h +++ b/lib/isc/include/isc/fsaccess.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: fsaccess.h,v 1.14.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: fsaccess.h,v 1.16 2009-01-17 23:47:43 tbox Exp $ */ #ifndef ISC_FSACCESS_H #define ISC_FSACCESS_H 1 diff --git a/lib/isc/include/isc/hash.h b/lib/isc/include/isc/hash.h index 9bfb709..543e5fd 100644 --- a/lib/isc/include/isc/hash.h +++ b/lib/isc/include/isc/hash.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: hash.h,v 1.10.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: hash.h,v 1.12 2009-01-17 23:47:43 tbox Exp $ */ #ifndef ISC_HASH_H #define ISC_HASH_H 1 diff --git a/lib/isc/include/isc/heap.h b/lib/isc/include/isc/heap.h index ae346c1..943ace3 100644 --- a/lib/isc/include/isc/heap.h +++ b/lib/isc/include/isc/heap.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: heap.h,v 1.24.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: heap.h,v 1.26 2009-01-17 23:47:43 tbox Exp $ */ #ifndef ISC_HEAP_H #define ISC_HEAP_H 1 diff --git a/lib/isc/include/isc/hmacmd5.h b/lib/isc/include/isc/hmacmd5.h index 68074ae..c7d7fff 100644 --- a/lib/isc/include/isc/hmacmd5.h +++ b/lib/isc/include/isc/hmacmd5.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: hmacmd5.h,v 1.12 2007-06-19 23:47:18 tbox Exp $ */ +/* $Id: hmacmd5.h,v 1.14 2009-02-06 23:47:42 tbox Exp $ */ /*! \file isc/hmacmd5.h * \brief This is the header file for the HMAC-MD5 keyed hash algorithm @@ -27,14 +27,23 @@ #include #include +#include #include #define ISC_HMACMD5_KEYLENGTH 64 +#ifdef ISC_PLATFORM_OPENSSLHASH +#include + +typedef HMAC_CTX isc_hmacmd5_t; + +#else + typedef struct { isc_md5_t md5ctx; unsigned char key[ISC_HMACMD5_KEYLENGTH]; } isc_hmacmd5_t; +#endif ISC_LANG_BEGINDECLS diff --git a/lib/isc/include/isc/hmacsha.h b/lib/isc/include/isc/hmacsha.h index c439883..286cafc 100644 --- a/lib/isc/include/isc/hmacsha.h +++ b/lib/isc/include/isc/hmacsha.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2005-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: hmacsha.h,v 1.7 2007-06-19 23:47:18 tbox Exp $ */ +/* $Id: hmacsha.h,v 1.9 2009-02-06 23:47:42 tbox Exp $ */ /*! \file isc/hmacsha.h * This is the header file for the HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, @@ -25,6 +25,7 @@ #define ISC_HMACSHA_H 1 #include +#include #include #include #include @@ -35,6 +36,17 @@ #define ISC_HMACSHA384_KEYLENGTH ISC_SHA384_BLOCK_LENGTH #define ISC_HMACSHA512_KEYLENGTH ISC_SHA512_BLOCK_LENGTH +#ifdef ISC_PLATFORM_OPENSSLHASH +#include + +typedef HMAC_CTX isc_hmacsha1_t; +typedef HMAC_CTX isc_hmacsha224_t; +typedef HMAC_CTX isc_hmacsha256_t; +typedef HMAC_CTX isc_hmacsha384_t; +typedef HMAC_CTX isc_hmacsha512_t; + +#else + typedef struct { isc_sha1_t sha1ctx; unsigned char key[ISC_HMACSHA1_KEYLENGTH]; @@ -59,6 +71,7 @@ typedef struct { isc_sha512_t sha512ctx; unsigned char key[ISC_HMACSHA512_KEYLENGTH]; } isc_hmacsha512_t; +#endif ISC_LANG_BEGINDECLS diff --git a/lib/isc/include/isc/lib.h b/lib/isc/include/isc/lib.h index 3804a07..c8bdbc6 100644 --- a/lib/isc/include/isc/lib.h +++ b/lib/isc/include/isc/lib.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lib.h,v 1.14 2007-06-19 23:47:18 tbox Exp $ */ +/* $Id: lib.h,v 1.16 2009-09-02 23:48:03 tbox Exp $ */ #ifndef ISC_LIB_H #define ISC_LIB_H 1 @@ -36,6 +36,15 @@ isc_lib_initmsgcat(void); * has not already been initialized. */ +void +isc_lib_register(void); +/*!< + * \brief Register the ISC library implementations for some base services + * such as memory or event management and handling socket or timer events. + * An external application that wants to use the ISC library must call this + * function very early in main(). + */ + ISC_LANG_ENDDECLS #endif /* ISC_LIB_H */ diff --git a/lib/isc/include/isc/log.h b/lib/isc/include/isc/log.h index fec3d9d..eac5755 100644 --- a/lib/isc/include/isc/log.h +++ b/lib/isc/include/isc/log.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: log.h,v 1.54.332.5 2009-02-16 02:04:05 marka Exp $ */ +/* $Id: log.h,v 1.59 2009-02-16 02:01:16 marka Exp $ */ #ifndef ISC_LOG_H #define ISC_LOG_H 1 diff --git a/lib/isc/include/isc/md5.h b/lib/isc/include/isc/md5.h index 9d5b1ec..9017115 100644 --- a/lib/isc/include/isc/md5.h +++ b/lib/isc/include/isc/md5.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: md5.h,v 1.16 2007-06-19 23:47:18 tbox Exp $ */ +/* $Id: md5.h,v 1.20 2010-01-07 23:48:54 tbox Exp $ */ /*! \file isc/md5.h * \brief This is the header file for the MD5 message-digest algorithm. @@ -44,15 +44,25 @@ #define ISC_MD5_H 1 #include +#include #include #define ISC_MD5_DIGESTLENGTH 16U +#define ISC_MD5_BLOCK_LENGTH 64U + +#ifdef ISC_PLATFORM_OPENSSLHASH +#include + +typedef EVP_MD_CTX isc_md5_t; + +#else typedef struct { isc_uint32_t buf[4]; isc_uint32_t bytes[2]; isc_uint32_t in[16]; } isc_md5_t; +#endif ISC_LANG_BEGINDECLS diff --git a/lib/isc/include/isc/mem.h b/lib/isc/include/isc/mem.h index d13d912..e0a7fe5 100644 --- a/lib/isc/include/isc/mem.h +++ b/lib/isc/include/isc/mem.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: mem.h,v 1.78.120.6 2010-08-11 23:04:21 jinmei Exp $ */ +/* $Id: mem.h,v 1.89 2010-08-11 22:54:58 jinmei Exp $ */ #ifndef ISC_MEM_H #define ISC_MEM_H 1 @@ -152,11 +152,29 @@ LIBISC_EXTERNAL_DATA extern unsigned int isc_mem_debugging; #endif -#define isc_mem_get(c, s) isc__mem_get((c), (s) _ISC_MEM_FILELINE) -#define isc_mem_allocate(c, s) isc__mem_allocate((c), (s) _ISC_MEM_FILELINE) -#define isc_mem_reallocate(c, p, s) isc__mem_reallocate((c), (p), (s) _ISC_MEM_FILELINE) -#define isc_mem_strdup(c, p) isc__mem_strdup((c), (p) _ISC_MEM_FILELINE) -#define isc_mempool_get(c) isc__mempool_get((c) _ISC_MEM_FILELINE) +/*%< + * We use either isc___mem (three underscores) or isc__mem (two) depending on + * whether it's for BIND9's internal purpose (with -DBIND9) or generic export + * library. This condition is generally handled in isc/namespace.h, but for + * Windows it doesn't work if it involves multiple times of macro expansion + * (such as isc_mem to isc__mem then to isc___mem). The following definitions + * are used to work around this portability issue. Right now, we don't support + * the export library for Windows, so we always use the three-underscore + * version. + */ +#ifdef WIN32 +#define ISCMEMFUNC(sfx) isc___mem_ ## sfx +#define ISCMEMPOOLFUNC(sfx) isc___mempool_ ## sfx +#else +#define ISCMEMFUNC(sfx) isc__mem_ ## sfx +#define ISCMEMPOOLFUNC(sfx) isc__mempool_ ## sfx +#endif + +#define isc_mem_get(c, s) ISCMEMFUNC(get)((c), (s) _ISC_MEM_FILELINE) +#define isc_mem_allocate(c, s) ISCMEMFUNC(allocate)((c), (s) _ISC_MEM_FILELINE) +#define isc_mem_reallocate(c, p, s) ISCMEMFUNC(reallocate)((c), (p), (s) _ISC_MEM_FILELINE) +#define isc_mem_strdup(c, p) ISCMEMFUNC(strdup)((c), (p) _ISC_MEM_FILELINE) +#define isc_mempool_get(c) ISCMEMPOOLFUNC(get)((c) _ISC_MEM_FILELINE) /*% * isc_mem_putanddetach() is a convenience function for use where you @@ -187,33 +205,102 @@ LIBISC_EXTERNAL_DATA extern unsigned int isc_mem_debugging; * \endcode */ +/*% memory and memory pool methods */ +typedef struct isc_memmethods { + void (*attach)(isc_mem_t *source, isc_mem_t **targetp); + void (*detach)(isc_mem_t **mctxp); + void (*destroy)(isc_mem_t **mctxp); + void *(*memget)(isc_mem_t *mctx, size_t size _ISC_MEM_FLARG); + void (*memput)(isc_mem_t *mctx, void *ptr, size_t size _ISC_MEM_FLARG); + void (*memputanddetach)(isc_mem_t **mctxp, void *ptr, + size_t size _ISC_MEM_FLARG); + void *(*memallocate)(isc_mem_t *mctx, size_t size _ISC_MEM_FLARG); + void *(*memreallocate)(isc_mem_t *mctx, void *ptr, + size_t size _ISC_MEM_FLARG); + char *(*memstrdup)(isc_mem_t *mctx, const char *s _ISC_MEM_FLARG); + void (*memfree)(isc_mem_t *mctx, void *ptr _ISC_MEM_FLARG); + void (*setdestroycheck)(isc_mem_t *mctx, isc_boolean_t flag); + void (*setwater)(isc_mem_t *ctx, isc_mem_water_t water, + void *water_arg, size_t hiwater, size_t lowater); + void (*waterack)(isc_mem_t *ctx, int flag); + size_t (*inuse)(isc_mem_t *mctx); + isc_boolean_t (*isovermem)(isc_mem_t *mctx); + isc_result_t (*mpcreate)(isc_mem_t *mctx, size_t size, + isc_mempool_t **mpctxp); +} isc_memmethods_t; + +typedef struct isc_mempoolmethods { + void (*destroy)(isc_mempool_t **mpctxp); + void *(*get)(isc_mempool_t *mpctx _ISC_MEM_FLARG); + void (*put)(isc_mempool_t *mpctx, void *mem _ISC_MEM_FLARG); + unsigned int (*getallocated)(isc_mempool_t *mpctx); + void (*setmaxalloc)(isc_mempool_t *mpctx, unsigned int limit); + void (*setfreemax)(isc_mempool_t *mpctx, unsigned int limit); + void (*setname)(isc_mempool_t *mpctx, const char *name); + void (*associatelock)(isc_mempool_t *mpctx, isc_mutex_t *lock); + void (*setfillcount)(isc_mempool_t *mpctx, unsigned int limit); +} isc_mempoolmethods_t; + +/*% + * This structure is actually just the common prefix of a memory context + * implementation's version of an isc_mem_t. + * \brief + * Direct use of this structure by clients is forbidden. mctx implementations + * may change the structure. 'magic' must be ISCAPI_MCTX_MAGIC for any of the + * isc_mem_ routines to work. mctx implementations must maintain all mctx + * invariants. + */ +struct isc_mem { + unsigned int impmagic; + unsigned int magic; + isc_memmethods_t *methods; +}; + +#define ISCAPI_MCTX_MAGIC ISC_MAGIC('A','m','c','x') +#define ISCAPI_MCTX_VALID(m) ((m) != NULL && \ + (m)->magic == ISCAPI_MCTX_MAGIC) + +/*% + * This is the common prefix of a memory pool context. The same note as + * that for the mem structure applies. + */ +struct isc_mempool { + unsigned int impmagic; + unsigned int magic; + isc_mempoolmethods_t *methods; +}; + +#define ISCAPI_MPOOL_MAGIC ISC_MAGIC('A','m','p','l') +#define ISCAPI_MPOOL_VALID(mp) ((mp) != NULL && \ + (mp)->magic == ISCAPI_MPOOL_MAGIC) + #if ISC_MEM_DEBUG #define isc_mem_put(c, p, s) \ do { \ - isc__mem_put((c), (p), (s) _ISC_MEM_FILELINE); \ + ISCMEMFUNC(put)((c), (p), (s) _ISC_MEM_FILELINE); \ (p) = NULL; \ } while (0) #define isc_mem_putanddetach(c, p, s) \ do { \ - isc__mem_putanddetach((c), (p), (s) _ISC_MEM_FILELINE); \ + ISCMEMFUNC(putanddetach)((c), (p), (s) _ISC_MEM_FILELINE); \ (p) = NULL; \ } while (0) #define isc_mem_free(c, p) \ do { \ - isc__mem_free((c), (p) _ISC_MEM_FILELINE); \ + ISCMEMFUNC(free)((c), (p) _ISC_MEM_FILELINE); \ (p) = NULL; \ } while (0) #define isc_mempool_put(c, p) \ do { \ - isc__mempool_put((c), (p) _ISC_MEM_FILELINE); \ + ISCMEMPOOLFUNC(put)((c), (p) _ISC_MEM_FILELINE); \ (p) = NULL; \ } while (0) #else -#define isc_mem_put(c, p, s) isc__mem_put((c), (p), (s) _ISC_MEM_FILELINE) +#define isc_mem_put(c, p, s) ISCMEMFUNC(put)((c), (p), (s) _ISC_MEM_FILELINE) #define isc_mem_putanddetach(c, p, s) \ - isc__mem_putanddetach((c), (p), (s) _ISC_MEM_FILELINE) -#define isc_mem_free(c, p) isc__mem_free((c), (p) _ISC_MEM_FILELINE) -#define isc_mempool_put(c, p) isc__mempool_put((c), (p) _ISC_MEM_FILELINE) + ISCMEMFUNC(putanddetach)((c), (p), (s) _ISC_MEM_FILELINE) +#define isc_mem_free(c, p) ISCMEMFUNC(free)((c), (p) _ISC_MEM_FILELINE) +#define isc_mempool_put(c, p) ISCMEMPOOLFUNC(put)((c), (p) _ISC_MEM_FILELINE) #endif /*@{*/ @@ -613,24 +700,50 @@ isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit); * Pseudo-private functions for use via macros. Do not call directly. */ void * -isc__mem_get(isc_mem_t *, size_t _ISC_MEM_FLARG); +ISCMEMFUNC(get)(isc_mem_t *, size_t _ISC_MEM_FLARG); void -isc__mem_putanddetach(isc_mem_t **, void *, - size_t _ISC_MEM_FLARG); +ISCMEMFUNC(putanddetach)(isc_mem_t **, void *, size_t _ISC_MEM_FLARG); void -isc__mem_put(isc_mem_t *, void *, size_t _ISC_MEM_FLARG); +ISCMEMFUNC(put)(isc_mem_t *, void *, size_t _ISC_MEM_FLARG); void * -isc__mem_allocate(isc_mem_t *, size_t _ISC_MEM_FLARG); +ISCMEMFUNC(allocate)(isc_mem_t *, size_t _ISC_MEM_FLARG); void * -isc__mem_reallocate(isc_mem_t *, void *, size_t _ISC_MEM_FLARG); +ISCMEMFUNC(reallocate)(isc_mem_t *, void *, size_t _ISC_MEM_FLARG); void -isc__mem_free(isc_mem_t *, void * _ISC_MEM_FLARG); +ISCMEMFUNC(free)(isc_mem_t *, void * _ISC_MEM_FLARG); char * -isc__mem_strdup(isc_mem_t *, const char *_ISC_MEM_FLARG); +ISCMEMFUNC(strdup)(isc_mem_t *, const char *_ISC_MEM_FLARG); void * -isc__mempool_get(isc_mempool_t * _ISC_MEM_FLARG); +ISCMEMPOOLFUNC(get)(isc_mempool_t * _ISC_MEM_FLARG); void -isc__mempool_put(isc_mempool_t *, void * _ISC_MEM_FLARG); +ISCMEMPOOLFUNC(put)(isc_mempool_t *, void * _ISC_MEM_FLARG); + +#ifdef USE_MEMIMPREGISTER + +/*%< + * See isc_mem_create2() above. + */ +typedef isc_result_t +(*isc_memcreatefunc_t)(size_t init_max_size, size_t target_size, + isc_mem_t **ctxp, unsigned int flags); + +isc_result_t +isc_mem_register(isc_memcreatefunc_t createfunc); +/*%< + * Register a new memory management implementation and add it to the list of + * supported implementations. This function must be called when a different + * memory management library is used than the one contained in the ISC library. + */ + +isc_result_t +isc__mem_register(void); +/*%< + * A short cut function that specifies the memory management module in the ISC + * library for isc_mem_register(). An application that uses the ISC library + * usually do not have to care about this function: it would call + * isc_lib_register(), which internally calls this function. + */ +#endif /* USE_MEMIMPREGISTER */ ISC_LANG_ENDDECLS diff --git a/lib/isc/include/isc/msgs.h b/lib/isc/include/isc/msgs.h index 674371f5..22dfde2 100644 --- a/lib/isc/include/isc/msgs.h +++ b/lib/isc/include/isc/msgs.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: msgs.h,v 1.17 2008-08-08 06:28:59 tbox Exp $ */ +/* $Id: msgs.h,v 1.19 2009-10-01 23:48:08 tbox Exp $ */ #ifndef ISC_MSGS_H #define ISC_MSGS_H 1 @@ -156,7 +156,7 @@ #define ISC_MSG_FILTER 1421 /*%< setsockopt(SO_ACCEPTFILTER): %s */ #define ISC_MSG_TOOMANYHANDLES 1422 /*%< %s: too many open WSA event handles: %s */ - +#define ISC_MSG_POKED 1423 /*%< "poked flags: %d" */ #define ISC_MSG_AWAKE 1502 /*%< "awake" */ #define ISC_MSG_WORKING 1503 /*%< "working" */ diff --git a/lib/isc/include/isc/namespace.h b/lib/isc/include/isc/namespace.h new file mode 100644 index 0000000..05a8b2c --- /dev/null +++ b/lib/isc/include/isc/namespace.h @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: namespace.h,v 1.9 2010-12-04 13:25:59 marka Exp $ */ + +#ifndef ISCAPI_NAMESPACE_H +#define ISCAPI_NAMESPACE_H 1 + +/*% + * name space conversions + */ + +#ifdef BIND9 + +#define isc_app_start isc__app_start +#define isc_app_ctxstart isc__app_ctxstart +#define isc_app_onrun isc__app_onrun +#define isc_app_run isc__app_run +#define isc_app_ctxrun isc__app_ctxrun +#define isc_app_shutdown isc__app_shutdown +#define isc_app_ctxshutdown isc__app_ctxshutdown +#define isc_app_ctxsuspend isc__app_ctxsuspend +#define isc_app_reload isc__app_reload +#define isc_app_finish isc__app_finish +#define isc_app_block isc__app_block +#define isc_app_unblock isc__app_unblock +#define isc_appctx_create isc__appctx_create +#define isc_appctx_destroy isc__appctx_destroy +#define isc_appctx_settaskmgr isc__appctx_settaskmgr +#define isc_appctx_setsocketmgr isc__appctx_setsocketmgr +#define isc_appctx_settimermgr isc__appctx_settimermgr + +#define isc_mem_checkdestroyed isc__mem_checkdestroyed +#define isc_mem_createx isc__mem_createx +#define isc_mem_createx2 isc__mem_createx2 +#define isc_mem_create isc__mem_create +#define isc_mem_create2 isc__mem_create2 +#define isc_mem_attach isc__mem_attach +#define isc_mem_detach isc__mem_detach +#define isc__mem_putanddetach isc___mem_putanddetach +#define isc_mem_destroy isc__mem_destroy +#define isc_mem_ondestroy isc__mem_ondestroy +#define isc__mem_get isc___mem_get +#define isc__mem_put isc___mem_put +#define isc_mem_stats isc__mem_stats +#define isc__mem_allocate isc___mem_allocate +#define isc__mem_free isc___mem_free +#define isc__mem_strdup isc___mem_strdup +#define isc__mem_reallocate isc___mem_reallocate +#define isc_mem_references isc__mem_references +#define isc_mem_setdestroycheck isc__mem_setdestroycheck +#define isc_mem_setquota isc__mem_setquota +#define isc_mem_getname isc__mem_getname +#define isc_mem_getquota isc__mem_getquota +#define isc_mem_gettag isc__mem_gettag +#define isc_mem_inuse isc__mem_inuse +#define isc_mem_isovermem isc__mem_isovermem +#define isc_mem_setname isc__mem_setname +#define isc_mem_setwater isc__mem_setwater +#define isc_mem_printallactive isc__mem_printallactive +#define isc_mem_waterack isc__mem_waterack +#define isc_mempool_create isc__mempool_create +#define isc_mempool_setname isc__mempool_setname +#define isc_mempool_destroy isc__mempool_destroy +#define isc_mempool_associatelock isc__mempool_associatelock +#define isc__mempool_get isc___mempool_get +#define isc__mempool_put isc___mempool_put +#define isc_mempool_setfreemax isc__mempool_setfreemax +#define isc_mempool_getfreemax isc__mempool_getfreemax +#define isc_mempool_getfreecount isc__mempool_getfreecount +#define isc_mempool_setmaxalloc isc__mempool_setmaxalloc +#define isc_mempool_getmaxalloc isc__mempool_getmaxalloc +#define isc_mempool_getallocated isc__mempool_getallocated +#define isc_mempool_setfillcount isc__mempool_setfillcount +#define isc_mempool_getfillcount isc__mempool_getfillcount + +#define isc_socket_create isc__socket_create +#define isc_socket_attach isc__socket_attach +#define isc_socket_detach isc__socket_detach +#define isc_socketmgr_create isc__socketmgr_create +#define isc_socketmgr_create2 isc__socketmgr_create2 +#define isc_socketmgr_destroy isc__socketmgr_destroy +#define isc_socket_open isc__socket_open +#define isc_socket_close isc__socket_close +#define isc_socket_recvv isc__socket_recvv +#define isc_socket_recv isc__socket_recv +#define isc_socket_recv2 isc__socket_recv2 +#define isc_socket_send isc__socket_send +#define isc_socket_sendto isc__socket_sendto +#define isc_socket_sendv isc__socket_sendv +#define isc_socket_sendtov isc__socket_sendtov +#define isc_socket_sendto2 isc__socket_sendto2 +#define isc_socket_cleanunix isc__socket_cleanunix +#define isc_socket_permunix isc__socket_permunix +#define isc_socket_bind isc__socket_bind +#define isc_socket_filter isc__socket_filter +#define isc_socket_listen isc__socket_listen +#define isc_socket_accept isc__socket_accept +#define isc_socket_connect isc__socket_connect +#define isc_socket_getname isc__socket_getname +#define isc_socket_gettag isc__socket_gettag +#define isc_socket_getpeername isc__socket_getpeername +#define isc_socket_getsockname isc__socket_getsockname +#define isc_socket_cancel isc__socket_cancel +#define isc_socket_gettype isc__socket_gettype +#define isc_socket_isbound isc__socket_isbound +#define isc_socket_ipv6only isc__socket_ipv6only +#define isc_socket_setname isc__socket_setname +#define isc_socketmgr_getmaxsockets isc__socketmgr_getmaxsockets +#define isc_socketmgr_setstats isc__socketmgr_setstats +#define isc_socketmgr_setreserved isc__socketmgr_setreserved +#define isc__socketmgr_maxudp isc___socketmgr_maxudp +#define isc_socket_fdwatchcreate isc__socket_fdwatchcreate +#define isc_socket_fdwatchpoke isc__socket_fdwatchpoke + +#define isc_task_create isc__task_create +#define isc_task_attach isc__task_attach +#define isc_task_detach isc__task_detach +/* #define isc_task_exiting isc__task_exiting XXXMPA */ +#define isc_task_send isc__task_send +#define isc_task_sendanddetach isc__task_sendanddetach +#define isc_task_purgerange isc__task_purgerange +#define isc_task_purge isc__task_purge +#define isc_task_purgeevent isc__task_purgeevent +#define isc_task_unsendrange isc__task_unsendrange +#define isc_task_unsend isc__task_unsend +#define isc_task_onshutdown isc__task_onshutdown +#define isc_task_shutdown isc__task_shutdown +#define isc_task_destroy isc__task_destroy +#define isc_task_setname isc__task_setname +#define isc_task_getname isc__task_getname +#define isc_task_gettag isc__task_gettag +#define isc_task_getcurrenttime isc__task_getcurrenttime +#define isc_taskmgr_create isc__taskmgr_create +#define isc_taskmgr_destroy isc__taskmgr_destroy +#define isc_task_beginexclusive isc__task_beginexclusive +#define isc_task_endexclusive isc__task_endexclusive + +#define isc_timer_create isc__timer_create +#define isc_timer_reset isc__timer_reset +#define isc_timer_gettype isc__timer_gettype +#define isc_timer_touch isc__timer_touch +#define isc_timer_attach isc__timer_attach +#define isc_timer_detach isc__timer_detach +#define isc_timermgr_create isc__timermgr_create +#define isc_timermgr_poke isc__timermgr_poke +#define isc_timermgr_destroy isc__timermgr_destroy + +#endif /* BIND9 */ + +#endif /* ISCAPI_NAMESPACE_H */ diff --git a/lib/isc/include/isc/netaddr.h b/lib/isc/include/isc/netaddr.h index 52418ec..04b7ec1 100644 --- a/lib/isc/include/isc/netaddr.h +++ b/lib/isc/include/isc/netaddr.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: netaddr.h,v 1.35.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: netaddr.h,v 1.37 2009-01-17 23:47:43 tbox Exp $ */ #ifndef ISC_NETADDR_H #define ISC_NETADDR_H 1 diff --git a/lib/isc/include/isc/netscope.h b/lib/isc/include/isc/netscope.h index 7b2c13c..1a50816 100644 --- a/lib/isc/include/isc/netscope.h +++ b/lib/isc/include/isc/netscope.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: netscope.h,v 1.11.332.2 2009-06-25 23:47:24 tbox Exp $ */ +/* $Id: netscope.h,v 1.13 2009-06-25 23:48:02 tbox Exp $ */ #ifndef ISC_NETSCOPE_H #define ISC_NETSCOPE_H 1 diff --git a/lib/isc/include/isc/platform.h.in b/lib/isc/include/isc/platform.h.in index 99c887b..2491274 100644 --- a/lib/isc/include/isc/platform.h.in +++ b/lib/isc/include/isc/platform.h.in @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: platform.h.in,v 1.48.84.4 2010-06-03 23:47:49 tbox Exp $ */ +/* $Id: platform.h.in,v 1.56 2010-12-18 01:56:23 each Exp $ */ #ifndef ISC_PLATFORM_H #define ISC_PLATFORM_H 1 @@ -146,6 +146,11 @@ */ @ISC_PLATFORM_HAVEDEVPOLL@ +/*! \brief + * Define if we want to log backtrace + */ +@ISC_PLATFORM_USEBACKTRACE@ + /* *** Printing. ***/ @@ -215,6 +220,12 @@ @ISC_PLATFORM_GSSAPIHEADER@ /* + * Defined to or for how to + * include the GSSAPI KRB5 header. + */ +@ISC_PLATFORM_GSSAPI_KRB5_HEADER@ + +/* * Defined to or for how to include * the KRB5 header. */ @@ -290,6 +301,17 @@ */ @ISC_PLATFORM_HAVESTRINGSH@ +/* + * Define if the hash functions must be provided by OpenSSL. + */ +@ISC_PLATFORM_OPENSSLHASH@ + +/* + * Defines for the noreturn attribute. + */ +@ISC_PLATFORM_NORETURN_PRE@ +@ISC_PLATFORM_NORETURN_POST@ + /*** *** Windows dll support. ***/ diff --git a/lib/isc/include/isc/portset.h b/lib/isc/include/isc/portset.h index a257322..2e27467 100644 --- a/lib/isc/include/isc/portset.h +++ b/lib/isc/include/isc/portset.h @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: portset.h,v 1.3.90.3 2009-06-25 05:31:51 marka Exp $ */ +/* $Id: portset.h,v 1.6 2009-06-25 05:28:34 marka Exp $ */ /*! \file isc/portset.h * \brief Transport Protocol Port Manipulation Module diff --git a/lib/isc/include/isc/radix.h b/lib/isc/include/isc/radix.h index fa5e294..ed8aaf2 100644 --- a/lib/isc/include/isc/radix.h +++ b/lib/isc/include/isc/radix.h @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: radix.h,v 1.11.44.2 2008-12-24 23:47:02 tbox Exp $ */ +/* $Id: radix.h,v 1.13 2008-12-01 23:47:45 tbox Exp $ */ /* * This source was adapted from MRT's RCS Ids: diff --git a/lib/isc/include/isc/random.h b/lib/isc/include/isc/random.h index 9743cb4..e05b204 100644 --- a/lib/isc/include/isc/random.h +++ b/lib/isc/include/isc/random.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: random.h,v 1.18.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: random.h,v 1.20 2009-01-17 23:47:43 tbox Exp $ */ #ifndef ISC_RANDOM_H #define ISC_RANDOM_H 1 diff --git a/lib/isc/include/isc/ratelimiter.h b/lib/isc/include/isc/ratelimiter.h index 7ed312a..f8a9819 100644 --- a/lib/isc/include/isc/ratelimiter.h +++ b/lib/isc/include/isc/ratelimiter.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ratelimiter.h,v 1.21.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: ratelimiter.h,v 1.23 2009-01-18 23:48:14 tbox Exp $ */ #ifndef ISC_RATELIMITER_H #define ISC_RATELIMITER_H 1 diff --git a/lib/isc/include/isc/refcount.h b/lib/isc/include/isc/refcount.h index 8e83a13..71f35f1 100644 --- a/lib/isc/include/isc/refcount.h +++ b/lib/isc/include/isc/refcount.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: refcount.h,v 1.15 2007-06-19 23:47:18 tbox Exp $ */ +/* $Id: refcount.h,v 1.17 2009-09-29 23:48:04 tbox Exp $ */ #ifndef ISC_REFCOUNT_H #define ISC_REFCOUNT_H 1 @@ -28,7 +28,7 @@ #include /*! \file isc/refcount.h - * \brief Implements a locked reference counter. + * \brief Implements a locked reference counter. * * These functions may actually be * implemented using macros, and implementations of these macros are below. @@ -42,7 +42,7 @@ ISC_LANG_BEGINDECLS * Function prototypes */ -/* +/* * isc_result_t * isc_refcount_init(isc_refcount_t *ref, unsigned int n); * @@ -103,7 +103,7 @@ typedef struct isc_refcount { isc_int32_t refs; } isc_refcount_t; -#define isc_refcount_destroy(rp) (REQUIRE((rp)->refs == 0)) +#define isc_refcount_destroy(rp) REQUIRE((rp)->refs == 0) #define isc_refcount_current(rp) ((unsigned int)((rp)->refs)) #define isc_refcount_increment0(rp, tp) \ @@ -192,7 +192,7 @@ typedef struct isc_refcount { int refs; } isc_refcount_t; -#define isc_refcount_destroy(rp) (REQUIRE((rp)->refs == 0)) +#define isc_refcount_destroy(rp) REQUIRE((rp)->refs == 0) #define isc_refcount_current(rp) ((unsigned int)((rp)->refs)) #define isc_refcount_increment0(rp, tp) \ diff --git a/lib/isc/include/isc/result.h b/lib/isc/include/isc/result.h index 804ab5e..cc591dc 100644 --- a/lib/isc/include/isc/result.h +++ b/lib/isc/include/isc/result.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: result.h,v 1.71 2008-09-25 04:02:39 tbox Exp $ */ +/* $Id: result.h,v 1.73 2009-09-02 23:48:03 tbox Exp $ */ #ifndef ISC_RESULT_H #define ISC_RESULT_H 1 @@ -42,6 +42,7 @@ #define ISC_R_EOF 14 /*%< end of file */ #define ISC_R_BOUND 15 /*%< socket already bound */ #define ISC_R_RELOAD 16 /*%< reload */ +#define ISC_R_SUSPEND ISC_R_RELOAD /*%< alias of 'reload' */ #define ISC_R_LOCKBUSY 17 /*%< lock busy */ #define ISC_R_EXISTS 18 /*%< already exists */ #define ISC_R_NOSPACE 19 /*%< ran out of space */ diff --git a/lib/isc/include/isc/resultclass.h b/lib/isc/include/isc/resultclass.h index 86c55b6..84f6c64 100644 --- a/lib/isc/include/isc/resultclass.h +++ b/lib/isc/include/isc/resultclass.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resultclass.h,v 1.18 2007-06-19 23:47:18 tbox Exp $ */ +/* $Id: resultclass.h,v 1.20 2009-09-02 23:48:03 tbox Exp $ */ #ifndef ISC_RESULTCLASS_H #define ISC_RESULTCLASS_H 1 @@ -45,6 +45,7 @@ #define ISC_RESULTCLASS_DNSRCODE ISC_RESULTCLASS_FROMNUM(3) #define ISC_RESULTCLASS_OMAPI ISC_RESULTCLASS_FROMNUM(4) #define ISC_RESULTCLASS_ISCCC ISC_RESULTCLASS_FROMNUM(5) +#define ISC_RESULTCLASS_DHCP ISC_RESULTCLASS_FROMNUM(6) #endif /* ISC_RESULTCLASS_H */ diff --git a/lib/isc/include/isc/serial.h b/lib/isc/include/isc/serial.h index 97d5fe1..332709d 100644 --- a/lib/isc/include/isc/serial.h +++ b/lib/isc/include/isc/serial.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: serial.h,v 1.16.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: serial.h,v 1.18 2009-01-18 23:48:14 tbox Exp $ */ #ifndef ISC_SERIAL_H #define ISC_SERIAL_H 1 diff --git a/lib/isc/include/isc/sha1.h b/lib/isc/include/isc/sha1.h index 4da682a..a9d08b9 100644 --- a/lib/isc/include/isc/sha1.h +++ b/lib/isc/include/isc/sha1.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -18,7 +18,7 @@ #ifndef ISC_SHA1_H #define ISC_SHA1_H 1 -/* $Id: sha1.h,v 1.17 2007-06-19 23:47:18 tbox Exp $ */ +/* $Id: sha1.h,v 1.19 2009-02-06 23:47:42 tbox Exp $ */ /* $NetBSD: sha1.h,v 1.2 1998/05/29 22:55:44 thorpej Exp $ */ @@ -29,16 +29,25 @@ */ #include +#include #include #define ISC_SHA1_DIGESTLENGTH 20U #define ISC_SHA1_BLOCK_LENGTH 64U +#ifdef ISC_PLATFORM_OPENSSLHASH +#include + +typedef EVP_MD_CTX isc_sha1_t; + +#else + typedef struct { isc_uint32_t state[5]; isc_uint32_t count[2]; unsigned char buffer[ISC_SHA1_BLOCK_LENGTH]; } isc_sha1_t; +#endif ISC_LANG_BEGINDECLS diff --git a/lib/isc/include/isc/sha2.h b/lib/isc/include/isc/sha2.h index c3130a8..8d4ffa6 100644 --- a/lib/isc/include/isc/sha2.h +++ b/lib/isc/include/isc/sha2.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2005-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sha2.h,v 1.9.332.2 2010-01-15 23:47:34 tbox Exp $ */ +/* $Id: sha2.h,v 1.12 2009-10-22 02:21:31 each Exp $ */ /* $FreeBSD$ */ /* $KAME: sha2.h,v 1.3 2001/03/12 08:27:48 itojun Exp $ */ @@ -58,6 +58,7 @@ #define ISC_SHA2_H #include +#include #include /*** SHA-224/256/384/512 Various Length Definitions ***********************/ @@ -75,10 +76,15 @@ #define ISC_SHA512_DIGESTLENGTH 64U #define ISC_SHA512_DIGESTSTRINGLENGTH (ISC_SHA512_DIGESTLENGTH * 2 + 1) +/*** SHA-256/384/512 Context Structures *******************************/ -ISC_LANG_BEGINDECLS +#ifdef ISC_PLATFORM_OPENSSLHASH +#include -/*** SHA-256/384/512 Context Structures *******************************/ +typedef EVP_MD_CTX isc_sha256_t; +typedef EVP_MD_CTX isc_sha512_t; + +#else /* * Keep buffer immediately after bitcount to preserve alignment. @@ -97,10 +103,13 @@ typedef struct { isc_uint64_t bitcount[2]; isc_uint8_t buffer[ISC_SHA512_BLOCK_LENGTH]; } isc_sha512_t; +#endif typedef isc_sha256_t isc_sha224_t; typedef isc_sha512_t isc_sha384_t; +ISC_LANG_BEGINDECLS + /*** SHA-224/256/384/512 Function Prototypes ******************************/ void isc_sha224_init (isc_sha224_t *); diff --git a/lib/isc/include/isc/sockaddr.h b/lib/isc/include/isc/sockaddr.h index 758cef7..c83655e 100644 --- a/lib/isc/include/isc/sockaddr.h +++ b/lib/isc/include/isc/sockaddr.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sockaddr.h,v 1.55.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: sockaddr.h,v 1.57 2009-01-18 23:48:14 tbox Exp $ */ #ifndef ISC_SOCKADDR_H #define ISC_SOCKADDR_H 1 diff --git a/lib/isc/include/isc/socket.h b/lib/isc/include/isc/socket.h index 749ee52..0aa71da 100644 --- a/lib/isc/include/isc/socket.h +++ b/lib/isc/include/isc/socket.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: socket.h,v 1.85.58.3 2009-01-29 22:40:35 jinmei Exp $ */ +/* $Id: socket.h,v 1.94 2009-10-01 01:30:01 sar Exp $ */ #ifndef ISC_SOCKET_H #define ISC_SOCKET_H 1 @@ -260,6 +260,85 @@ typedef enum { #define ISC_SOCKFDWATCH_WRITE 0x00000002 /*%< watch for writable */ /*@}*/ +/*% Socket and socket manager methods */ +typedef struct isc_socketmgrmethods { + void (*destroy)(isc_socketmgr_t **managerp); + isc_result_t (*socketcreate)(isc_socketmgr_t *manager, int pf, + isc_sockettype_t type, + isc_socket_t **socketp); + isc_result_t (*fdwatchcreate)(isc_socketmgr_t *manager, int fd, + int flags, + isc_sockfdwatch_t callback, + void *cbarg, isc_task_t *task, + isc_socket_t **socketp); +} isc_socketmgrmethods_t; + +typedef struct isc_socketmethods { + void (*attach)(isc_socket_t *socket, + isc_socket_t **socketp); + void (*detach)(isc_socket_t **socketp); + isc_result_t (*bind)(isc_socket_t *sock, isc_sockaddr_t *sockaddr, + unsigned int options); + isc_result_t (*sendto)(isc_socket_t *sock, isc_region_t *region, + isc_task_t *task, isc_taskaction_t action, + const void *arg, isc_sockaddr_t *address, + struct in6_pktinfo *pktinfo); + isc_result_t (*connect)(isc_socket_t *sock, isc_sockaddr_t *addr, + isc_task_t *task, isc_taskaction_t action, + const void *arg); + isc_result_t (*recv)(isc_socket_t *sock, isc_region_t *region, + unsigned int minimum, isc_task_t *task, + isc_taskaction_t action, const void *arg); + void (*cancel)(isc_socket_t *sock, isc_task_t *task, + unsigned int how); + isc_result_t (*getsockname)(isc_socket_t *sock, + isc_sockaddr_t *addressp); + isc_sockettype_t (*gettype)(isc_socket_t *sock); + void (*ipv6only)(isc_socket_t *sock, isc_boolean_t yes); + isc_result_t (*fdwatchpoke)(isc_socket_t *sock, int flags); +} isc_socketmethods_t; + +/*% + * This structure is actually just the common prefix of a socket manager + * object implementation's version of an isc_socketmgr_t. + * \brief + * Direct use of this structure by clients is forbidden. socket implementations + * may change the structure. 'magic' must be ISCAPI_SOCKETMGR_MAGIC for any + * of the isc_socket_ routines to work. socket implementations must maintain + * all socket invariants. + * In effect, this definition is used only for non-BIND9 version ("export") + * of the library, and the export version does not work for win32. So, to avoid + * the definition conflict with win32/socket.c, we enable this definition only + * for non-Win32 (i.e. Unix) platforms. + */ +#ifndef WIN32 +struct isc_socketmgr { + unsigned int impmagic; + unsigned int magic; + isc_socketmgrmethods_t *methods; +}; +#endif + +#define ISCAPI_SOCKETMGR_MAGIC ISC_MAGIC('A','s','m','g') +#define ISCAPI_SOCKETMGR_VALID(m) ((m) != NULL && \ + (m)->magic == ISCAPI_SOCKETMGR_MAGIC) + +/*% + * This is the common prefix of a socket object. The same note as + * that for the socketmgr structure applies. + */ +#ifndef WIN32 +struct isc_socket { + unsigned int impmagic; + unsigned int magic; + isc_socketmethods_t *methods; +}; +#endif + +#define ISCAPI_SOCKET_MAGIC ISC_MAGIC('A','s','c','t') +#define ISCAPI_SOCKET_VALID(s) ((s) != NULL && \ + (s)->magic == ISCAPI_SOCKET_MAGIC) + /*** *** Socket and Socket Manager Functions *** @@ -307,6 +386,35 @@ isc_socket_fdwatchcreate(isc_socketmgr_t *manager, */ isc_result_t +isc_socket_fdwatchpoke(isc_socket_t *sock, + int flags); +/*%< + * Poke a file descriptor watch socket informing the manager that it + * should restart watching the socket + * + * Note: + * + *\li 'sock' is the socket returned by isc_socket_fdwatchcreate + * + *\li 'flags' indicates what the manager should watch for on the socket + * in addition to what it may already be watching. It can be one or + * both of ISC_SOCKFDWATCH_READ and ISC_SOCKFDWATCH_WRITE. To + * temporarily disable watching on a socket the value indicating + * no more data should be returned from the call back routine. + * + *\li This function is not available on Windows. + * + * Requires: + * + *\li 'sock' is a valid isc socket + * + * + * Returns: + * + *\li #ISC_R_SUCCESS + */ + +isc_result_t isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, @@ -821,6 +929,10 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region, /*@}*/ isc_result_t +isc_socketmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, + isc_socketmgr_t **managerp); + +isc_result_t isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp); isc_result_t @@ -831,6 +943,8 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, * maximum number of sockets that the created manager should handle. * isc_socketmgr_create() is equivalent of isc_socketmgr_create2() with * "maxsocks" being zero. + * isc_socketmgr_createinctx() also associates the new manager with the + * specified application context. * * Notes: * @@ -842,6 +956,8 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, * *\li 'managerp' points to a NULL isc_socketmgr_t. * + *\li 'actx' is a valid application context (for createinctx()). + * * Ensures: * *\li '*managerp' is a valid isc_socketmgr_t. @@ -992,6 +1108,12 @@ isc__socketmgr_setreserved(isc_socketmgr_t *mgr, isc_uint32_t); * Temporary. For use by named only. */ +void +isc__socketmgr_maxudp(isc_socketmgr_t *mgr, int maxudp); +/*%< + * Test interface. Drop UDP packet > 'maxudp'. + */ + #ifdef HAVE_LIBXML2 void @@ -1002,6 +1124,31 @@ isc_socketmgr_renderxml(isc_socketmgr_t *mgr, xmlTextWriterPtr writer); #endif /* HAVE_LIBXML2 */ +#ifdef USE_SOCKETIMPREGISTER +/*%< + * See isc_socketmgr_create() above. + */ +typedef isc_result_t +(*isc_socketmgrcreatefunc_t)(isc_mem_t *mctx, isc_socketmgr_t **managerp); + +isc_result_t +isc_socket_register(isc_socketmgrcreatefunc_t createfunc); +/*%< + * Register a new socket I/O implementation and add it to the list of + * supported implementations. This function must be called when a different + * event library is used than the one contained in the ISC library. + */ + +isc_result_t +isc__socket_register(void); +/*%< + * A short cut function that specifies the socket I/O module in the ISC + * library for isc_socket_register(). An application that uses the ISC library + * usually do not have to care about this function: it would call + * isc_lib_register(), which internally calls this function. + */ +#endif /* USE_SOCKETIMPREGISTER */ + ISC_LANG_ENDDECLS #endif /* ISC_SOCKET_H */ diff --git a/lib/isc/include/isc/stats.h b/lib/isc/include/isc/stats.h index 1148a16..226bc08 100644 --- a/lib/isc/include/isc/stats.h +++ b/lib/isc/include/isc/stats.h @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: stats.h,v 1.4.2.2 2009-01-29 23:47:44 tbox Exp $ */ +/* $Id: stats.h,v 1.4 2009-01-29 01:03:56 jinmei Exp $ */ #ifndef ISC_STATS_H #define ISC_STATS_H 1 diff --git a/lib/isc/include/isc/symtab.h b/lib/isc/include/isc/symtab.h index a1d7102..c61d0ea 100644 --- a/lib/isc/include/isc/symtab.h +++ b/lib/isc/include/isc/symtab.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: symtab.h,v 1.24.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: symtab.h,v 1.26 2009-01-18 23:48:14 tbox Exp $ */ #ifndef ISC_SYMTAB_H #define ISC_SYMTAB_H 1 diff --git a/lib/isc/include/isc/task.h b/lib/isc/include/isc/task.h index a8c7569..a2a1bbe 100644 --- a/lib/isc/include/isc/task.h +++ b/lib/isc/include/isc/task.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: task.h,v 1.61.332.4 2010-12-03 23:45:47 tbox Exp $ */ +/* $Id: task.h,v 1.69.14.1.2.1 2011-06-02 23:47:36 tbox Exp $ */ #ifndef ISC_TASK_H #define ISC_TASK_H 1 @@ -96,6 +96,72 @@ ISC_LANG_BEGINDECLS +/*** + *** Types + ***/ + +/*% Task and task manager methods */ +typedef struct isc_taskmgrmethods { + void (*destroy)(isc_taskmgr_t **managerp); + isc_result_t (*taskcreate)(isc_taskmgr_t *manager, + unsigned int quantum, + isc_task_t **taskp); +} isc_taskmgrmethods_t; + +typedef struct isc_taskmethods { + void (*attach)(isc_task_t *source, isc_task_t **targetp); + void (*detach)(isc_task_t **taskp); + void (*destroy)(isc_task_t **taskp); + void (*send)(isc_task_t *task, isc_event_t **eventp); + void (*sendanddetach)(isc_task_t **taskp, isc_event_t **eventp); + unsigned int (*unsend)(isc_task_t *task, void *sender, isc_eventtype_t type, + void *tag, isc_eventlist_t *events); + isc_result_t (*onshutdown)(isc_task_t *task, isc_taskaction_t action, + const void *arg); + void (*shutdown)(isc_task_t *task); + void (*setname)(isc_task_t *task, const char *name, void *tag); + unsigned int (*purgeevents)(isc_task_t *task, void *sender, + isc_eventtype_t type, void *tag); + unsigned int (*purgerange)(isc_task_t *task, void *sender, + isc_eventtype_t first, isc_eventtype_t last, + void *tag); + isc_result_t (*beginexclusive)(isc_task_t *task); + void (*endexclusive)(isc_task_t *task); +} isc_taskmethods_t; + +/*% + * This structure is actually just the common prefix of a task manager + * object implementation's version of an isc_taskmgr_t. + * \brief + * Direct use of this structure by clients is forbidden. task implementations + * may change the structure. 'magic' must be ISCAPI_TASKMGR_MAGIC for any + * of the isc_task_ routines to work. task implementations must maintain + * all task invariants. + */ +struct isc_taskmgr { + unsigned int impmagic; + unsigned int magic; + isc_taskmgrmethods_t *methods; +}; + +#define ISCAPI_TASKMGR_MAGIC ISC_MAGIC('A','t','m','g') +#define ISCAPI_TASKMGR_VALID(m) ((m) != NULL && \ + (m)->magic == ISCAPI_TASKMGR_MAGIC) + +/*% + * This is the common prefix of a task object. The same note as + * that for the taskmgr structure applies. + */ +struct isc_task { + unsigned int impmagic; + unsigned int magic; + isc_taskmethods_t *methods; +}; + +#define ISCAPI_TASK_MAGIC ISC_MAGIC('A','t','s','t') +#define ISCAPI_TASK_VALID(s) ((s) != NULL && \ + (s)->magic == ISCAPI_TASK_MAGIC) + isc_result_t isc_task_create(isc_taskmgr_t *manager, unsigned int quantum, isc_task_t **taskp); @@ -550,10 +616,15 @@ isc_task_exiting(isc_task_t *t); *****/ isc_result_t +isc_taskmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, + unsigned int workers, unsigned int default_quantum, + isc_taskmgr_t **managerp); +isc_result_t isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, unsigned int default_quantum, isc_taskmgr_t **managerp); /*%< - * Create a new task manager. + * Create a new task manager. isc_taskmgr_createinctx() also associates + * the new manager with the specified application context. * * Notes: * @@ -575,6 +646,8 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, * *\li managerp != NULL && *managerp == NULL * + *\li 'actx' is a valid application context (for createinctx()). + * * Ensures: * *\li On success, '*managerp' will be attached to the newly created task @@ -584,8 +657,10 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, * *\li #ISC_R_SUCCESS *\li #ISC_R_NOMEMORY - *\li #ISC_R_NOTHREADS No threads could be created. + *\li #ISC_R_NOTHREADS No threads could be created. *\li #ISC_R_UNEXPECTED An unexpected error occurred. + *\li #ISC_R_SHUTTINGDOWN The non-threaded, shared, task + * manager shutting down. */ void @@ -629,6 +704,31 @@ isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer); #endif +/*%< + * See isc_taskmgr_create() above. + */ +typedef isc_result_t +(*isc_taskmgrcreatefunc_t)(isc_mem_t *mctx, unsigned int workers, + unsigned int default_quantum, + isc_taskmgr_t **managerp); + +isc_result_t +isc_task_register(isc_taskmgrcreatefunc_t createfunc); +/*%< + * Register a new task management implementation and add it to the list of + * supported implementations. This function must be called when a different + * event library is used than the one contained in the ISC library. + */ + +isc_result_t +isc__task_register(void); +/*%< + * A short cut function that specifies the task management module in the ISC + * library for isc_task_register(). An application that uses the ISC library + * usually do not have to care about this function: it would call + * isc_lib_register(), which internally calls this function. + */ + ISC_LANG_ENDDECLS #endif /* ISC_TASK_H */ diff --git a/lib/isc/include/isc/timer.h b/lib/isc/include/isc/timer.h index 052e25b..a54e73b 100644 --- a/lib/isc/include/isc/timer.h +++ b/lib/isc/include/isc/timer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: timer.h,v 1.40 2008-06-23 23:47:11 tbox Exp $ */ +/* $Id: timer.h,v 1.43 2009-09-02 23:48:03 tbox Exp $ */ #ifndef ISC_TIMER_H #define ISC_TIMER_H 1 @@ -103,6 +103,61 @@ typedef struct isc_timerevent { #define ISC_TIMEREVENT_LIFE (ISC_EVENTCLASS_TIMER + 3) #define ISC_TIMEREVENT_LASTEVENT (ISC_EVENTCLASS_TIMER + 65535) +/*% Timer and timer manager methods */ +typedef struct { + void (*destroy)(isc_timermgr_t **managerp); + isc_result_t (*timercreate)(isc_timermgr_t *manager, + isc_timertype_t type, + isc_time_t *expires, + isc_interval_t *interval, + isc_task_t *task, + isc_taskaction_t action, + const void *arg, + isc_timer_t **timerp); +} isc_timermgrmethods_t; + +typedef struct { + void (*attach)(isc_timer_t *timer, isc_timer_t **timerp); + void (*detach)(isc_timer_t **timerp); + isc_result_t (*reset)(isc_timer_t *timer, isc_timertype_t type, + isc_time_t *expires, isc_interval_t *interval, + isc_boolean_t purge); + isc_result_t (*touch)(isc_timer_t *timer); +} isc_timermethods_t; + +/*% + * This structure is actually just the common prefix of a timer manager + * object implementation's version of an isc_timermgr_t. + * \brief + * Direct use of this structure by clients is forbidden. timer implementations + * may change the structure. 'magic' must be ISCAPI_TIMERMGR_MAGIC for any + * of the isc_timer_ routines to work. timer implementations must maintain + * all timer invariants. + */ +struct isc_timermgr { + unsigned int impmagic; + unsigned int magic; + isc_timermgrmethods_t *methods; +}; + +#define ISCAPI_TIMERMGR_MAGIC ISC_MAGIC('A','t','m','g') +#define ISCAPI_TIMERMGR_VALID(m) ((m) != NULL && \ + (m)->magic == ISCAPI_TIMERMGR_MAGIC) + +/*% + * This is the common prefix of a timer object. The same note as + * that for the timermgr structure applies. + */ +struct isc_timer { + unsigned int impmagic; + unsigned int magic; + isc_timermethods_t *methods; +}; + +#define ISCAPI_TIMER_MAGIC ISC_MAGIC('A','t','m','r') +#define ISCAPI_TIMER_VALID(s) ((s) != NULL && \ + (s)->magic == ISCAPI_TIMER_MAGIC) + /*** *** Timer and Timer Manager Functions *** @@ -289,9 +344,14 @@ isc_timer_gettype(isc_timer_t *timer); */ isc_result_t +isc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, + isc_timermgr_t **managerp); + +isc_result_t isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp); /*%< - * Create a timer manager. + * Create a timer manager. isc_timermgr_createinctx() also associates + * the new manager with the specified application context. * * Notes: * @@ -303,6 +363,8 @@ isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp); * *\li 'managerp' points to a NULL isc_timermgr_t. * + *\li 'actx' is a valid application context (for createinctx()). + * * Ensures: * *\li '*managerp' is a valid isc_timermgr_t. @@ -339,6 +401,31 @@ isc_timermgr_destroy(isc_timermgr_t **managerp); void isc_timermgr_poke(isc_timermgr_t *m); +#ifdef USE_TIMERIMPREGISTER +/*%< + * See isc_timermgr_create() above. + */ +typedef isc_result_t +(*isc_timermgrcreatefunc_t)(isc_mem_t *mctx, isc_timermgr_t **managerp); + +isc_result_t +isc__timer_register(void); +/*%< + * Register a new timer management implementation and add it to the list of + * supported implementations. This function must be called when a different + * event library is used than the one contained in the ISC library. + */ + +isc_result_t +isc_timer_register(isc_timermgrcreatefunc_t createfunc); +/*%< + * A short cut function that specifies the timer management module in the ISC + * library for isc_timer_register(). An application that uses the ISC library + * usually do not have to care about this function: it would call + * isc_lib_register(), which internally calls this function. + */ +#endif /* USE_TIMERIMPREGISTER */ + ISC_LANG_ENDDECLS #endif /* ISC_TIMER_H */ diff --git a/lib/isc/include/isc/types.h b/lib/isc/include/isc/types.h index 01362b8..10da62b 100644 --- a/lib/isc/include/isc/types.h +++ b/lib/isc/include/isc/types.h @@ -15,11 +15,14 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: types.h,v 1.46.84.2 2009-01-29 23:47:44 tbox Exp $ */ +/* $Id: types.h,v 1.52 2009-12-05 23:31:41 each Exp $ */ #ifndef ISC_TYPES_H #define ISC_TYPES_H 1 +#include +#include + /*! \file isc/types.h * \brief * OS-specific types, from the OS-specific include directories. @@ -40,6 +43,8 @@ /* Core Types. Alphabetized by defined type. */ +typedef struct isc_appctx isc_appctx_t; /*%< Application context */ +typedef struct isc_backtrace_symmap isc_backtrace_symmap_t; /*%< Symbol Table Entry */ typedef struct isc_bitstring isc_bitstring_t; /*%< Bitstring */ typedef struct isc_buffer isc_buffer_t; /*%< Buffer */ typedef ISC_LIST(isc_buffer_t) isc_bufferlist_t; /*%< Buffer List */ @@ -94,7 +99,7 @@ typedef struct isc_timer isc_timer_t; /*%< Timer */ typedef struct isc_timermgr isc_timermgr_t; /*%< Timer Manager */ typedef void (*isc_taskaction_t)(isc_task_t *, isc_event_t *); -typedef int (*isc_sockfdwatch_t)(isc_task_t *, isc_socket_t *, void *); +typedef int (*isc_sockfdwatch_t)(isc_task_t *, isc_socket_t *, void *, int); /* The following cannot be listed alphabetically due to forward reference */ typedef isc_result_t (isc_httpdaction_t)(const char *url, diff --git a/lib/isc/include/isc/util.h b/lib/isc/include/isc/util.h index 8ccad8d..11d0044 100644 --- a/lib/isc/include/isc/util.h +++ b/lib/isc/include/isc/util.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: util.h,v 1.30.332.2 2010-01-11 23:47:22 tbox Exp $ */ +/* $Id: util.h,v 1.32 2010-01-11 23:48:37 tbox Exp $ */ #ifndef ISC_UTIL_H #define ISC_UTIL_H 1 diff --git a/lib/isc/inet_aton.c b/lib/isc/inet_aton.c index 3c25ca3..9e35a36 100644 --- a/lib/isc/inet_aton.c +++ b/lib/isc/inet_aton.c @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 1996-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -71,7 +71,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93"; -static char rcsid[] = "$Id: inet_aton.c,v 1.21.332.2 2009-03-05 23:47:03 tbox Exp $"; +static char rcsid[] = "$Id: inet_aton.c,v 1.23 2008-12-01 23:47:45 tbox Exp $"; #endif /* LIBC_SCCS and not lint */ #include diff --git a/lib/isc/inet_ntop.c b/lib/isc/inet_ntop.c index 22930f3..581ebe8 100644 --- a/lib/isc/inet_ntop.c +++ b/lib/isc/inet_ntop.c @@ -19,7 +19,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static char rcsid[] = - "$Id: inet_ntop.c,v 1.19.332.2 2009-07-18 23:47:25 tbox Exp $"; + "$Id: inet_ntop.c,v 1.21 2009-07-17 23:47:41 tbox Exp $"; #endif /* LIBC_SCCS and not lint */ #include diff --git a/lib/isc/iterated_hash.c b/lib/isc/iterated_hash.c index ebc5076..7185075 100644 --- a/lib/isc/iterated_hash.c +++ b/lib/isc/iterated_hash.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: iterated_hash.c,v 1.4.48.2 2009-02-18 23:47:12 tbox Exp $ */ +/* $Id: iterated_hash.c,v 1.6 2009-02-18 23:47:48 tbox Exp $ */ #include "config.h" diff --git a/lib/isc/lib.c b/lib/isc/lib.c index 99b0178..1b6ccc0 100644 --- a/lib/isc/lib.c +++ b/lib/isc/lib.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lib.c,v 1.14 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: lib.c,v 1.16 2009-09-02 23:48:02 tbox Exp $ */ /*! \file */ @@ -24,9 +24,15 @@ #include #include -#include -#include +#include #include +#include +#include +#include +#include +#include +#include +#include /*** *** Globals @@ -41,7 +47,6 @@ LIBISC_EXTERNAL_DATA isc_msgcat_t * isc_msgcat = NULL; static isc_once_t msgcat_once = ISC_ONCE_INIT; - /*** *** Functions ***/ @@ -77,3 +82,22 @@ isc_lib_initmsgcat(void) { abort(); } } + +#ifndef BIND9 +static isc_once_t register_once = ISC_ONCE_INIT; + +static void +do_register(void) { + RUNTIME_CHECK(isc__mem_register() == ISC_R_SUCCESS); + RUNTIME_CHECK(isc__app_register() == ISC_R_SUCCESS); + RUNTIME_CHECK(isc__task_register() == ISC_R_SUCCESS); + RUNTIME_CHECK(isc__socket_register() == ISC_R_SUCCESS); + RUNTIME_CHECK(isc__timer_register() == ISC_R_SUCCESS); +} + +void +isc_lib_register() { + RUNTIME_CHECK(isc_once_do(®ister_once, do_register) + == ISC_R_SUCCESS); +} +#endif diff --git a/lib/isc/log.c b/lib/isc/log.c index 121bd25..7ef6692 100644 --- a/lib/isc/log.c +++ b/lib/isc/log.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: log.c,v 1.94.332.5 2009-02-16 02:04:05 marka Exp $ */ +/* $Id: log.c,v 1.99 2009-02-16 02:01:16 marka Exp $ */ /*! \file * \author Principal Authors: DCL */ diff --git a/lib/isc/md5.c b/lib/isc/md5.c index b9ec42c..b778177 100644 --- a/lib/isc/md5.c +++ b/lib/isc/md5.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: md5.c,v 1.14 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: md5.c,v 1.16 2009-02-06 23:47:42 tbox Exp $ */ /*! \file * This code implements the MD5 message-digest algorithm. @@ -38,10 +38,35 @@ #include #include +#include #include #include #include +#ifdef ISC_PLATFORM_OPENSSLHASH + +void +isc_md5_init(isc_md5_t *ctx) { + EVP_DigestInit(ctx, EVP_md5()); +} + +void +isc_md5_invalidate(isc_md5_t *ctx) { + EVP_MD_CTX_cleanup(ctx); +} + +void +isc_md5_update(isc_md5_t *ctx, const unsigned char *buf, unsigned int len) { + EVP_DigestUpdate(ctx, (const void *) buf, (size_t) len); +} + +void +isc_md5_final(isc_md5_t *ctx, unsigned char *digest) { + EVP_DigestFinal(ctx, digest, NULL); +} + +#else + static void byteSwap(isc_uint32_t *buf, unsigned words) { @@ -249,3 +274,4 @@ isc_md5_final(isc_md5_t *ctx, unsigned char *digest) { memcpy(digest, ctx->buf, 16); memset(ctx, 0, sizeof(isc_md5_t)); /* In case it's sensitive */ } +#endif diff --git a/lib/isc/mem.c b/lib/isc/mem.c index aeacfc0..8311569 100644 --- a/lib/isc/mem.c +++ b/lib/isc/mem.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: mem.c,v 1.145.120.9 2010-08-11 23:45:49 tbox Exp $ */ +/* $Id: mem.c,v 1.160 2010-12-08 02:46:16 marka Exp $ */ /*! \file */ @@ -60,6 +60,9 @@ LIBISC_EXTERNAL_DATA unsigned int isc_mem_debugging = ISC_MEM_DEBUGGING; /* * Types. */ +typedef struct isc__mem isc__mem_t; +typedef struct isc__mempool isc__mempool_t; + #if ISC_MEM_TRACKLINES typedef struct debuglink debuglink_t; struct debuglink { @@ -89,7 +92,7 @@ typedef struct { */ union { size_t size; - isc_mem_t *ctx; + isc__mem_t *ctx; char bytes[ALIGNMENT_SIZE]; } u; } size_info; @@ -110,7 +113,7 @@ typedef ISC_LIST(debuglink_t) debuglist_t; /* List of all active memory contexts. */ -static ISC_LIST(isc_mem_t) contexts; +static ISC_LIST(isc__mem_t) contexts; static isc_once_t once = ISC_ONCE_INIT; static isc_mutex_t lock; @@ -120,8 +123,8 @@ static isc_mutex_t lock; */ static isc_uint64_t totallost; -struct isc_mem { - unsigned int magic; +struct isc__mem { + isc_mem_t common; isc_ondestroy_t ondestroy; unsigned int flags; isc_mutex_t lock; @@ -144,7 +147,7 @@ struct isc_mem { isc_boolean_t is_overmem; isc_mem_water_t water; void * water_arg; - ISC_LIST(isc_mempool_t) pools; + ISC_LIST(isc__mempool_t) pools; unsigned int poolcnt; /* ISC_MEMFLAG_INTERNAL */ @@ -163,19 +166,19 @@ struct isc_mem { #endif unsigned int memalloc_failures; - ISC_LINK(isc_mem_t) link; + ISC_LINK(isc__mem_t) link; }; #define MEMPOOL_MAGIC ISC_MAGIC('M', 'E', 'M', 'p') #define VALID_MEMPOOL(c) ISC_MAGIC_VALID(c, MEMPOOL_MAGIC) -struct isc_mempool { +struct isc__mempool { /* always unlocked */ - unsigned int magic; /*%< magic number */ + isc_mempool_t common; /*%< common header of mempool's */ isc_mutex_t *lock; /*%< optional lock */ - isc_mem_t *mctx; /*%< our memory context */ + isc__mem_t *mctx; /*%< our memory context */ /*%< locked via the memory context's lock */ - ISC_LINK(isc_mempool_t) link; /*%< next pool in this mem context */ + ISC_LINK(isc__mempool_t) link; /*%< next pool in this mem context */ /*%< optionally locked from here down */ element *items; /*%< low water item list */ size_t size; /*%< size of each item on this pool */ @@ -210,13 +213,187 @@ struct isc_mempool { #define DELETE_TRACE(a, b, c, d, e) delete_trace_entry(a, b, c, d, e) static void -print_active(isc_mem_t *ctx, FILE *out); +print_active(isc__mem_t *ctx, FILE *out); + +/*% + * The following can be either static or public, depending on build environment. + */ + +#ifdef BIND9 +#define ISC_MEMFUNC_SCOPE +#else +#define ISC_MEMFUNC_SCOPE static +#endif + +ISC_MEMFUNC_SCOPE isc_result_t +isc__mem_createx(size_t init_max_size, size_t target_size, + isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg, + isc_mem_t **ctxp); +ISC_MEMFUNC_SCOPE isc_result_t +isc__mem_createx2(size_t init_max_size, size_t target_size, + isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg, + isc_mem_t **ctxp, unsigned int flags); +ISC_MEMFUNC_SCOPE isc_result_t +isc__mem_create(size_t init_max_size, size_t target_size, isc_mem_t **ctxp); +ISC_MEMFUNC_SCOPE isc_result_t +isc__mem_create2(size_t init_max_size, size_t target_size, + isc_mem_t **ctxp, unsigned int flags); +ISC_MEMFUNC_SCOPE void +isc__mem_attach(isc_mem_t *source, isc_mem_t **targetp); +ISC_MEMFUNC_SCOPE void +isc__mem_detach(isc_mem_t **ctxp); +ISC_MEMFUNC_SCOPE void +isc___mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG); +ISC_MEMFUNC_SCOPE void +isc__mem_destroy(isc_mem_t **ctxp); +ISC_MEMFUNC_SCOPE isc_result_t +isc__mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event); +ISC_MEMFUNC_SCOPE void * +isc___mem_get(isc_mem_t *ctx, size_t size FLARG); +ISC_MEMFUNC_SCOPE void +isc___mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG); +ISC_MEMFUNC_SCOPE void +isc__mem_stats(isc_mem_t *ctx, FILE *out); +ISC_MEMFUNC_SCOPE void * +isc___mem_allocate(isc_mem_t *ctx, size_t size FLARG); +ISC_MEMFUNC_SCOPE void * +isc___mem_reallocate(isc_mem_t *ctx, void *ptr, size_t size FLARG); +ISC_MEMFUNC_SCOPE void +isc___mem_free(isc_mem_t *ctx, void *ptr FLARG); +ISC_MEMFUNC_SCOPE char * +isc___mem_strdup(isc_mem_t *mctx, const char *s FLARG); +ISC_MEMFUNC_SCOPE void +isc__mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag); +ISC_MEMFUNC_SCOPE void +isc__mem_setquota(isc_mem_t *ctx, size_t quota); +ISC_MEMFUNC_SCOPE size_t +isc__mem_getquota(isc_mem_t *ctx); +ISC_MEMFUNC_SCOPE size_t +isc__mem_inuse(isc_mem_t *ctx); +ISC_MEMFUNC_SCOPE isc_boolean_t +isc__mem_isovermem(isc_mem_t *ctx); +ISC_MEMFUNC_SCOPE void +isc__mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg, + size_t hiwater, size_t lowater); +ISC_MEMFUNC_SCOPE void +isc__mem_waterack(isc_mem_t *ctx0, int flag); +ISC_MEMFUNC_SCOPE void +isc__mem_setname(isc_mem_t *ctx, const char *name, void *tag); +ISC_MEMFUNC_SCOPE const char * +isc__mem_getname(isc_mem_t *ctx); +ISC_MEMFUNC_SCOPE void * +isc__mem_gettag(isc_mem_t *ctx); +ISC_MEMFUNC_SCOPE isc_result_t +isc__mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp); +ISC_MEMFUNC_SCOPE void +isc__mempool_setname(isc_mempool_t *mpctx, const char *name); +ISC_MEMFUNC_SCOPE void +isc__mempool_destroy(isc_mempool_t **mpctxp); +ISC_MEMFUNC_SCOPE void +isc__mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock); +ISC_MEMFUNC_SCOPE void * +isc___mempool_get(isc_mempool_t *mpctx FLARG); +ISC_MEMFUNC_SCOPE void +isc___mempool_put(isc_mempool_t *mpctx, void *mem FLARG); +ISC_MEMFUNC_SCOPE void +isc__mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit); +ISC_MEMFUNC_SCOPE unsigned int +isc__mempool_getfreemax(isc_mempool_t *mpctx); +ISC_MEMFUNC_SCOPE unsigned int +isc__mempool_getfreecount(isc_mempool_t *mpctx); +ISC_MEMFUNC_SCOPE void +isc__mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit); +ISC_MEMFUNC_SCOPE unsigned int +isc__mempool_getmaxalloc(isc_mempool_t *mpctx); +ISC_MEMFUNC_SCOPE unsigned int +isc__mempool_getallocated(isc_mempool_t *mpctx); +ISC_MEMFUNC_SCOPE void +isc__mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit); +ISC_MEMFUNC_SCOPE unsigned int +isc__mempool_getfillcount(isc_mempool_t *mpctx); +#ifdef BIND9 +ISC_MEMFUNC_SCOPE void +isc__mem_printactive(isc_mem_t *ctx0, FILE *file); +ISC_MEMFUNC_SCOPE void +isc__mem_printallactive(FILE *file); +ISC_MEMFUNC_SCOPE void +isc__mem_checkdestroyed(FILE *file); +ISC_MEMFUNC_SCOPE unsigned int +isc__mem_references(isc_mem_t *ctx0); +#endif + +static struct isc__memmethods { + isc_memmethods_t methods; + + /*% + * The following are defined just for avoiding unused static functions. + */ +#ifndef BIND9 + void *createx, *create, *create2, *ondestroy, *stats, + *setquota, *getquota, *setname, *getname, *gettag; +#endif +} memmethods = { + { + isc__mem_attach, + isc__mem_detach, + isc__mem_destroy, + isc___mem_get, + isc___mem_put, + isc___mem_putanddetach, + isc___mem_allocate, + isc___mem_reallocate, + isc___mem_strdup, + isc___mem_free, + isc__mem_setdestroycheck, + isc__mem_setwater, + isc__mem_waterack, + isc__mem_inuse, + isc__mem_isovermem, + isc__mempool_create + } +#ifndef BIND9 + , + (void *)isc__mem_createx, (void *)isc__mem_create, + (void *)isc__mem_create2, (void *)isc__mem_ondestroy, + (void *)isc__mem_stats, (void *)isc__mem_setquota, + (void *)isc__mem_getquota, (void *)isc__mem_setname, + (void *)isc__mem_getname, (void *)isc__mem_gettag +#endif +}; + +static struct isc__mempoolmethods { + isc_mempoolmethods_t methods; + + /*% + * The following are defined just for avoiding unused static functions. + */ +#ifndef BIND9 + void *getfreemax, *getfreecount, *getmaxalloc, *getfillcount; +#endif +} mempoolmethods = { + { + isc__mempool_destroy, + isc___mempool_get, + isc___mempool_put, + isc__mempool_getallocated, + isc__mempool_setmaxalloc, + isc__mempool_setfreemax, + isc__mempool_setname, + isc__mempool_associatelock, + isc__mempool_setfillcount + } +#ifndef BIND9 + , + (void *)isc__mempool_getfreemax, (void *)isc__mempool_getfreecount, + (void *)isc__mempool_getmaxalloc, (void *)isc__mempool_getfillcount +#endif +}; /*! * mctx must be locked. */ static inline void -add_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size +add_trace_entry(isc__mem_t *mctx, const void *ptr, unsigned int size FLARG) { debuglink_t *dl; @@ -276,7 +453,7 @@ add_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size } static inline void -delete_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size, +delete_trace_entry(isc__mem_t *mctx, const void *ptr, unsigned int size, const char *file, unsigned int line) { debuglink_t *dl; @@ -347,7 +524,7 @@ quantize(size_t size) { } static inline isc_boolean_t -more_basic_blocks(isc_mem_t *ctx) { +more_basic_blocks(isc__mem_t *ctx) { void *new; unsigned char *curr, *next; unsigned char *first, *last; @@ -417,7 +594,7 @@ more_basic_blocks(isc_mem_t *ctx) { } static inline isc_boolean_t -more_frags(isc_mem_t *ctx, size_t new_size) { +more_frags(isc__mem_t *ctx, size_t new_size) { int i, frags; size_t total_size; void *new; @@ -479,7 +656,7 @@ more_frags(isc_mem_t *ctx, size_t new_size) { } static inline void * -mem_getunlocked(isc_mem_t *ctx, size_t size) { +mem_getunlocked(isc__mem_t *ctx, size_t size) { size_t new_size = quantize(size); void *ret; @@ -560,7 +737,7 @@ check_overrun(void *mem, size_t size, size_t new_size) { #endif static inline void -mem_putunlocked(isc_mem_t *ctx, void *mem, size_t size) { +mem_putunlocked(isc__mem_t *ctx, void *mem, size_t size) { size_t new_size = quantize(size); if (size == ctx->max_size || new_size >= ctx->max_size) { @@ -608,7 +785,7 @@ mem_putunlocked(isc_mem_t *ctx, void *mem, size_t size) { * Perform a malloc, doing memory filling and overrun detection as necessary. */ static inline void * -mem_get(isc_mem_t *ctx, size_t size) { +mem_get(isc__mem_t *ctx, size_t size) { char *ret; #if ISC_MEM_CHECKOVERRUN @@ -636,7 +813,7 @@ mem_get(isc_mem_t *ctx, size_t size) { * Perform a free, doing memory filling and overrun detection as necessary. */ static inline void -mem_put(isc_mem_t *ctx, void *mem, size_t size) { +mem_put(isc__mem_t *ctx, void *mem, size_t size) { #if ISC_MEM_CHECKOVERRUN INSIST(((unsigned char *)mem)[size] == 0xbe); #endif @@ -652,7 +829,7 @@ mem_put(isc_mem_t *ctx, void *mem, size_t size) { * Update internal counters after a memory get. */ static inline void -mem_getstats(isc_mem_t *ctx, size_t size) { +mem_getstats(isc__mem_t *ctx, size_t size) { ctx->total += size; ctx->inuse += size; @@ -669,7 +846,7 @@ mem_getstats(isc_mem_t *ctx, size_t size) { * Update internal counters after a memory put. */ static inline void -mem_putstats(isc_mem_t *ctx, void *ptr, size_t size) { +mem_putstats(isc__mem_t *ctx, void *ptr, size_t size) { UNUSED(ptr); INSIST(ctx->inuse >= size); @@ -713,22 +890,22 @@ initialize_action(void) { * Public. */ -isc_result_t -isc_mem_createx(size_t init_max_size, size_t target_size, - isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg, - isc_mem_t **ctxp) +ISC_MEMFUNC_SCOPE isc_result_t +isc__mem_createx(size_t init_max_size, size_t target_size, + isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg, + isc_mem_t **ctxp) { - return (isc_mem_createx2(init_max_size, target_size, memalloc, memfree, - arg, ctxp, ISC_MEMFLAG_DEFAULT)); + return (isc__mem_createx2(init_max_size, target_size, memalloc, memfree, + arg, ctxp, ISC_MEMFLAG_DEFAULT)); } -isc_result_t -isc_mem_createx2(size_t init_max_size, size_t target_size, - isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg, - isc_mem_t **ctxp, unsigned int flags) +ISC_MEMFUNC_SCOPE isc_result_t +isc__mem_createx2(size_t init_max_size, size_t target_size, + isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg, + isc_mem_t **ctxp, unsigned int flags) { - isc_mem_t *ctx; + isc__mem_t *ctx; isc_result_t result; REQUIRE(ctxp != NULL && *ctxp == NULL); @@ -769,7 +946,9 @@ isc_mem_createx2(size_t init_max_size, size_t target_size, ctx->is_overmem = ISC_FALSE; ctx->water = NULL; ctx->water_arg = NULL; - ctx->magic = MEM_MAGIC; + ctx->common.impmagic = MEM_MAGIC; + ctx->common.magic = ISCAPI_MCTX_MAGIC; + ctx->common.methods = (isc_memmethods_t *)&memmethods; isc_ondestroy_init(&ctx->ondestroy); ctx->memalloc = memalloc; ctx->memfree = memfree; @@ -834,7 +1013,7 @@ isc_mem_createx2(size_t init_max_size, size_t target_size, ISC_LIST_INITANDAPPEND(contexts, ctx, link); UNLOCK(&lock); - *ctxp = ctx; + *ctxp = (isc_mem_t *)ctx; return (ISC_R_SUCCESS); error: @@ -855,26 +1034,24 @@ isc_mem_createx2(size_t init_max_size, size_t target_size, return (result); } -isc_result_t -isc_mem_create(size_t init_max_size, size_t target_size, - isc_mem_t **ctxp) -{ - return (isc_mem_createx2(init_max_size, target_size, - default_memalloc, default_memfree, NULL, - ctxp, ISC_MEMFLAG_DEFAULT)); +ISC_MEMFUNC_SCOPE isc_result_t +isc__mem_create(size_t init_max_size, size_t target_size, isc_mem_t **ctxp) { + return (isc__mem_createx2(init_max_size, target_size, + default_memalloc, default_memfree, NULL, + ctxp, ISC_MEMFLAG_DEFAULT)); } -isc_result_t -isc_mem_create2(size_t init_max_size, size_t target_size, - isc_mem_t **ctxp, unsigned int flags) +ISC_MEMFUNC_SCOPE isc_result_t +isc__mem_create2(size_t init_max_size, size_t target_size, + isc_mem_t **ctxp, unsigned int flags) { - return (isc_mem_createx2(init_max_size, target_size, - default_memalloc, default_memfree, NULL, - ctxp, flags)); + return (isc__mem_createx2(init_max_size, target_size, + default_memalloc, default_memfree, NULL, + ctxp, flags)); } static void -destroy(isc_mem_t *ctx) { +destroy(isc__mem_t *ctx) { unsigned int i; isc_ondestroy_t ondest; @@ -883,7 +1060,8 @@ destroy(isc_mem_t *ctx) { totallost += ctx->inuse; UNLOCK(&lock); - ctx->magic = 0; + ctx->common.impmagic = 0; + ctx->common.magic = 0; INSIST(ISC_LIST_EMPTY(ctx->pools)); @@ -941,8 +1119,10 @@ destroy(isc_mem_t *ctx) { isc_ondestroy_notify(&ondest, ctx); } -void -isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) { +ISC_MEMFUNC_SCOPE void +isc__mem_attach(isc_mem_t *source0, isc_mem_t **targetp) { + isc__mem_t *source = (isc__mem_t *)source0; + REQUIRE(VALID_CONTEXT(source)); REQUIRE(targetp != NULL && *targetp == NULL); @@ -950,16 +1130,16 @@ isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) { source->references++; MCTXUNLOCK(source, &source->lock); - *targetp = source; + *targetp = (isc_mem_t *)source; } -void -isc_mem_detach(isc_mem_t **ctxp) { - isc_mem_t *ctx; +ISC_MEMFUNC_SCOPE void +isc__mem_detach(isc_mem_t **ctxp) { + isc__mem_t *ctx; isc_boolean_t want_destroy = ISC_FALSE; REQUIRE(ctxp != NULL); - ctx = *ctxp; + ctx = (isc__mem_t *)*ctxp; REQUIRE(VALID_CONTEXT(ctx)); MCTXLOCK(ctx, &ctx->lock); @@ -985,15 +1165,15 @@ isc_mem_detach(isc_mem_t **ctxp) { * isc_mem_detach(&mctx); */ -void -isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) { - isc_mem_t *ctx; +ISC_MEMFUNC_SCOPE void +isc___mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) { + isc__mem_t *ctx; isc_boolean_t want_destroy = ISC_FALSE; size_info *si; size_t oldsize; REQUIRE(ctxp != NULL); - ctx = *ctxp; + ctx = (isc__mem_t *)*ctxp; REQUIRE(VALID_CONTEXT(ctx)); REQUIRE(ptr != NULL); @@ -1011,7 +1191,7 @@ isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) { oldsize -= ALIGNMENT_SIZE; INSIST(oldsize == size); } - isc__mem_free(ctx, ptr FLARG_PASS); + isc_mem_free((isc_mem_t *)ctx, ptr); MCTXLOCK(ctx, &ctx->lock); ctx->references--; @@ -1045,9 +1225,9 @@ isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) { destroy(ctx); } -void -isc_mem_destroy(isc_mem_t **ctxp) { - isc_mem_t *ctx; +ISC_MEMFUNC_SCOPE void +isc__mem_destroy(isc_mem_t **ctxp) { + isc__mem_t *ctx; /* * This routine provides legacy support for callers who use mctxs @@ -1055,7 +1235,7 @@ isc_mem_destroy(isc_mem_t **ctxp) { */ REQUIRE(ctxp != NULL); - ctx = *ctxp; + ctx = (isc__mem_t *)*ctxp; REQUIRE(VALID_CONTEXT(ctx)); MCTXLOCK(ctx, &ctx->lock); @@ -1072,8 +1252,9 @@ isc_mem_destroy(isc_mem_t **ctxp) { *ctxp = NULL; } -isc_result_t -isc_mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event) { +ISC_MEMFUNC_SCOPE isc_result_t +isc__mem_ondestroy(isc_mem_t *ctx0, isc_task_t *task, isc_event_t **event) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; isc_result_t res; MCTXLOCK(ctx, &ctx->lock); @@ -1083,16 +1264,16 @@ isc_mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event) { return (res); } - -void * -isc__mem_get(isc_mem_t *ctx, size_t size FLARG) { +ISC_MEMFUNC_SCOPE void * +isc___mem_get(isc_mem_t *ctx0, size_t size FLARG) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; void *ptr; isc_boolean_t call_water = ISC_FALSE; REQUIRE(VALID_CONTEXT(ctx)); if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0) - return (isc__mem_allocate(ctx, size FLARG_PASS)); + return (isc__mem_allocate(ctx0, size FLARG_PASS)); if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) { MCTXLOCK(ctx, &ctx->lock); @@ -1128,9 +1309,9 @@ isc__mem_get(isc_mem_t *ctx, size_t size FLARG) { return (ptr); } -void -isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG) -{ +ISC_MEMFUNC_SCOPE void +isc___mem_put(isc_mem_t *ctx0, void *ptr, size_t size FLARG) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; isc_boolean_t call_water = ISC_FALSE; size_info *si; size_t oldsize; @@ -1146,7 +1327,7 @@ isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG) oldsize -= ALIGNMENT_SIZE; INSIST(oldsize == size); } - isc__mem_free(ctx, ptr FLARG_PASS); + isc_mem_free((isc_mem_t *)ctx, ptr); return; } @@ -1181,8 +1362,10 @@ isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG) (ctx->water)(ctx->water_arg, ISC_MEM_LOWATER); } -void -isc_mem_waterack(isc_mem_t *ctx, int flag) { +ISC_MEMFUNC_SCOPE void +isc__mem_waterack(isc_mem_t *ctx0, int flag) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; + REQUIRE(VALID_CONTEXT(ctx)); MCTXLOCK(ctx, &ctx->lock); @@ -1195,7 +1378,7 @@ isc_mem_waterack(isc_mem_t *ctx, int flag) { #if ISC_MEM_TRACKLINES static void -print_active(isc_mem_t *mctx, FILE *out) { +print_active(isc__mem_t *mctx, FILE *out) { if (mctx->debuglist != NULL) { debuglink_t *dl; unsigned int i, j; @@ -1237,11 +1420,12 @@ print_active(isc_mem_t *mctx, FILE *out) { /* * Print the stats[] on the stream "out" with suitable formatting. */ -void -isc_mem_stats(isc_mem_t *ctx, FILE *out) { +ISC_MEMFUNC_SCOPE void +isc__mem_stats(isc_mem_t *ctx0, FILE *out) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; size_t i; const struct stats *s; - const isc_mempool_t *pool; + const isc__mempool_t *pool; REQUIRE(VALID_CONTEXT(ctx)); MCTXLOCK(ctx, &ctx->lock); @@ -1314,7 +1498,8 @@ isc_mem_stats(isc_mem_t *ctx, FILE *out) { */ static void * -isc__mem_allocateunlocked(isc_mem_t *ctx, size_t size) { +isc__mem_allocateunlocked(isc_mem_t *ctx0, size_t size) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; size_info *si; size += ALIGNMENT_SIZE; @@ -1336,8 +1521,9 @@ isc__mem_allocateunlocked(isc_mem_t *ctx, size_t size) { return (&si[1]); } -void * -isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) { +ISC_MEMFUNC_SCOPE void * +isc___mem_allocate(isc_mem_t *ctx0, size_t size FLARG) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; size_info *si; isc_boolean_t call_water = ISC_FALSE; @@ -1345,9 +1531,9 @@ isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) { if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) { MCTXLOCK(ctx, &ctx->lock); - si = isc__mem_allocateunlocked(ctx, size); + si = isc__mem_allocateunlocked((isc_mem_t *)ctx, size); } else { - si = isc__mem_allocateunlocked(ctx, size); + si = isc__mem_allocateunlocked((isc_mem_t *)ctx, size); MCTXLOCK(ctx, &ctx->lock); if (si != NULL) mem_getstats(ctx, si[-1].u.size); @@ -1381,8 +1567,9 @@ isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) { return (si); } -void * -isc__mem_reallocate(isc_mem_t *ctx, void *ptr, size_t size FLARG) { +ISC_MEMFUNC_SCOPE void * +isc___mem_reallocate(isc_mem_t *ctx0, void *ptr, size_t size FLARG) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; void *new_ptr = NULL; size_t oldsize, copysize; @@ -1400,23 +1587,24 @@ isc__mem_reallocate(isc_mem_t *ctx, void *ptr, size_t size FLARG) { * NULL if allocation fails or doesn't happen. */ if (size > 0U) { - new_ptr = isc__mem_allocate(ctx, size FLARG_PASS); + new_ptr = isc__mem_allocate(ctx0, size FLARG_PASS); if (new_ptr != NULL && ptr != NULL) { oldsize = (((size_info *)ptr)[-1]).u.size; INSIST(oldsize >= ALIGNMENT_SIZE); oldsize -= ALIGNMENT_SIZE; copysize = oldsize > size ? size : oldsize; memcpy(new_ptr, ptr, copysize); - isc__mem_free(ctx, ptr FLARG_PASS); + isc__mem_free(ctx0, ptr FLARG_PASS); } } else if (ptr != NULL) - isc__mem_free(ctx, ptr FLARG_PASS); + isc__mem_free(ctx0, ptr FLARG_PASS); return (new_ptr); } -void -isc__mem_free(isc_mem_t *ctx, void *ptr FLARG) { +ISC_MEMFUNC_SCOPE void +isc___mem_free(isc_mem_t *ctx0, void *ptr FLARG) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; size_info *si; size_t size; isc_boolean_t call_water= ISC_FALSE; @@ -1472,8 +1660,9 @@ isc__mem_free(isc_mem_t *ctx, void *ptr FLARG) { * Other useful things. */ -char * -isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) { +ISC_MEMFUNC_SCOPE char * +isc___mem_strdup(isc_mem_t *mctx0, const char *s FLARG) { + isc__mem_t *mctx = (isc__mem_t *)mctx0; size_t len; char *ns; @@ -1482,7 +1671,7 @@ isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) { len = strlen(s); - ns = isc__mem_allocate(mctx, len + 1 FLARG_PASS); + ns = isc___mem_allocate((isc_mem_t *)mctx, len + 1 FLARG_PASS); if (ns != NULL) strncpy(ns, s, len + 1); @@ -1490,8 +1679,10 @@ isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) { return (ns); } -void -isc_mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag) { +ISC_MEMFUNC_SCOPE void +isc__mem_setdestroycheck(isc_mem_t *ctx0, isc_boolean_t flag) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; + REQUIRE(VALID_CONTEXT(ctx)); MCTXLOCK(ctx, &ctx->lock); @@ -1504,8 +1695,10 @@ isc_mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag) { * Quotas */ -void -isc_mem_setquota(isc_mem_t *ctx, size_t quota) { +ISC_MEMFUNC_SCOPE void +isc__mem_setquota(isc_mem_t *ctx0, size_t quota) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; + REQUIRE(VALID_CONTEXT(ctx)); MCTXLOCK(ctx, &ctx->lock); @@ -1514,8 +1707,9 @@ isc_mem_setquota(isc_mem_t *ctx, size_t quota) { MCTXUNLOCK(ctx, &ctx->lock); } -size_t -isc_mem_getquota(isc_mem_t *ctx) { +ISC_MEMFUNC_SCOPE size_t +isc__mem_getquota(isc_mem_t *ctx0) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; size_t quota; REQUIRE(VALID_CONTEXT(ctx)); @@ -1528,8 +1722,9 @@ isc_mem_getquota(isc_mem_t *ctx) { return (quota); } -size_t -isc_mem_inuse(isc_mem_t *ctx) { +ISC_MEMFUNC_SCOPE size_t +isc__mem_inuse(isc_mem_t *ctx0) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; size_t inuse; REQUIRE(VALID_CONTEXT(ctx)); @@ -1542,10 +1737,11 @@ isc_mem_inuse(isc_mem_t *ctx) { return (inuse); } -void -isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg, +ISC_MEMFUNC_SCOPE void +isc__mem_setwater(isc_mem_t *ctx0, isc_mem_water_t water, void *water_arg, size_t hiwater, size_t lowater) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; isc_boolean_t callwater = ISC_FALSE; isc_mem_water_t oldwater; void *oldwater_arg; @@ -1580,8 +1776,10 @@ isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg, (oldwater)(oldwater_arg, ISC_MEM_LOWATER); } -isc_boolean_t -isc_mem_isovermem(isc_mem_t *ctx) { +ISC_MEMFUNC_SCOPE isc_boolean_t +isc__mem_isovermem(isc_mem_t *ctx0) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; + REQUIRE(VALID_CONTEXT(ctx)); /* @@ -1592,8 +1790,10 @@ isc_mem_isovermem(isc_mem_t *ctx) { return (ctx->is_overmem); } -void -isc_mem_setname(isc_mem_t *ctx, const char *name, void *tag) { +ISC_MEMFUNC_SCOPE void +isc__mem_setname(isc_mem_t *ctx0, const char *name, void *tag) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; + REQUIRE(VALID_CONTEXT(ctx)); LOCK(&ctx->lock); @@ -1603,15 +1803,19 @@ isc_mem_setname(isc_mem_t *ctx, const char *name, void *tag) { UNLOCK(&ctx->lock); } -const char * -isc_mem_getname(isc_mem_t *ctx) { +ISC_MEMFUNC_SCOPE const char * +isc__mem_getname(isc_mem_t *ctx0) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; + REQUIRE(VALID_CONTEXT(ctx)); return (ctx->name); } -void * -isc_mem_gettag(isc_mem_t *ctx) { +ISC_MEMFUNC_SCOPE void * +isc__mem_gettag(isc_mem_t *ctx0) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; + REQUIRE(VALID_CONTEXT(ctx)); return (ctx->tag); @@ -1621,9 +1825,10 @@ isc_mem_gettag(isc_mem_t *ctx) { * Memory pool stuff */ -isc_result_t -isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) { - isc_mempool_t *mpctx; +ISC_MEMFUNC_SCOPE isc_result_t +isc__mempool_create(isc_mem_t *mctx0, size_t size, isc_mempool_t **mpctxp) { + isc__mem_t *mctx = (isc__mem_t *)mctx0; + isc__mempool_t *mpctx; REQUIRE(VALID_CONTEXT(mctx)); REQUIRE(size > 0U); @@ -1633,11 +1838,13 @@ isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) { * Allocate space for this pool, initialize values, and if all works * well, attach to the memory context. */ - mpctx = isc_mem_get(mctx, sizeof(isc_mempool_t)); + mpctx = isc_mem_get((isc_mem_t *)mctx, sizeof(isc__mempool_t)); if (mpctx == NULL) return (ISC_R_NOMEMORY); - mpctx->magic = MEMPOOL_MAGIC; + mpctx->common.methods = (isc_mempoolmethods_t *)&mempoolmethods; + mpctx->common.impmagic = MEMPOOL_MAGIC; + mpctx->common.magic = ISCAPI_MPOOL_MAGIC; mpctx->lock = NULL; mpctx->mctx = mctx; mpctx->size = size; @@ -1652,7 +1859,7 @@ isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) { #endif mpctx->items = NULL; - *mpctxp = mpctx; + *mpctxp = (isc_mempool_t *)mpctx; MCTXLOCK(mctx, &mctx->lock); ISC_LIST_INITANDAPPEND(mctx->pools, mpctx, link); @@ -1662,9 +1869,12 @@ isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) { return (ISC_R_SUCCESS); } -void -isc_mempool_setname(isc_mempool_t *mpctx, const char *name) { +ISC_MEMFUNC_SCOPE void +isc__mempool_setname(isc_mempool_t *mpctx0, const char *name) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; + REQUIRE(name != NULL); + REQUIRE(VALID_MEMPOOL(mpctx)); #if ISC_MEMPOOL_NAMES if (mpctx->lock != NULL) @@ -1681,20 +1891,20 @@ isc_mempool_setname(isc_mempool_t *mpctx, const char *name) { #endif } -void -isc_mempool_destroy(isc_mempool_t **mpctxp) { - isc_mempool_t *mpctx; - isc_mem_t *mctx; +ISC_MEMFUNC_SCOPE void +isc__mempool_destroy(isc_mempool_t **mpctxp) { + isc__mempool_t *mpctx; + isc__mem_t *mctx; isc_mutex_t *lock; element *item; REQUIRE(mpctxp != NULL); - mpctx = *mpctxp; + mpctx = (isc__mempool_t *)*mpctxp; REQUIRE(VALID_MEMPOOL(mpctx)); #if ISC_MEMPOOL_NAMES if (mpctx->allocated > 0) UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_mempool_destroy(): mempool %s " + "isc__mempool_destroy(): mempool %s " "leaked memory", mpctx->name); #endif @@ -1734,9 +1944,10 @@ isc_mempool_destroy(isc_mempool_t **mpctxp) { mctx->poolcnt--; MCTXUNLOCK(mctx, &mctx->lock); - mpctx->magic = 0; + mpctx->common.impmagic = 0; + mpctx->common.magic = 0; - isc_mem_put(mpctx->mctx, mpctx, sizeof(isc_mempool_t)); + isc_mem_put((isc_mem_t *)mpctx->mctx, mpctx, sizeof(isc__mempool_t)); if (lock != NULL) UNLOCK(lock); @@ -1744,8 +1955,10 @@ isc_mempool_destroy(isc_mempool_t **mpctxp) { *mpctxp = NULL; } -void -isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock) { +ISC_MEMFUNC_SCOPE void +isc__mempool_associatelock(isc_mempool_t *mpctx0, isc_mutex_t *lock) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; + REQUIRE(VALID_MEMPOOL(mpctx)); REQUIRE(mpctx->lock == NULL); REQUIRE(lock != NULL); @@ -1753,10 +1966,11 @@ isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock) { mpctx->lock = lock; } -void * -isc__mempool_get(isc_mempool_t *mpctx FLARG) { +ISC_MEMFUNC_SCOPE void * +isc___mempool_get(isc_mempool_t *mpctx0 FLARG) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; element *item; - isc_mem_t *mctx; + isc__mem_t *mctx; unsigned int i; REQUIRE(VALID_MEMPOOL(mpctx)); @@ -1835,9 +2049,10 @@ isc__mempool_get(isc_mempool_t *mpctx FLARG) { return (item); } -void -isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) { - isc_mem_t *mctx; +ISC_MEMFUNC_SCOPE void +isc___mempool_put(isc_mempool_t *mpctx0, void *mem FLARG) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; + isc__mem_t *mctx; element *item; REQUIRE(VALID_MEMPOOL(mpctx)); @@ -1892,8 +2107,10 @@ isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) { * Quotas */ -void -isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit) { +ISC_MEMFUNC_SCOPE void +isc__mempool_setfreemax(isc_mempool_t *mpctx0, unsigned int limit) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; + REQUIRE(VALID_MEMPOOL(mpctx)); if (mpctx->lock != NULL) @@ -1905,8 +2122,9 @@ isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit) { UNLOCK(mpctx->lock); } -unsigned int -isc_mempool_getfreemax(isc_mempool_t *mpctx) { +ISC_MEMFUNC_SCOPE unsigned int +isc__mempool_getfreemax(isc_mempool_t *mpctx0) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; unsigned int freemax; REQUIRE(VALID_MEMPOOL(mpctx)); @@ -1922,8 +2140,9 @@ isc_mempool_getfreemax(isc_mempool_t *mpctx) { return (freemax); } -unsigned int -isc_mempool_getfreecount(isc_mempool_t *mpctx) { +ISC_MEMFUNC_SCOPE unsigned int +isc__mempool_getfreecount(isc_mempool_t *mpctx0) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; unsigned int freecount; REQUIRE(VALID_MEMPOOL(mpctx)); @@ -1939,8 +2158,10 @@ isc_mempool_getfreecount(isc_mempool_t *mpctx) { return (freecount); } -void -isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit) { +ISC_MEMFUNC_SCOPE void +isc__mempool_setmaxalloc(isc_mempool_t *mpctx0, unsigned int limit) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; + REQUIRE(limit > 0); REQUIRE(VALID_MEMPOOL(mpctx)); @@ -1954,8 +2175,9 @@ isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit) { UNLOCK(mpctx->lock); } -unsigned int -isc_mempool_getmaxalloc(isc_mempool_t *mpctx) { +ISC_MEMFUNC_SCOPE unsigned int +isc__mempool_getmaxalloc(isc_mempool_t *mpctx0) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; unsigned int maxalloc; REQUIRE(VALID_MEMPOOL(mpctx)); @@ -1971,8 +2193,9 @@ isc_mempool_getmaxalloc(isc_mempool_t *mpctx) { return (maxalloc); } -unsigned int -isc_mempool_getallocated(isc_mempool_t *mpctx) { +ISC_MEMFUNC_SCOPE unsigned int +isc__mempool_getallocated(isc_mempool_t *mpctx0) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; unsigned int allocated; REQUIRE(VALID_MEMPOOL(mpctx)); @@ -1988,8 +2211,10 @@ isc_mempool_getallocated(isc_mempool_t *mpctx) { return (allocated); } -void -isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit) { +ISC_MEMFUNC_SCOPE void +isc__mempool_setfillcount(isc_mempool_t *mpctx0, unsigned int limit) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; + REQUIRE(limit > 0); REQUIRE(VALID_MEMPOOL(mpctx)); @@ -2002,8 +2227,10 @@ isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit) { UNLOCK(mpctx->lock); } -unsigned int -isc_mempool_getfillcount(isc_mempool_t *mpctx) { +ISC_MEMFUNC_SCOPE unsigned int +isc__mempool_getfillcount(isc_mempool_t *mpctx0) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; + unsigned int fillcount; REQUIRE(VALID_MEMPOOL(mpctx)); @@ -2019,8 +2246,17 @@ isc_mempool_getfillcount(isc_mempool_t *mpctx) { return (fillcount); } -void -isc_mem_printactive(isc_mem_t *ctx, FILE *file) { +#ifdef USE_MEMIMPREGISTER +isc_result_t +isc__mem_register() { + return (isc_mem_register(isc__mem_create2)); +} +#endif + +#ifdef BIND9 +ISC_MEMFUNC_SCOPE void +isc__mem_printactive(isc_mem_t *ctx0, FILE *file) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; REQUIRE(VALID_CONTEXT(ctx)); REQUIRE(file != NULL); @@ -2033,12 +2269,12 @@ isc_mem_printactive(isc_mem_t *ctx, FILE *file) { #endif } -void -isc_mem_printallactive(FILE *file) { +ISC_MEMFUNC_SCOPE void +isc__mem_printallactive(FILE *file) { #if !ISC_MEM_TRACKLINES UNUSED(file); #else - isc_mem_t *ctx; + isc__mem_t *ctx; RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS); @@ -2053,15 +2289,15 @@ isc_mem_printallactive(FILE *file) { #endif } -void -isc_mem_checkdestroyed(FILE *file) { +ISC_MEMFUNC_SCOPE void +isc__mem_checkdestroyed(FILE *file) { RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS); LOCK(&lock); if (!ISC_LIST_EMPTY(contexts)) { #if ISC_MEM_TRACKLINES - isc_mem_t *ctx; + isc__mem_t *ctx; for (ctx = ISC_LIST_HEAD(contexts); ctx != NULL; @@ -2076,9 +2312,11 @@ isc_mem_checkdestroyed(FILE *file) { UNLOCK(&lock); } -unsigned int -isc_mem_references(isc_mem_t *ctx) { +ISC_MEMFUNC_SCOPE unsigned int +isc_mem_references(isc_mem_t *ctx0) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; unsigned int references; + REQUIRE(VALID_CONTEXT(ctx)); MCTXLOCK(ctx, &ctx->lock); @@ -2098,7 +2336,7 @@ typedef struct summarystat { } summarystat_t; static void -renderctx(isc_mem_t *ctx, summarystat_t *summary, xmlTextWriterPtr writer) { +renderctx(isc__mem_t *ctx, summarystat_t *summary, xmlTextWriterPtr writer) { REQUIRE(VALID_CONTEXT(ctx)); xmlTextWriterStartElement(writer, ISC_XMLCHAR "context"); @@ -2184,7 +2422,7 @@ renderctx(isc_mem_t *ctx, summarystat_t *summary, xmlTextWriterPtr writer) { void isc_mem_renderxml(xmlTextWriterPtr writer) { - isc_mem_t *ctx; + isc__mem_t *ctx; summarystat_t summary; isc_uint64_t lost; @@ -2236,3 +2474,4 @@ isc_mem_renderxml(xmlTextWriterPtr writer) { } #endif /* HAVE_LIBXML2 */ +#endif /* BIND9 */ diff --git a/lib/isc/mem_api.c b/lib/isc/mem_api.c new file mode 100644 index 0000000..638efcd --- /dev/null +++ b/lib/isc/mem_api.c @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: mem_api.c,v 1.8 2010-08-12 21:30:26 jinmei Exp $ */ + +#include + +#include +#include +#include +#include + +#if ISC_MEM_TRACKLINES +#define FLARG_PASS , file, line +#define FLARG , const char *file, unsigned int line +#else +#define FLARG_PASS +#define FLARG +#endif + +static isc_mutex_t createlock; +static isc_once_t once = ISC_ONCE_INIT; +static isc_memcreatefunc_t mem_createfunc = NULL; + +static void +initialize(void) { + RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS); +} + +isc_result_t +isc_mem_register(isc_memcreatefunc_t createfunc) { + isc_result_t result = ISC_R_SUCCESS; + + RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); + + LOCK(&createlock); + if (mem_createfunc == NULL) + mem_createfunc = createfunc; + else + result = ISC_R_EXISTS; + UNLOCK(&createlock); + + return (result); +} + +isc_result_t +isc_mem_create(size_t init_max_size, size_t target_size, isc_mem_t **mctxp) { + isc_result_t result; + + LOCK(&createlock); + + REQUIRE(mem_createfunc != NULL); + result = (*mem_createfunc)(init_max_size, target_size, mctxp, + ISC_MEMFLAG_DEFAULT); + + UNLOCK(&createlock); + + return (result); +} + +isc_result_t +isc_mem_create2(size_t init_max_size, size_t target_size, isc_mem_t **mctxp, + unsigned int flags) +{ + isc_result_t result; + + LOCK(&createlock); + + REQUIRE(mem_createfunc != NULL); + result = (*mem_createfunc)(init_max_size, target_size, mctxp, flags); + + UNLOCK(&createlock); + + return (result); +} + +void +isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) { + REQUIRE(ISCAPI_MCTX_VALID(source)); + REQUIRE(targetp != NULL && *targetp == NULL); + + source->methods->attach(source, targetp); + + ENSURE(*targetp == source); +} + +void +isc_mem_detach(isc_mem_t **mctxp) { + REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp)); + + (*mctxp)->methods->detach(mctxp); + + ENSURE(*mctxp == NULL); +} + +void +isc_mem_destroy(isc_mem_t **mctxp) { + REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp)); + + (*mctxp)->methods->destroy(mctxp); + + ENSURE(*mctxp == NULL); +} + +void * +isc__mem_get(isc_mem_t *mctx, size_t size FLARG) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + return (mctx->methods->memget(mctx, size FLARG_PASS)); +} + +void +isc__mem_put(isc_mem_t *mctx, void *ptr, size_t size FLARG) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + mctx->methods->memput(mctx, ptr, size FLARG_PASS); +} + +void +isc__mem_putanddetach(isc_mem_t **mctxp, void *ptr, size_t size FLARG) { + REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp)); + + (*mctxp)->methods->memputanddetach(mctxp, ptr, size FLARG_PASS); + + /* + * XXX: We cannot always ensure *mctxp == NULL here + * (see lib/isc/mem.c). + */ +} + +void * +isc__mem_allocate(isc_mem_t *mctx, size_t size FLARG) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + return (mctx->methods->memallocate(mctx, size FLARG_PASS)); +} + +void * +isc__mem_reallocate(isc_mem_t *mctx, void *ptr, size_t size FLARG) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + return (mctx->methods->memreallocate(mctx, ptr, size FLARG_PASS)); +} + +char * +isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + return (mctx->methods->memstrdup(mctx, s FLARG_PASS)); +} + +void +isc__mem_free(isc_mem_t *mctx, void *ptr FLARG) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + mctx->methods->memfree(mctx, ptr FLARG_PASS); +} + +void +isc_mem_setdestroycheck(isc_mem_t *mctx, isc_boolean_t flag) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + mctx->methods->setdestroycheck(mctx, flag); +} + +void +isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg, + size_t hiwater, size_t lowater) +{ + REQUIRE(ISCAPI_MCTX_VALID(ctx)); + + ctx->methods->setwater(ctx, water, water_arg, hiwater, lowater); +} + +void +isc_mem_waterack(isc_mem_t *ctx, int flag) { + REQUIRE(ISCAPI_MCTX_VALID(ctx)); + + ctx->methods->waterack(ctx, flag); +} + +size_t +isc_mem_inuse(isc_mem_t *mctx) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + return (mctx->methods->inuse(mctx)); +} + +isc_boolean_t +isc_mem_isovermem(isc_mem_t *mctx) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + return (mctx->methods->isovermem(mctx)); +} + +void +isc_mem_setname(isc_mem_t *mctx, const char *name, void *tag) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + UNUSED(name); + UNUSED(tag); + + return; +} + +const char * +isc_mem_getname(isc_mem_t *mctx) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + return (""); +} + +void * +isc_mem_gettag(isc_mem_t *mctx) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + return (NULL); +} + +isc_result_t +isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + return (mctx->methods->mpcreate(mctx, size, mpctxp)); +} + +void +isc_mempool_destroy(isc_mempool_t **mpctxp) { + REQUIRE(mpctxp != NULL && ISCAPI_MPOOL_VALID(*mpctxp)); + + (*mpctxp)->methods->destroy(mpctxp); + + ENSURE(*mpctxp == NULL); +} + +void * +isc__mempool_get(isc_mempool_t *mpctx FLARG) { + REQUIRE(ISCAPI_MPOOL_VALID(mpctx)); + + return (mpctx->methods->get(mpctx FLARG_PASS)); +} + +void +isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) { + REQUIRE(ISCAPI_MPOOL_VALID(mpctx)); + + mpctx->methods->put(mpctx, mem FLARG_PASS); +} + +unsigned int +isc_mempool_getallocated(isc_mempool_t *mpctx) { + REQUIRE(ISCAPI_MPOOL_VALID(mpctx)); + + return (mpctx->methods->getallocated(mpctx)); +} + +void +isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit) { + REQUIRE(ISCAPI_MPOOL_VALID(mpctx)); + + mpctx->methods->setmaxalloc(mpctx, limit); +} + +void +isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit) { + REQUIRE(ISCAPI_MPOOL_VALID(mpctx)); + + mpctx->methods->setfreemax(mpctx, limit); +} + +void +isc_mempool_setname(isc_mempool_t *mpctx, const char *name) { + REQUIRE(ISCAPI_MPOOL_VALID(mpctx)); + + mpctx->methods->setname(mpctx, name); +} + +void +isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock) { + REQUIRE(ISCAPI_MPOOL_VALID(mpctx)); + + mpctx->methods->associatelock(mpctx, lock); +} + +void +isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit) { + REQUIRE(ISCAPI_MPOOL_VALID(mpctx)); + + mpctx->methods->setfillcount(mpctx, limit); +} diff --git a/lib/isc/netaddr.c b/lib/isc/netaddr.c index 92c4fe5..33dddb8 100644 --- a/lib/isc/netaddr.c +++ b/lib/isc/netaddr.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: netaddr.c,v 1.38 2007-06-18 23:47:44 tbox Exp $ */ +/* $Id: netaddr.c,v 1.41 2010-11-17 23:47:08 tbox Exp $ */ /*! \file */ @@ -303,18 +303,18 @@ isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6) { isc_result_t isc_netaddr_frompath(isc_netaddr_t *netaddr, const char *path) { #ifdef ISC_PLATFORM_HAVESYSUNH - if (strlen(path) > sizeof(netaddr->type.un) - 1) - return (ISC_R_NOSPACE); - - memset(netaddr, 0, sizeof(*netaddr)); - netaddr->family = AF_UNIX; - strcpy(netaddr->type.un, path); - netaddr->zone = 0; - return (ISC_R_SUCCESS); -#else + if (strlen(path) > sizeof(netaddr->type.un) - 1) + return (ISC_R_NOSPACE); + + memset(netaddr, 0, sizeof(*netaddr)); + netaddr->family = AF_UNIX; + strcpy(netaddr->type.un, path); + netaddr->zone = 0; + return (ISC_R_SUCCESS); +#else UNUSED(netaddr); UNUSED(path); - return (ISC_R_NOTIMPLEMENTED); + return (ISC_R_NOTIMPLEMENTED); #endif } diff --git a/lib/isc/nls/Makefile.in b/lib/isc/nls/Makefile.in index c4ec7a1..bfd8dd0 100644 --- a/lib/isc/nls/Makefile.in +++ b/lib/isc/nls/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 1999-2001 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.14 2007-06-19 23:47:18 tbox Exp $ +# $Id: Makefile.in,v 1.17 2009-12-05 23:31:41 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ diff --git a/lib/isc/nothreads/Makefile.in b/lib/isc/nothreads/Makefile.in index 042cfce..29bacd6 100644 --- a/lib/isc/nothreads/Makefile.in +++ b/lib/isc/nothreads/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2007, 2010 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 2000, 2001 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,11 +13,11 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.7.332.2 2010-06-09 23:48:16 tbox Exp $ +# $Id: Makefile.in,v 1.12 2010-06-09 23:50:58 tbox Exp $ -srcdir = @srcdir@ -VPATH = @srcdir@ top_srcdir = @top_srcdir@ +srcdir = @top_srcdir@/lib/isc/nothreads +VPATH = @top_srcdir@/lib/isc/nothreads CINCLUDES = -I${srcdir}/include \ -I${srcdir}/../unix/include \ diff --git a/lib/isc/powerpc/include/isc/atomic.h b/lib/isc/powerpc/include/isc/atomic.h index 074fea1..2e11e39 100644 --- a/lib/isc/powerpc/include/isc/atomic.h +++ b/lib/isc/powerpc/include/isc/atomic.h @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: atomic.h,v 1.6.332.2 2009-10-14 23:47:14 tbox Exp $ */ +/* $Id: atomic.h,v 1.8 2009-10-14 23:47:51 tbox Exp $ */ #ifndef ISC_ATOMIC_H #define ISC_ATOMIC_H 1 diff --git a/lib/isc/print.c b/lib/isc/print.c index 5d800f3..bd7b580 100644 --- a/lib/isc/print.c +++ b/lib/isc/print.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: print.c,v 1.35.130.2 2010-10-18 23:46:17 tbox Exp $ */ +/* $Id: print.c,v 1.37 2010-10-18 23:47:08 tbox Exp $ */ /*! \file */ diff --git a/lib/isc/pthreads/Makefile.in b/lib/isc/pthreads/Makefile.in index 572d76c..7aae93d 100644 --- a/lib/isc/pthreads/Makefile.in +++ b/lib/isc/pthreads/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 1998-2001 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.19 2007-06-19 23:47:18 tbox Exp $ +# $Id: Makefile.in,v 1.22 2009-12-05 23:31:41 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ diff --git a/lib/isc/pthreads/mutex.c b/lib/isc/pthreads/mutex.c index efe38db..fa5a701 100644 --- a/lib/isc/pthreads/mutex.c +++ b/lib/isc/pthreads/mutex.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: mutex.c,v 1.16.112.2 2011-01-04 23:45:43 tbox Exp $ */ +/* $Id: mutex.c,v 1.18 2011-01-04 23:47:14 tbox Exp $ */ /*! \file */ diff --git a/lib/isc/radix.c b/lib/isc/radix.c index d72ed33..be2e841 100644 --- a/lib/isc/radix.c +++ b/lib/isc/radix.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: radix.c,v 1.20.36.3 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: radix.c,v 1.23 2009-01-18 23:48:14 tbox Exp $ */ /* * This source was adapted from MRT's RCS Ids: diff --git a/lib/isc/random.c b/lib/isc/random.c index 09145f4..f082fe6 100644 --- a/lib/isc/random.c +++ b/lib/isc/random.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: random.c,v 1.25.332.2 2009-07-16 23:47:17 tbox Exp $ */ +/* $Id: random.c,v 1.28 2009-07-16 05:52:46 marka Exp $ */ /*! \file */ @@ -103,7 +103,7 @@ isc_uint32_t isc_random_jitter(isc_uint32_t max, isc_uint32_t jitter) { isc_uint32_t rnd; - REQUIRE(jitter < max); + REQUIRE(jitter < max || (jitter == 0 && max == 0)); if (jitter == 0) return (max); diff --git a/lib/isc/rwlock.c b/lib/isc/rwlock.c index 39b90d7..fce7516 100644 --- a/lib/isc/rwlock.c +++ b/lib/isc/rwlock.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rwlock.c,v 1.44.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: rwlock.c,v 1.46 2009-01-18 23:48:14 tbox Exp $ */ /*! \file */ diff --git a/lib/isc/sha1.c b/lib/isc/sha1.c index 20ee28d..d72eb9c 100644 --- a/lib/isc/sha1.c +++ b/lib/isc/sha1.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sha1.c,v 1.18 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: sha1.c,v 1.20 2009-02-06 23:47:42 tbox Exp $ */ /* $NetBSD: sha1.c,v 1.5 2000/01/22 22:19:14 mycroft Exp $ */ /* $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $ */ @@ -38,11 +38,47 @@ #include "config.h" #include +#include #include #include #include #include +#ifdef ISC_PLATFORM_OPENSSLHASH + +void +isc_sha1_init(isc_sha1_t *context) +{ + INSIST(context != NULL); + + EVP_DigestInit(context, EVP_sha1()); +} + +void +isc_sha1_invalidate(isc_sha1_t *context) { + EVP_MD_CTX_cleanup(context); +} + +void +isc_sha1_update(isc_sha1_t *context, const unsigned char *data, + unsigned int len) +{ + INSIST(context != 0); + INSIST(data != 0); + + EVP_DigestUpdate(context, (const void *) data, (size_t) len); +} + +void +isc_sha1_final(isc_sha1_t *context, unsigned char *digest) { + INSIST(digest != 0); + INSIST(context != 0); + + EVP_DigestFinal(context, digest, NULL); +} + +#else + #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) /*@{*/ @@ -313,3 +349,4 @@ isc_sha1_final(isc_sha1_t *context, unsigned char *digest) { memset(context, 0, sizeof(isc_sha1_t)); } +#endif diff --git a/lib/isc/sha2.c b/lib/isc/sha2.c index 22f1d47..1dc05a70 100644 --- a/lib/isc/sha2.c +++ b/lib/isc/sha2.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2005-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sha2.c,v 1.13.332.4 2010-01-15 23:47:34 tbox Exp $ */ +/* $Id: sha2.c,v 1.18 2009-10-22 02:21:31 each Exp $ */ /* $FreeBSD$ */ /* $KAME: sha2.c,v 1.8 2001/11/08 01:07:52 itojun Exp $ */ @@ -58,10 +58,169 @@ #include #include +#include #include #include #include +#ifdef ISC_PLATFORM_OPENSSLHASH + +void +isc_sha224_init(isc_sha224_t *context) { + if (context == (isc_sha224_t *)0) { + return; + } + EVP_DigestInit(context, EVP_sha224()); +} + +void +isc_sha224_invalidate(isc_sha224_t *context) { + EVP_MD_CTX_cleanup(context); +} + +void +isc_sha224_update(isc_sha224_t *context, const isc_uint8_t* data, size_t len) { + if (len == 0U) { + /* Calling with no data is valid - we do nothing */ + return; + } + + /* Sanity check: */ + REQUIRE(context != (isc_sha224_t *)0 && data != (isc_uint8_t*)0); + + EVP_DigestUpdate(context, (const void *) data, len); +} + +void +isc_sha224_final(isc_uint8_t digest[], isc_sha224_t *context) { + /* Sanity check: */ + REQUIRE(context != (isc_sha224_t *)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (isc_uint8_t*)0) { + EVP_DigestFinal(context, digest, NULL); + } else { + EVP_MD_CTX_cleanup(context); + } +} + +void +isc_sha256_init(isc_sha256_t *context) { + if (context == (isc_sha256_t *)0) { + return; + } + EVP_DigestInit(context, EVP_sha256()); +} + +void +isc_sha256_invalidate(isc_sha256_t *context) { + EVP_MD_CTX_cleanup(context); +} + +void +isc_sha256_update(isc_sha256_t *context, const isc_uint8_t *data, size_t len) { + if (len == 0U) { + /* Calling with no data is valid - we do nothing */ + return; + } + + /* Sanity check: */ + REQUIRE(context != (isc_sha256_t *)0 && data != (isc_uint8_t*)0); + + EVP_DigestUpdate(context, (const void *) data, len); +} + +void +isc_sha256_final(isc_uint8_t digest[], isc_sha256_t *context) { + /* Sanity check: */ + REQUIRE(context != (isc_sha256_t *)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (isc_uint8_t*)0) { + EVP_DigestFinal(context, digest, NULL); + } else { + EVP_MD_CTX_cleanup(context); + } +} + +void +isc_sha512_init(isc_sha512_t *context) { + if (context == (isc_sha512_t *)0) { + return; + } + EVP_DigestInit(context, EVP_sha512()); +} + +void +isc_sha512_invalidate(isc_sha512_t *context) { + EVP_MD_CTX_cleanup(context); +} + +void isc_sha512_update(isc_sha512_t *context, const isc_uint8_t *data, size_t len) { + if (len == 0U) { + /* Calling with no data is valid - we do nothing */ + return; + } + + /* Sanity check: */ + REQUIRE(context != (isc_sha512_t *)0 && data != (isc_uint8_t*)0); + + EVP_DigestUpdate(context, (const void *) data, len); +} + +void isc_sha512_final(isc_uint8_t digest[], isc_sha512_t *context) { + /* Sanity check: */ + REQUIRE(context != (isc_sha512_t *)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (isc_uint8_t*)0) { + EVP_DigestFinal(context, digest, NULL); + } else { + EVP_MD_CTX_cleanup(context); + } +} + +void +isc_sha384_init(isc_sha384_t *context) { + if (context == (isc_sha384_t *)0) { + return; + } + EVP_DigestInit(context, EVP_sha384()); +} + +void +isc_sha384_invalidate(isc_sha384_t *context) { + EVP_MD_CTX_cleanup(context); +} + +void +isc_sha384_update(isc_sha384_t *context, const isc_uint8_t* data, size_t len) { + if (len == 0U) { + /* Calling with no data is valid - we do nothing */ + return; + } + + /* Sanity check: */ + REQUIRE(context != (isc_sha512_t *)0 && data != (isc_uint8_t*)0); + + EVP_DigestUpdate(context, (const void *) data, len); +} + +void +isc_sha384_final(isc_uint8_t digest[], isc_sha384_t *context) { + /* Sanity check: */ + REQUIRE(context != (isc_sha384_t *)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (isc_uint8_t*)0) { + EVP_DigestFinal(context, digest, NULL); + } else { + EVP_MD_CTX_cleanup(context); + } +} + +#else + /* * UNROLLED TRANSFORM LOOP NOTE: * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform @@ -394,13 +553,6 @@ static const isc_uint64_t sha512_initial_hash_value[8] = { }; #endif -/* - * Constant used by SHA256/384/512_End() functions for converting the - * digest to a readable hexadecimal character string: - */ -static const char *sha2_hex_digits = "0123456789abcdef"; - - /*** SHA-224: *********************************************************/ void @@ -432,41 +584,6 @@ isc_sha224_final(isc_uint8_t digest[], isc_sha224_t *context) { memset(sha256_digest, 0, ISC_SHA256_DIGESTLENGTH); } -char * -isc_sha224_end(isc_sha224_t *context, char buffer[]) { - isc_uint8_t digest[ISC_SHA224_DIGESTLENGTH], *d = digest; - unsigned int i; - - /* Sanity check: */ - REQUIRE(context != (isc_sha224_t *)0); - - if (buffer != (char*)0) { - isc_sha224_final(digest, context); - - for (i = 0; i < ISC_SHA224_DIGESTLENGTH; i++) { - *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; - *buffer++ = sha2_hex_digits[*d & 0x0f]; - d++; - } - *buffer = (char)0; - } else { - memset(context, 0, sizeof(context)); - } - memset(digest, 0, ISC_SHA224_DIGESTLENGTH); - return buffer; -} - -char* -isc_sha224_data(const isc_uint8_t *data, size_t len, - char digest[ISC_SHA224_DIGESTSTRINGLENGTH]) -{ - isc_sha224_t context; - - isc_sha224_init(&context); - isc_sha224_update(&context, data, len); - return (isc_sha224_end(&context, digest)); -} - /*** SHA-256: *********************************************************/ void isc_sha256_init(isc_sha256_t *context) { @@ -479,6 +596,11 @@ isc_sha256_init(isc_sha256_t *context) { context->bitcount = 0; } +void +isc_sha256_invalidate(isc_sha256_t *context) { + memset(context, 0, sizeof(isc_sha256_t)); +} + #ifdef ISC_SHA2_UNROLL_TRANSFORM /* Unrolled SHA-256 round macros: */ @@ -656,11 +778,6 @@ isc_sha256_transform(isc_sha256_t *context, const isc_uint32_t* data) { #endif /* ISC_SHA2_UNROLL_TRANSFORM */ void -isc_sha256_invalidate(isc_sha256_t *context) { - memset(context, 0, sizeof(isc_sha256_t)); -} - -void isc_sha256_update(isc_sha256_t *context, const isc_uint8_t *data, size_t len) { unsigned int freespace, usedspace; @@ -782,42 +899,6 @@ isc_sha256_final(isc_uint8_t digest[], isc_sha256_t *context) { usedspace = 0; } -char * -isc_sha256_end(isc_sha256_t *context, char buffer[]) { - isc_uint8_t digest[ISC_SHA256_DIGESTLENGTH], *d = digest; - unsigned int i; - - /* Sanity check: */ - REQUIRE(context != (isc_sha256_t *)0); - - if (buffer != (char*)0) { - isc_sha256_final(digest, context); - - for (i = 0; i < ISC_SHA256_DIGESTLENGTH; i++) { - *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; - *buffer++ = sha2_hex_digits[*d & 0x0f]; - d++; - } - *buffer = (char)0; - } else { - memset(context, 0, sizeof(context)); - } - memset(digest, 0, ISC_SHA256_DIGESTLENGTH); - return buffer; -} - -char * -isc_sha256_data(const isc_uint8_t* data, size_t len, - char digest[ISC_SHA256_DIGESTSTRINGLENGTH]) -{ - isc_sha256_t context; - - isc_sha256_init(&context); - isc_sha256_update(&context, data, len); - return (isc_sha256_end(&context, digest)); -} - - /*** SHA-512: *********************************************************/ void isc_sha512_init(isc_sha512_t *context) { @@ -830,6 +911,11 @@ isc_sha512_init(isc_sha512_t *context) { context->bitcount[0] = context->bitcount[1] = 0; } +void +isc_sha512_invalidate(isc_sha512_t *context) { + memset(context, 0, sizeof(isc_sha512_t)); +} + #ifdef ISC_SHA2_UNROLL_TRANSFORM /* Unrolled SHA-512 round macros: */ @@ -1000,13 +1086,7 @@ isc_sha512_transform(isc_sha512_t *context, const isc_uint64_t* data) { #endif /* ISC_SHA2_UNROLL_TRANSFORM */ -void -isc_sha512_invalidate(isc_sha512_t *context) { - memset(context, 0, sizeof(isc_sha512_t)); -} - -void -isc_sha512_update(isc_sha512_t *context, const isc_uint8_t *data, size_t len) { +void isc_sha512_update(isc_sha512_t *context, const isc_uint8_t *data, size_t len) { unsigned int freespace, usedspace; if (len == 0U) { @@ -1131,41 +1211,6 @@ void isc_sha512_final(isc_uint8_t digest[], isc_sha512_t *context) { memset(context, 0, sizeof(context)); } -char * -isc_sha512_end(isc_sha512_t *context, char buffer[]) { - isc_uint8_t digest[ISC_SHA512_DIGESTLENGTH], *d = digest; - unsigned int i; - - /* Sanity check: */ - REQUIRE(context != (isc_sha512_t *)0); - - if (buffer != (char*)0) { - isc_sha512_final(digest, context); - - for (i = 0; i < ISC_SHA512_DIGESTLENGTH; i++) { - *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; - *buffer++ = sha2_hex_digits[*d & 0x0f]; - d++; - } - *buffer = (char)0; - } else { - memset(context, 0, sizeof(context)); - } - memset(digest, 0, ISC_SHA512_DIGESTLENGTH); - return buffer; -} - -char * -isc_sha512_data(const isc_uint8_t *data, size_t len, - char digest[ISC_SHA512_DIGESTSTRINGLENGTH]) -{ - isc_sha512_t context; - - isc_sha512_init(&context); - isc_sha512_update(&context, data, len); - return (isc_sha512_end(&context, digest)); -} - /*** SHA-384: *********************************************************/ void @@ -1218,6 +1263,130 @@ isc_sha384_final(isc_uint8_t digest[], isc_sha384_t *context) { /* Zero out state data */ memset(context, 0, sizeof(context)); } +#endif /* !ISC_PLATFORM_OPENSSLHASH */ + +/* + * Constant used by SHA256/384/512_End() functions for converting the + * digest to a readable hexadecimal character string: + */ +static const char *sha2_hex_digits = "0123456789abcdef"; + +char * +isc_sha224_end(isc_sha224_t *context, char buffer[]) { + isc_uint8_t digest[ISC_SHA224_DIGESTLENGTH], *d = digest; + unsigned int i; + + /* Sanity check: */ + REQUIRE(context != (isc_sha224_t *)0); + + if (buffer != (char*)0) { + isc_sha224_final(digest, context); + + for (i = 0; i < ISC_SHA224_DIGESTLENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char)0; + } else { +#ifdef ISC_PLATFORM_OPENSSLHASH + EVP_MD_CTX_cleanup(context); +#else + memset(context, 0, sizeof(context)); +#endif + } + memset(digest, 0, ISC_SHA224_DIGESTLENGTH); + return buffer; +} + +char * +isc_sha224_data(const isc_uint8_t *data, size_t len, + char digest[ISC_SHA224_DIGESTSTRINGLENGTH]) +{ + isc_sha224_t context; + + isc_sha224_init(&context); + isc_sha224_update(&context, data, len); + return (isc_sha224_end(&context, digest)); +} + +char * +isc_sha256_end(isc_sha256_t *context, char buffer[]) { + isc_uint8_t digest[ISC_SHA256_DIGESTLENGTH], *d = digest; + unsigned int i; + + /* Sanity check: */ + REQUIRE(context != (isc_sha256_t *)0); + + if (buffer != (char*)0) { + isc_sha256_final(digest, context); + + for (i = 0; i < ISC_SHA256_DIGESTLENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char)0; + } else { +#ifdef ISC_PLATFORM_OPENSSLHASH + EVP_MD_CTX_cleanup(context); +#else + memset(context, 0, sizeof(context)); +#endif + } + memset(digest, 0, ISC_SHA256_DIGESTLENGTH); + return buffer; +} + +char * +isc_sha256_data(const isc_uint8_t* data, size_t len, + char digest[ISC_SHA256_DIGESTSTRINGLENGTH]) +{ + isc_sha256_t context; + + isc_sha256_init(&context); + isc_sha256_update(&context, data, len); + return (isc_sha256_end(&context, digest)); +} + +char * +isc_sha512_end(isc_sha512_t *context, char buffer[]) { + isc_uint8_t digest[ISC_SHA512_DIGESTLENGTH], *d = digest; + unsigned int i; + + /* Sanity check: */ + REQUIRE(context != (isc_sha512_t *)0); + + if (buffer != (char*)0) { + isc_sha512_final(digest, context); + + for (i = 0; i < ISC_SHA512_DIGESTLENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char)0; + } else { +#ifdef ISC_PLATFORM_OPENSSLHASH + EVP_MD_CTX_cleanup(context); +#else + memset(context, 0, sizeof(context)); +#endif + } + memset(digest, 0, ISC_SHA512_DIGESTLENGTH); + return buffer; +} + +char * +isc_sha512_data(const isc_uint8_t *data, size_t len, + char digest[ISC_SHA512_DIGESTSTRINGLENGTH]) +{ + isc_sha512_t context; + + isc_sha512_init(&context); + isc_sha512_update(&context, data, len); + return (isc_sha512_end(&context, digest)); +} char * isc_sha384_end(isc_sha384_t *context, char buffer[]) { @@ -1237,13 +1406,17 @@ isc_sha384_end(isc_sha384_t *context, char buffer[]) { } *buffer = (char)0; } else { +#ifdef ISC_PLATFORM_OPENSSLHASH + EVP_MD_CTX_cleanup(context); +#else memset(context, 0, sizeof(context)); +#endif } memset(digest, 0, ISC_SHA384_DIGESTLENGTH); return buffer; } -char* +char * isc_sha384_data(const isc_uint8_t *data, size_t len, char digest[ISC_SHA384_DIGESTSTRINGLENGTH]) { diff --git a/lib/isc/sockaddr.c b/lib/isc/sockaddr.c index 19833e4..9661ee4 100644 --- a/lib/isc/sockaddr.c +++ b/lib/isc/sockaddr.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sockaddr.c,v 1.70 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: sockaddr.c,v 1.73 2010-11-17 23:47:09 tbox Exp $ */ /*! \file */ @@ -390,8 +390,8 @@ isc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na, #endif sockaddr->type.sin6.sin6_port = htons(port); break; - default: - INSIST(0); + default: + INSIST(0); } ISC_LINK_INIT(sockaddr, link); } diff --git a/lib/isc/socket_api.c b/lib/isc/socket_api.c new file mode 100644 index 0000000..c1e5fd4 --- /dev/null +++ b/lib/isc/socket_api.c @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: socket_api.c,v 1.5 2009-10-01 01:30:01 sar Exp $ */ + +#include + +#include +#include +#include +#include +#include +#include + +static isc_mutex_t createlock; +static isc_once_t once = ISC_ONCE_INIT; +static isc_socketmgrcreatefunc_t socketmgr_createfunc = NULL; + +static void +initialize(void) { + RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS); +} + +isc_result_t +isc_socket_register(isc_socketmgrcreatefunc_t createfunc) { + isc_result_t result = ISC_R_SUCCESS; + + RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); + + LOCK(&createlock); + if (socketmgr_createfunc == NULL) + socketmgr_createfunc = createfunc; + else + result = ISC_R_EXISTS; + UNLOCK(&createlock); + + return (result); +} + +isc_result_t +isc_socketmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, + isc_socketmgr_t **managerp) +{ + isc_result_t result; + + LOCK(&createlock); + + REQUIRE(socketmgr_createfunc != NULL); + result = (*socketmgr_createfunc)(mctx, managerp); + + UNLOCK(&createlock); + + if (result == ISC_R_SUCCESS) + isc_appctx_setsocketmgr(actx, *managerp); + + return (result); +} + +isc_result_t +isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) { + isc_result_t result; + + LOCK(&createlock); + + REQUIRE(socketmgr_createfunc != NULL); + result = (*socketmgr_createfunc)(mctx, managerp); + + UNLOCK(&createlock); + + return (result); +} + +void +isc_socketmgr_destroy(isc_socketmgr_t **managerp) { + REQUIRE(managerp != NULL && ISCAPI_SOCKETMGR_VALID(*managerp)); + + (*managerp)->methods->destroy(managerp); + + ENSURE(*managerp == NULL); +} + +isc_result_t +isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, + isc_socket_t **socketp) +{ + REQUIRE(ISCAPI_SOCKETMGR_VALID(manager)); + + return (manager->methods->socketcreate(manager, pf, type, socketp)); +} + +void +isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) { + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + REQUIRE(socketp != NULL && *socketp == NULL); + + sock->methods->attach(sock, socketp); + + ENSURE(*socketp == sock); +} + +void +isc_socket_detach(isc_socket_t **socketp) { + REQUIRE(socketp != NULL && ISCAPI_SOCKET_VALID(*socketp)); + + (*socketp)->methods->detach(socketp); + + ENSURE(*socketp == NULL); +} + +isc_result_t +isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr, + unsigned int options) +{ + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + + return (sock->methods->bind(sock, sockaddr, options)); +} + +isc_result_t +isc_socket_sendto(isc_socket_t *sock, isc_region_t *region, isc_task_t *task, + isc_taskaction_t action, const void *arg, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo) +{ + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + + return (sock->methods->sendto(sock, region, task, action, arg, address, + pktinfo)); +} + +isc_result_t +isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, isc_task_t *task, + isc_taskaction_t action, const void *arg) +{ + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + + return (sock->methods->connect(sock, addr, task, action, arg)); +} + +isc_result_t +isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum, + isc_task_t *task, isc_taskaction_t action, const void *arg) +{ + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + + return (sock->methods->recv(sock, region, minimum, task, action, arg)); +} + +void +isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) { + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + + sock->methods->cancel(sock, task, how); +} + +isc_result_t +isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) { + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + + return (sock->methods->getsockname(sock, addressp)); +} + +void +isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) { + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + + sock->methods->ipv6only(sock, yes); +} + +isc_sockettype_t +isc_socket_gettype(isc_socket_t *sock) { + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + + return (sock->methods->gettype(sock)); +} + +void +isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) { + REQUIRE(ISCAPI_SOCKET_VALID(socket)); + + UNUSED(socket); /* in case REQUIRE() is empty */ + UNUSED(name); + UNUSED(tag); +} + +isc_result_t +isc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags, + isc_sockfdwatch_t callback, void *cbarg, + isc_task_t *task, isc_socket_t **socketp) +{ + REQUIRE(ISCAPI_SOCKETMGR_VALID(manager)); + + return (manager->methods->fdwatchcreate(manager, fd, flags, + callback, cbarg, task, + socketp)); +} + +isc_result_t +isc_socket_fdwatchpoke(isc_socket_t *sock, int flags) +{ + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + + return(sock->methods->fdwatchpoke(sock, flags)); +} diff --git a/lib/isc/stats.c b/lib/isc/stats.c index ac66bcf..e72fb54 100644 --- a/lib/isc/stats.c +++ b/lib/isc/stats.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: stats.c,v 1.3.6.2 2009-01-29 23:47:44 tbox Exp $ */ +/* $Id: stats.c,v 1.3 2009-01-27 23:47:54 tbox Exp $ */ /*! \file */ diff --git a/lib/isc/task.c b/lib/isc/task.c index 5d87f21..a9dfd1f 100644 --- a/lib/isc/task.c +++ b/lib/isc/task.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: task.c,v 1.107.120.2 2010-12-03 23:45:47 tbox Exp $ */ +/* $Id: task.c,v 1.115.14.1.2.1 2011-06-02 23:47:36 tbox Exp $ */ /*! \file * \author Principal Author: Bob Halley @@ -40,9 +40,33 @@ #include #include -#ifndef ISC_PLATFORM_USETHREADS +#ifdef OPENSSL_LEAKS +#include +#endif + +/*% + * For BIND9 internal applications: + * when built with threads we use multiple worker threads shared by the whole + * application. + * when built without threads we share a single global task manager and use + * an integrated event loop for socket, timer, and other generic task events. + * For generic library: + * we don't use either of them: an application can have multiple task managers + * whether or not it's threaded, and if the application is threaded each thread + * is expected to have a separate manager; no "worker threads" are shared by + * the application threads. + */ +#ifdef BIND9 +#ifdef ISC_PLATFORM_USETHREADS +#define USE_WORKER_THREADS +#else +#define USE_SHARED_MANAGER +#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* BIND9 */ + +#ifndef USE_WORKER_THREADS #include "task_p.h" -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ #ifdef ISC_TASK_TRACE #define XTRACE(m) fprintf(stderr, "task %p thread %lu: %s\n", \ @@ -66,7 +90,7 @@ typedef enum { task_state_done } task_state_t; -#ifdef HAVE_LIBXML2 +#if defined(HAVE_LIBXML2) && defined(BIND9) static const char *statenames[] = { "idle", "ready", "running", "done", }; @@ -75,10 +99,13 @@ static const char *statenames[] = { #define TASK_MAGIC ISC_MAGIC('T', 'A', 'S', 'K') #define VALID_TASK(t) ISC_MAGIC_VALID(t, TASK_MAGIC) -struct isc_task { +typedef struct isc__task isc__task_t; +typedef struct isc__taskmgr isc__taskmgr_t; + +struct isc__task { /* Not locked. */ - unsigned int magic; - isc_taskmgr_t * manager; + isc_task_t common; + isc__taskmgr_t * manager; isc_mutex_t lock; /* Locked by task lock. */ task_state_t state; @@ -91,8 +118,8 @@ struct isc_task { char name[16]; void * tag; /* Locked by task manager lock. */ - LINK(isc_task_t) link; - LINK(isc_task_t) ready_link; + LINK(isc__task_t) link; + LINK(isc__task_t) ready_link; }; #define TASK_F_SHUTTINGDOWN 0x01 @@ -103,9 +130,11 @@ struct isc_task { #define TASK_MANAGER_MAGIC ISC_MAGIC('T', 'S', 'K', 'M') #define VALID_MANAGER(m) ISC_MAGIC_VALID(m, TASK_MANAGER_MAGIC) -struct isc_taskmgr { +typedef ISC_LIST(isc__task_t) isc__tasklist_t; + +struct isc__taskmgr { /* Not locked. */ - unsigned int magic; + isc_taskmgr_t common; isc_mem_t * mctx; isc_mutex_t lock; #ifdef ISC_PLATFORM_USETHREADS @@ -114,8 +143,8 @@ struct isc_taskmgr { #endif /* ISC_PLATFORM_USETHREADS */ /* Locked by task manager lock. */ unsigned int default_quantum; - LIST(isc_task_t) tasks; - isc_tasklist_t ready_tasks; + LIST(isc__task_t) tasks; + isc__tasklist_t ready_tasks; #ifdef ISC_PLATFORM_USETHREADS isc_condition_t work_available; isc_condition_t exclusive_granted; @@ -123,7 +152,7 @@ struct isc_taskmgr { unsigned int tasks_running; isc_boolean_t exclusive_requested; isc_boolean_t exiting; -#ifndef ISC_PLATFORM_USETHREADS +#ifdef USE_SHARED_MANAGER unsigned int refs; #endif /* ISC_PLATFORM_USETHREADS */ }; @@ -132,17 +161,116 @@ struct isc_taskmgr { #define DEFAULT_DEFAULT_QUANTUM 5 #define FINISHED(m) ((m)->exiting && EMPTY((m)->tasks)) -#ifndef ISC_PLATFORM_USETHREADS -static isc_taskmgr_t *taskmgr = NULL; -#endif /* ISC_PLATFORM_USETHREADS */ +#ifdef USE_SHARED_MANAGER +static isc__taskmgr_t *taskmgr = NULL; +#endif /* USE_SHARED_MANAGER */ + +/*% + * The following can be either static or public, depending on build environment. + */ + +#ifdef BIND9 +#define ISC_TASKFUNC_SCOPE +#else +#define ISC_TASKFUNC_SCOPE static +#endif + +ISC_TASKFUNC_SCOPE isc_result_t +isc__task_create(isc_taskmgr_t *manager0, unsigned int quantum, + isc_task_t **taskp); +ISC_TASKFUNC_SCOPE void +isc__task_attach(isc_task_t *source0, isc_task_t **targetp); +ISC_TASKFUNC_SCOPE void +isc__task_detach(isc_task_t **taskp); +ISC_TASKFUNC_SCOPE void +isc__task_send(isc_task_t *task0, isc_event_t **eventp); +ISC_TASKFUNC_SCOPE void +isc__task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp); +ISC_TASKFUNC_SCOPE unsigned int +isc__task_purgerange(isc_task_t *task0, void *sender, isc_eventtype_t first, + isc_eventtype_t last, void *tag); +ISC_TASKFUNC_SCOPE unsigned int +isc__task_purge(isc_task_t *task, void *sender, isc_eventtype_t type, + void *tag); +ISC_TASKFUNC_SCOPE isc_boolean_t +isc__task_purgeevent(isc_task_t *task0, isc_event_t *event); +ISC_TASKFUNC_SCOPE unsigned int +isc__task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first, + isc_eventtype_t last, void *tag, + isc_eventlist_t *events); +ISC_TASKFUNC_SCOPE unsigned int +isc__task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type, + void *tag, isc_eventlist_t *events); +ISC_TASKFUNC_SCOPE isc_result_t +isc__task_onshutdown(isc_task_t *task0, isc_taskaction_t action, + const void *arg); +ISC_TASKFUNC_SCOPE void +isc__task_shutdown(isc_task_t *task0); +ISC_TASKFUNC_SCOPE void +isc__task_destroy(isc_task_t **taskp); +ISC_TASKFUNC_SCOPE void +isc__task_setname(isc_task_t *task0, const char *name, void *tag); +ISC_TASKFUNC_SCOPE const char * +isc__task_getname(isc_task_t *task0); +ISC_TASKFUNC_SCOPE void * +isc__task_gettag(isc_task_t *task0); +ISC_TASKFUNC_SCOPE void +isc__task_getcurrenttime(isc_task_t *task0, isc_stdtime_t *t); +ISC_TASKFUNC_SCOPE isc_result_t +isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers, + unsigned int default_quantum, isc_taskmgr_t **managerp); +ISC_TASKFUNC_SCOPE void +isc__taskmgr_destroy(isc_taskmgr_t **managerp); +ISC_TASKFUNC_SCOPE isc_result_t +isc__task_beginexclusive(isc_task_t *task); +ISC_TASKFUNC_SCOPE void +isc__task_endexclusive(isc_task_t *task0); + +static struct isc__taskmethods { + isc_taskmethods_t methods; + + /*% + * The following are defined just for avoiding unused static functions. + */ +#ifndef BIND9 + void *purgeevent, *unsendrange, *getname, *gettag, *getcurrenttime; +#endif +} taskmethods = { + { + isc__task_attach, + isc__task_detach, + isc__task_destroy, + isc__task_send, + isc__task_sendanddetach, + isc__task_unsend, + isc__task_onshutdown, + isc__task_shutdown, + isc__task_setname, + isc__task_purge, + isc__task_purgerange, + isc__task_beginexclusive, + isc__task_endexclusive + } +#ifndef BIND9 + , + (void *)isc__task_purgeevent, (void *)isc__task_unsendrange, + (void *)isc__task_getname, (void *)isc__task_gettag, + (void *)isc__task_getcurrenttime +#endif +}; + +static isc_taskmgrmethods_t taskmgrmethods = { + isc__taskmgr_destroy, + isc__task_create +}; /*** *** Tasks. ***/ static void -task_finished(isc_task_t *task) { - isc_taskmgr_t *manager = task->manager; +task_finished(isc__task_t *task) { + isc__taskmgr_t *manager = task->manager; REQUIRE(EMPTY(task->events)); REQUIRE(EMPTY(task->on_shutdown)); @@ -153,7 +281,7 @@ task_finished(isc_task_t *task) { LOCK(&manager->lock); UNLINK(manager->tasks, task, link); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS if (FINISHED(manager)) { /* * All tasks have completed and the @@ -163,19 +291,21 @@ task_finished(isc_task_t *task) { */ BROADCAST(&manager->work_available); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ UNLOCK(&manager->lock); DESTROYLOCK(&task->lock); - task->magic = 0; + task->common.impmagic = 0; + task->common.magic = 0; isc_mem_put(manager->mctx, task, sizeof(*task)); } -isc_result_t -isc_task_create(isc_taskmgr_t *manager, unsigned int quantum, - isc_task_t **taskp) +ISC_TASKFUNC_SCOPE isc_result_t +isc__task_create(isc_taskmgr_t *manager0, unsigned int quantum, + isc_task_t **taskp) { - isc_task_t *task; + isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0; + isc__task_t *task; isc_boolean_t exiting; isc_result_t result; @@ -220,14 +350,17 @@ isc_task_create(isc_taskmgr_t *manager, unsigned int quantum, return (ISC_R_SHUTTINGDOWN); } - task->magic = TASK_MAGIC; - *taskp = task; + task->common.methods = (isc_taskmethods_t *)&taskmethods; + task->common.magic = ISCAPI_TASK_MAGIC; + task->common.impmagic = TASK_MAGIC; + *taskp = (isc_task_t *)task; return (ISC_R_SUCCESS); } -void -isc_task_attach(isc_task_t *source, isc_task_t **targetp) { +ISC_TASKFUNC_SCOPE void +isc__task_attach(isc_task_t *source0, isc_task_t **targetp) { + isc__task_t *source = (isc__task_t *)source0; /* * Attach *targetp to source. @@ -242,11 +375,11 @@ isc_task_attach(isc_task_t *source, isc_task_t **targetp) { source->references++; UNLOCK(&source->lock); - *targetp = source; + *targetp = (isc_task_t *)source; } static inline isc_boolean_t -task_shutdown(isc_task_t *task) { +task_shutdown(isc__task_t *task) { isc_boolean_t was_idle = ISC_FALSE; isc_event_t *event, *prev; @@ -283,8 +416,8 @@ task_shutdown(isc_task_t *task) { } static inline void -task_ready(isc_task_t *task) { - isc_taskmgr_t *manager = task->manager; +task_ready(isc__task_t *task) { + isc__taskmgr_t *manager = task->manager; REQUIRE(VALID_MANAGER(manager)); REQUIRE(task->state == task_state_ready); @@ -294,15 +427,15 @@ task_ready(isc_task_t *task) { LOCK(&manager->lock); ENQUEUE(manager->ready_tasks, task, ready_link); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS SIGNAL(&manager->work_available); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ UNLOCK(&manager->lock); } static inline isc_boolean_t -task_detach(isc_task_t *task) { +task_detach(isc__task_t *task) { /* * Caller must be holding the task lock. @@ -330,9 +463,9 @@ task_detach(isc_task_t *task) { return (ISC_FALSE); } -void -isc_task_detach(isc_task_t **taskp) { - isc_task_t *task; +ISC_TASKFUNC_SCOPE void +isc__task_detach(isc_task_t **taskp) { + isc__task_t *task; isc_boolean_t was_idle; /* @@ -340,7 +473,7 @@ isc_task_detach(isc_task_t **taskp) { */ REQUIRE(taskp != NULL); - task = *taskp; + task = (isc__task_t *)*taskp; REQUIRE(VALID_TASK(task)); XTRACE("isc_task_detach"); @@ -356,7 +489,7 @@ isc_task_detach(isc_task_t **taskp) { } static inline isc_boolean_t -task_send(isc_task_t *task, isc_event_t **eventp) { +task_send(isc__task_t *task, isc_event_t **eventp) { isc_boolean_t was_idle = ISC_FALSE; isc_event_t *event; @@ -385,8 +518,9 @@ task_send(isc_task_t *task, isc_event_t **eventp) { return (was_idle); } -void -isc_task_send(isc_task_t *task, isc_event_t **eventp) { +ISC_TASKFUNC_SCOPE void +isc__task_send(isc_task_t *task0, isc_event_t **eventp) { + isc__task_t *task = (isc__task_t *)task0; isc_boolean_t was_idle; /* @@ -426,10 +560,10 @@ isc_task_send(isc_task_t *task, isc_event_t **eventp) { } } -void -isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) { +ISC_TASKFUNC_SCOPE void +isc__task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) { isc_boolean_t idle1, idle2; - isc_task_t *task; + isc__task_t *task; /* * Send '*event' to '*taskp' and then detach '*taskp' from its @@ -437,7 +571,7 @@ isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) { */ REQUIRE(taskp != NULL); - task = *taskp; + task = (isc__task_t *)*taskp; REQUIRE(VALID_TASK(task)); XTRACE("isc_task_sendanddetach"); @@ -463,7 +597,7 @@ isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) { #define PURGE_OK(event) (((event)->ev_attributes & ISC_EVENTATTR_NOPURGE) == 0) static unsigned int -dequeue_events(isc_task_t *task, void *sender, isc_eventtype_t first, +dequeue_events(isc__task_t *task, void *sender, isc_eventtype_t first, isc_eventtype_t last, void *tag, isc_eventlist_t *events, isc_boolean_t purging) { @@ -502,10 +636,11 @@ dequeue_events(isc_task_t *task, void *sender, isc_eventtype_t first, return (count); } -unsigned int -isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first, - isc_eventtype_t last, void *tag) +ISC_TASKFUNC_SCOPE unsigned int +isc__task_purgerange(isc_task_t *task0, void *sender, isc_eventtype_t first, + isc_eventtype_t last, void *tag) { + isc__task_t *task = (isc__task_t *)task0; unsigned int count; isc_eventlist_t events; isc_event_t *event, *next_event; @@ -533,9 +668,9 @@ isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first, return (count); } -unsigned int -isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type, - void *tag) +ISC_TASKFUNC_SCOPE unsigned int +isc__task_purge(isc_task_t *task, void *sender, isc_eventtype_t type, + void *tag) { /* * Purge events from a task's event queue. @@ -543,11 +678,12 @@ isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type, XTRACE("isc_task_purge"); - return (isc_task_purgerange(task, sender, type, type, tag)); + return (isc__task_purgerange(task, sender, type, type, tag)); } -isc_boolean_t -isc_task_purgeevent(isc_task_t *task, isc_event_t *event) { +ISC_TASKFUNC_SCOPE isc_boolean_t +isc__task_purgeevent(isc_task_t *task0, isc_event_t *event) { + isc__task_t *task = (isc__task_t *)task0; isc_event_t *curr_event, *next_event; /* @@ -588,10 +724,10 @@ isc_task_purgeevent(isc_task_t *task, isc_event_t *event) { return (ISC_TRUE); } -unsigned int -isc_task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first, - isc_eventtype_t last, void *tag, - isc_eventlist_t *events) +ISC_TASKFUNC_SCOPE unsigned int +isc__task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first, + isc_eventtype_t last, void *tag, + isc_eventlist_t *events) { /* * Remove events from a task's event queue. @@ -599,13 +735,13 @@ isc_task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first, XTRACE("isc_task_unsendrange"); - return (dequeue_events(task, sender, first, last, tag, events, - ISC_FALSE)); + return (dequeue_events((isc__task_t *)task, sender, first, + last, tag, events, ISC_FALSE)); } -unsigned int -isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type, - void *tag, isc_eventlist_t *events) +ISC_TASKFUNC_SCOPE unsigned int +isc__task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type, + void *tag, isc_eventlist_t *events) { /* * Remove events from a task's event queue. @@ -613,13 +749,15 @@ isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type, XTRACE("isc_task_unsend"); - return (dequeue_events(task, sender, type, type, tag, events, - ISC_FALSE)); + return (dequeue_events((isc__task_t *)task, sender, type, + type, tag, events, ISC_FALSE)); } -isc_result_t -isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, const void *arg) +ISC_TASKFUNC_SCOPE isc_result_t +isc__task_onshutdown(isc_task_t *task0, isc_taskaction_t action, + const void *arg) { + isc__task_t *task = (isc__task_t *)task0; isc_boolean_t disallowed = ISC_FALSE; isc_result_t result = ISC_R_SUCCESS; isc_event_t *event; @@ -655,8 +793,9 @@ isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, const void *arg) return (result); } -void -isc_task_shutdown(isc_task_t *task) { +ISC_TASKFUNC_SCOPE void +isc__task_shutdown(isc_task_t *task0) { + isc__task_t *task = (isc__task_t *)task0; isc_boolean_t was_idle; /* @@ -673,8 +812,8 @@ isc_task_shutdown(isc_task_t *task) { task_ready(task); } -void -isc_task_destroy(isc_task_t **taskp) { +ISC_TASKFUNC_SCOPE void +isc__task_destroy(isc_task_t **taskp) { /* * Destroy '*taskp'. @@ -686,8 +825,9 @@ isc_task_destroy(isc_task_t **taskp) { isc_task_detach(taskp); } -void -isc_task_setname(isc_task_t *task, const char *name, void *tag) { +ISC_TASKFUNC_SCOPE void +isc__task_setname(isc_task_t *task0, const char *name, void *tag) { + isc__task_t *task = (isc__task_t *)task0; /* * Name 'task'. @@ -702,18 +842,28 @@ isc_task_setname(isc_task_t *task, const char *name, void *tag) { UNLOCK(&task->lock); } -const char * -isc_task_getname(isc_task_t *task) { +ISC_TASKFUNC_SCOPE const char * +isc__task_getname(isc_task_t *task0) { + isc__task_t *task = (isc__task_t *)task0; + + REQUIRE(VALID_TASK(task)); + return (task->name); } -void * -isc_task_gettag(isc_task_t *task) { +ISC_TASKFUNC_SCOPE void * +isc__task_gettag(isc_task_t *task0) { + isc__task_t *task = (isc__task_t *)task0; + + REQUIRE(VALID_TASK(task)); + return (task->tag); } -void -isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t) { +ISC_TASKFUNC_SCOPE void +isc__task_getcurrenttime(isc_task_t *task0, isc_stdtime_t *t) { + isc__task_t *task = (isc__task_t *)task0; + REQUIRE(VALID_TASK(task)); REQUIRE(t != NULL); @@ -728,12 +878,12 @@ isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t) { *** Task Manager. ***/ static void -dispatch(isc_taskmgr_t *manager) { - isc_task_t *task; -#ifndef ISC_PLATFORM_USETHREADS +dispatch(isc__taskmgr_t *manager) { + isc__task_t *task; +#ifndef USE_WORKER_THREADS unsigned int total_dispatch_count = 0; - isc_tasklist_t ready_tasks; -#endif /* ISC_PLATFORM_USETHREADS */ + isc__tasklist_t ready_tasks; +#endif /* USE_WORKER_THREADS */ REQUIRE(VALID_MANAGER(manager)); @@ -787,12 +937,12 @@ dispatch(isc_taskmgr_t *manager) { * unlocks. The while expression is always protected by the lock. */ -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_WORKER_THREADS ISC_LIST_INIT(ready_tasks); #endif LOCK(&manager->lock); while (!FINISHED(manager)) { -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS /* * For reasons similar to those given in the comment in * isc_task_send() above, it is safe for us to dequeue @@ -812,11 +962,11 @@ dispatch(isc_taskmgr_t *manager) { ISC_MSGSET_TASK, ISC_MSG_AWAKE, "awake")); } -#else /* ISC_PLATFORM_USETHREADS */ +#else /* USE_WORKER_THREADS */ if (total_dispatch_count >= DEFAULT_TASKMGR_QUANTUM || EMPTY(manager->ready_tasks)) break; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TASK, ISC_MSG_WORKING, "working")); @@ -859,13 +1009,15 @@ dispatch(isc_taskmgr_t *manager) { "execute action")); if (event->ev_action != NULL) { UNLOCK(&task->lock); - (event->ev_action)(task,event); + (event->ev_action)( + (isc_task_t *)task, + event); LOCK(&task->lock); } dispatch_count++; -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_WORKER_THREADS total_dispatch_count++; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ } if (task->references == 0 && @@ -950,12 +1102,12 @@ dispatch(isc_taskmgr_t *manager) { LOCK(&manager->lock); manager->tasks_running--; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS if (manager->exclusive_requested && manager->tasks_running == 1) { SIGNAL(&manager->exclusive_granted); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ if (requeue) { /* * We know we're awake, so we don't have @@ -976,7 +1128,7 @@ dispatch(isc_taskmgr_t *manager) { * were usually nonempty, the 'optimization' * might even hurt rather than help. */ -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS ENQUEUE(manager->ready_tasks, task, ready_link); #else @@ -985,19 +1137,19 @@ dispatch(isc_taskmgr_t *manager) { } } } -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_WORKER_THREADS ISC_LIST_APPENDLIST(manager->ready_tasks, ready_tasks, ready_link); #endif UNLOCK(&manager->lock); } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS static isc_threadresult_t #ifdef _WIN32 WINAPI #endif run(void *uap) { - isc_taskmgr_t *manager = uap; + isc__taskmgr_t *manager = uap; XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_STARTING, "starting")); @@ -1007,33 +1159,42 @@ run(void *uap) { XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_EXITING, "exiting")); +#ifdef OPENSSL_LEAKS + ERR_remove_state(0); +#endif + return ((isc_threadresult_t)0); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ static void -manager_free(isc_taskmgr_t *manager) { +manager_free(isc__taskmgr_t *manager) { isc_mem_t *mctx; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS (void)isc_condition_destroy(&manager->exclusive_granted); (void)isc_condition_destroy(&manager->work_available); isc_mem_free(manager->mctx, manager->threads); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ DESTROYLOCK(&manager->lock); - manager->magic = 0; + manager->common.impmagic = 0; + manager->common.magic = 0; mctx = manager->mctx; isc_mem_put(mctx, manager, sizeof(*manager)); isc_mem_detach(&mctx); + +#ifdef USE_SHARED_MANAGER + taskmgr = NULL; +#endif /* USE_SHARED_MANAGER */ } -isc_result_t -isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, - unsigned int default_quantum, isc_taskmgr_t **managerp) +ISC_TASKFUNC_SCOPE isc_result_t +isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers, + unsigned int default_quantum, isc_taskmgr_t **managerp) { isc_result_t result; unsigned int i, started = 0; - isc_taskmgr_t *manager; + isc__taskmgr_t *manager; /* * Create a new task manager. @@ -1042,28 +1203,33 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, REQUIRE(workers > 0); REQUIRE(managerp != NULL && *managerp == NULL); -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_WORKER_THREADS UNUSED(i); UNUSED(started); - UNUSED(workers); +#endif +#ifdef USE_SHARED_MANAGER if (taskmgr != NULL) { + if (taskmgr->refs == 0) + return (ISC_R_SHUTTINGDOWN); taskmgr->refs++; - *managerp = taskmgr; + *managerp = (isc_taskmgr_t *)taskmgr; return (ISC_R_SUCCESS); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_SHARED_MANAGER */ manager = isc_mem_get(mctx, sizeof(*manager)); if (manager == NULL) return (ISC_R_NOMEMORY); - manager->magic = TASK_MANAGER_MAGIC; + manager->common.methods = &taskmgrmethods; + manager->common.impmagic = TASK_MANAGER_MAGIC; + manager->common.magic = ISCAPI_TASKMGR_MAGIC; manager->mctx = NULL; result = isc_mutex_init(&manager->lock); if (result != ISC_R_SUCCESS) goto cleanup_mgr; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS manager->workers = 0; manager->threads = isc_mem_allocate(mctx, workers * sizeof(isc_thread_t)); @@ -1087,7 +1253,7 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, result = ISC_R_UNEXPECTED; goto cleanup_workavailable; } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ if (default_quantum == 0) default_quantum = DEFAULT_DEFAULT_QUANTUM; manager->default_quantum = default_quantum; @@ -1099,7 +1265,7 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, isc_mem_attach(mctx, &manager->mctx); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS LOCK(&manager->lock); /* * Start workers. @@ -1119,16 +1285,17 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, return (ISC_R_NOTHREADS); } isc_thread_setconcurrency(workers); -#else /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ +#ifdef USE_SHARED_MANAGER manager->refs = 1; taskmgr = manager; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_SHARED_MANAGER */ - *managerp = manager; + *managerp = (isc_taskmgr_t *)manager; return (ISC_R_SUCCESS); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS cleanup_workavailable: (void)isc_condition_destroy(&manager->work_available); cleanup_threads: @@ -1141,10 +1308,10 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, return (result); } -void -isc_taskmgr_destroy(isc_taskmgr_t **managerp) { - isc_taskmgr_t *manager; - isc_task_t *task; +ISC_TASKFUNC_SCOPE void +isc__taskmgr_destroy(isc_taskmgr_t **managerp) { + isc__taskmgr_t *manager; + isc__task_t *task; unsigned int i; /* @@ -1152,18 +1319,20 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) { */ REQUIRE(managerp != NULL); - manager = *managerp; + manager = (isc__taskmgr_t *)*managerp; REQUIRE(VALID_MANAGER(manager)); -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_WORKER_THREADS UNUSED(i); +#endif /* USE_WORKER_THREADS */ - if (manager->refs > 1) { - manager->refs--; +#ifdef USE_SHARED_MANAGER + manager->refs--; + if (manager->refs > 0) { *managerp = NULL; return; } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif XTHREADTRACE("isc_taskmgr_destroy"); /* @@ -1203,7 +1372,7 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) { ENQUEUE(manager->ready_tasks, task, ready_link); UNLOCK(&task->lock); } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS /* * Wake up any sleeping workers. This ensures we get work done if * there's work left to do, and if there are already no tasks left @@ -1217,36 +1386,51 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) { */ for (i = 0; i < manager->workers; i++) (void)isc_thread_join(manager->threads[i], NULL); -#else /* ISC_PLATFORM_USETHREADS */ +#else /* USE_WORKER_THREADS */ /* * Dispatch the shutdown events. */ UNLOCK(&manager->lock); - while (isc__taskmgr_ready()) - (void)isc__taskmgr_dispatch(); + while (isc__taskmgr_ready((isc_taskmgr_t *)manager)) + (void)isc__taskmgr_dispatch((isc_taskmgr_t *)manager); +#ifdef BIND9 if (!ISC_LIST_EMPTY(manager->tasks)) isc_mem_printallactive(stderr); +#endif INSIST(ISC_LIST_EMPTY(manager->tasks)); -#endif /* ISC_PLATFORM_USETHREADS */ +#ifdef USE_SHARED_MANAGER + taskmgr = NULL; +#endif +#endif /* USE_WORKER_THREADS */ manager_free(manager); *managerp = NULL; } -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_WORKER_THREADS isc_boolean_t -isc__taskmgr_ready(void) { - if (taskmgr == NULL) +isc__taskmgr_ready(isc_taskmgr_t *manager0) { + isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0; + +#ifdef USE_SHARED_MANAGER + if (manager == NULL) + manager = taskmgr; +#endif + if (manager == NULL) return (ISC_FALSE); - return (ISC_TF(!ISC_LIST_EMPTY(taskmgr->ready_tasks))); + return (ISC_TF(!ISC_LIST_EMPTY(manager->ready_tasks))); } isc_result_t -isc__taskmgr_dispatch(void) { - isc_taskmgr_t *manager = taskmgr; +isc__taskmgr_dispatch(isc_taskmgr_t *manager0) { + isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0; - if (taskmgr == NULL) +#ifdef USE_SHARED_MANAGER + if (manager == NULL) + manager = taskmgr; +#endif + if (manager == NULL) return (ISC_R_NOTFOUND); dispatch(manager); @@ -1254,12 +1438,13 @@ isc__taskmgr_dispatch(void) { return (ISC_R_SUCCESS); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ -isc_result_t -isc_task_beginexclusive(isc_task_t *task) { -#ifdef ISC_PLATFORM_USETHREADS - isc_taskmgr_t *manager = task->manager; +ISC_TASKFUNC_SCOPE isc_result_t +isc__task_beginexclusive(isc_task_t *task0) { +#ifdef USE_WORKER_THREADS + isc__task_t *task = (isc__task_t *)task0; + isc__taskmgr_t *manager = task->manager; REQUIRE(task->state == task_state_running); LOCK(&manager->lock); if (manager->exclusive_requested) { @@ -1272,15 +1457,17 @@ isc_task_beginexclusive(isc_task_t *task) { } UNLOCK(&manager->lock); #else - UNUSED(task); + UNUSED(task0); #endif return (ISC_R_SUCCESS); } -void -isc_task_endexclusive(isc_task_t *task) { -#ifdef ISC_PLATFORM_USETHREADS - isc_taskmgr_t *manager = task->manager; +ISC_TASKFUNC_SCOPE void +isc__task_endexclusive(isc_task_t *task0) { +#ifdef USE_WORKER_THREADS + isc__task_t *task = (isc__task_t *)task0; + isc__taskmgr_t *manager = task->manager; + REQUIRE(task->state == task_state_running); LOCK(&manager->lock); REQUIRE(manager->exclusive_requested); @@ -1288,23 +1475,31 @@ isc_task_endexclusive(isc_task_t *task) { BROADCAST(&manager->work_available); UNLOCK(&manager->lock); #else - UNUSED(task); + UNUSED(task0); #endif } +#ifdef USE_SOCKETIMPREGISTER +isc_result_t +isc__task_register() { + return (isc_task_register(isc__taskmgr_create)); +} +#endif + isc_boolean_t isc_task_exiting(isc_task_t *t) { - isc_task_t *task = (isc_task_t *)t; + isc__task_t *task = (isc__task_t *)t; REQUIRE(VALID_TASK(task)); return (TASK_SHUTTINGDOWN(task)); } -#ifdef HAVE_LIBXML2 + +#if defined(HAVE_LIBXML2) && defined(BIND9) void -isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer) -{ - isc_task_t *task; +isc_taskmgr_renderxml(isc_taskmgr_t *mgr0, xmlTextWriterPtr writer) { + isc__taskmgr_t *mgr = (isc__taskmgr_t *)mgr0; + isc__task_t *task; LOCK(&mgr->lock); @@ -1380,4 +1575,4 @@ isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer) UNLOCK(&mgr->lock); } -#endif /* HAVE_LIBXML2 */ +#endif /* HAVE_LIBXML2 && BIND9 */ diff --git a/lib/isc/task_api.c b/lib/isc/task_api.c new file mode 100644 index 0000000..4e03db2 --- /dev/null +++ b/lib/isc/task_api.c @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: task_api.c,v 1.7 2010-12-22 23:46:59 tbox Exp $ */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +static isc_mutex_t createlock; +static isc_once_t once = ISC_ONCE_INIT; +static isc_taskmgrcreatefunc_t taskmgr_createfunc = NULL; + +static void +initialize(void) { + RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS); +} + +isc_result_t +isc_task_register(isc_taskmgrcreatefunc_t createfunc) { + isc_result_t result = ISC_R_SUCCESS; + + RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); + + LOCK(&createlock); + if (taskmgr_createfunc == NULL) + taskmgr_createfunc = createfunc; + else + result = ISC_R_EXISTS; + UNLOCK(&createlock); + + return (result); +} + +isc_result_t +isc_taskmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, + unsigned int workers, unsigned int default_quantum, + isc_taskmgr_t **managerp) +{ + isc_result_t result; + + LOCK(&createlock); + + REQUIRE(taskmgr_createfunc != NULL); + result = (*taskmgr_createfunc)(mctx, workers, default_quantum, + managerp); + + UNLOCK(&createlock); + + if (result == ISC_R_SUCCESS) + isc_appctx_settaskmgr(actx, *managerp); + + return (result); +} + +isc_result_t +isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, + unsigned int default_quantum, isc_taskmgr_t **managerp) +{ + isc_result_t result; + + LOCK(&createlock); + + REQUIRE(taskmgr_createfunc != NULL); + result = (*taskmgr_createfunc)(mctx, workers, default_quantum, + managerp); + + UNLOCK(&createlock); + + return (result); +} + +void +isc_taskmgr_destroy(isc_taskmgr_t **managerp) { + REQUIRE(managerp != NULL && ISCAPI_TASKMGR_VALID(*managerp)); + + (*managerp)->methods->destroy(managerp); + + ENSURE(*managerp == NULL); +} + +isc_result_t +isc_task_create(isc_taskmgr_t *manager, unsigned int quantum, + isc_task_t **taskp) +{ + REQUIRE(ISCAPI_TASKMGR_VALID(manager)); + REQUIRE(taskp != NULL && *taskp == NULL); + + return (manager->methods->taskcreate(manager, quantum, taskp)); +} + +void +isc_task_attach(isc_task_t *source, isc_task_t **targetp) { + REQUIRE(ISCAPI_TASK_VALID(source)); + REQUIRE(targetp != NULL && *targetp == NULL); + + source->methods->attach(source, targetp); + + ENSURE(*targetp == source); +} + +void +isc_task_detach(isc_task_t **taskp) { + REQUIRE(taskp != NULL && ISCAPI_TASK_VALID(*taskp)); + + (*taskp)->methods->detach(taskp); + + ENSURE(*taskp == NULL); +} + +void +isc_task_send(isc_task_t *task, isc_event_t **eventp) { + REQUIRE(ISCAPI_TASK_VALID(task)); + REQUIRE(eventp != NULL && *eventp != NULL); + + task->methods->send(task, eventp); + + ENSURE(*eventp == NULL); +} + +void +isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) { + REQUIRE(taskp != NULL && ISCAPI_TASK_VALID(*taskp)); + REQUIRE(eventp != NULL && *eventp != NULL); + + (*taskp)->methods->sendanddetach(taskp, eventp); + + ENSURE(*taskp == NULL && *eventp == NULL); +} + +unsigned int +isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type, + void *tag, isc_eventlist_t *events) +{ + REQUIRE(ISCAPI_TASK_VALID(task)); + + return (task->methods->unsend(task, sender, type, tag, events)); +} + +isc_result_t +isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, const void *arg) +{ + REQUIRE(ISCAPI_TASK_VALID(task)); + + return (task->methods->onshutdown(task, action, arg)); +} + +void +isc_task_shutdown(isc_task_t *task) { + REQUIRE(ISCAPI_TASK_VALID(task)); + + task->methods->shutdown(task); +} + +void +isc_task_setname(isc_task_t *task, const char *name, void *tag) { + REQUIRE(ISCAPI_TASK_VALID(task)); + + task->methods->setname(task, name, tag); +} + +unsigned int +isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type, void *tag) +{ + REQUIRE(ISCAPI_TASK_VALID(task)); + + return (task->methods->purgeevents(task, sender, type, tag)); +} + +isc_result_t +isc_task_beginexclusive(isc_task_t *task) { + REQUIRE(ISCAPI_TASK_VALID(task)); + + return (task->methods->beginexclusive(task)); +} + +void +isc_task_endexclusive(isc_task_t *task) { + REQUIRE(ISCAPI_TASK_VALID(task)); + + task->methods->endexclusive(task); +} + + +/*% + * This is necessary for libisc's internal timer implementation. Other + * implementation might skip implementing this. + */ +unsigned int +isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first, + isc_eventtype_t last, void *tag) +{ + REQUIRE(ISCAPI_TASK_VALID(task)); + + return (task->methods->purgerange(task, sender, first, last, tag)); +} diff --git a/lib/isc/task_p.h b/lib/isc/task_p.h index 7bf208a..1bcdca6 100644 --- a/lib/isc/task_p.h +++ b/lib/isc/task_p.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: task_p.h,v 1.11 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: task_p.h,v 1.13 2009-09-02 23:48:02 tbox Exp $ */ #ifndef ISC_TASK_P_H #define ISC_TASK_P_H @@ -23,9 +23,9 @@ /*! \file */ isc_boolean_t -isc__taskmgr_ready(void); +isc__taskmgr_ready(isc_taskmgr_t *taskmgr); isc_result_t -isc__taskmgr_dispatch(void); +isc__taskmgr_dispatch(isc_taskmgr_t *taskmgr); #endif /* ISC_TASK_P_H */ diff --git a/lib/isc/timer.c b/lib/isc/timer.c index 6342688..ab89cdd 100644 --- a/lib/isc/timer.c +++ b/lib/isc/timer.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007-2009, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: timer.c,v 1.84.58.4 2009-01-23 23:47:21 tbox Exp $ */ +/* $Id: timer.c,v 1.95.302.1.2.1 2011-06-02 23:47:36 tbox Exp $ */ /*! \file */ @@ -34,9 +34,22 @@ #include #include -#ifndef ISC_PLATFORM_USETHREADS +#ifdef OPENSSL_LEAKS +#include +#endif + +/* See task.c about the following definition: */ +#ifdef BIND9 +#ifdef ISC_PLATFORM_USETHREADS +#define USE_TIMER_THREAD +#else +#define USE_SHARED_MANAGER +#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* BIND9 */ + +#ifndef USE_TIMER_THREAD #include "timer_p.h" -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ #ifdef ISC_TIMER_TRACE #define XTRACE(s) fprintf(stderr, "%s\n", (s)) @@ -58,10 +71,13 @@ #define TIMER_MAGIC ISC_MAGIC('T', 'I', 'M', 'R') #define VALID_TIMER(t) ISC_MAGIC_VALID(t, TIMER_MAGIC) -struct isc_timer { +typedef struct isc__timer isc__timer_t; +typedef struct isc__timermgr isc__timermgr_t; + +struct isc__timer { /*! Not locked. */ - unsigned int magic; - isc_timermgr_t * manager; + isc_timer_t common; + isc__timermgr_t * manager; isc_mutex_t lock; /*! Locked by timer lock. */ unsigned int references; @@ -75,45 +91,119 @@ struct isc_timer { void * arg; unsigned int index; isc_time_t due; - LINK(isc_timer_t) link; + LINK(isc__timer_t) link; }; #define TIMER_MANAGER_MAGIC ISC_MAGIC('T', 'I', 'M', 'M') #define VALID_MANAGER(m) ISC_MAGIC_VALID(m, TIMER_MANAGER_MAGIC) -struct isc_timermgr { +struct isc__timermgr { /* Not locked. */ - unsigned int magic; + isc_timermgr_t common; isc_mem_t * mctx; isc_mutex_t lock; /* Locked by manager lock. */ isc_boolean_t done; - LIST(isc_timer_t) timers; + LIST(isc__timer_t) timers; unsigned int nscheduled; isc_time_t due; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD isc_condition_t wakeup; isc_thread_t thread; -#else /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ +#ifdef USE_SHARED_MANAGER unsigned int refs; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_SHARED_MANAGER */ isc_heap_t * heap; }; -#ifndef ISC_PLATFORM_USETHREADS +/*% + * The followings can be either static or public, depending on build + * environment. + */ + +#ifdef BIND9 +#define ISC_TIMERFUNC_SCOPE +#else +#define ISC_TIMERFUNC_SCOPE static +#endif + +ISC_TIMERFUNC_SCOPE isc_result_t +isc__timer_create(isc_timermgr_t *manager, isc_timertype_t type, + isc_time_t *expires, isc_interval_t *interval, + isc_task_t *task, isc_taskaction_t action, const void *arg, + isc_timer_t **timerp); +ISC_TIMERFUNC_SCOPE isc_result_t +isc__timer_reset(isc_timer_t *timer, isc_timertype_t type, + isc_time_t *expires, isc_interval_t *interval, + isc_boolean_t purge); +ISC_TIMERFUNC_SCOPE isc_timertype_t +isc__timer_gettype(isc_timer_t *timer); +ISC_TIMERFUNC_SCOPE isc_result_t +isc__timer_touch(isc_timer_t *timer); +ISC_TIMERFUNC_SCOPE void +isc__timer_attach(isc_timer_t *timer0, isc_timer_t **timerp); +ISC_TIMERFUNC_SCOPE void +isc__timer_detach(isc_timer_t **timerp); +ISC_TIMERFUNC_SCOPE isc_result_t +isc__timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp); +ISC_TIMERFUNC_SCOPE void +isc__timermgr_poke(isc_timermgr_t *manager0); +ISC_TIMERFUNC_SCOPE void +isc__timermgr_destroy(isc_timermgr_t **managerp); + +static struct isc__timermethods { + isc_timermethods_t methods; + + /*% + * The following are defined just for avoiding unused static functions. + */ +#ifndef BIND9 + void *gettype; +#endif +} timermethods = { + { + isc__timer_attach, + isc__timer_detach, + isc__timer_reset, + isc__timer_touch + } +#ifndef BIND9 + , + (void *)isc__timer_gettype +#endif +}; + +static struct isc__timermgrmethods { + isc_timermgrmethods_t methods; +#ifndef BIND9 + void *poke; /* see above */ +#endif +} timermgrmethods = { + { + isc__timermgr_destroy, + isc__timer_create + } +#ifndef BIND9 + , + (void *)isc__timermgr_poke +#endif +}; + +#ifdef USE_SHARED_MANAGER /*! - * If threads are not in use, there can be only one. + * If the manager is supposed to be shared, there can be only one. */ -static isc_timermgr_t *timermgr = NULL; -#endif /* ISC_PLATFORM_USETHREADS */ +static isc__timermgr_t *timermgr = NULL; +#endif /* USE_SHARED_MANAGER */ static inline isc_result_t -schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) { +schedule(isc__timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) { isc_result_t result; - isc_timermgr_t *manager; + isc__timermgr_t *manager; isc_time_t due; int cmp; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD isc_boolean_t timedwait; #endif @@ -123,13 +213,13 @@ schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) { REQUIRE(timer->type != isc_timertype_inactive); -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_TIMER_THREAD UNUSED(signal_ok); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ manager = timer->manager; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD /*! * If the manager was timed wait, we may need to signal the * manager to force a wakeup. @@ -199,7 +289,7 @@ schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) { * the current "next" timer. We do this either by waking up the * run thread, or explicitly setting the value in the manager. */ -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD /* * This is a temporary (probably) hack to fix a bug on tru64 5.1 @@ -232,19 +322,19 @@ schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) { "signal (schedule)")); SIGNAL(&manager->wakeup); } -#else /* ISC_PLATFORM_USETHREADS */ +#else /* USE_TIMER_THREAD */ if (timer->index == 1 && isc_time_compare(&timer->due, &manager->due) < 0) manager->due = timer->due; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ return (ISC_R_SUCCESS); } static inline void -deschedule(isc_timer_t *timer) { +deschedule(isc__timer_t *timer) { isc_boolean_t need_wakeup = ISC_FALSE; - isc_timermgr_t *manager; + isc__timermgr_t *manager; /* * The caller must ensure locking. @@ -258,20 +348,20 @@ deschedule(isc_timer_t *timer) { timer->index = 0; INSIST(manager->nscheduled > 0); manager->nscheduled--; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD if (need_wakeup) { XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER, ISC_MSG_SIGNALDESCHED, "signal (deschedule)")); SIGNAL(&manager->wakeup); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ } } static void -destroy(isc_timer_t *timer) { - isc_timermgr_t *manager = timer->manager; +destroy(isc__timer_t *timer) { + isc__timermgr_t *manager = timer->manager; /* * The caller must ensure it is safe to destroy the timer. @@ -291,17 +381,19 @@ destroy(isc_timer_t *timer) { isc_task_detach(&timer->task); DESTROYLOCK(&timer->lock); - timer->magic = 0; + timer->common.impmagic = 0; + timer->common.magic = 0; isc_mem_put(manager->mctx, timer, sizeof(*timer)); } -isc_result_t -isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type, - isc_time_t *expires, isc_interval_t *interval, - isc_task_t *task, isc_taskaction_t action, const void *arg, - isc_timer_t **timerp) +ISC_TIMERFUNC_SCOPE isc_result_t +isc__timer_create(isc_timermgr_t *manager0, isc_timertype_t type, + isc_time_t *expires, isc_interval_t *interval, + isc_task_t *task, isc_taskaction_t action, const void *arg, + isc_timer_t **timerp) { - isc_timer_t *timer; + isc__timermgr_t *manager = (isc__timermgr_t *)manager0; + isc__timer_t *timer; isc_result_t result; isc_time_t now; @@ -382,7 +474,9 @@ isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type, return (result); } ISC_LINK_INIT(timer, link); - timer->magic = TIMER_MAGIC; + timer->common.impmagic = TIMER_MAGIC; + timer->common.magic = ISCAPI_TIMER_MAGIC; + timer->common.methods = (isc_timermethods_t *)&timermethods; LOCK(&manager->lock); @@ -401,25 +495,27 @@ isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type, UNLOCK(&manager->lock); if (result != ISC_R_SUCCESS) { - timer->magic = 0; + timer->common.impmagic = 0; + timer->common.magic = 0; DESTROYLOCK(&timer->lock); isc_task_detach(&timer->task); isc_mem_put(manager->mctx, timer, sizeof(*timer)); return (result); } - *timerp = timer; + *timerp = (isc_timer_t *)timer; return (ISC_R_SUCCESS); } -isc_result_t -isc_timer_reset(isc_timer_t *timer, isc_timertype_t type, - isc_time_t *expires, isc_interval_t *interval, - isc_boolean_t purge) +ISC_TIMERFUNC_SCOPE isc_result_t +isc__timer_reset(isc_timer_t *timer0, isc_timertype_t type, + isc_time_t *expires, isc_interval_t *interval, + isc_boolean_t purge) { + isc__timer_t *timer = (isc__timer_t *)timer0; isc_time_t now; - isc_timermgr_t *manager; + isc__timermgr_t *manager; isc_result_t result; /* @@ -489,8 +585,9 @@ isc_timer_reset(isc_timer_t *timer, isc_timertype_t type, return (result); } -isc_timertype_t -isc_timer_gettype(isc_timer_t *timer) { +ISC_TIMERFUNC_SCOPE isc_timertype_t +isc__timer_gettype(isc_timer_t *timer0) { + isc__timer_t *timer = (isc__timer_t *)timer0; isc_timertype_t t; REQUIRE(VALID_TIMER(timer)); @@ -502,8 +599,9 @@ isc_timer_gettype(isc_timer_t *timer) { return (t); } -isc_result_t -isc_timer_touch(isc_timer_t *timer) { +ISC_TIMERFUNC_SCOPE isc_result_t +isc__timer_touch(isc_timer_t *timer0) { + isc__timer_t *timer = (isc__timer_t *)timer0; isc_result_t result; isc_time_t now; @@ -532,8 +630,10 @@ isc_timer_touch(isc_timer_t *timer) { return (result); } -void -isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp) { +ISC_TIMERFUNC_SCOPE void +isc__timer_attach(isc_timer_t *timer0, isc_timer_t **timerp) { + isc__timer_t *timer = (isc__timer_t *)timer0; + /* * Attach *timerp to timer. */ @@ -545,12 +645,12 @@ isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp) { timer->references++; UNLOCK(&timer->lock); - *timerp = timer; + *timerp = (isc_timer_t *)timer; } -void -isc_timer_detach(isc_timer_t **timerp) { - isc_timer_t *timer; +ISC_TIMERFUNC_SCOPE void +isc__timer_detach(isc_timer_t **timerp) { + isc__timer_t *timer; isc_boolean_t free_timer = ISC_FALSE; /* @@ -558,7 +658,7 @@ isc_timer_detach(isc_timer_t **timerp) { */ REQUIRE(timerp != NULL); - timer = *timerp; + timer = (isc__timer_t *)*timerp; REQUIRE(VALID_TIMER(timer)); LOCK(&timer->lock); @@ -575,11 +675,11 @@ isc_timer_detach(isc_timer_t **timerp) { } static void -dispatch(isc_timermgr_t *manager, isc_time_t *now) { +dispatch(isc__timermgr_t *manager, isc_time_t *now) { isc_boolean_t done = ISC_FALSE, post_event, need_schedule; isc_timerevent_t *event; isc_eventtype_t type = 0; - isc_timer_t *timer; + isc__timer_t *timer; isc_result_t result; isc_boolean_t idle; @@ -693,13 +793,13 @@ dispatch(isc_timermgr_t *manager, isc_time_t *now) { } } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD static isc_threadresult_t #ifdef _WIN32 /* XXXDCL */ WINAPI #endif run(void *uap) { - isc_timermgr_t *manager = uap; + isc__timermgr_t *manager = uap; isc_time_t now; isc_result_t result; @@ -732,13 +832,17 @@ run(void *uap) { } UNLOCK(&manager->lock); +#ifdef OPENSSL_LEAKS + ERR_remove_state(0); +#endif + return ((isc_threadresult_t)0); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ static isc_boolean_t sooner(void *v1, void *v2) { - isc_timer_t *t1, *t2; + isc__timer_t *t1, *t2; t1 = v1; t2 = v2; @@ -752,7 +856,7 @@ sooner(void *v1, void *v2) { static void set_index(void *what, unsigned int index) { - isc_timer_t *timer; + isc__timer_t *timer; timer = what; REQUIRE(VALID_TIMER(timer)); @@ -760,9 +864,9 @@ set_index(void *what, unsigned int index) { timer->index = index; } -isc_result_t -isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) { - isc_timermgr_t *manager; +ISC_TIMERFUNC_SCOPE isc_result_t +isc__timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) { + isc__timermgr_t *manager; isc_result_t result; /* @@ -771,19 +875,21 @@ isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) { REQUIRE(managerp != NULL && *managerp == NULL); -#ifndef ISC_PLATFORM_USETHREADS +#ifdef USE_SHARED_MANAGER if (timermgr != NULL) { timermgr->refs++; - *managerp = timermgr; + *managerp = (isc_timermgr_t *)timermgr; return (ISC_R_SUCCESS); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_SHARED_MANAGER */ manager = isc_mem_get(mctx, sizeof(*manager)); if (manager == NULL) return (ISC_R_NOMEMORY); - manager->magic = TIMER_MANAGER_MAGIC; + manager->common.impmagic = TIMER_MANAGER_MAGIC; + manager->common.magic = ISCAPI_TIMERMGR_MAGIC; + manager->common.methods = (isc_timermgrmethods_t *)&timermgrmethods; manager->mctx = NULL; manager->done = ISC_FALSE; INIT_LIST(manager->timers); @@ -803,7 +909,7 @@ isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) { return (result); } isc_mem_attach(mctx, &manager->mctx); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD if (isc_condition_init(&manager->wakeup) != ISC_R_SUCCESS) { isc_mem_detach(&manager->mctx); DESTROYLOCK(&manager->lock); @@ -828,30 +934,33 @@ isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) { ISC_MSG_FAILED, "failed")); return (ISC_R_UNEXPECTED); } -#else /* ISC_PLATFORM_USETHREADS */ +#endif +#ifdef USE_SHARED_MANAGER manager->refs = 1; timermgr = manager; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_SHARED_MANAGER */ - *managerp = manager; + *managerp = (isc_timermgr_t *)manager; return (ISC_R_SUCCESS); } -void -isc_timermgr_poke(isc_timermgr_t *manager) { -#ifdef ISC_PLATFORM_USETHREADS +ISC_TIMERFUNC_SCOPE void +isc__timermgr_poke(isc_timermgr_t *manager0) { +#ifdef USE_TIMER_THREAD + isc__timermgr_t *manager = (isc__timermgr_t *)manager0; + REQUIRE(VALID_MANAGER(manager)); SIGNAL(&manager->wakeup); #else - UNUSED(manager); + UNUSED(manager0); #endif } -void -isc_timermgr_destroy(isc_timermgr_t **managerp) { - isc_timermgr_t *manager; +ISC_TIMERFUNC_SCOPE void +isc__timermgr_destroy(isc_timermgr_t **managerp) { + isc__timermgr_t *manager; isc_mem_t *mctx; /* @@ -859,34 +968,37 @@ isc_timermgr_destroy(isc_timermgr_t **managerp) { */ REQUIRE(managerp != NULL); - manager = *managerp; + manager = (isc__timermgr_t *)*managerp; REQUIRE(VALID_MANAGER(manager)); LOCK(&manager->lock); -#ifndef ISC_PLATFORM_USETHREADS - if (manager->refs > 1) { - manager->refs--; +#ifdef USE_SHARED_MANAGER + manager->refs--; + if (manager->refs > 0) { UNLOCK(&manager->lock); *managerp = NULL; return; } + timermgr = NULL; +#endif /* USE_SHARED_MANAGER */ - isc__timermgr_dispatch(); -#endif /* ISC_PLATFORM_USETHREADS */ +#ifndef USE_TIMER_THREAD + isc__timermgr_dispatch((isc_timermgr_t *)manager); +#endif REQUIRE(EMPTY(manager->timers)); manager->done = ISC_TRUE; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER, ISC_MSG_SIGNALDESTROY, "signal (destroy)")); SIGNAL(&manager->wakeup); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ UNLOCK(&manager->lock); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD /* * Wait for thread to exit. */ @@ -895,39 +1007,63 @@ isc_timermgr_destroy(isc_timermgr_t **managerp) { "isc_thread_join() %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed")); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ /* * Clean up. */ -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD (void)isc_condition_destroy(&manager->wakeup); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ DESTROYLOCK(&manager->lock); isc_heap_destroy(&manager->heap); - manager->magic = 0; + manager->common.impmagic = 0; + manager->common.magic = 0; mctx = manager->mctx; isc_mem_put(mctx, manager, sizeof(*manager)); isc_mem_detach(&mctx); *managerp = NULL; + +#ifdef USE_SHARED_MANAGER + timermgr = NULL; +#endif } -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_TIMER_THREAD isc_result_t -isc__timermgr_nextevent(isc_time_t *when) { - if (timermgr == NULL || timermgr->nscheduled == 0) +isc__timermgr_nextevent(isc_timermgr_t *manager0, isc_time_t *when) { + isc__timermgr_t *manager = (isc__timermgr_t *)manager0; + +#ifdef USE_SHARED_MANAGER + if (manager == NULL) + manager = timermgr; +#endif + if (manager == NULL || manager->nscheduled == 0) return (ISC_R_NOTFOUND); - *when = timermgr->due; + *when = manager->due; return (ISC_R_SUCCESS); } void -isc__timermgr_dispatch(void) { +isc__timermgr_dispatch(isc_timermgr_t *manager0) { + isc__timermgr_t *manager = (isc__timermgr_t *)manager0; isc_time_t now; - if (timermgr == NULL) + +#ifdef USE_SHARED_MANAGER + if (manager == NULL) + manager = timermgr; +#endif + if (manager == NULL) return; TIME_NOW(&now); - dispatch(timermgr, &now); + dispatch(manager, &now); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ + +#ifdef USE_TIMERIMPREGISTER +isc_result_t +isc__timer_register() { + return (isc_timer_register(isc__timermgr_create)); +} +#endif diff --git a/lib/isc/timer_api.c b/lib/isc/timer_api.c new file mode 100644 index 0000000..5a9bf9d --- /dev/null +++ b/lib/isc/timer_api.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: timer_api.c,v 1.4 2009-09-02 23:48:02 tbox Exp $ */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +static isc_mutex_t createlock; +static isc_once_t once = ISC_ONCE_INIT; +static isc_timermgrcreatefunc_t timermgr_createfunc = NULL; + +static void +initialize(void) { + RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS); +} + +isc_result_t +isc_timer_register(isc_timermgrcreatefunc_t createfunc) { + isc_result_t result = ISC_R_SUCCESS; + + RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); + + LOCK(&createlock); + if (timermgr_createfunc == NULL) + timermgr_createfunc = createfunc; + else + result = ISC_R_EXISTS; + UNLOCK(&createlock); + + return (result); +} + +isc_result_t +isc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, + isc_timermgr_t **managerp) +{ + isc_result_t result; + + LOCK(&createlock); + + REQUIRE(timermgr_createfunc != NULL); + result = (*timermgr_createfunc)(mctx, managerp); + + UNLOCK(&createlock); + + if (result == ISC_R_SUCCESS) + isc_appctx_settimermgr(actx, *managerp); + + return (result); +} + +isc_result_t +isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) { + isc_result_t result; + + LOCK(&createlock); + + REQUIRE(timermgr_createfunc != NULL); + result = (*timermgr_createfunc)(mctx, managerp); + + UNLOCK(&createlock); + + return (result); +} + +void +isc_timermgr_destroy(isc_timermgr_t **managerp) { + REQUIRE(*managerp != NULL && ISCAPI_TIMERMGR_VALID(*managerp)); + + (*managerp)->methods->destroy(managerp); + + ENSURE(*managerp == NULL); +} + +isc_result_t +isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type, + isc_time_t *expires, isc_interval_t *interval, + isc_task_t *task, isc_taskaction_t action, const void *arg, + isc_timer_t **timerp) +{ + REQUIRE(ISCAPI_TIMERMGR_VALID(manager)); + + return (manager->methods->timercreate(manager, type, expires, + interval, task, action, arg, + timerp)); +} + +void +isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp) { + REQUIRE(ISCAPI_TIMER_VALID(timer)); + REQUIRE(timerp != NULL && *timerp == NULL); + + timer->methods->attach(timer, timerp); + + ENSURE(*timerp == timer); +} + +void +isc_timer_detach(isc_timer_t **timerp) { + REQUIRE(timerp != NULL && ISCAPI_TIMER_VALID(*timerp)); + + (*timerp)->methods->detach(timerp); + + ENSURE(*timerp == NULL); +} + +isc_result_t +isc_timer_reset(isc_timer_t *timer, isc_timertype_t type, + isc_time_t *expires, isc_interval_t *interval, + isc_boolean_t purge) +{ + REQUIRE(ISCAPI_TIMER_VALID(timer)); + + return (timer->methods->reset(timer, type, expires, interval, purge)); +} + +isc_result_t +isc_timer_touch(isc_timer_t *timer) { + REQUIRE(ISCAPI_TIMER_VALID(timer)); + + return (timer->methods->touch(timer)); +} diff --git a/lib/isc/timer_p.h b/lib/isc/timer_p.h index b41f922..657b695 100644 --- a/lib/isc/timer_p.h +++ b/lib/isc/timer_p.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: timer_p.h,v 1.10 2007-06-19 23:47:17 tbox Exp $ */ +/* $Id: timer_p.h,v 1.12 2009-09-02 23:48:02 tbox Exp $ */ #ifndef ISC_TIMER_P_H #define ISC_TIMER_P_H @@ -23,9 +23,9 @@ /*! \file */ isc_result_t -isc__timermgr_nextevent(isc_time_t *when); +isc__timermgr_nextevent(isc_timermgr_t *timermgr, isc_time_t *when); void -isc__timermgr_dispatch(void); +isc__timermgr_dispatch(isc_timermgr_t *timermgr); #endif /* ISC_TIMER_P_H */ diff --git a/lib/isc/unix/Makefile.in b/lib/isc/unix/Makefile.in index 7d23b96..2c91756 100644 --- a/lib/isc/unix/Makefile.in +++ b/lib/isc/unix/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 1998-2001 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.41 2007-06-19 23:47:18 tbox Exp $ +# $Id: Makefile.in,v 1.44 2009-12-05 23:31:41 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ diff --git a/lib/isc/unix/app.c b/lib/isc/unix/app.c index 6bd1660..4dc5130 100644 --- a/lib/isc/unix/app.c +++ b/lib/isc/unix/app.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: app.c,v 1.60 2008-10-15 03:41:17 marka Exp $ */ +/* $Id: app.c,v 1.64 2009-11-04 05:58:46 marka Exp $ */ /*! \file */ @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -47,31 +48,129 @@ #include #include +/*% + * For BIND9 internal applications built with threads, we use a single app + * context and let multiple worker, I/O, timer threads do actual jobs. + * For other cases (including BIND9 built without threads) an app context acts + * as an event loop dispatching various events. + */ +#if defined(ISC_PLATFORM_USETHREADS) && defined(BIND9) +#define USE_THREADS_SINGLECTX +#endif + #ifdef ISC_PLATFORM_USETHREADS #include -#else /* ISC_PLATFORM_USETHREADS */ +#endif + +#ifndef USE_THREADS_SINGLECTX #include "../timer_p.h" #include "../task_p.h" #include "socket_p.h" +#endif /* USE_THREADS_SINGLECTX */ + +#ifdef ISC_PLATFORM_USETHREADS +static pthread_t blockedthread; #endif /* ISC_PLATFORM_USETHREADS */ -static isc_eventlist_t on_run; -static isc_mutex_t lock; -static isc_boolean_t shutdown_requested = ISC_FALSE; -static isc_boolean_t running = ISC_FALSE; -/*! - * We assume that 'want_shutdown' can be read and written atomically. +/*% + * The following can be either static or public, depending on build environment. */ -static volatile isc_boolean_t want_shutdown = ISC_FALSE; + +#ifdef BIND9 +#define ISC_APPFUNC_SCOPE +#else +#define ISC_APPFUNC_SCOPE static +#endif + +ISC_APPFUNC_SCOPE isc_result_t isc__app_start(void); +ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxstart(isc_appctx_t *ctx); +ISC_APPFUNC_SCOPE isc_result_t isc__app_onrun(isc_mem_t *mctx, + isc_task_t *task, + isc_taskaction_t action, + void *arg); +ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxrun(isc_appctx_t *ctx); +ISC_APPFUNC_SCOPE isc_result_t isc__app_run(void); +ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxshutdown(isc_appctx_t *ctx); +ISC_APPFUNC_SCOPE isc_result_t isc__app_shutdown(void); +ISC_APPFUNC_SCOPE isc_result_t isc__app_reload(void); +ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxsuspend(isc_appctx_t *ctx); +ISC_APPFUNC_SCOPE void isc__app_ctxfinish(isc_appctx_t *ctx); +ISC_APPFUNC_SCOPE void isc__app_finish(void); +ISC_APPFUNC_SCOPE void isc__app_block(void); +ISC_APPFUNC_SCOPE void isc__app_unblock(void); +ISC_APPFUNC_SCOPE isc_result_t isc__appctx_create(isc_mem_t *mctx, + isc_appctx_t **ctxp); +ISC_APPFUNC_SCOPE void isc__appctx_destroy(isc_appctx_t **ctxp); +ISC_APPFUNC_SCOPE void isc__appctx_settaskmgr(isc_appctx_t *ctx, + isc_taskmgr_t *taskmgr); +ISC_APPFUNC_SCOPE void isc__appctx_setsocketmgr(isc_appctx_t *ctx, + isc_socketmgr_t *socketmgr); +ISC_APPFUNC_SCOPE void isc__appctx_settimermgr(isc_appctx_t *ctx, + isc_timermgr_t *timermgr); + /* - * We assume that 'want_reload' can be read and written atomically. + * The application context of this module. This implementation actually + * doesn't use it. (This may change in the future). */ -static volatile isc_boolean_t want_reload = ISC_FALSE; +#define APPCTX_MAGIC ISC_MAGIC('A', 'p', 'c', 'x') +#define VALID_APPCTX(c) ISC_MAGIC_VALID(c, APPCTX_MAGIC) + +typedef struct isc__appctx { + isc_appctx_t common; + isc_mem_t *mctx; + isc_mutex_t lock; + isc_eventlist_t on_run; + isc_boolean_t shutdown_requested; + isc_boolean_t running; + + /*! + * We assume that 'want_shutdown' can be read and written atomically. + */ + isc_boolean_t want_shutdown; + /* + * We assume that 'want_reload' can be read and written atomically. + */ + isc_boolean_t want_reload; -static isc_boolean_t blocked = ISC_FALSE; -#ifdef ISC_PLATFORM_USETHREADS -static pthread_t blockedthread; -#endif /* ISC_PLATFORM_USETHREADS */ + isc_boolean_t blocked; + + isc_taskmgr_t *taskmgr; + isc_socketmgr_t *socketmgr; + isc_timermgr_t *timermgr; +} isc__appctx_t; + +static isc__appctx_t isc_g_appctx; + +static struct { + isc_appmethods_t methods; + + /*% + * The following are defined just for avoiding unused static functions. + */ +#ifndef BIND9 + void *run, *shutdown, *start, *onrun, *reload, *finish, + *block, *unblock; +#endif +} appmethods = { + { + isc__appctx_destroy, + isc__app_ctxstart, + isc__app_ctxrun, + isc__app_ctxsuspend, + isc__app_ctxshutdown, + isc__app_ctxfinish, + isc__appctx_settaskmgr, + isc__appctx_setsocketmgr, + isc__appctx_settimermgr + } +#ifndef BIND9 + , + (void *)isc__app_run, (void *)isc__app_shutdown, + (void *)isc__app_start, (void *)isc__app_onrun, (void *)isc__app_reload, + (void *)isc__app_finish, (void *)isc__app_block, + (void *)isc__app_unblock +#endif +}; #ifdef HAVE_LINUXTHREADS /*! @@ -91,13 +190,13 @@ static pthread_t main_thread; static void exit_action(int arg) { UNUSED(arg); - want_shutdown = ISC_TRUE; + isc_g_appctx.want_shutdown = ISC_TRUE; } static void reload_action(int arg) { UNUSED(arg); - want_reload = ISC_TRUE; + isc_g_appctx.want_reload = ISC_TRUE; } #endif @@ -123,12 +222,12 @@ handle_signal(int sig, void (*handler)(int)) { return (ISC_R_SUCCESS); } -isc_result_t -isc_app_start(void) { +ISC_APPFUNC_SCOPE isc_result_t +isc__app_ctxstart(isc_appctx_t *ctx0) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; isc_result_t result; - int presult; - sigset_t sset; - char strbuf[ISC_STRERRORSIZE]; + + REQUIRE(VALID_APPCTX(ctx)); /* * Start an ISC library application. @@ -151,7 +250,35 @@ isc_app_start(void) { main_thread = pthread_self(); #endif - result = isc_mutex_init(&lock); + result = isc_mutex_init(&ctx->lock); + if (result != ISC_R_SUCCESS) + return (result); + + ISC_LIST_INIT(ctx->on_run); + + ctx->shutdown_requested = ISC_FALSE; + ctx->running = ISC_FALSE; + ctx->want_shutdown = ISC_FALSE; + ctx->want_reload = ISC_FALSE; + ctx->blocked = ISC_FALSE; + + return (ISC_R_SUCCESS); +} + +ISC_APPFUNC_SCOPE isc_result_t +isc__app_start(void) { + isc_result_t result; + int presult; + sigset_t sset; + char strbuf[ISC_STRERRORSIZE]; + + isc_g_appctx.common.impmagic = APPCTX_MAGIC; + isc_g_appctx.common.magic = ISCAPI_APPCTX_MAGIC; + isc_g_appctx.common.methods = &appmethods.methods; + isc_g_appctx.mctx = NULL; + /* The remaining members will be initialized in ctxstart() */ + + result = isc__app_ctxstart((isc_appctx_t *)&isc_g_appctx); if (result != ISC_R_SUCCESS) return (result); @@ -253,22 +380,20 @@ isc_app_start(void) { } #endif /* ISC_PLATFORM_USETHREADS */ - ISC_LIST_INIT(on_run); - return (ISC_R_SUCCESS); } -isc_result_t -isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, +ISC_APPFUNC_SCOPE isc_result_t +isc__app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, void *arg) { isc_event_t *event; isc_task_t *cloned_task = NULL; isc_result_t result; - LOCK(&lock); + LOCK(&isc_g_appctx.lock); - if (running) { + if (isc_g_appctx.running) { result = ISC_R_ALREADYRUNNING; goto unlock; } @@ -285,24 +410,25 @@ isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, goto unlock; } - ISC_LIST_APPEND(on_run, event, ev_link); + ISC_LIST_APPEND(isc_g_appctx.on_run, event, ev_link); result = ISC_R_SUCCESS; unlock: - UNLOCK(&lock); + UNLOCK(&isc_g_appctx.lock); return (result); } -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_THREADS_SINGLECTX /*! * Event loop for nonthreaded programs. */ static isc_result_t -evloop(void) { +evloop(isc__appctx_t *ctx) { isc_result_t result; - while (!want_shutdown) { + + while (!ctx->want_shutdown) { int n; isc_time_t when, now; struct timeval tv, *tvp; @@ -310,14 +436,27 @@ evloop(void) { isc_boolean_t readytasks; isc_boolean_t call_timer_dispatch = ISC_FALSE; - readytasks = isc__taskmgr_ready(); + /* + * Check the reload (or suspend) case first for exiting the + * loop as fast as possible in case: + * - the direct call to isc__taskmgr_dispatch() in + * isc__app_ctxrun() completes all the tasks so far, + * - there is thus currently no active task, and + * - there is a timer event + */ + if (ctx->want_reload) { + ctx->want_reload = ISC_FALSE; + return (ISC_R_RELOAD); + } + + readytasks = isc__taskmgr_ready(ctx->taskmgr); if (readytasks) { tv.tv_sec = 0; tv.tv_usec = 0; tvp = &tv; call_timer_dispatch = ISC_TRUE; } else { - result = isc__timermgr_nextevent(&when); + result = isc__timermgr_nextevent(ctx->timermgr, &when); if (result != ISC_R_SUCCESS) tvp = NULL; else { @@ -334,7 +473,7 @@ evloop(void) { } swait = NULL; - n = isc__socketmgr_waitevents(tvp, &swait); + n = isc__socketmgr_waitevents(ctx->socketmgr, tvp, &swait); if (n == 0 || call_timer_dispatch) { /* @@ -351,20 +490,17 @@ evloop(void) { * call, since this loop only runs in the non-thread * mode. */ - isc__timermgr_dispatch(); + isc__timermgr_dispatch(ctx->timermgr); } if (n > 0) - (void)isc__socketmgr_dispatch(swait); - (void)isc__taskmgr_dispatch(); - - if (want_reload) { - want_reload = ISC_FALSE; - return (ISC_R_RELOAD); - } + (void)isc__socketmgr_dispatch(ctx->socketmgr, swait); + (void)isc__taskmgr_dispatch(ctx->taskmgr); } return (ISC_R_SUCCESS); } +#endif /* USE_THREADS_SINGLECTX */ +#ifndef ISC_PLATFORM_USETHREADS /* * This is a gross hack to support waiting for condition * variables in nonthreaded programs in a limited way; @@ -400,11 +536,11 @@ isc__nothread_wait_hack(isc_condition_t *cp, isc_mutex_t *mp) { INSIST(*mp == 1); /* Mutex must be locked on entry. */ --*mp; - result = evloop(); + result = evloop(&isc_g_appctx); if (result == ISC_R_RELOAD) - want_reload = ISC_TRUE; + isc_g_appctx.want_reload = ISC_TRUE; if (signalled) { - want_shutdown = ISC_FALSE; + isc_g_appctx.want_shutdown = ISC_FALSE; signalled = ISC_FALSE; } @@ -420,43 +556,46 @@ isc__nothread_signal_hack(isc_condition_t *cp) { INSIST(in_recursive_evloop); - want_shutdown = ISC_TRUE; + isc_g_appctx.want_shutdown = ISC_TRUE; signalled = ISC_TRUE; return (ISC_R_SUCCESS); } #endif /* ISC_PLATFORM_USETHREADS */ -isc_result_t -isc_app_run(void) { +ISC_APPFUNC_SCOPE isc_result_t +isc__app_ctxrun(isc_appctx_t *ctx0) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; int result; isc_event_t *event, *next_event; isc_task_t *task; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_THREADS_SINGLECTX sigset_t sset; char strbuf[ISC_STRERRORSIZE]; #ifdef HAVE_SIGWAIT int sig; #endif -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_THREADS_SINGLECTX */ + + REQUIRE(VALID_APPCTX(ctx)); #ifdef HAVE_LINUXTHREADS REQUIRE(main_thread == pthread_self()); #endif - LOCK(&lock); + LOCK(&ctx->lock); - if (!running) { - running = ISC_TRUE; + if (!ctx->running) { + ctx->running = ISC_TRUE; /* * Post any on-run events (in FIFO order). */ - for (event = ISC_LIST_HEAD(on_run); + for (event = ISC_LIST_HEAD(ctx->on_run); event != NULL; event = next_event) { next_event = ISC_LIST_NEXT(event, ev_link); - ISC_LIST_UNLINK(on_run, event, ev_link); + ISC_LIST_UNLINK(ctx->on_run, event, ev_link); task = event->ev_sender; event->ev_sender = NULL; isc_task_sendanddetach(&task, &event); @@ -464,7 +603,7 @@ isc_app_run(void) { } - UNLOCK(&lock); + UNLOCK(&ctx->lock); #ifndef HAVE_SIGWAIT /* @@ -473,19 +612,27 @@ isc_app_run(void) { * We do this here to ensure that the signal handler is installed * (i.e. that it wasn't a "one-shot" handler). */ - result = handle_signal(SIGHUP, reload_action); - if (result != ISC_R_SUCCESS) - return (ISC_R_SUCCESS); + if (ctx == &isc_g_appctx) { + result = handle_signal(SIGHUP, reload_action); + if (result != ISC_R_SUCCESS) + return (ISC_R_SUCCESS); + } #endif -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_THREADS_SINGLECTX + /* + * When we are using multiple contexts, we don't rely on signals. + */ + if (ctx != &isc_g_appctx) + return (ISC_R_SUCCESS); + /* * There is no danger if isc_app_shutdown() is called before we wait * for signals. Signals are blocked, so any such signal will simply * be made pending and we will get it when we call sigwait(). */ - while (!want_shutdown) { + while (!ctx->want_shutdown) { #ifdef HAVE_SIGWAIT /* * Wait for SIGHUP, SIGINT, or SIGTERM. @@ -503,21 +650,19 @@ isc_app_run(void) { #ifndef HAVE_UNIXWARE_SIGWAIT result = sigwait(&sset, &sig); if (result == 0) { - if (sig == SIGINT || - sig == SIGTERM) - want_shutdown = ISC_TRUE; + if (sig == SIGINT || sig == SIGTERM) + ctx->want_shutdown = ISC_TRUE; else if (sig == SIGHUP) - want_reload = ISC_TRUE; + ctx->want_reload = ISC_TRUE; } #else /* Using UnixWare sigwait semantics. */ sig = sigwait(&sset); if (sig >= 0) { - if (sig == SIGINT || - sig == SIGTERM) - want_shutdown = ISC_TRUE; + if (sig == SIGINT || sig == SIGTERM) + ctx->want_shutdown = ISC_TRUE; else if (sig == SIGHUP) - want_reload = ISC_TRUE; + ctx->want_reload = ISC_TRUE; } #endif /* HAVE_UNIXWARE_SIGWAIT */ @@ -528,131 +673,174 @@ isc_app_run(void) { if (sigemptyset(&sset) != 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_run() sigsetops: %s", strbuf); + "isc_app_run() sigsetops: %s", + strbuf); return (ISC_R_UNEXPECTED); } result = sigsuspend(&sset); #endif /* HAVE_SIGWAIT */ - if (want_reload) { - want_reload = ISC_FALSE; + if (ctx->want_reload) { + ctx->want_reload = ISC_FALSE; return (ISC_R_RELOAD); } - if (want_shutdown && blocked) + if (ctx->want_shutdown && ctx->blocked) exit(1); } -#else /* ISC_PLATFORM_USETHREADS */ +#else /* USE_THREADS_SINGLECTX */ - (void)isc__taskmgr_dispatch(); + (void)isc__taskmgr_dispatch(ctx->taskmgr); - result = evloop(); + result = evloop(ctx); if (result != ISC_R_SUCCESS) return (result); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_THREADS_SINGLECTX */ return (ISC_R_SUCCESS); } -isc_result_t -isc_app_shutdown(void) { +ISC_APPFUNC_SCOPE isc_result_t +isc__app_run() { + return (isc__app_ctxrun((isc_appctx_t *)&isc_g_appctx)); +} + +ISC_APPFUNC_SCOPE isc_result_t +isc__app_ctxshutdown(isc_appctx_t *ctx0) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; isc_boolean_t want_kill = ISC_TRUE; char strbuf[ISC_STRERRORSIZE]; - LOCK(&lock); + REQUIRE(VALID_APPCTX(ctx)); - REQUIRE(running); + LOCK(&ctx->lock); - if (shutdown_requested) + REQUIRE(ctx->running); + + if (ctx->shutdown_requested) want_kill = ISC_FALSE; else - shutdown_requested = ISC_TRUE; + ctx->shutdown_requested = ISC_TRUE; - UNLOCK(&lock); + UNLOCK(&ctx->lock); if (want_kill) { + if (ctx != &isc_g_appctx) + ctx->want_shutdown = ISC_TRUE; + else { #ifdef HAVE_LINUXTHREADS - int result; - - result = pthread_kill(main_thread, SIGTERM); - if (result != 0) { - isc__strerror(result, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_shutdown() pthread_kill: %s", - strbuf); - return (ISC_R_UNEXPECTED); - } + int result; + + result = pthread_kill(main_thread, SIGTERM); + if (result != 0) { + isc__strerror(result, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_app_shutdown() " + "pthread_kill: %s", + strbuf); + return (ISC_R_UNEXPECTED); + } #else - if (kill(getpid(), SIGTERM) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_shutdown() kill: %s", strbuf); - return (ISC_R_UNEXPECTED); + if (kill(getpid(), SIGTERM) < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_app_shutdown() " + "kill: %s", strbuf); + return (ISC_R_UNEXPECTED); + } +#endif /* HAVE_LINUXTHREADS */ } -#endif } return (ISC_R_SUCCESS); } -isc_result_t -isc_app_reload(void) { +ISC_APPFUNC_SCOPE isc_result_t +isc__app_shutdown() { + return (isc__app_ctxshutdown((isc_appctx_t *)&isc_g_appctx)); +} + +ISC_APPFUNC_SCOPE isc_result_t +isc__app_ctxsuspend(isc_appctx_t *ctx0) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; isc_boolean_t want_kill = ISC_TRUE; char strbuf[ISC_STRERRORSIZE]; - LOCK(&lock); + REQUIRE(VALID_APPCTX(ctx)); + + LOCK(&ctx->lock); - REQUIRE(running); + REQUIRE(ctx->running); /* * Don't send the reload signal if we're shutting down. */ - if (shutdown_requested) + if (ctx->shutdown_requested) want_kill = ISC_FALSE; - UNLOCK(&lock); + UNLOCK(&ctx->lock); if (want_kill) { + if (ctx != &isc_g_appctx) + ctx->want_reload = ISC_TRUE; + else { #ifdef HAVE_LINUXTHREADS - int result; - - result = pthread_kill(main_thread, SIGHUP); - if (result != 0) { - isc__strerror(result, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_reload() pthread_kill: %s", - strbuf); - return (ISC_R_UNEXPECTED); - } + int result; + + result = pthread_kill(main_thread, SIGHUP); + if (result != 0) { + isc__strerror(result, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_app_reload() " + "pthread_kill: %s", + strbuf); + return (ISC_R_UNEXPECTED); + } #else - if (kill(getpid(), SIGHUP) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_reload() kill: %s", strbuf); - return (ISC_R_UNEXPECTED); - } + if (kill(getpid(), SIGHUP) < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_app_reload() " + "kill: %s", strbuf); + return (ISC_R_UNEXPECTED); + } #endif + } } return (ISC_R_SUCCESS); } -void -isc_app_finish(void) { - DESTROYLOCK(&lock); +ISC_APPFUNC_SCOPE isc_result_t +isc__app_reload(void) { + return (isc__app_ctxsuspend((isc_appctx_t *)&isc_g_appctx)); +} + +ISC_APPFUNC_SCOPE void +isc__app_ctxfinish(isc_appctx_t *ctx0) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; + + REQUIRE(VALID_APPCTX(ctx)); + + DESTROYLOCK(&ctx->lock); +} + +ISC_APPFUNC_SCOPE void +isc__app_finish(void) { + isc__app_ctxfinish((isc_appctx_t *)&isc_g_appctx); } -void -isc_app_block(void) { +ISC_APPFUNC_SCOPE void +isc__app_block(void) { #ifdef ISC_PLATFORM_USETHREADS sigset_t sset; #endif /* ISC_PLATFORM_USETHREADS */ - REQUIRE(running); - REQUIRE(!blocked); + REQUIRE(isc_g_appctx.running); + REQUIRE(!isc_g_appctx.blocked); - blocked = ISC_TRUE; + isc_g_appctx.blocked = ISC_TRUE; #ifdef ISC_PLATFORM_USETHREADS blockedthread = pthread_self(); RUNTIME_CHECK(sigemptyset(&sset) == 0 && @@ -662,16 +850,16 @@ isc_app_block(void) { #endif /* ISC_PLATFORM_USETHREADS */ } -void -isc_app_unblock(void) { +ISC_APPFUNC_SCOPE void +isc__app_unblock(void) { #ifdef ISC_PLATFORM_USETHREADS sigset_t sset; #endif /* ISC_PLATFORM_USETHREADS */ - REQUIRE(running); - REQUIRE(blocked); + REQUIRE(isc_g_appctx.running); + REQUIRE(isc_g_appctx.blocked); - blocked = ISC_FALSE; + isc_g_appctx.blocked = ISC_FALSE; #ifdef ISC_PLATFORM_USETHREADS REQUIRE(blockedthread == pthread_self()); @@ -682,3 +870,77 @@ isc_app_unblock(void) { RUNTIME_CHECK(pthread_sigmask(SIG_BLOCK, &sset, NULL) == 0); #endif /* ISC_PLATFORM_USETHREADS */ } + +ISC_APPFUNC_SCOPE isc_result_t +isc__appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp) { + isc__appctx_t *ctx; + + REQUIRE(mctx != NULL); + REQUIRE(ctxp != NULL && *ctxp == NULL); + + ctx = isc_mem_get(mctx, sizeof(*ctx)); + if (ctx == NULL) + return (ISC_R_NOMEMORY); + + ctx->common.impmagic = APPCTX_MAGIC; + ctx->common.magic = ISCAPI_APPCTX_MAGIC; + ctx->common.methods = &appmethods.methods; + + ctx->mctx = NULL; + isc_mem_attach(mctx, &ctx->mctx); + + ctx->taskmgr = NULL; + ctx->socketmgr = NULL; + ctx->timermgr = NULL; + + *ctxp = (isc_appctx_t *)ctx; + + return (ISC_R_SUCCESS); +} + +ISC_APPFUNC_SCOPE void +isc__appctx_destroy(isc_appctx_t **ctxp) { + isc__appctx_t *ctx; + + REQUIRE(ctxp != NULL); + ctx = (isc__appctx_t *)*ctxp; + REQUIRE(VALID_APPCTX(ctx)); + + isc_mem_putanddetach(&ctx->mctx, ctx, sizeof(*ctx)); + + *ctxp = NULL; +} + +ISC_APPFUNC_SCOPE void +isc__appctx_settaskmgr(isc_appctx_t *ctx0, isc_taskmgr_t *taskmgr) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; + + REQUIRE(VALID_APPCTX(ctx)); + + ctx->taskmgr = taskmgr; +} + +ISC_APPFUNC_SCOPE void +isc__appctx_setsocketmgr(isc_appctx_t *ctx0, isc_socketmgr_t *socketmgr) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; + + REQUIRE(VALID_APPCTX(ctx)); + + ctx->socketmgr = socketmgr; +} + +ISC_APPFUNC_SCOPE void +isc__appctx_settimermgr(isc_appctx_t *ctx0, isc_timermgr_t *timermgr) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; + + REQUIRE(VALID_APPCTX(ctx)); + + ctx->timermgr = timermgr; +} + +#ifdef USE_APPIMPREGISTER +isc_result_t +isc__app_register() { + return (isc_app_register(isc__appctx_create)); +} +#endif diff --git a/lib/isc/unix/dir.c b/lib/isc/unix/dir.c index 8053c42..0caf882 100644 --- a/lib/isc/unix/dir.c +++ b/lib/isc/unix/dir.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dir.c,v 1.25.332.3 2009-02-16 23:47:15 tbox Exp $ */ +/* $Id: dir.c,v 1.29 2009-02-16 23:48:04 tbox Exp $ */ /*! \file * \author Principal Authors: DCL */ diff --git a/lib/isc/unix/entropy.c b/lib/isc/unix/entropy.c index bdff8d9..9044632 100644 --- a/lib/isc/unix/entropy.c +++ b/lib/isc/unix/entropy.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: entropy.c,v 1.80.332.2 2009-02-16 23:47:15 tbox Exp $ */ +/* $Id: entropy.c,v 1.82 2008-12-01 23:47:45 tbox Exp $ */ /* \file unix/entropy.c * \brief diff --git a/lib/isc/unix/file.c b/lib/isc/unix/file.c index ae737b8..25d856c 100644 --- a/lib/isc/unix/file.c +++ b/lib/isc/unix/file.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -48,7 +48,7 @@ * SUCH DAMAGE. */ -/* $Id: file.c,v 1.51.332.2 2009-02-16 23:47:15 tbox Exp $ */ +/* $Id: file.c,v 1.57 2011-01-11 23:47:14 tbox Exp $ */ /*! \file */ @@ -68,6 +68,7 @@ #include #include #include +#include #include #include #include @@ -242,16 +243,26 @@ isc_file_renameunique(const char *file, char *templet) { return (ISC_R_SUCCESS); } - isc_result_t isc_file_openunique(char *templet, FILE **fp) { + int mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; + return (isc_file_openuniquemode(templet, mode, fp)); +} + +isc_result_t +isc_file_openuniqueprivate(char *templet, FILE **fp) { + int mode = S_IWUSR|S_IRUSR; + return (isc_file_openuniquemode(templet, mode, fp)); +} + +isc_result_t +isc_file_openuniquemode(char *templet, int mode, FILE **fp) { int fd; FILE *f; isc_result_t result = ISC_R_SUCCESS; char *x; char *cp; isc_uint32_t which; - int mode; REQUIRE(templet != NULL); REQUIRE(fp != NULL && *fp == NULL); @@ -269,7 +280,6 @@ isc_file_openunique(char *templet, FILE **fp) { x = cp--; } - mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; while ((fd = open(templet, O_RDWR|O_CREAT|O_EXCL, mode)) == -1) { if (errno != EEXIST) @@ -442,3 +452,73 @@ isc_file_truncate(const char *filename, isc_offset_t size) { result = isc__errno2result(errno); return (result); } + +isc_result_t +isc_file_safecreate(const char *filename, FILE **fp) { + isc_result_t result; + int flags; + struct stat sb; + FILE *f; + int fd; + + REQUIRE(filename != NULL); + REQUIRE(fp != NULL && *fp == NULL); + + result = file_stats(filename, &sb); + if (result == ISC_R_SUCCESS) { + if ((sb.st_mode & S_IFREG) == 0) + return (ISC_R_INVALIDFILE); + flags = O_WRONLY | O_TRUNC; + } else if (result == ISC_R_FILENOTFOUND) { + flags = O_WRONLY | O_CREAT | O_EXCL; + } else + return (result); + + fd = open(filename, flags, S_IRUSR | S_IWUSR); + if (fd == -1) + return (isc__errno2result(errno)); + + f = fdopen(fd, "w"); + if (f == NULL) { + result = isc__errno2result(errno); + close(fd); + return (result); + } + + *fp = f; + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_file_splitpath(isc_mem_t *mctx, char *path, char **dirname, char **basename) +{ + char *dir, *file, *slash; + + slash = strrchr(path, '/'); + + if (slash == path) { + file = ++slash; + dir = isc_mem_strdup(mctx, "/"); + } else if (slash != NULL) { + file = ++slash; + dir = isc_mem_allocate(mctx, slash - path); + if (dir != NULL) + strlcpy(dir, path, slash - path); + } else { + file = path; + dir = isc_mem_strdup(mctx, "."); + } + + if (dir == NULL) + return (ISC_R_NOMEMORY); + + if (*file == '\0') { + isc_mem_free(mctx, dir); + return (ISC_R_INVALIDFILE); + } + + *dirname = dir; + *basename = file; + + return (ISC_R_SUCCESS); +} diff --git a/lib/isc/unix/ifiter_getifaddrs.c b/lib/isc/unix/ifiter_getifaddrs.c index 1e9c814..90a3faf 100644 --- a/lib/isc/unix/ifiter_getifaddrs.c +++ b/lib/isc/unix/ifiter_getifaddrs.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ifiter_getifaddrs.c,v 1.11.120.2 2009-09-24 23:47:34 tbox Exp $ */ +/* $Id: ifiter_getifaddrs.c,v 1.13 2009-09-24 23:48:13 tbox Exp $ */ /*! \file * \brief diff --git a/lib/isc/unix/ifiter_ioctl.c b/lib/isc/unix/ifiter_ioctl.c index c004f61..010b365 100644 --- a/lib/isc/unix/ifiter_ioctl.c +++ b/lib/isc/unix/ifiter_ioctl.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ifiter_ioctl.c,v 1.60.120.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: ifiter_ioctl.c,v 1.62 2009-01-18 23:48:14 tbox Exp $ */ /*! \file * \brief diff --git a/lib/isc/unix/include/isc/net.h b/lib/isc/unix/include/isc/net.h index 5fad793..112f1d7 100644 --- a/lib/isc/unix/include/isc/net.h +++ b/lib/isc/unix/include/isc/net.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: net.h,v 1.48.84.2 2009-02-16 23:47:15 tbox Exp $ */ +/* $Id: net.h,v 1.50 2008-12-01 04:14:54 marka Exp $ */ #ifndef ISC_NET_H #define ISC_NET_H 1 diff --git a/lib/isc/unix/include/isc/offset.h b/lib/isc/unix/include/isc/offset.h index 91f43c37..2920899 100644 --- a/lib/isc/unix/include/isc/offset.h +++ b/lib/isc/unix/include/isc/offset.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: offset.h,v 1.15.332.2 2009-02-16 23:47:15 tbox Exp $ */ +/* $Id: offset.h,v 1.17 2008-12-01 23:47:45 tbox Exp $ */ #ifndef ISC_OFFSET_H #define ISC_OFFSET_H 1 diff --git a/lib/isc/unix/include/isc/strerror.h b/lib/isc/unix/include/isc/strerror.h index e094e96..ac8d496 100644 --- a/lib/isc/unix/include/isc/strerror.h +++ b/lib/isc/unix/include/isc/strerror.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: strerror.h,v 1.8.332.2 2009-02-16 23:47:15 tbox Exp $ */ +/* $Id: strerror.h,v 1.10 2008-12-01 23:47:45 tbox Exp $ */ #ifndef ISC_STRERROR_H #define ISC_STRERROR_H diff --git a/lib/isc/unix/include/isc/time.h b/lib/isc/unix/include/isc/time.h index 2149011..19f0810 100644 --- a/lib/isc/unix/include/isc/time.h +++ b/lib/isc/unix/include/isc/time.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: time.h,v 1.38.56.2 2009-01-05 23:47:23 tbox Exp $ */ +/* $Id: time.h,v 1.40 2009-01-05 23:47:54 tbox Exp $ */ #ifndef ISC_TIME_H #define ISC_TIME_H 1 diff --git a/lib/isc/unix/interfaceiter.c b/lib/isc/unix/interfaceiter.c index 2d60a33..37fc3b1 100644 --- a/lib/isc/unix/interfaceiter.c +++ b/lib/isc/unix/interfaceiter.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: interfaceiter.c,v 1.44.120.2 2009-02-16 23:47:15 tbox Exp $ */ +/* $Id: interfaceiter.c,v 1.45 2008-12-01 03:51:47 marka Exp $ */ /*! \file */ diff --git a/lib/isc/unix/resource.c b/lib/isc/unix/resource.c index 1061282..99a4b8c 100644 --- a/lib/isc/unix/resource.c +++ b/lib/isc/unix/resource.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resource.c,v 1.21.66.2 2009-02-13 23:47:39 tbox Exp $ */ +/* $Id: resource.c,v 1.23 2009-02-13 23:48:14 tbox Exp $ */ #include diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c index 055e883..ec7487e 100644 --- a/lib/isc/unix/socket.c +++ b/lib/isc/unix/socket.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: socket.c,v 1.308.12.17 2010-12-22 03:28:13 marka Exp $ */ +/* $Id: socket.c,v 1.333.14.2.2.1 2011-06-02 23:47:36 tbox Exp $ */ /*! \file */ @@ -76,9 +76,19 @@ #include "errno2result.h" -#ifndef ISC_PLATFORM_USETHREADS +/* See task.c about the following definition: */ +#ifdef BIND9 +#ifdef ISC_PLATFORM_USETHREADS +#define USE_WATCHER_THREAD +#else +#define USE_SHARED_MANAGER +#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* BIND9 */ + +#ifndef USE_WATCHER_THREAD #include "socket_p.h" -#endif /* ISC_PLATFORM_USETHREADS */ +#include "../task_p.h" +#endif /* USE_WATCHER_THREAD */ #if defined(SO_BSDCOMPAT) && defined(__linux__) #include @@ -101,7 +111,7 @@ typedef struct { #define USE_SELECT #endif /* ISC_PLATFORM_HAVEKQUEUE */ -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_WATCHER_THREAD #if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL) struct isc_socketwait { int nevents; @@ -114,7 +124,7 @@ struct isc_socketwait { int maxfd; }; #endif /* USE_KQUEUE */ -#endif /* !ISC_PLATFORM_USETHREADS */ +#endif /* !USE_WATCHER_THREAD */ /*% * Maximum number of allowable open sockets. This is also the maximum @@ -248,7 +258,7 @@ typedef enum { poll_idle, poll_active, poll_checking } pollstate_t; typedef isc_event_t intev_t; #define SOCKET_MAGIC ISC_MAGIC('I', 'O', 'i', 'o') -#define VALID_SOCKET(t) ISC_MAGIC_VALID(t, SOCKET_MAGIC) +#define VALID_SOCKET(s) ISC_MAGIC_VALID(s, SOCKET_MAGIC) /*! * IPv6 control information. If the socket is an IPv6 socket we want @@ -282,16 +292,21 @@ typedef isc_event_t intev_t; */ #define NRETRIES 10 -struct isc_socket { +typedef struct isc__socket isc__socket_t; +typedef struct isc__socketmgr isc__socketmgr_t; + +#define NEWCONNSOCK(ev) ((isc__socket_t *)(ev)->newsocket) + +struct isc__socket { /* Not locked. */ - unsigned int magic; - isc_socketmgr_t *manager; + isc_socket_t common; + isc__socketmgr_t *manager; isc_mutex_t lock; isc_sockettype_t type; const isc_statscounter_t *statsindex; /* Locked by socket lock. */ - ISC_LINK(isc_socket_t) link; + ISC_LINK(isc__socket_t) link; unsigned int references; int fd; int pf; @@ -339,9 +354,9 @@ struct isc_socket { #define SOCKET_MANAGER_MAGIC ISC_MAGIC('I', 'O', 'm', 'g') #define VALID_MANAGER(m) ISC_MAGIC_VALID(m, SOCKET_MANAGER_MAGIC) -struct isc_socketmgr { +struct isc__socketmgr { /* Not locked. */ - unsigned int magic; + isc_socketmgr_t common; isc_mem_t *mctx; isc_mutex_t lock; isc_mutex_t *fdlock; @@ -370,14 +385,14 @@ struct isc_socketmgr { #endif /* Locked by fdlock. */ - isc_socket_t **fds; + isc__socket_t **fds; int *fdstate; #ifdef USE_DEVPOLL pollinfo_t *fdpollinfo; #endif /* Locked by manager lock. */ - ISC_LIST(isc_socket_t) socklist; + ISC_LIST(isc__socket_t) socklist; #ifdef USE_SELECT fd_set *read_fds; fd_set *read_fds_copy; @@ -386,17 +401,18 @@ struct isc_socketmgr { int maxfd; #endif /* USE_SELECT */ int reserved; /* unlocked */ -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD isc_thread_t watcher; isc_condition_t shutdown_ok; -#else /* ISC_PLATFORM_USETHREADS */ +#else /* USE_WATCHER_THREAD */ unsigned int refs; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ + int maxudp; }; -#ifndef ISC_PLATFORM_USETHREADS -static isc_socketmgr_t *socketmgr = NULL; -#endif /* ISC_PLATFORM_USETHREADS */ +#ifdef USE_SHARED_MANAGER +static isc__socketmgr_t *socketmgr = NULL; +#endif /* USE_SHARED_MANAGER */ #define CLOSED 0 /* this one must be zero */ #define MANAGED 1 @@ -412,26 +428,165 @@ static isc_socketmgr_t *socketmgr = NULL; # define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER) #endif -static void send_recvdone_event(isc_socket_t *, isc_socketevent_t **); -static void send_senddone_event(isc_socket_t *, isc_socketevent_t **); -static void free_socket(isc_socket_t **); -static isc_result_t allocate_socket(isc_socketmgr_t *, isc_sockettype_t, - isc_socket_t **); -static void destroy(isc_socket_t **); +static void send_recvdone_event(isc__socket_t *, isc_socketevent_t **); +static void send_senddone_event(isc__socket_t *, isc_socketevent_t **); +static void free_socket(isc__socket_t **); +static isc_result_t allocate_socket(isc__socketmgr_t *, isc_sockettype_t, + isc__socket_t **); +static void destroy(isc__socket_t **); static void internal_accept(isc_task_t *, isc_event_t *); static void internal_connect(isc_task_t *, isc_event_t *); static void internal_recv(isc_task_t *, isc_event_t *); static void internal_send(isc_task_t *, isc_event_t *); static void internal_fdwatch_write(isc_task_t *, isc_event_t *); static void internal_fdwatch_read(isc_task_t *, isc_event_t *); -static void process_cmsg(isc_socket_t *, struct msghdr *, isc_socketevent_t *); -static void build_msghdr_send(isc_socket_t *, isc_socketevent_t *, +static void process_cmsg(isc__socket_t *, struct msghdr *, isc_socketevent_t *); +static void build_msghdr_send(isc__socket_t *, isc_socketevent_t *, struct msghdr *, struct iovec *, size_t *); -static void build_msghdr_recv(isc_socket_t *, isc_socketevent_t *, +static void build_msghdr_recv(isc__socket_t *, isc_socketevent_t *, struct msghdr *, struct iovec *, size_t *); -#ifdef ISC_PLATFORM_USETHREADS -static isc_boolean_t process_ctlfd(isc_socketmgr_t *manager); +#ifdef USE_WATCHER_THREAD +static isc_boolean_t process_ctlfd(isc__socketmgr_t *manager); +#endif + +/*% + * The following can be either static or public, depending on build environment. + */ + +#ifdef BIND9 +#define ISC_SOCKETFUNC_SCOPE +#else +#define ISC_SOCKETFUNC_SCOPE static +#endif + +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, + isc_socket_t **socketp); +ISC_SOCKETFUNC_SCOPE void +isc__socket_attach(isc_socket_t *sock, isc_socket_t **socketp); +ISC_SOCKETFUNC_SCOPE void +isc__socket_detach(isc_socket_t **socketp); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, + unsigned int maxsocks); +ISC_SOCKETFUNC_SCOPE void +isc__socketmgr_destroy(isc_socketmgr_t **managerp); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist, + unsigned int minimum, isc_task_t *task, + isc_taskaction_t action, const void *arg); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_recv(isc_socket_t *sock, isc_region_t *region, + unsigned int minimum, isc_task_t *task, + isc_taskaction_t action, const void *arg); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_recv2(isc_socket_t *sock, isc_region_t *region, + unsigned int minimum, isc_task_t *task, + isc_socketevent_t *event, unsigned int flags); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_send(isc_socket_t *sock, isc_region_t *region, + isc_task_t *task, isc_taskaction_t action, const void *arg); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_sendto(isc_socket_t *sock, isc_region_t *region, + isc_task_t *task, isc_taskaction_t action, const void *arg, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist, + isc_task_t *task, isc_taskaction_t action, const void *arg); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist, + isc_task_t *task, isc_taskaction_t action, const void *arg, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_sendto2(isc_socket_t *sock, isc_region_t *region, + isc_task_t *task, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, + isc_socketevent_t *event, unsigned int flags); +ISC_SOCKETFUNC_SCOPE void +isc__socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm, + isc_uint32_t owner, isc_uint32_t group); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr, + unsigned int options); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_filter(isc_socket_t *sock, const char *filter); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_listen(isc_socket_t *sock, unsigned int backlog); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_accept(isc_socket_t *sock, + isc_task_t *task, isc_taskaction_t action, const void *arg); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, + isc_task_t *task, isc_taskaction_t action, + const void *arg); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp); +ISC_SOCKETFUNC_SCOPE void +isc__socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how); +ISC_SOCKETFUNC_SCOPE isc_sockettype_t +isc__socket_gettype(isc_socket_t *sock); +ISC_SOCKETFUNC_SCOPE isc_boolean_t +isc__socket_isbound(isc_socket_t *sock); +ISC_SOCKETFUNC_SCOPE void +isc__socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes); +#if defined(HAVE_LIBXML2) && defined(BIND9) +ISC_SOCKETFUNC_SCOPE void +isc__socketmgr_renderxml(isc_socketmgr_t *mgr0, xmlTextWriterPtr writer); +#endif + +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags, + isc_sockfdwatch_t callback, void *cbarg, + isc_task_t *task, isc_socket_t **socketp); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_fdwatchpoke(isc_socket_t *sock, int flags); + +static struct { + isc_socketmethods_t methods; + + /*% + * The following are defined just for avoiding unused static functions. + */ +#ifndef BIND9 + void *recvv, *send, *sendv, *sendto2, *cleanunix, *permunix, *filter, + *listen, *accept, *getpeername, *isbound; +#endif +} socketmethods = { + { + isc__socket_attach, + isc__socket_detach, + isc__socket_bind, + isc__socket_sendto, + isc__socket_connect, + isc__socket_recv, + isc__socket_cancel, + isc__socket_getsockname, + isc__socket_gettype, + isc__socket_ipv6only, + isc__socket_fdwatchpoke + } +#ifndef BIND9 + , + (void *)isc__socket_recvv, (void *)isc__socket_send, + (void *)isc__socket_sendv, (void *)isc__socket_sendto2, + (void *)isc__socket_cleanunix, (void *)isc__socket_permunix, + (void *)isc__socket_filter, (void *)isc__socket_listen, + (void *)isc__socket_accept, (void *)isc__socket_getpeername, + (void *)isc__socket_isbound #endif +}; + +static isc_socketmgrmethods_t socketmgrmethods = { + isc__socketmgr_destroy, + isc__socket_create, + isc__socket_fdwatchcreate +}; #define SELECT_POKE_SHUTDOWN (-1) #define SELECT_POKE_NOTHING (-2) @@ -531,12 +686,14 @@ static const isc_statscounter_t fdwatchstatsindex[] = { isc_sockstatscounter_fdwatchrecvfail }; +#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL) || \ + defined(USE_WATCHER_THREAD) static void -manager_log(isc_socketmgr_t *sockmgr, +manager_log(isc__socketmgr_t *sockmgr, isc_logcategory_t *category, isc_logmodule_t *module, int level, const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6); static void -manager_log(isc_socketmgr_t *sockmgr, +manager_log(isc__socketmgr_t *sockmgr, isc_logcategory_t *category, isc_logmodule_t *module, int level, const char *fmt, ...) { @@ -553,14 +710,15 @@ manager_log(isc_socketmgr_t *sockmgr, isc_log_write(isc_lctx, category, module, level, "sockmgr %p: %s", sockmgr, msgbuf); } +#endif static void -socket_log(isc_socket_t *sock, isc_sockaddr_t *address, +socket_log(isc__socket_t *sock, isc_sockaddr_t *address, isc_logcategory_t *category, isc_logmodule_t *module, int level, isc_msgcat_t *msgcat, int msgset, int message, const char *fmt, ...) ISC_FORMAT_PRINTF(9, 10); static void -socket_log(isc_socket_t *sock, isc_sockaddr_t *address, +socket_log(isc__socket_t *sock, isc_sockaddr_t *address, isc_logcategory_t *category, isc_logmodule_t *module, int level, isc_msgcat_t *msgcat, int msgset, int message, const char *fmt, ...) @@ -595,7 +753,7 @@ socket_log(isc_socket_t *sock, isc_sockaddr_t *address, * setting IPV6_V6ONLY. */ static void -FIX_IPV6_RECVPKTINFO(isc_socket_t *sock) +FIX_IPV6_RECVPKTINFO(isc__socket_t *sock) { char strbuf[ISC_STRERRORSIZE]; int on = 1; @@ -632,7 +790,7 @@ inc_stats(isc_stats_t *stats, isc_statscounter_t counterid) { } static inline isc_result_t -watch_fd(isc_socketmgr_t *manager, int fd, int msg) { +watch_fd(isc__socketmgr_t *manager, int fd, int msg) { isc_result_t result = ISC_R_SUCCESS; #ifdef USE_KQUEUE @@ -700,7 +858,7 @@ watch_fd(isc_socketmgr_t *manager, int fd, int msg) { } static inline isc_result_t -unwatch_fd(isc_socketmgr_t *manager, int fd, int msg) { +unwatch_fd(isc__socketmgr_t *manager, int fd, int msg) { isc_result_t result = ISC_R_SUCCESS; #ifdef USE_KQUEUE @@ -787,7 +945,7 @@ unwatch_fd(isc_socketmgr_t *manager, int fd, int msg) { } static void -wakeup_socket(isc_socketmgr_t *manager, int fd, int msg) { +wakeup_socket(isc__socketmgr_t *manager, int fd, int msg) { isc_result_t result; int lockid = FDLOCK_ID(fd); @@ -848,14 +1006,14 @@ wakeup_socket(isc_socketmgr_t *manager, int fd, int msg) { } } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD /* * Poke the select loop when there is something for us to do. * The write is required (by POSIX) to complete. That is, we * will not get partial writes. */ static void -select_poke(isc_socketmgr_t *mgr, int fd, int msg) { +select_poke(isc__socketmgr_t *mgr, int fd, int msg) { int cc; int buf[2]; char strbuf[ISC_STRERRORSIZE]; @@ -894,7 +1052,7 @@ select_poke(isc_socketmgr_t *mgr, int fd, int msg) { * Read a message on the internal fd. */ static void -select_readmsg(isc_socketmgr_t *mgr, int *fd, int *msg) { +select_readmsg(isc__socketmgr_t *mgr, int *fd, int *msg) { int buf[2]; int cc; char strbuf[ISC_STRERRORSIZE]; @@ -921,19 +1079,19 @@ select_readmsg(isc_socketmgr_t *mgr, int *fd, int *msg) { *fd = buf[0]; *msg = buf[1]; } -#else /* ISC_PLATFORM_USETHREADS */ +#else /* USE_WATCHER_THREAD */ /* * Update the state of the socketmgr when something changes. */ static void -select_poke(isc_socketmgr_t *manager, int fd, int msg) { +select_poke(isc__socketmgr_t *manager, int fd, int msg) { if (msg == SELECT_POKE_SHUTDOWN) return; else if (fd >= 0) wakeup_socket(manager, fd, msg); return; } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ /* * Make a fd non-blocking. @@ -1026,7 +1184,7 @@ cmsg_space(ISC_SOCKADDR_LEN_T len) { * Process control messages received on a socket. */ static void -process_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) { +process_cmsg(isc__socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) { #ifdef USE_CMSG struct cmsghdr *cmsgp; #ifdef ISC_PLATFORM_HAVEIN6PKTINFO @@ -1129,7 +1287,7 @@ process_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) { * this transaction can send. */ static void -build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev, +build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev, struct msghdr *msg, struct iovec *iov, size_t *write_countp) { unsigned int iovcount; @@ -1248,7 +1406,7 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev, * this transaction can receive. */ static void -build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev, +build_msghdr_recv(isc__socket_t *sock, isc_socketevent_t *dev, struct msghdr *msg, struct iovec *iov, size_t *read_countp) { unsigned int iovcount; @@ -1369,7 +1527,7 @@ build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev, } static void -set_dev_address(isc_sockaddr_t *address, isc_socket_t *sock, +set_dev_address(isc_sockaddr_t *address, isc__socket_t *sock, isc_socketevent_t *dev) { if (sock->type == isc_sockettype_udp) { @@ -1393,7 +1551,7 @@ destroy_socketevent(isc_event_t *event) { } static isc_socketevent_t * -allocate_socketevent(isc_socket_t *sock, isc_eventtype_t eventtype, +allocate_socketevent(isc__socket_t *sock, isc_eventtype_t eventtype, isc_taskaction_t action, const void *arg) { isc_socketevent_t *ev; @@ -1446,7 +1604,7 @@ dump_msg(struct msghdr *msg) { #define DOIO_EOF 3 /* EOF, no event sent */ static int -doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) { +doio_recv(isc__socket_t *sock, isc_socketevent_t *dev) { int cc; struct iovec iov[MAXSCATTERGATHER_RECV]; size_t read_count; @@ -1554,6 +1712,12 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) { } return (DOIO_SOFT); } + /* + * Simulate a firewall blocking UDP responses bigger than + * 512 bytes. + */ + if (sock->manager->maxudp != 0 && cc > sock->manager->maxudp) + return (DOIO_SOFT); } socket_log(sock, &dev->address, IOEVENT, @@ -1630,7 +1794,7 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) { * No other return values are possible. */ static int -doio_send(isc_socket_t *sock, isc_socketevent_t *dev) { +doio_send(isc__socket_t *sock, isc_socketevent_t *dev) { int cc; struct iovec iov[MAXSCATTERGATHER_SEND]; size_t write_count; @@ -1741,7 +1905,7 @@ doio_send(isc_socket_t *sock, isc_socketevent_t *dev) { * references exist. */ static void -closesocket(isc_socketmgr_t *manager, isc_socket_t *sock, int fd) { +closesocket(isc__socketmgr_t *manager, isc__socket_t *sock, int fd) { isc_sockettype_t type = sock->type; int lockid = FDLOCK_ID(fd); @@ -1804,10 +1968,10 @@ closesocket(isc_socketmgr_t *manager, isc_socket_t *sock, int fd) { } static void -destroy(isc_socket_t **sockp) { +destroy(isc__socket_t **sockp) { int fd; - isc_socket_t *sock = *sockp; - isc_socketmgr_t *manager = sock->manager; + isc__socket_t *sock = *sockp; + isc__socketmgr_t *manager = sock->manager; socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_DESTROYING, "destroying"); @@ -1828,10 +1992,10 @@ destroy(isc_socket_t **sockp) { ISC_LIST_UNLINK(manager->socklist, sock, link); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD if (ISC_LIST_EMPTY(manager->socklist)) SIGNAL(&manager->shutdown_ok); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ UNLOCK(&manager->lock); @@ -1839,10 +2003,10 @@ destroy(isc_socket_t **sockp) { } static isc_result_t -allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, - isc_socket_t **socketp) +allocate_socket(isc__socketmgr_t *manager, isc_sockettype_t type, + isc__socket_t **socketp) { - isc_socket_t *sock; + isc__socket_t *sock; isc_result_t result; ISC_SOCKADDR_LEN_T cmsgbuflen; @@ -1853,7 +2017,8 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, result = ISC_R_UNEXPECTED; - sock->magic = 0; + sock->common.magic = 0; + sock->common.impmagic = 0; sock->references = 0; sock->manager = manager; @@ -1917,7 +2082,8 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, */ result = isc_mutex_init(&sock->lock); if (result != ISC_R_SUCCESS) { - sock->magic = 0; + sock->common.magic = 0; + sock->common.impmagic = 0; goto error; } @@ -1931,7 +2097,8 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, ISC_EVENTATTR_NOPURGE, NULL, ISC_SOCKEVENT_INTW, NULL, sock, sock, NULL, NULL); - sock->magic = SOCKET_MAGIC; + sock->common.magic = ISCAPI_SOCKET_MAGIC; + sock->common.impmagic = SOCKET_MAGIC; *socketp = sock; return (ISC_R_SUCCESS); @@ -1956,8 +2123,8 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, * also close the socket. */ static void -free_socket(isc_socket_t **socketp) { - isc_socket_t *sock = *socketp; +free_socket(isc__socket_t **socketp) { + isc__socket_t *sock = *socketp; INSIST(sock->references == 0); INSIST(VALID_SOCKET(sock)); @@ -1977,7 +2144,8 @@ free_socket(isc_socket_t **socketp) { isc_mem_put(sock->manager->mctx, sock->sendcmsgbuf, sock->sendcmsgbuflen); - sock->magic = 0; + sock->common.magic = 0; + sock->common.impmagic = 0; DESTROYLOCK(&sock->lock); @@ -2025,7 +2193,7 @@ clear_bsdcompat(void) { #endif static isc_result_t -opensocket(isc_socketmgr_t *manager, isc_socket_t *sock) { +opensocket(isc__socketmgr_t *manager, isc__socket_t *sock) { char strbuf[ISC_STRERRORSIZE]; const char *err = "socket"; int tries = 0; @@ -2316,11 +2484,12 @@ opensocket(isc_socketmgr_t *manager, isc_socket_t *sock) { * called with 'arg' as the arg value. The new socket is returned * in 'socketp'. */ -isc_result_t -isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, - isc_socket_t **socketp) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type, + isc_socket_t **socketp) { - isc_socket_t *sock = NULL; + isc__socket_t *sock = NULL; + isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; isc_result_t result; int lockid; @@ -2356,8 +2525,9 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, return (result); } + sock->common.methods = (isc_socketmethods_t *)&socketmethods; sock->references = 1; - *socketp = sock; + *socketp = (isc_socket_t *)sock; /* * Note we don't have to lock the socket like we normally would because @@ -2388,9 +2558,11 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, return (ISC_R_SUCCESS); } -isc_result_t -isc_socket_open(isc_socket_t *sock) { +#ifdef BIND9 +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_open(isc_socket_t *sock0) { isc_result_t result; + isc__socket_t *sock = (isc__socket_t *)sock0; REQUIRE(VALID_SOCKET(sock)); @@ -2430,6 +2602,7 @@ isc_socket_open(isc_socket_t *sock) { return (result); } +#endif /* BIND9 */ /* * Create a new 'type' socket managed by 'manager'. Events @@ -2437,12 +2610,13 @@ isc_socket_open(isc_socket_t *sock) { * called with 'arg' as the arg value. The new socket is returned * in 'socketp'. */ -isc_result_t -isc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags, - isc_sockfdwatch_t callback, void *cbarg, - isc_task_t *task, isc_socket_t **socketp) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_fdwatchcreate(isc_socketmgr_t *manager0, int fd, int flags, + isc_sockfdwatch_t callback, void *cbarg, + isc_task_t *task, isc_socket_t **socketp) { - isc_socket_t *sock = NULL; + isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; + isc__socket_t *sock = NULL; isc_result_t result; int lockid; @@ -2460,8 +2634,9 @@ isc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags, sock->fdwatchtask = task; sock->statsindex = fdwatchstatsindex; + sock->common.methods = (isc_socketmethods_t *)&socketmethods; sock->references = 1; - *socketp = sock; + *socketp = (isc_socket_t *)sock; /* * Note we don't have to lock the socket like we normally would because @@ -2494,10 +2669,50 @@ isc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags, } /* + * Indicate to the manager that it should watch the socket again. + * This can be used to restart watching if the previous event handler + * didn't indicate there was more data to be processed. Primarily + * it is for writing but could be used for reading if desired + */ + +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_fdwatchpoke(isc_socket_t *sock0, int flags) +{ + isc__socket_t *sock = (isc__socket_t *)sock0; + + REQUIRE(VALID_SOCKET(sock)); + + /* + * We check both flags first to allow us to get the lock + * once but only if we need it. + */ + + if ((flags & (ISC_SOCKFDWATCH_READ | ISC_SOCKFDWATCH_WRITE)) != 0) { + LOCK(&sock->lock); + if (((flags & ISC_SOCKFDWATCH_READ) != 0) && + !sock->pending_recv) + select_poke(sock->manager, sock->fd, + SELECT_POKE_READ); + if (((flags & ISC_SOCKFDWATCH_WRITE) != 0) && + !sock->pending_send) + select_poke(sock->manager, sock->fd, + SELECT_POKE_WRITE); + UNLOCK(&sock->lock); + } + + socket_log(sock, NULL, TRACE, isc_msgcat, ISC_MSGSET_SOCKET, + ISC_MSG_POKED, "fdwatch-poked flags: %d", flags); + + return (ISC_R_SUCCESS); +} + +/* * Attach to a socket. Caller must explicitly detach when it is done. */ -void -isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) { +ISC_SOCKETFUNC_SCOPE void +isc__socket_attach(isc_socket_t *sock0, isc_socket_t **socketp) { + isc__socket_t *sock = (isc__socket_t *)sock0; + REQUIRE(VALID_SOCKET(sock)); REQUIRE(socketp != NULL && *socketp == NULL); @@ -2505,20 +2720,20 @@ isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) { sock->references++; UNLOCK(&sock->lock); - *socketp = sock; + *socketp = (isc_socket_t *)sock; } /* * Dereference a socket. If this is the last reference to it, clean things * up by destroying the socket. */ -void -isc_socket_detach(isc_socket_t **socketp) { - isc_socket_t *sock; +ISC_SOCKETFUNC_SCOPE void +isc__socket_detach(isc_socket_t **socketp) { + isc__socket_t *sock; isc_boolean_t kill_socket = ISC_FALSE; REQUIRE(socketp != NULL); - sock = *socketp; + sock = (isc__socket_t *)*socketp; REQUIRE(VALID_SOCKET(sock)); LOCK(&sock->lock); @@ -2534,10 +2749,12 @@ isc_socket_detach(isc_socket_t **socketp) { *socketp = NULL; } -isc_result_t -isc_socket_close(isc_socket_t *sock) { +#ifdef BIND9 +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_close(isc_socket_t *sock0) { + isc__socket_t *sock = (isc__socket_t *)sock0; int fd; - isc_socketmgr_t *manager; + isc__socketmgr_t *manager; isc_sockettype_t type; REQUIRE(VALID_SOCKET(sock)); @@ -2575,6 +2792,7 @@ isc_socket_close(isc_socket_t *sock) { return (ISC_R_SUCCESS); } +#endif /* BIND9 */ /* * I/O is possible on a given socket. Schedule an event to this task that @@ -2585,7 +2803,7 @@ isc_socket_close(isc_socket_t *sock) { * The socket and manager must be locked before calling this function. */ static void -dispatch_recv(isc_socket_t *sock) { +dispatch_recv(isc__socket_t *sock) { intev_t *iev; isc_socketevent_t *ev; isc_task_t *sender; @@ -2619,7 +2837,7 @@ dispatch_recv(isc_socket_t *sock) { } static void -dispatch_send(isc_socket_t *sock) { +dispatch_send(isc__socket_t *sock) { intev_t *iev; isc_socketevent_t *ev; isc_task_t *sender; @@ -2656,7 +2874,7 @@ dispatch_send(isc_socket_t *sock) { * Dispatch an internal accept event. */ static void -dispatch_accept(isc_socket_t *sock) { +dispatch_accept(isc__socket_t *sock) { intev_t *iev; isc_socket_newconnev_t *ev; @@ -2682,7 +2900,7 @@ dispatch_accept(isc_socket_t *sock) { } static void -dispatch_connect(isc_socket_t *sock) { +dispatch_connect(isc__socket_t *sock) { intev_t *iev; isc_socket_connev_t *ev; @@ -2712,7 +2930,7 @@ dispatch_connect(isc_socket_t *sock) { * Caller must have the socket locked if the event is attached to the socket. */ static void -send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev) { +send_recvdone_event(isc__socket_t *sock, isc_socketevent_t **dev) { isc_task_t *task; task = (*dev)->ev_sender; @@ -2735,7 +2953,7 @@ send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev) { * Caller must have the socket locked if the event is attached to the socket. */ static void -send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev) { +send_senddone_event(isc__socket_t *sock, isc_socketevent_t **dev) { isc_task_t *task; INSIST(dev != NULL && *dev != NULL); @@ -2766,8 +2984,8 @@ send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev) { */ static void internal_accept(isc_task_t *me, isc_event_t *ev) { - isc_socket_t *sock; - isc_socketmgr_t *manager; + isc__socket_t *sock; + isc__socketmgr_t *manager; isc_socket_newconnev_t *dev; isc_task_t *task; ISC_SOCKADDR_LEN_T addrlen; @@ -2822,9 +3040,9 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { * daemons such as BIND 8 and Apache. */ - addrlen = sizeof(dev->newsocket->peer_address.type); - memset(&dev->newsocket->peer_address.type, 0, addrlen); - fd = accept(sock->fd, &dev->newsocket->peer_address.type.sa, + addrlen = sizeof(NEWCONNSOCK(dev)->peer_address.type); + memset(&NEWCONNSOCK(dev)->peer_address.type, 0, addrlen); + fd = accept(sock->fd, &NEWCONNSOCK(dev)->peer_address.type.sa, (void *)&addrlen); #ifdef F_DUPFD @@ -2894,14 +3112,14 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { (void)close(fd); goto soft_error; - } else if (dev->newsocket->peer_address.type.sa.sa_family != + } else if (NEWCONNSOCK(dev)->peer_address.type.sa.sa_family != sock->pf) { UNEXPECTED_ERROR(__FILE__, __LINE__, "internal_accept(): " "accept() returned peer address " "family %u (expected %u)", - dev->newsocket->peer_address. + NEWCONNSOCK(dev)->peer_address. type.sa.sa_family, sock->pf); (void)close(fd); @@ -2920,8 +3138,8 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { } if (fd != -1) { - dev->newsocket->peer_address.length = addrlen; - dev->newsocket->pf = sock->pf; + NEWCONNSOCK(dev)->peer_address.length = addrlen; + NEWCONNSOCK(dev)->pf = sock->pf; } /* @@ -2950,28 +3168,28 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { int lockid = FDLOCK_ID(fd); LOCK(&manager->fdlock[lockid]); - manager->fds[fd] = dev->newsocket; + manager->fds[fd] = NEWCONNSOCK(dev); manager->fdstate[fd] = MANAGED; UNLOCK(&manager->fdlock[lockid]); LOCK(&manager->lock); - ISC_LIST_APPEND(manager->socklist, dev->newsocket, link); + ISC_LIST_APPEND(manager->socklist, NEWCONNSOCK(dev), link); - dev->newsocket->fd = fd; - dev->newsocket->bound = 1; - dev->newsocket->connected = 1; + NEWCONNSOCK(dev)->fd = fd; + NEWCONNSOCK(dev)->bound = 1; + NEWCONNSOCK(dev)->connected = 1; /* * Save away the remote address */ - dev->address = dev->newsocket->peer_address; + dev->address = NEWCONNSOCK(dev)->peer_address; #ifdef USE_SELECT if (manager->maxfd < fd) manager->maxfd = fd; #endif - socket_log(sock, &dev->newsocket->peer_address, CREATION, + socket_log(sock, &NEWCONNSOCK(dev)->peer_address, CREATION, isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN, "accepted connection, new socket %p", dev->newsocket); @@ -2981,8 +3199,8 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { inc_stats(manager->stats, sock->statsindex[STATID_ACCEPT]); } else { inc_stats(manager->stats, sock->statsindex[STATID_ACCEPTFAIL]); - dev->newsocket->references--; - free_socket(&dev->newsocket); + NEWCONNSOCK(dev)->references--; + free_socket((isc__socket_t **)&dev->newsocket); } /* @@ -3006,7 +3224,7 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { static void internal_recv(isc_task_t *me, isc_event_t *ev) { isc_socketevent_t *dev; - isc_socket_t *sock; + isc__socket_t *sock; INSIST(ev->ev_type == ISC_SOCKEVENT_INTR); @@ -3071,14 +3289,14 @@ internal_recv(isc_task_t *me, isc_event_t *ev) { static void internal_send(isc_task_t *me, isc_event_t *ev) { isc_socketevent_t *dev; - isc_socket_t *sock; + isc__socket_t *sock; INSIST(ev->ev_type == ISC_SOCKEVENT_INTW); /* * Find out what socket this is and lock it. */ - sock = (isc_socket_t *)ev->ev_sender; + sock = (isc__socket_t *)ev->ev_sender; INSIST(VALID_SOCKET(sock)); LOCK(&sock->lock); @@ -3125,7 +3343,7 @@ internal_send(isc_task_t *me, isc_event_t *ev) { static void internal_fdwatch_write(isc_task_t *me, isc_event_t *ev) { - isc_socket_t *sock; + isc__socket_t *sock; int more_data; INSIST(ev->ev_type == ISC_SOCKEVENT_INTW); @@ -3133,7 +3351,7 @@ internal_fdwatch_write(isc_task_t *me, isc_event_t *ev) { /* * Find out what socket this is and lock it. */ - sock = (isc_socket_t *)ev->ev_sender; + sock = (isc__socket_t *)ev->ev_sender; INSIST(VALID_SOCKET(sock)); LOCK(&sock->lock); @@ -3144,7 +3362,8 @@ internal_fdwatch_write(isc_task_t *me, isc_event_t *ev) { INSIST(sock->pending_send == 1); UNLOCK(&sock->lock); - more_data = (sock->fdwatchcb)(me, sock, sock->fdwatcharg); + more_data = (sock->fdwatchcb)(me, (isc_socket_t *)sock, + sock->fdwatcharg, ISC_SOCKFDWATCH_WRITE); LOCK(&sock->lock); sock->pending_send = 0; @@ -3165,7 +3384,7 @@ internal_fdwatch_write(isc_task_t *me, isc_event_t *ev) { static void internal_fdwatch_read(isc_task_t *me, isc_event_t *ev) { - isc_socket_t *sock; + isc__socket_t *sock; int more_data; INSIST(ev->ev_type == ISC_SOCKEVENT_INTR); @@ -3173,7 +3392,7 @@ internal_fdwatch_read(isc_task_t *me, isc_event_t *ev) { /* * Find out what socket this is and lock it. */ - sock = (isc_socket_t *)ev->ev_sender; + sock = (isc__socket_t *)ev->ev_sender; INSIST(VALID_SOCKET(sock)); LOCK(&sock->lock); @@ -3184,7 +3403,8 @@ internal_fdwatch_read(isc_task_t *me, isc_event_t *ev) { INSIST(sock->pending_recv == 1); UNLOCK(&sock->lock); - more_data = (sock->fdwatchcb)(me, sock, sock->fdwatcharg); + more_data = (sock->fdwatchcb)(me, (isc_socket_t *)sock, + sock->fdwatcharg, ISC_SOCKFDWATCH_READ); LOCK(&sock->lock); sock->pending_recv = 0; @@ -3208,10 +3428,10 @@ internal_fdwatch_read(isc_task_t *me, isc_event_t *ev) { * and unlocking twice if both reads and writes are possible. */ static void -process_fd(isc_socketmgr_t *manager, int fd, isc_boolean_t readable, +process_fd(isc__socketmgr_t *manager, int fd, isc_boolean_t readable, isc_boolean_t writeable) { - isc_socket_t *sock; + isc__socket_t *sock; isc_boolean_t unlock_sock; isc_boolean_t unwatch_read = ISC_FALSE, unwatch_write = ISC_FALSE; int lockid = FDLOCK_ID(fd); @@ -3277,11 +3497,11 @@ check_write: #ifdef USE_KQUEUE static isc_boolean_t -process_fds(isc_socketmgr_t *manager, struct kevent *events, int nevents) { +process_fds(isc__socketmgr_t *manager, struct kevent *events, int nevents) { int i; isc_boolean_t readable, writable; isc_boolean_t done = ISC_FALSE; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD isc_boolean_t have_ctlevent = ISC_FALSE; #endif @@ -3299,7 +3519,7 @@ process_fds(isc_socketmgr_t *manager, struct kevent *events, int nevents) { for (i = 0; i < nevents; i++) { REQUIRE(events[i].ident < manager->maxsocks); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD if (events[i].ident == (uintptr_t)manager->pipe_fds[0]) { have_ctlevent = ISC_TRUE; continue; @@ -3310,7 +3530,7 @@ process_fds(isc_socketmgr_t *manager, struct kevent *events, int nevents) { process_fd(manager, events[i].ident, readable, writable); } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD if (have_ctlevent) done = process_ctlfd(manager); #endif @@ -3319,10 +3539,11 @@ process_fds(isc_socketmgr_t *manager, struct kevent *events, int nevents) { } #elif defined(USE_EPOLL) static isc_boolean_t -process_fds(isc_socketmgr_t *manager, struct epoll_event *events, int nevents) { +process_fds(isc__socketmgr_t *manager, struct epoll_event *events, int nevents) +{ int i; isc_boolean_t done = ISC_FALSE; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD isc_boolean_t have_ctlevent = ISC_FALSE; #endif @@ -3335,7 +3556,7 @@ process_fds(isc_socketmgr_t *manager, struct epoll_event *events, int nevents) { for (i = 0; i < nevents; i++) { REQUIRE(events[i].data.fd < (int)manager->maxsocks); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD if (events[i].data.fd == manager->pipe_fds[0]) { have_ctlevent = ISC_TRUE; continue; @@ -3357,7 +3578,7 @@ process_fds(isc_socketmgr_t *manager, struct epoll_event *events, int nevents) { (events[i].events & EPOLLOUT) != 0); } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD if (have_ctlevent) done = process_ctlfd(manager); #endif @@ -3366,10 +3587,10 @@ process_fds(isc_socketmgr_t *manager, struct epoll_event *events, int nevents) { } #elif defined(USE_DEVPOLL) static isc_boolean_t -process_fds(isc_socketmgr_t *manager, struct pollfd *events, int nevents) { +process_fds(isc__socketmgr_t *manager, struct pollfd *events, int nevents) { int i; isc_boolean_t done = ISC_FALSE; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD isc_boolean_t have_ctlevent = ISC_FALSE; #endif @@ -3382,7 +3603,7 @@ process_fds(isc_socketmgr_t *manager, struct pollfd *events, int nevents) { for (i = 0; i < nevents; i++) { REQUIRE(events[i].fd < (int)manager->maxsocks); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD if (events[i].fd == manager->pipe_fds[0]) { have_ctlevent = ISC_TRUE; continue; @@ -3393,7 +3614,7 @@ process_fds(isc_socketmgr_t *manager, struct pollfd *events, int nevents) { (events[i].events & POLLOUT) != 0); } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD if (have_ctlevent) done = process_ctlfd(manager); #endif @@ -3402,27 +3623,27 @@ process_fds(isc_socketmgr_t *manager, struct pollfd *events, int nevents) { } #elif defined(USE_SELECT) static void -process_fds(isc_socketmgr_t *manager, int maxfd, - fd_set *readfds, fd_set *writefds) +process_fds(isc__socketmgr_t *manager, int maxfd, fd_set *readfds, + fd_set *writefds) { int i; REQUIRE(maxfd <= (int)manager->maxsocks); for (i = 0; i < maxfd; i++) { -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD if (i == manager->pipe_fds[0] || i == manager->pipe_fds[1]) continue; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ process_fd(manager, i, FD_ISSET(i, readfds), FD_ISSET(i, writefds)); } } #endif -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD static isc_boolean_t -process_ctlfd(isc_socketmgr_t *manager) { +process_ctlfd(isc__socketmgr_t *manager) { int msg, fd; for (;;) { @@ -3470,7 +3691,7 @@ process_ctlfd(isc_socketmgr_t *manager) { */ static isc_threadresult_t watcher(void *uap) { - isc_socketmgr_t *manager = uap; + isc__socketmgr_t *manager = uap; isc_boolean_t done; int ctlfd; int cc; @@ -3585,22 +3806,34 @@ watcher(void *uap) { return ((isc_threadresult_t)0); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ -void -isc__socketmgr_setreserved(isc_socketmgr_t *manager, isc_uint32_t reserved) { +#ifdef BIND9 +ISC_SOCKETFUNC_SCOPE void +isc__socketmgr_setreserved(isc_socketmgr_t *manager0, isc_uint32_t reserved) { + isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; REQUIRE(VALID_MANAGER(manager)); manager->reserved = reserved; } +ISC_SOCKETFUNC_SCOPE void +isc___socketmgr_maxudp(isc_socketmgr_t *manager0, int maxudp) { + isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; + + REQUIRE(VALID_MANAGER(manager)); + + manager->maxudp = maxudp; +} +#endif /* BIND9 */ + /* * Create a new socket manager. */ static isc_result_t -setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { +setup_watcher(isc_mem_t *mctx, isc__socketmgr_t *manager) { isc_result_t result; #if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL) char strbuf[ISC_STRERRORSIZE]; @@ -3626,7 +3859,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { return (result); } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ); if (result != ISC_R_SUCCESS) { close(manager->kqueue_fd); @@ -3634,7 +3867,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { sizeof(struct kevent) * manager->nevents); return (result); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ #elif defined(USE_EPOLL) manager->nevents = ISC_SOCKET_MAXEVENTS; manager->events = isc_mem_get(mctx, sizeof(struct epoll_event) * @@ -3654,7 +3887,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { sizeof(struct epoll_event) * manager->nevents); return (result); } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ); if (result != ISC_R_SUCCESS) { close(manager->epoll_fd); @@ -3662,7 +3895,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { sizeof(struct epoll_event) * manager->nevents); return (result); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ #elif defined(USE_DEVPOLL) /* * XXXJT: /dev/poll seems to reject large numbers of events, @@ -3700,7 +3933,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { sizeof(pollinfo_t) * manager->maxsocks); return (result); } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ); if (result != ISC_R_SUCCESS) { close(manager->devpoll_fd); @@ -3710,7 +3943,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { sizeof(pollinfo_t) * manager->maxsocks); return (result); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ #elif defined(USE_SELECT) UNUSED(result); @@ -3758,20 +3991,20 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { memset(manager->read_fds, 0, manager->fd_bufsize); memset(manager->write_fds, 0, manager->fd_bufsize); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD (void)watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ); manager->maxfd = manager->pipe_fds[0]; -#else /* ISC_PLATFORM_USETHREADS */ +#else /* USE_WATCHER_THREAD */ manager->maxfd = 0; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ #endif /* USE_KQUEUE */ return (ISC_R_SUCCESS); } static void -cleanup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { -#ifdef ISC_PLATFORM_USETHREADS +cleanup_watcher(isc_mem_t *mctx, isc__socketmgr_t *manager) { +#ifdef USE_WATCHER_THREAD isc_result_t result; result = unwatch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ); @@ -3781,7 +4014,7 @@ cleanup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed")); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ #ifdef USE_KQUEUE close(manager->kqueue_fd); @@ -3809,35 +4042,35 @@ cleanup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { #endif /* USE_KQUEUE */ } -isc_result_t -isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) { - return (isc_socketmgr_create2(mctx, managerp, 0)); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) { + return (isc__socketmgr_create2(mctx, managerp, 0)); } -isc_result_t -isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, - unsigned int maxsocks) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, + unsigned int maxsocks) { int i; - isc_socketmgr_t *manager; -#ifdef ISC_PLATFORM_USETHREADS + isc__socketmgr_t *manager; +#ifdef USE_WATCHER_THREAD char strbuf[ISC_STRERRORSIZE]; #endif isc_result_t result; REQUIRE(managerp != NULL && *managerp == NULL); -#ifndef ISC_PLATFORM_USETHREADS +#ifdef USE_SHARED_MANAGER if (socketmgr != NULL) { /* Don't allow maxsocks to be updated */ if (maxsocks > 0 && socketmgr->maxsocks != maxsocks) return (ISC_R_EXISTS); socketmgr->refs++; - *managerp = socketmgr; + *managerp = (isc_socketmgr_t *)socketmgr; return (ISC_R_SUCCESS); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_SHARED_MANAGER */ if (maxsocks == 0) maxsocks = ISC_SOCKET_MAXSOCKETS; @@ -3850,8 +4083,9 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, memset(manager, 0, sizeof(*manager)); manager->maxsocks = maxsocks; manager->reserved = 0; + manager->maxudp = 0; manager->fds = isc_mem_get(mctx, - manager->maxsocks * sizeof(isc_socket_t *)); + manager->maxsocks * sizeof(isc__socket_t *)); if (manager->fds == NULL) { result = ISC_R_NOMEMORY; goto free_manager; @@ -3863,7 +4097,9 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, } manager->stats = NULL; - manager->magic = SOCKET_MANAGER_MAGIC; + manager->common.methods = &socketmgrmethods; + manager->common.magic = ISCAPI_SOCKETMGR_MAGIC; + manager->common.impmagic = SOCKET_MANAGER_MAGIC; manager->mctx = NULL; memset(manager->fds, 0, manager->maxsocks * sizeof(isc_socket_t *)); ISC_LIST_INIT(manager->socklist); @@ -3887,7 +4123,7 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, } } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD if (isc_condition_init(&manager->shutdown_ok) != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_condition_init() %s", @@ -3916,9 +4152,11 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, #if 0 RUNTIME_CHECK(make_nonblock(manager->pipe_fds[1]) == ISC_R_SUCCESS); #endif -#else /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ + +#ifdef USE_SHARED_MANAGER manager->refs = 1; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_SHARED_MANAGER */ /* * Set up initial state for the select loop @@ -3927,7 +4165,7 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, if (result != ISC_R_SUCCESS) goto cleanup; memset(manager->fdstate, 0, manager->maxsocks * sizeof(int)); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD /* * Start up the select/poll thread. */ @@ -3941,26 +4179,26 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, result = ISC_R_UNEXPECTED; goto cleanup; } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ isc_mem_attach(mctx, &manager->mctx); -#ifndef ISC_PLATFORM_USETHREADS +#ifdef USE_SHARED_MANAGER socketmgr = manager; -#endif /* ISC_PLATFORM_USETHREADS */ - *managerp = manager; +#endif /* USE_SHARED_MANAGER */ + *managerp = (isc_socketmgr_t *)manager; return (ISC_R_SUCCESS); cleanup: -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD (void)close(manager->pipe_fds[0]); (void)close(manager->pipe_fds[1]); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD cleanup_condition: (void)isc_condition_destroy(&manager->shutdown_ok); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ cleanup_lock: @@ -3988,8 +4226,10 @@ free_manager: return (result); } +#ifdef BIND9 isc_result_t -isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) { +isc__socketmgr_getmaxsockets(isc_socketmgr_t *manager0, unsigned int *nsockp) { + isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; REQUIRE(VALID_MANAGER(manager)); REQUIRE(nsockp != NULL); @@ -3999,7 +4239,9 @@ isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) { } void -isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) { +isc__socketmgr_setstats(isc_socketmgr_t *manager0, isc_stats_t *stats) { + isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; + REQUIRE(VALID_MANAGER(manager)); REQUIRE(ISC_LIST_EMPTY(manager->socklist)); REQUIRE(manager->stats == NULL); @@ -4007,10 +4249,11 @@ isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) { isc_stats_attach(stats, &manager->stats); } +#endif -void -isc_socketmgr_destroy(isc_socketmgr_t **managerp) { - isc_socketmgr_t *manager; +ISC_SOCKETFUNC_SCOPE void +isc__socketmgr_destroy(isc_socketmgr_t **managerp) { + isc__socketmgr_t *manager; int i; isc_mem_t *mctx; @@ -4019,42 +4262,36 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) { */ REQUIRE(managerp != NULL); - manager = *managerp; + manager = (isc__socketmgr_t *)*managerp; REQUIRE(VALID_MANAGER(manager)); -#ifndef ISC_PLATFORM_USETHREADS - if (manager->refs > 1) { - manager->refs--; +#ifdef USE_SHARED_MANAGER + manager->refs--; + if (manager->refs > 0) { *managerp = NULL; return; } -#endif /* ISC_PLATFORM_USETHREADS */ + socketmgr = NULL; +#endif /* USE_SHARED_MANAGER */ LOCK(&manager->lock); -#ifdef ISC_PLATFORM_USETHREADS /* * Wait for all sockets to be destroyed. */ while (!ISC_LIST_EMPTY(manager->socklist)) { +#ifdef USE_WATCHER_THREAD manager_log(manager, CREATION, "%s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_SOCKETSREMAIN, "sockets exist")); WAIT(&manager->shutdown_ok, &manager->lock); +#else /* USE_WATCHER_THREAD */ + UNLOCK(&manager->lock); + isc__taskmgr_dispatch(NULL); + LOCK(&manager->lock); +#endif /* USE_WATCHER_THREAD */ } -#else /* ISC_PLATFORM_USETHREADS */ - /* - * Hope all sockets have been destroyed. - */ - if (!ISC_LIST_EMPTY(manager->socklist)) { - manager_log(manager, CREATION, "%s", - isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, - ISC_MSG_SOCKETSREMAIN, - "sockets exist")); - INSIST(0); - } -#endif /* ISC_PLATFORM_USETHREADS */ UNLOCK(&manager->lock); @@ -4065,7 +4302,7 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) { */ select_poke(manager, 0, SELECT_POKE_SHUTDOWN); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD /* * Wait for thread to exit. */ @@ -4074,25 +4311,25 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) { "isc_thread_join() %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed")); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ /* * Clean up. */ cleanup_watcher(manager->mctx, manager); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD (void)close(manager->pipe_fds[0]); (void)close(manager->pipe_fds[1]); (void)isc_condition_destroy(&manager->shutdown_ok); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ for (i = 0; i < (int)manager->maxsocks; i++) if (manager->fdstate[i] == CLOSE_PENDING) /* no need to lock */ (void)close(i); isc_mem_put(manager->mctx, manager->fds, - manager->maxsocks * sizeof(isc_socket_t *)); + manager->maxsocks * sizeof(isc__socket_t *)); isc_mem_put(manager->mctx, manager->fdstate, manager->maxsocks * sizeof(int)); @@ -4106,17 +4343,22 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) { FDLOCK_COUNT * sizeof(isc_mutex_t)); } DESTROYLOCK(&manager->lock); - manager->magic = 0; + manager->common.magic = 0; + manager->common.impmagic = 0; mctx= manager->mctx; isc_mem_put(mctx, manager, sizeof(*manager)); isc_mem_detach(&mctx); *managerp = NULL; + +#ifdef USE_SHARED_MANAGER + socketmgr = NULL; +#endif } static isc_result_t -socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, +socket_recv(isc__socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, unsigned int flags) { int io_state; @@ -4187,13 +4429,14 @@ socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, return (result); } -isc_result_t -isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist, - unsigned int minimum, isc_task_t *task, - isc_taskaction_t action, const void *arg) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_recvv(isc_socket_t *sock0, isc_bufferlist_t *buflist, + unsigned int minimum, isc_task_t *task, + isc_taskaction_t action, const void *arg) { + isc__socket_t *sock = (isc__socket_t *)sock0; isc_socketevent_t *dev; - isc_socketmgr_t *manager; + isc__socketmgr_t *manager; unsigned int iocount; isc_buffer_t *buffer; @@ -4241,12 +4484,14 @@ isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist, return (socket_recv(sock, dev, task, 0)); } -isc_result_t -isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum, - isc_task_t *task, isc_taskaction_t action, const void *arg) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_recv(isc_socket_t *sock0, isc_region_t *region, + unsigned int minimum, isc_task_t *task, + isc_taskaction_t action, const void *arg) { + isc__socket_t *sock = (isc__socket_t *)sock0; isc_socketevent_t *dev; - isc_socketmgr_t *manager; + isc__socketmgr_t *manager; REQUIRE(VALID_SOCKET(sock)); REQUIRE(action != NULL); @@ -4260,14 +4505,16 @@ isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum, if (dev == NULL) return (ISC_R_NOMEMORY); - return (isc_socket_recv2(sock, region, minimum, task, dev, 0)); + return (isc__socket_recv2(sock0, region, minimum, task, dev, 0)); } -isc_result_t -isc_socket_recv2(isc_socket_t *sock, isc_region_t *region, - unsigned int minimum, isc_task_t *task, - isc_socketevent_t *event, unsigned int flags) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_recv2(isc_socket_t *sock0, isc_region_t *region, + unsigned int minimum, isc_task_t *task, + isc_socketevent_t *event, unsigned int flags) { + isc__socket_t *sock = (isc__socket_t *)sock0; + event->ev_sender = sock; event->result = ISC_R_UNEXPECTED; ISC_LIST_INIT(event->bufferlist); @@ -4292,7 +4539,7 @@ isc_socket_recv2(isc_socket_t *sock, isc_region_t *region, } static isc_result_t -socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, +socket_send(isc__socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, unsigned int flags) { @@ -4383,24 +4630,25 @@ socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, return (result); } -isc_result_t -isc_socket_send(isc_socket_t *sock, isc_region_t *region, - isc_task_t *task, isc_taskaction_t action, const void *arg) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_send(isc_socket_t *sock, isc_region_t *region, + isc_task_t *task, isc_taskaction_t action, const void *arg) { /* * REQUIRE() checking is performed in isc_socket_sendto(). */ - return (isc_socket_sendto(sock, region, task, action, arg, NULL, - NULL)); + return (isc__socket_sendto(sock, region, task, action, arg, NULL, + NULL)); } -isc_result_t -isc_socket_sendto(isc_socket_t *sock, isc_region_t *region, - isc_task_t *task, isc_taskaction_t action, const void *arg, - isc_sockaddr_t *address, struct in6_pktinfo *pktinfo) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_sendto(isc_socket_t *sock0, isc_region_t *region, + isc_task_t *task, isc_taskaction_t action, const void *arg, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo) { + isc__socket_t *sock = (isc__socket_t *)sock0; isc_socketevent_t *dev; - isc_socketmgr_t *manager; + isc__socketmgr_t *manager; REQUIRE(VALID_SOCKET(sock)); REQUIRE(region != NULL); @@ -4422,21 +4670,22 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region, return (socket_send(sock, dev, task, address, pktinfo, 0)); } -isc_result_t -isc_socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist, - isc_task_t *task, isc_taskaction_t action, const void *arg) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist, + isc_task_t *task, isc_taskaction_t action, const void *arg) { - return (isc_socket_sendtov(sock, buflist, task, action, arg, NULL, - NULL)); + return (isc__socket_sendtov(sock, buflist, task, action, arg, NULL, + NULL)); } -isc_result_t -isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist, - isc_task_t *task, isc_taskaction_t action, const void *arg, - isc_sockaddr_t *address, struct in6_pktinfo *pktinfo) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_sendtov(isc_socket_t *sock0, isc_bufferlist_t *buflist, + isc_task_t *task, isc_taskaction_t action, const void *arg, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo) { + isc__socket_t *sock = (isc__socket_t *)sock0; isc_socketevent_t *dev; - isc_socketmgr_t *manager; + isc__socketmgr_t *manager; unsigned int iocount; isc_buffer_t *buffer; @@ -4470,12 +4719,15 @@ isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist, return (socket_send(sock, dev, task, address, pktinfo, 0)); } -isc_result_t -isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region, - isc_task_t *task, - isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, - isc_socketevent_t *event, unsigned int flags) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_sendto2(isc_socket_t *sock0, isc_region_t *region, + isc_task_t *task, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, + isc_socketevent_t *event, unsigned int flags) { + isc__socket_t *sock = (isc__socket_t *)sock0; + + REQUIRE(VALID_SOCKET(sock)); REQUIRE((flags & ~(ISC_SOCKFLAG_IMMEDIATE|ISC_SOCKFLAG_NORETRY)) == 0); if ((flags & ISC_SOCKFLAG_NORETRY) != 0) REQUIRE(sock->type == isc_sockettype_udp); @@ -4490,8 +4742,8 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region, return (socket_send(sock, event, task, address, pktinfo, flags)); } -void -isc_socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active) { +ISC_SOCKETFUNC_SCOPE void +isc__socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active) { #ifdef ISC_PLATFORM_HAVESYSUNH int s; struct stat sb; @@ -4620,8 +4872,8 @@ isc_socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active) { #endif } -isc_result_t -isc_socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm, +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm, isc_uint32_t owner, isc_uint32_t group) { #ifdef ISC_PLATFORM_HAVESYSUNH @@ -4674,12 +4926,15 @@ isc_socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm, #endif } -isc_result_t -isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr, - unsigned int options) { +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_bind(isc_socket_t *sock0, isc_sockaddr_t *sockaddr, + unsigned int options) { + isc__socket_t *sock = (isc__socket_t *)sock0; char strbuf[ISC_STRERRORSIZE]; int on = 1; + REQUIRE(VALID_SOCKET(sock)); + LOCK(&sock->lock); INSIST(!sock->bound); @@ -4745,8 +5000,9 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr, */ #undef ENABLE_ACCEPTFILTER -isc_result_t -isc_socket_filter(isc_socket_t *sock, const char *filter) { +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_filter(isc_socket_t *sock0, const char *filter) { + isc__socket_t *sock = (isc__socket_t *)sock0; #if defined(SO_ACCEPTFILTER) && defined(ENABLE_ACCEPTFILTER) char strbuf[ISC_STRERRORSIZE]; struct accept_filter_arg afa; @@ -4784,8 +5040,9 @@ isc_socket_filter(isc_socket_t *sock, const char *filter) { * is a new connection we'll have to allocate a new one anyway, so we might * as well keep things simple rather than having to track them. */ -isc_result_t -isc_socket_listen(isc_socket_t *sock, unsigned int backlog) { +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_listen(isc_socket_t *sock0, unsigned int backlog) { + isc__socket_t *sock = (isc__socket_t *)sock0; char strbuf[ISC_STRERRORSIZE]; REQUIRE(VALID_SOCKET(sock)); @@ -4818,14 +5075,15 @@ isc_socket_listen(isc_socket_t *sock, unsigned int backlog) { /* * This should try to do aggressive accept() XXXMLG */ -isc_result_t -isc_socket_accept(isc_socket_t *sock, +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_accept(isc_socket_t *sock0, isc_task_t *task, isc_taskaction_t action, const void *arg) { + isc__socket_t *sock = (isc__socket_t *)sock0; isc_socket_newconnev_t *dev; - isc_socketmgr_t *manager; + isc__socketmgr_t *manager; isc_task_t *ntask = NULL; - isc_socket_t *nsock; + isc__socket_t *nsock; isc_result_t result; isc_boolean_t do_poke = ISC_FALSE; @@ -4872,7 +5130,7 @@ isc_socket_accept(isc_socket_t *sock, nsock->statsindex = sock->statsindex; dev->ev_sender = ntask; - dev->newsocket = nsock; + dev->newsocket = (isc_socket_t *)nsock; /* * Poke watcher here. We still have the socket locked, so there @@ -4891,13 +5149,14 @@ isc_socket_accept(isc_socket_t *sock, return (ISC_R_SUCCESS); } -isc_result_t -isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_connect(isc_socket_t *sock0, isc_sockaddr_t *addr, isc_task_t *task, isc_taskaction_t action, const void *arg) { + isc__socket_t *sock = (isc__socket_t *)sock0; isc_socket_connev_t *dev; isc_task_t *ntask = NULL; - isc_socketmgr_t *manager; + isc__socketmgr_t *manager; int cc; char strbuf[ISC_STRERRORSIZE]; char addrbuf[ISC_SOCKADDR_FORMATSIZE]; @@ -5037,7 +5296,7 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, */ static void internal_connect(isc_task_t *me, isc_event_t *ev) { - isc_socket_t *sock; + isc__socket_t *sock; isc_socket_connev_t *dev; isc_task_t *task; int cc; @@ -5151,8 +5410,9 @@ internal_connect(isc_task_t *me, isc_event_t *ev) { isc_task_sendanddetach(&task, ISC_EVENT_PTR(&dev)); } -isc_result_t -isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) { +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_getpeername(isc_socket_t *sock0, isc_sockaddr_t *addressp) { + isc__socket_t *sock = (isc__socket_t *)sock0; isc_result_t result; REQUIRE(VALID_SOCKET(sock)); @@ -5172,8 +5432,9 @@ isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) { return (result); } -isc_result_t -isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) { +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_getsockname(isc_socket_t *sock0, isc_sockaddr_t *addressp) { + isc__socket_t *sock = (isc__socket_t *)sock0; ISC_SOCKADDR_LEN_T len; isc_result_t result; char strbuf[ISC_STRERRORSIZE]; @@ -5210,8 +5471,9 @@ isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) { * Run through the list of events on this socket, and cancel the ones * queued for task "task" of type "how". "how" is a bitmask. */ -void -isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) { +ISC_SOCKETFUNC_SCOPE void +isc__socket_cancel(isc_socket_t *sock0, isc_task_t *task, unsigned int how) { + isc__socket_t *sock = (isc__socket_t *)sock0; REQUIRE(VALID_SOCKET(sock)); @@ -5290,8 +5552,8 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) { ISC_LIST_UNLINK(sock->accept_list, dev, ev_link); - dev->newsocket->references--; - free_socket(&dev->newsocket); + NEWCONNSOCK(dev)->references--; + free_socket((isc__socket_t **)&dev->newsocket); dev->result = ISC_R_CANCELED; dev->ev_sender = sock; @@ -5330,17 +5592,22 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) { UNLOCK(&sock->lock); } -isc_sockettype_t -isc_socket_gettype(isc_socket_t *sock) { +ISC_SOCKETFUNC_SCOPE isc_sockettype_t +isc__socket_gettype(isc_socket_t *sock0) { + isc__socket_t *sock = (isc__socket_t *)sock0; + REQUIRE(VALID_SOCKET(sock)); return (sock->type); } -isc_boolean_t -isc_socket_isbound(isc_socket_t *sock) { +ISC_SOCKETFUNC_SCOPE isc_boolean_t +isc__socket_isbound(isc_socket_t *sock0) { + isc__socket_t *sock = (isc__socket_t *)sock0; isc_boolean_t val; + REQUIRE(VALID_SOCKET(sock)); + LOCK(&sock->lock); val = ((sock->bound) ? ISC_TRUE : ISC_FALSE); UNLOCK(&sock->lock); @@ -5348,8 +5615,9 @@ isc_socket_isbound(isc_socket_t *sock) { return (val); } -void -isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) { +ISC_SOCKETFUNC_SCOPE void +isc__socket_ipv6only(isc_socket_t *sock0, isc_boolean_t yes) { + isc__socket_t *sock = (isc__socket_t *)sock0; #if defined(IPV6_V6ONLY) int onoff = yes ? 1 : 0; #else @@ -5379,12 +5647,21 @@ isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) { #endif } -#ifndef ISC_PLATFORM_USETHREADS -/* In our assumed scenario, we can simply use a single static object. */ +#ifndef USE_WATCHER_THREAD +/* + * In our assumed scenario, we can simply use a single static object. + * XXX: this is not true if the application uses multiple threads with + * 'multi-context' mode. Fixing this is a future TODO item. + */ static isc_socketwait_t swait_private; int -isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) { +isc__socketmgr_waitevents(isc_socketmgr_t *manager0, struct timeval *tvp, + isc_socketwait_t **swaitp) +{ + isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; + + int n; #ifdef USE_KQUEUE struct timespec ts, *tsp; @@ -5398,7 +5675,11 @@ isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) { REQUIRE(swaitp != NULL && *swaitp == NULL); - if (socketmgr == NULL) +#ifdef USE_SHARED_MANAGER + if (manager == NULL) + manager = socketmgr; +#endif + if (manager == NULL) return (0); #ifdef USE_KQUEUE @@ -5408,8 +5689,8 @@ isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) { tsp = &ts; } else tsp = NULL; - swait_private.nevents = kevent(socketmgr->kqueue_fd, NULL, 0, - socketmgr->events, socketmgr->nevents, + swait_private.nevents = kevent(manager->kqueue_fd, NULL, 0, + manager->events, manager->nevents, tsp); n = swait_private.nevents; #elif defined(USE_EPOLL) @@ -5417,29 +5698,28 @@ isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) { timeout = tvp->tv_sec * 1000 + (tvp->tv_usec + 999) / 1000; else timeout = -1; - swait_private.nevents = epoll_wait(socketmgr->epoll_fd, - socketmgr->events, - socketmgr->nevents, timeout); + swait_private.nevents = epoll_wait(manager->epoll_fd, + manager->events, + manager->nevents, timeout); n = swait_private.nevents; #elif defined(USE_DEVPOLL) - dvp.dp_fds = socketmgr->events; - dvp.dp_nfds = socketmgr->nevents; + dvp.dp_fds = manager->events; + dvp.dp_nfds = manager->nevents; if (tvp != NULL) { dvp.dp_timeout = tvp->tv_sec * 1000 + (tvp->tv_usec + 999) / 1000; } else dvp.dp_timeout = -1; - swait_private.nevents = ioctl(socketmgr->devpoll_fd, DP_POLL, &dvp); + swait_private.nevents = ioctl(manager->devpoll_fd, DP_POLL, &dvp); n = swait_private.nevents; #elif defined(USE_SELECT) - memcpy(socketmgr->read_fds_copy, socketmgr->read_fds, - socketmgr->fd_bufsize); - memcpy(socketmgr->write_fds_copy, socketmgr->write_fds, - socketmgr->fd_bufsize); + memcpy(manager->read_fds_copy, manager->read_fds, manager->fd_bufsize); + memcpy(manager->write_fds_copy, manager->write_fds, + manager->fd_bufsize); - swait_private.readset = socketmgr->read_fds_copy; - swait_private.writeset = socketmgr->write_fds_copy; - swait_private.maxfd = socketmgr->maxfd + 1; + swait_private.readset = manager->read_fds_copy; + swait_private.writeset = manager->write_fds_copy; + swait_private.maxfd = manager->maxfd + 1; n = select(swait_private.maxfd, swait_private.readset, swait_private.writeset, NULL, tvp); @@ -5450,24 +5730,32 @@ isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) { } isc_result_t -isc__socketmgr_dispatch(isc_socketwait_t *swait) { +isc__socketmgr_dispatch(isc_socketmgr_t *manager0, isc_socketwait_t *swait) { + isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; + REQUIRE(swait == &swait_private); - if (socketmgr == NULL) +#ifdef USE_SHARED_MANAGER + if (manager == NULL) + manager = socketmgr; +#endif + if (manager == NULL) return (ISC_R_NOTFOUND); #if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL) - (void)process_fds(socketmgr, socketmgr->events, swait->nevents); + (void)process_fds(manager, manager->events, swait->nevents); return (ISC_R_SUCCESS); #elif defined(USE_SELECT) - process_fds(socketmgr, swait->maxfd, swait->readset, swait->writeset); + process_fds(manager, swait->maxfd, swait->readset, swait->writeset); return (ISC_R_SUCCESS); #endif } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ +#ifdef BIND9 void -isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) { +isc__socket_setname(isc_socket_t *socket0, const char *name, void *tag) { + isc__socket_t *socket = (isc__socket_t *)socket0; /* * Name 'socket'. @@ -5482,17 +5770,29 @@ isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) { UNLOCK(&socket->lock); } -const char * -isc_socket_getname(isc_socket_t *socket) { +ISC_SOCKETFUNC_SCOPE const char * +isc__socket_getname(isc_socket_t *socket0) { + isc__socket_t *socket = (isc__socket_t *)socket0; + return (socket->name); } void * -isc_socket_gettag(isc_socket_t *socket) { +isc__socket_gettag(isc_socket_t *socket0) { + isc__socket_t *socket = (isc__socket_t *)socket0; + return (socket->tag); } +#endif /* BIND9 */ -#ifdef HAVE_LIBXML2 +#ifdef USE_SOCKETIMPREGISTER +isc_result_t +isc__socket_register() { + return (isc_socket_register(isc__socketmgr_create)); +} +#endif + +#if defined(HAVE_LIBXML2) && defined(BIND9) static const char * _socktype(isc_sockettype_t type) @@ -5509,21 +5809,21 @@ _socktype(isc_sockettype_t type) return ("not-initialized"); } -void -isc_socketmgr_renderxml(isc_socketmgr_t *mgr, xmlTextWriterPtr writer) -{ - isc_socket_t *sock; +ISC_SOCKETFUNC_SCOPE void +isc_socketmgr_renderxml(isc_socketmgr_t *mgr0, xmlTextWriterPtr writer) { + isc__socketmgr_t *mgr = (isc__socketmgr_t *)mgr0; + isc__socket_t *sock; char peerbuf[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_t addr; ISC_SOCKADDR_LEN_T len; LOCK(&mgr->lock); -#ifndef ISC_PLATFORM_USETHREADS +#ifdef USE_SHARED_MANAGER xmlTextWriterStartElement(writer, ISC_XMLCHAR "references"); xmlTextWriterWriteFormatString(writer, "%d", mgr->refs); xmlTextWriterEndElement(writer); -#endif +#endif /* USE_SHARED_MANAGER */ xmlTextWriterStartElement(writer, ISC_XMLCHAR "sockets"); sock = ISC_LIST_HEAD(mgr->socklist); diff --git a/lib/isc/unix/socket_p.h b/lib/isc/unix/socket_p.h index b9a2347..b6c4b6a 100644 --- a/lib/isc/unix/socket_p.h +++ b/lib/isc/unix/socket_p.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: socket_p.h,v 1.13 2008-06-23 23:47:11 tbox Exp $ */ +/* $Id: socket_p.h,v 1.15 2009-09-02 23:48:03 tbox Exp $ */ #ifndef ISC_SOCKET_P_H #define ISC_SOCKET_P_H @@ -27,6 +27,7 @@ #endif typedef struct isc_socketwait isc_socketwait_t; -int isc__socketmgr_waitevents(struct timeval *, isc_socketwait_t **); -isc_result_t isc__socketmgr_dispatch(isc_socketwait_t *); +int isc__socketmgr_waitevents(isc_socketmgr_t *, struct timeval *, + isc_socketwait_t **); +isc_result_t isc__socketmgr_dispatch(isc_socketmgr_t *, isc_socketwait_t *); #endif /* ISC_SOCKET_P_H */ diff --git a/lib/isc/unix/strerror.c b/lib/isc/unix/strerror.c index 08ea52d..4a61a97 100644 --- a/lib/isc/unix/strerror.c +++ b/lib/isc/unix/strerror.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: strerror.c,v 1.8.332.2 2009-02-16 23:47:15 tbox Exp $ */ +/* $Id: strerror.c,v 1.10 2009-02-16 23:48:04 tbox Exp $ */ /*! \file */ diff --git a/lib/isccc/Makefile.in b/lib/isccc/Makefile.in index fb08fcd..1417172 100644 --- a/lib/isccc/Makefile.in +++ b/lib/isccc/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2007, 2009, 2011 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 2001, 2003 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.9 2007-06-19 23:47:21 tbox Exp $ +# $Id: Makefile.in,v 1.12.244.1.2.1 2011-06-02 23:47:37 tbox Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -71,7 +71,7 @@ libisccc.la: ${OBJS} ${LIBTOOL_MODE_LINK} \ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisccc.la -rpath ${libdir} \ -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ - ${OBJS} ${LIBS} ${ISCLIBS} + ${OBJS} ${ISCLIBS} ${LIBS} timestamp: libisccc.@A@ touch timestamp diff --git a/lib/isccc/api b/lib/isccc/api index 2240cdd..94575eb 100644 --- a/lib/isccc/api +++ b/lib/isccc/api @@ -1,3 +1,3 @@ -LIBINTERFACE = 50 -LIBREVISION = 1 +LIBINTERFACE = 80 +LIBREVISION = 0 LIBAGE = 0 diff --git a/lib/isccfg/Makefile.in b/lib/isccfg/Makefile.in index 4c55a16..37b0a26 100644 --- a/lib/isccfg/Makefile.in +++ b/lib/isccfg/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2005, 2007, 2009, 2011 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 2001-2003 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.18 2007-06-19 23:47:22 tbox Exp $ +# $Id: Makefile.in,v 1.21.244.1.2.1 2011-06-02 23:47:37 tbox Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -27,7 +27,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = -I. ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCFG_INCLUDES} -CDEFINES = @USE_DLZ@ +CDEFINES = @USE_DLZ@ CWARNINGS = ISCLIBS = ../../lib/isc/libisc.@A@ @@ -68,7 +68,7 @@ libisccfg.la: ${OBJS} ${LIBTOOL_MODE_LINK} \ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisccfg.la -rpath ${libdir} \ -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ - ${OBJS} ${LIBS} ${DNSLIBS} ${ISCCCLIBS} ${ISCLIBS} + ${OBJS} ${DNSLIBS} ${ISCCCLIBS} ${ISCLIBS} ${LIBS} timestamp: libisccfg.@A@ touch timestamp diff --git a/lib/isccfg/aclconf.c b/lib/isccfg/aclconf.c index 6bf0ad8..44d436a4 100644 --- a/lib/isccfg/aclconf.c +++ b/lib/isccfg/aclconf.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: aclconf.c,v 1.22.34.4 2009-10-01 23:47:17 tbox Exp $ */ +/* $Id: aclconf.c,v 1.29 2010-08-13 23:47:03 tbox Exp $ */ #include @@ -39,7 +39,7 @@ cfg_aclconfctx_init(cfg_aclconfctx_t *ctx) { } void -cfg_aclconfctx_destroy(cfg_aclconfctx_t *ctx) { +cfg_aclconfctx_clear(cfg_aclconfctx_t *ctx) { dns_acl_t *dacl, *next; for (dacl = ISC_LIST_HEAD(ctx->named_acl_cache); @@ -51,6 +51,23 @@ cfg_aclconfctx_destroy(cfg_aclconfctx_t *ctx) { } } +void +cfg_aclconfctx_clone(cfg_aclconfctx_t *src, cfg_aclconfctx_t *dest) { + dns_acl_t *dacl, *next; + REQUIRE(src != NULL && dest != NULL); + + cfg_aclconfctx_init(dest); + for (dacl = ISC_LIST_HEAD(src->named_acl_cache); + dacl != NULL; + dacl = next) + { + dns_acl_t *copy; + next = ISC_LIST_NEXT(dacl, nextincache); + dns_acl_attach(dacl, ©); + ISC_LIST_APPEND(dest->named_acl_cache, copy, nextincache); + } +} + /* * Find the definition of the named acl whose name is "name". */ @@ -150,7 +167,7 @@ convert_keyname(const cfg_obj_t *keyobj, isc_log_t *lctx, isc_mem_t *mctx, isc_buffer_add(&buf, keylen); dns_fixedname_init(&fixname); result = dns_name_fromtext(dns_fixedname_name(&fixname), &buf, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { cfg_obj_log(keyobj, lctx, ISC_LOG_WARNING, "key name '%s' is not a valid domain name", diff --git a/lib/isccfg/api b/lib/isccfg/api index fbbf923..7821c32 100644 --- a/lib/isccfg/api +++ b/lib/isccfg/api @@ -1,3 +1,3 @@ -LIBINTERFACE = 50 -LIBREVISION = 3 -LIBAGE = 0 +LIBINTERFACE = 81 +LIBREVISION = 1 +LIBAGE = 1 diff --git a/lib/isccfg/dnsconf.c b/lib/isccfg/dnsconf.c new file mode 100644 index 0000000..7091d63 --- /dev/null +++ b/lib/isccfg/dnsconf.c @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: dnsconf.c,v 1.4 2009-09-02 23:48:03 tbox Exp $ */ + +/*! \file */ + +#include + +#include +#include + +/*% + * A trusted key, as used in the "trusted-keys" statement. + */ +static cfg_tuplefielddef_t trustedkey_fields[] = { + { "name", &cfg_type_astring, 0 }, + { "flags", &cfg_type_uint32, 0 }, + { "protocol", &cfg_type_uint32, 0 }, + { "algorithm", &cfg_type_uint32, 0 }, + { "key", &cfg_type_qstring, 0 }, + { NULL, NULL, 0 } +}; + +static cfg_type_t cfg_type_trustedkey = { + "trustedkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, + &cfg_rep_tuple, trustedkey_fields +}; + +static cfg_type_t cfg_type_trustedkeys = { + "trusted-keys", cfg_parse_bracketed_list, cfg_print_bracketed_list, + cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_trustedkey +}; + +/*% + * Clauses that can be found within the top level of the dns.conf + * file only. + */ +static cfg_clausedef_t +dnsconf_clauses[] = { + { "trusted-keys", &cfg_type_trustedkeys, CFG_CLAUSEFLAG_MULTI }, + { NULL, NULL, 0 } +}; + +/*% The top-level dns.conf syntax. */ + +static cfg_clausedef_t * +dnsconf_clausesets[] = { + dnsconf_clauses, + NULL +}; + +LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_dnsconf = { + "dnsconf", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody, + &cfg_rep_map, dnsconf_clausesets +}; diff --git a/lib/isccfg/include/isccfg/aclconf.h b/lib/isccfg/include/isccfg/aclconf.h index f2ab70f..49aef03 100644 --- a/lib/isccfg/include/isccfg/aclconf.h +++ b/lib/isccfg/include/isccfg/aclconf.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: aclconf.h,v 1.10 2007-10-12 04:17:18 each Exp $ */ +/* $Id: aclconf.h,v 1.12 2010-08-13 23:47:04 tbox Exp $ */ #ifndef ISCCFG_ACLCONF_H #define ISCCFG_ACLCONF_H 1 @@ -44,9 +44,15 @@ cfg_aclconfctx_init(cfg_aclconfctx_t *ctx); */ void -cfg_aclconfctx_destroy(cfg_aclconfctx_t *ctx); +cfg_aclconfctx_clone(cfg_aclconfctx_t *src, cfg_aclconfctx_t *dest); /* - * Destroy an ACL configuration context. + * Copy the contents of one ACL configuration context into another. + */ + +void +cfg_aclconfctx_clear(cfg_aclconfctx_t *ctx); +/* + * Clear the contents of an ACL configuration context. */ isc_result_t diff --git a/lib/isccfg/include/isccfg/cfg.h b/lib/isccfg/include/isccfg/cfg.h index 06efa35..82900d6 100644 --- a/lib/isccfg/include/isccfg/cfg.h +++ b/lib/isccfg/include/isccfg/cfg.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: cfg.h,v 1.44 2007-10-12 04:17:18 each Exp $ */ +/* $Id: cfg.h,v 1.46 2010-08-13 23:47:04 tbox Exp $ */ #ifndef ISCCFG_CFG_H #define ISCCFG_CFG_H 1 @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -70,7 +71,7 @@ typedef struct cfg_obj cfg_obj_t; typedef struct cfg_listelt cfg_listelt_t; /*% - * A callback function to be called when parsing an option + * A callback function to be called when parsing an option * that needs to be interpreted at parsing time, like * "directory". */ @@ -83,6 +84,12 @@ typedef isc_result_t ISC_LANG_BEGINDECLS +void +cfg_parser_attach(cfg_parser_t *src, cfg_parser_t **dest); +/*%< + * Reference a parser object. + */ + isc_result_t cfg_parser_create(isc_mem_t *mctx, isc_log_t *lctx, cfg_parser_t **ret); /*%< @@ -123,7 +130,7 @@ cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer, * (isc_parse_buffer()). * * Returns an error if the file does not parse correctly. - * + * * Requires: *\li "filename" is valid. *\li "mem" is valid. @@ -140,13 +147,14 @@ cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer, void cfg_parser_destroy(cfg_parser_t **pctxp); /*%< - * Destroy a configuration parser. + * Remove a reference to a configuration parser; destroy it if there are no + * more references. */ isc_boolean_t cfg_obj_isvoid(const cfg_obj_t *obj); /*%< - * Return true iff 'obj' is of void type (e.g., an optional + * Return true iff 'obj' is of void type (e.g., an optional * value not specified). */ @@ -355,7 +363,7 @@ cfg_list_length(const cfg_obj_t *obj, isc_boolean_t recurse); * all contained lists. */ -const cfg_obj_t * +cfg_obj_t * cfg_listelt_value(const cfg_listelt_t *elt); /*%< * Returns the configuration object associated with cfg_listelt_t. @@ -389,17 +397,25 @@ cfg_print_grammar(const cfg_type_t *type, isc_boolean_t cfg_obj_istype(const cfg_obj_t *obj, const cfg_type_t *type); /*%< - * Return true iff 'obj' is of type 'type'. + * Return true iff 'obj' is of type 'type'. */ -void cfg_obj_destroy(cfg_parser_t *pctx, cfg_obj_t **obj); +void +cfg_obj_attach(cfg_obj_t *src, cfg_obj_t **dest); +/*%< + * Reference a configuration object. + */ + +void +cfg_obj_destroy(cfg_parser_t *pctx, cfg_obj_t **obj); /*%< - * Destroy a configuration object. + * Delete a reference to a configuration object; destroy the object if + * there are no more references. */ void cfg_obj_log(const cfg_obj_t *obj, isc_log_t *lctx, int level, - const char *fmt, ...) + const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5); /*%< * Log a message concerning configuration object 'obj' to the logging diff --git a/lib/isccfg/include/isccfg/dnsconf.h b/lib/isccfg/include/isccfg/dnsconf.h new file mode 100644 index 0000000..bb71338 --- /dev/null +++ b/lib/isccfg/include/isccfg/dnsconf.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: dnsconf.h,v 1.3 2009-09-02 23:48:03 tbox Exp $ */ + +#ifndef ISCCFG_NAMEDCONF_H +#define ISCCFG_NAMEDCONF_H 1 + +/*! \file + * \brief + * This module defines the named.conf, rndc.conf, and rndc.key grammars. + */ + +#include + +/* + * Configuration object types. + */ +LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_dnsconf; +/*%< A complete dns.conf file. */ + +#endif /* ISCCFG_CFG_H */ diff --git a/lib/isccfg/include/isccfg/grammar.h b/lib/isccfg/include/isccfg/grammar.h index b8b845b..afc95bc 100644 --- a/lib/isccfg/include/isccfg/grammar.h +++ b/lib/isccfg/include/isccfg/grammar.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2002, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: grammar.h,v 1.17 2008-09-25 04:02:39 tbox Exp $ */ +/* $Id: grammar.h,v 1.24 2011-01-04 23:47:14 tbox Exp $ */ #ifndef ISCCFG_GRAMMAR_H #define ISCCFG_GRAMMAR_H 1 @@ -53,6 +53,8 @@ #define CFG_CLAUSEFLAG_CALLBACK 0x00000020 /*% A option that is only used in testing. */ #define CFG_CLAUSEFLAG_TESTONLY 0x00000040 +/*% A configuration option that was not configured at compile time. */ +#define CFG_CLAUSEFLAG_NOTCONFIGURED 0x00000080 typedef struct cfg_clausedef cfg_clausedef_t; typedef struct cfg_tuplefielddef cfg_tuplefielddef_t; @@ -157,6 +159,7 @@ struct cfg_obj { isc_sockaddr_t sockaddr; cfg_netprefix_t netprefix; } value; + isc_refcount_t references; /*%< reference counter */ const char * file; unsigned int line; }; @@ -210,10 +213,21 @@ struct cfg_parser { */ unsigned int line; + /*% + * Parser context flags, used for maintaining state + * from one token to the next. + */ + unsigned int flags; + + /*%< Reference counter */ + isc_refcount_t references; + cfg_parsecallback_t callback; void *callbackarg; }; +/* Parser context flags */ +#define CFG_PCTX_SKIP 0x1 /*@{*/ /*% @@ -314,10 +328,16 @@ cfg_parse_rawport(cfg_parser_t *pctx, unsigned int flags, in_port_t *port); isc_result_t cfg_parse_sockaddr(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); +isc_result_t +cfg_parse_boolean(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); + void cfg_print_sockaddr(cfg_printer_t *pctx, const cfg_obj_t *obj); void +cfg_print_boolean(cfg_printer_t *pctx, const cfg_obj_t *obj); + +void cfg_doc_sockaddr(cfg_printer_t *pctx, const cfg_type_t *type); isc_result_t diff --git a/lib/isccfg/include/isccfg/log.h b/lib/isccfg/include/isccfg/log.h index f45e4c2..2c9dc12 100644 --- a/lib/isccfg/include/isccfg/log.h +++ b/lib/isccfg/include/isccfg/log.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: log.h,v 1.12.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: log.h,v 1.14 2009-01-18 23:48:14 tbox Exp $ */ #ifndef ISCCFG_LOG_H #define ISCCFG_LOG_H 1 diff --git a/lib/isccfg/include/isccfg/namedconf.h b/lib/isccfg/include/isccfg/namedconf.h index 34aa3e8..9242cf3 100644 --- a/lib/isccfg/include/isccfg/namedconf.h +++ b/lib/isccfg/include/isccfg/namedconf.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: namedconf.h,v 1.9.332.2 2009-06-25 23:47:28 tbox Exp $ */ +/* $Id: namedconf.h,v 1.18 2010-08-11 18:14:20 each Exp $ */ #ifndef ISCCFG_NAMEDCONF_H #define ISCCFG_NAMEDCONF_H 1 @@ -33,12 +33,24 @@ LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_namedconf; /*%< A complete named.conf file. */ +LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_bindkeys; +/*%< A bind.keys file. */ + +LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_newzones; +/*%< A new-zones file (for zones added by 'rndc addzone'). */ + +LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_addzoneconf; +/*%< A single zone passed via the addzone rndc command. */ + LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_rndcconf; /*%< A complete rndc.conf file. */ LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_rndckey; /*%< A complete rndc.key file. */ +LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_sessionkey; +/*%< A complete session.key file. */ + LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_keyref; /*%< A key reference, used as an ACL element */ diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index f291507..f80d34b 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2002, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: namedconf.c,v 1.92.44.2 2010-05-13 23:47:49 tbox Exp $ */ +/* $Id: namedconf.c,v 1.131.8.1 2011-02-03 05:50:08 marka Exp $ */ /*! \file */ @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -35,9 +36,9 @@ #define TOKEN_STRING(pctx) (pctx->token.value.as_textregion.base) /*% Check a return value. */ -#define CHECK(op) \ - do { result = (op); \ - if (result != ISC_R_SUCCESS) goto cleanup; \ +#define CHECK(op) \ + do { result = (op); \ + if (result != ISC_R_SUCCESS) goto cleanup; \ } while (0) /*% Clean up a configuration object if non-NULL. */ @@ -57,7 +58,17 @@ static isc_result_t parse_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); static isc_result_t -parse_optional_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); +parse_optional_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, + cfg_obj_t **ret); + +static isc_result_t +parse_updatepolicy(cfg_parser_t *pctx, const cfg_type_t *type, + cfg_obj_t **ret); +static void +print_updatepolicy(cfg_printer_t *pctx, const cfg_obj_t *obj); + +static void +doc_updatepolicy(cfg_printer_t *pctx, const cfg_type_t *type); static void print_keyvalue(cfg_printer_t *pctx, const cfg_obj_t *obj); @@ -111,6 +122,7 @@ static cfg_type_t cfg_type_zone; static cfg_type_t cfg_type_zoneopts; static cfg_type_t cfg_type_dynamically_loadable_zones; static cfg_type_t cfg_type_dynamically_loadable_zones_opts; +static cfg_type_t cfg_type_v4_aaaa; /* * Clauses that can be found in a 'dynamically loadable zones' statement @@ -241,30 +253,76 @@ static cfg_tuplefielddef_t pubkey_fields[] = { { NULL, NULL, 0 } }; static cfg_type_t cfg_type_pubkey = { - "pubkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, pubkey_fields }; + "pubkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, + &cfg_rep_tuple, pubkey_fields }; /*% * A list of RR types, used in grant statements. * Note that the old parser allows quotes around the RR type names. */ static cfg_type_t cfg_type_rrtypelist = { - "rrtypelist", cfg_parse_spacelist, cfg_print_spacelist, cfg_doc_terminal, - &cfg_rep_list, &cfg_type_astring + "rrtypelist", cfg_parse_spacelist, cfg_print_spacelist, + cfg_doc_terminal, &cfg_rep_list, &cfg_type_astring }; static const char *mode_enums[] = { "grant", "deny", NULL }; static cfg_type_t cfg_type_mode = { - "mode", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, &cfg_rep_string, - &mode_enums + "mode", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, + &cfg_rep_string, &mode_enums }; +static isc_result_t +parse_matchtype(cfg_parser_t *pctx, const cfg_type_t *type, + cfg_obj_t **ret) { + isc_result_t result; + + CHECK(cfg_peektoken(pctx, 0)); + if (pctx->token.type == isc_tokentype_string && + strcasecmp(TOKEN_STRING(pctx), "zonesub") == 0) { + pctx->flags |= CFG_PCTX_SKIP; + } + return (cfg_parse_enum(pctx, type, ret)); + + cleanup: + return (result); +} + +static isc_result_t +parse_matchname(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { + isc_result_t result; + cfg_obj_t *obj = NULL; + + if ((pctx->flags & CFG_PCTX_SKIP) != 0) { + pctx->flags &= ~CFG_PCTX_SKIP; + CHECK(cfg_parse_void(pctx, NULL, &obj)); + } else + result = cfg_parse_astring(pctx, type, &obj); + + *ret = obj; + cleanup: + return (result); +} + +static void +doc_matchname(cfg_printer_t *pctx, const cfg_type_t *type) { + cfg_print_chars(pctx, "[ ", 2); + cfg_doc_obj(pctx, type->of); + cfg_print_chars(pctx, " ]", 2); +} + static const char *matchtype_enums[] = { "name", "subdomain", "wildcard", "self", "selfsub", "selfwild", "krb5-self", "ms-self", "krb5-subdomain", "ms-subdomain", - "tcp-self", "6to4-self", NULL }; + "tcp-self", "6to4-self", "zonesub", "external", NULL }; + static cfg_type_t cfg_type_matchtype = { - "matchtype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, &cfg_rep_string, - &matchtype_enums + "matchtype", parse_matchtype, cfg_print_ustring, + cfg_doc_enum, &cfg_rep_string, &matchtype_enums +}; + +static cfg_type_t cfg_type_matchname = { + "optional_matchname", parse_matchname, cfg_print_ustring, + &doc_matchname, &cfg_rep_tuple, &cfg_type_ustring }; /*% @@ -274,18 +332,70 @@ static cfg_tuplefielddef_t grant_fields[] = { { "mode", &cfg_type_mode, 0 }, { "identity", &cfg_type_astring, 0 }, /* domain name */ { "matchtype", &cfg_type_matchtype, 0 }, - { "name", &cfg_type_astring, 0 }, /* domain name */ + { "name", &cfg_type_matchname, 0 }, /* domain name */ { "types", &cfg_type_rrtypelist, 0 }, { NULL, NULL, 0 } }; static cfg_type_t cfg_type_grant = { - "grant", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, grant_fields }; + "grant", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, + &cfg_rep_tuple, grant_fields +}; static cfg_type_t cfg_type_updatepolicy = { - "update_policy", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list, - &cfg_rep_list, &cfg_type_grant + "update_policy", parse_updatepolicy, print_updatepolicy, + doc_updatepolicy, &cfg_rep_list, &cfg_type_grant }; +static isc_result_t +parse_updatepolicy(cfg_parser_t *pctx, const cfg_type_t *type, + cfg_obj_t **ret) { + isc_result_t result; + CHECK(cfg_gettoken(pctx, 0)); + if (pctx->token.type == isc_tokentype_special && + pctx->token.value.as_char == '{') { + cfg_ungettoken(pctx); + return (cfg_parse_bracketed_list(pctx, type, ret)); + } + + if (pctx->token.type == isc_tokentype_string && + strcasecmp(TOKEN_STRING(pctx), "local") == 0) { + cfg_obj_t *obj = NULL; + CHECK(cfg_create_obj(pctx, &cfg_type_ustring, &obj)); + obj->value.string.length = strlen("local"); + obj->value.string.base = isc_mem_get(pctx->mctx, + obj->value.string.length + 1); + if (obj->value.string.base == NULL) { + isc_mem_put(pctx->mctx, obj, sizeof(*obj)); + return (ISC_R_NOMEMORY); + } + memcpy(obj->value.string.base, "local", 5); + obj->value.string.base[5] = '\0'; + *ret = obj; + return (ISC_R_SUCCESS); + } + + cfg_ungettoken(pctx); + return (ISC_R_UNEXPECTEDTOKEN); + + cleanup: + return (result); +} + +static void +print_updatepolicy(cfg_printer_t *pctx, const cfg_obj_t *obj) { + if (cfg_obj_isstring(obj)) + cfg_print_ustring(pctx, obj); + else + cfg_print_bracketed_list(pctx, obj); +} + +static void +doc_updatepolicy(cfg_printer_t *pctx, const cfg_type_t *type) { + cfg_print_cstr(pctx, "( local | { "); + cfg_doc_obj(pctx, type->of); + cfg_print_cstr(pctx, "; ... }"); +} + /*% * A view statement. */ @@ -296,7 +406,9 @@ static cfg_tuplefielddef_t view_fields[] = { { NULL, NULL, 0 } }; static cfg_type_t cfg_type_view = { - "view", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, view_fields }; + "view", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, + &cfg_rep_tuple, view_fields +}; /*% * A zone statement. @@ -308,7 +420,9 @@ static cfg_tuplefielddef_t zone_fields[] = { { NULL, NULL, 0 } }; static cfg_type_t cfg_type_zone = { - "zone", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, zone_fields }; + "zone", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, + &cfg_rep_tuple, zone_fields +}; /*% * A "category" clause in the "logging" statement. @@ -319,13 +433,15 @@ static cfg_tuplefielddef_t category_fields[] = { { NULL, NULL, 0 } }; static cfg_type_t cfg_type_category = { - "category", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, category_fields }; + "category", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, + &cfg_rep_tuple, category_fields +}; /*% - * A trusted key, as used in the "trusted-keys" statement. + * A dnssec key, as used in the "trusted-keys" statement. */ -static cfg_tuplefielddef_t trustedkey_fields[] = { +static cfg_tuplefielddef_t dnsseckey_fields[] = { { "name", &cfg_type_astring, 0 }, { "flags", &cfg_type_uint32, 0 }, { "protocol", &cfg_type_uint32, 0 }, @@ -333,9 +449,27 @@ static cfg_tuplefielddef_t trustedkey_fields[] = { { "key", &cfg_type_qstring, 0 }, { NULL, NULL, 0 } }; -static cfg_type_t cfg_type_trustedkey = { - "trustedkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, - trustedkey_fields +static cfg_type_t cfg_type_dnsseckey = { + "dnsseckey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, + &cfg_rep_tuple, dnsseckey_fields +}; + +/*% + * A managed key initialization specifier, as used in the + * "managed-keys" statement. + */ +static cfg_tuplefielddef_t managedkey_fields[] = { + { "name", &cfg_type_astring, 0 }, + { "init", &cfg_type_ustring, 0 }, /* must be literal "initial-key" */ + { "flags", &cfg_type_uint32, 0 }, + { "protocol", &cfg_type_uint32, 0 }, + { "algorithm", &cfg_type_uint32, 0 }, + { "key", &cfg_type_qstring, 0 }, + { NULL, NULL, 0 } +}; +static cfg_type_t cfg_type_managedkey = { + "managedkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, + &cfg_rep_tuple, managedkey_fields }; static keyword_type_t wild_class_kw = { "class", &cfg_type_ustring }; @@ -397,6 +531,7 @@ static cfg_tuplefielddef_t checknames_fields[] = { { "mode", &cfg_type_checkmode, 0 }, { NULL, NULL, 0 } }; + static cfg_type_t cfg_type_checknames = { "checknames", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, checknames_fields @@ -407,6 +542,13 @@ static cfg_type_t cfg_type_bracketed_sockaddrlist = { &cfg_rep_list, &cfg_type_sockaddr }; +static const char *autodnssec_enums[] = { "allow", "maintain", "create", + "off", NULL }; +static cfg_type_t cfg_type_autodnssec = { + "autodnssec", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, + &cfg_rep_string, &autodnssec_enums +}; + static cfg_type_t cfg_type_rrsetorder = { "rrsetorder", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_rrsetorderingelement @@ -421,13 +563,27 @@ static cfg_type_t cfg_type_optional_port = { /*% A list of keys, as in the "key" clause of the controls statement. */ static cfg_type_t cfg_type_keylist = { - "keylist", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list, - &cfg_type_astring + "keylist", cfg_parse_bracketed_list, cfg_print_bracketed_list, + cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_astring +}; + +/*% A list of dnssec keys, as in "trusted-keys" */ +static cfg_type_t cfg_type_dnsseckeys = { + "dnsseckeys", cfg_parse_bracketed_list, cfg_print_bracketed_list, + cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_dnsseckey }; -static cfg_type_t cfg_type_trustedkeys = { - "trusted-keys", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list, - &cfg_type_trustedkey +/*% + * A list of managed key entries, as in "trusted-keys". Currently + * (9.7.0) this has a format similar to dnssec keys, except the keyname + * is followed by the keyword "initial-key". In future releases, this + * keyword may take other values indicating different methods for the + * key to be initialized. + */ + +static cfg_type_t cfg_type_managedkeys = { + "managedkeys", cfg_parse_bracketed_list, cfg_print_bracketed_list, + cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_managedkey }; static const char *forwardtype_enums[] = { "first", "only", NULL }; @@ -437,7 +593,8 @@ static cfg_type_t cfg_type_forwardtype = { }; static const char *zonetype_enums[] = { - "master", "slave", "stub", "hint", "forward", "delegation-only", NULL }; + "master", "slave", "stub", "static-stub", "hint", "forward", + "delegation-only", NULL }; static cfg_type_t cfg_type_zonetype = { "zonetype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, &cfg_rep_string, &zonetype_enums @@ -479,6 +636,7 @@ parse_qstringornone(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { isc_result_t result; + CHECK(cfg_gettoken(pctx, CFG_LEXOPT_QSTRING)); if (pctx->token.type == isc_tokentype_string && strcasecmp(TOKEN_STRING(pctx), "none") == 0) @@ -496,13 +654,65 @@ doc_qstringornone(cfg_printer_t *pctx, const cfg_type_t *type) { } static cfg_type_t cfg_type_qstringornone = { - "qstringornone", parse_qstringornone, NULL, doc_qstringornone, NULL, NULL }; + "qstringornone", parse_qstringornone, NULL, doc_qstringornone, + NULL, NULL +}; /*% - * keyword hostname + * A boolean ("yes" or "no"), or the special keyword "auto". + * Used in the dnssec-validation option. */ +static void +print_auto(cfg_printer_t *pctx, const cfg_obj_t *obj) { + UNUSED(obj); + cfg_print_cstr(pctx, "auto"); +} + +static cfg_type_t cfg_type_auto = { + "auto", NULL, print_auto, NULL, &cfg_rep_void, NULL +}; + +static isc_result_t +parse_boolorauto(cfg_parser_t *pctx, const cfg_type_t *type, + cfg_obj_t **ret) +{ + isc_result_t result; + + CHECK(cfg_gettoken(pctx, CFG_LEXOPT_QSTRING)); + if (pctx->token.type == isc_tokentype_string && + strcasecmp(TOKEN_STRING(pctx), "auto") == 0) + return (cfg_create_obj(pctx, &cfg_type_auto, ret)); + cfg_ungettoken(pctx); + return (cfg_parse_boolean(pctx, type, ret)); + cleanup: + return (result); +} static void +print_boolorauto(cfg_printer_t *pctx, const cfg_obj_t *obj) { + if (obj->type->rep == &cfg_rep_void) + cfg_print_chars(pctx, "auto", 4); + else if (obj->value.boolean) + cfg_print_chars(pctx, "yes", 3); + else + cfg_print_chars(pctx, "no", 2); +} + +static void +doc_boolorauto(cfg_printer_t *pctx, const cfg_type_t *type) { + UNUSED(type); + cfg_print_cstr(pctx, "( yes | no | auto )"); +} + +static cfg_type_t cfg_type_boolorauto = { + "boolorauto", parse_boolorauto, print_boolorauto, + doc_boolorauto, NULL, NULL +}; + +/*% + * keyword hostname + */ +static void print_hostname(cfg_printer_t *pctx, const cfg_obj_t *obj) { UNUSED(obj); cfg_print_cstr(pctx, "hostname"); @@ -652,7 +862,18 @@ namedconf_or_view_clauses[] = { /* only 1 DLZ per view allowed */ { "dlz", &cfg_type_dynamically_loadable_zones, 0 }, { "server", &cfg_type_server, CFG_CLAUSEFLAG_MULTI }, - { "trusted-keys", &cfg_type_trustedkeys, CFG_CLAUSEFLAG_MULTI }, + { "trusted-keys", &cfg_type_dnsseckeys, CFG_CLAUSEFLAG_MULTI }, + { "managed-keys", &cfg_type_managedkeys, CFG_CLAUSEFLAG_MULTI }, + { NULL, NULL, 0 } +}; + +/*% + * Clauses that can occur in the bind.keys file. + */ +static cfg_clausedef_t +bindkeys_clauses[] = { + { "trusted-keys", &cfg_type_dnsseckeys, CFG_CLAUSEFLAG_MULTI }, + { "managed-keys", &cfg_type_managedkeys, CFG_CLAUSEFLAG_MULTI }, { NULL, NULL, 0 } }; @@ -661,18 +882,21 @@ namedconf_or_view_clauses[] = { */ static cfg_clausedef_t options_clauses[] = { - { "use-v4-udp-ports", &cfg_type_bracketed_portlist, 0 }, - { "use-v6-udp-ports", &cfg_type_bracketed_portlist, 0 }, { "avoid-v4-udp-ports", &cfg_type_bracketed_portlist, 0 }, { "avoid-v6-udp-ports", &cfg_type_bracketed_portlist, 0 }, + { "bindkeys-file", &cfg_type_qstring, 0 }, { "blackhole", &cfg_type_bracketed_aml, 0 }, { "coresize", &cfg_type_size, 0 }, { "datasize", &cfg_type_size, 0 }, + { "session-keyfile", &cfg_type_qstringornone, 0 }, + { "session-keyname", &cfg_type_astring, 0 }, + { "session-keyalg", &cfg_type_astring, 0 }, { "deallocate-on-exit", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, { "directory", &cfg_type_qstring, CFG_CLAUSEFLAG_CALLBACK }, { "dump-file", &cfg_type_qstring, 0 }, { "fake-iquery", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, { "files", &cfg_type_size, 0 }, + { "flush-zones-on-shutdown", &cfg_type_boolean, 0 }, { "has-old-clients", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, { "heartbeat-interval", &cfg_type_uint32, 0 }, { "host-statistics", &cfg_type_boolean, CFG_CLAUSEFLAG_NOTIMP }, @@ -681,6 +905,7 @@ options_clauses[] = { { "interface-interval", &cfg_type_uint32, 0 }, { "listen-on", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI }, { "listen-on-v6", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI }, + { "managed-keys-directory", &cfg_type_qstring, 0 }, { "match-mapped-addresses", &cfg_type_boolean, 0 }, { "memstatistics-file", &cfg_type_qstring, 0 }, { "memstatistics", &cfg_type_boolean, 0 }, @@ -693,6 +918,7 @@ options_clauses[] = { { "random-device", &cfg_type_qstring, 0 }, { "recursive-clients", &cfg_type_uint32, 0 }, { "reserved-sockets", &cfg_type_uint32, 0 }, + { "secroots-file", &cfg_type_qstring, 0 }, { "serial-queries", &cfg_type_uint32, CFG_CLAUSEFLAG_OBSOLETE }, { "serial-query-rate", &cfg_type_uint32, 0 }, { "server-id", &cfg_type_serverid, 0 }, @@ -703,6 +929,7 @@ options_clauses[] = { { "tcp-listen-queue", &cfg_type_uint32, 0 }, { "tkey-dhkey", &cfg_type_tkey_dhkey, 0 }, { "tkey-gssapi-credential", &cfg_type_qstring, 0 }, + { "tkey-gssapi-keytab", &cfg_type_qstring, 0 }, { "tkey-domain", &cfg_type_qstring, 0 }, { "transfers-per-ns", &cfg_type_uint32, 0 }, { "transfers-in", &cfg_type_uint32, 0 }, @@ -710,12 +937,12 @@ options_clauses[] = { { "treat-cr-as-space", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, { "use-id-pool", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, { "use-ixfr", &cfg_type_boolean, 0 }, + { "use-v4-udp-ports", &cfg_type_bracketed_portlist, 0 }, + { "use-v6-udp-ports", &cfg_type_bracketed_portlist, 0 }, { "version", &cfg_type_qstringornone, 0 }, - { "flush-zones-on-shutdown", &cfg_type_boolean, 0 }, { NULL, NULL, 0 } }; - static cfg_type_t cfg_type_namelist = { "namelist", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_qstring }; @@ -726,6 +953,34 @@ static cfg_type_t cfg_type_optional_exclude = { "optional_exclude", parse_optional_keyvalue, print_keyvalue, doc_optional_keyvalue, &cfg_rep_list, &exclude_kw }; +static keyword_type_t exceptionnames_kw = { "except-from", &cfg_type_namelist }; + +static cfg_type_t cfg_type_optional_exceptionnames = { + "optional_allow", parse_optional_keyvalue, print_keyvalue, + doc_optional_keyvalue, &cfg_rep_list, &exceptionnames_kw }; + +static cfg_tuplefielddef_t denyaddresses_fields[] = { + { "acl", &cfg_type_bracketed_aml, 0 }, + { "except-from", &cfg_type_optional_exceptionnames, 0 }, + { NULL, NULL, 0 } +}; + +static cfg_type_t cfg_type_denyaddresses = { + "denyaddresses", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, + &cfg_rep_tuple, denyaddresses_fields +}; + +static cfg_tuplefielddef_t denyaliases_fields[] = { + { "name", &cfg_type_namelist, 0 }, + { "except-from", &cfg_type_optional_exceptionnames, 0 }, + { NULL, NULL, 0 } +}; + +static cfg_type_t cfg_type_denyaliases = { + "denyaliases", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, + &cfg_rep_tuple, denyaliases_fields +}; + static cfg_type_t cfg_type_algorithmlist = { "algorithmlist", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_astring }; @@ -758,20 +1013,134 @@ static cfg_type_t cfg_type_masterformat = { &cfg_rep_string, &masterformat_enums }; + + +/* + * response-policy { + * zone [ policy (given|no-op|nxdomain|nodata|cname ) ]; + * }; + * + * this is a chimera of doc_optional_keyvalue() and cfg_doc_enum() + */ +static void +doc_rpz_policies(cfg_printer_t *pctx, const cfg_type_t *type) { + const keyword_type_t *kw; + const char * const *p; + + kw = type->of; + cfg_print_chars(pctx, "[ ", 2); + cfg_print_cstr(pctx, kw->name); + cfg_print_chars(pctx, " ", 1); + + cfg_print_chars(pctx, "( ", 2); + for (p = kw->type->of; *p != NULL; p++) { + cfg_print_cstr(pctx, *p); + if (p[1] != NULL) + cfg_print_chars(pctx, " | ", 3); + } +} + +/* + * print_qstring() from parser.c + */ +static void +print_rpz_cname(cfg_printer_t *pctx, const cfg_obj_t *obj) +{ + cfg_print_chars(pctx, "\"", 1); + cfg_print_ustring(pctx, obj); + cfg_print_chars(pctx, "\"", 1); +} + +static void +doc_rpz_cname(cfg_printer_t *pctx, const cfg_type_t *type) { + cfg_doc_terminal(pctx, type); + cfg_print_chars(pctx, " ) ]", 4); +} + +static isc_result_t +parse_rpz(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { + isc_result_t result; + cfg_obj_t *obj = NULL; + const cfg_tuplefielddef_t *fields = type->of; + + CHECK(cfg_create_tuple(pctx, type, &obj)); + CHECK(cfg_parse_obj(pctx, fields[0].type, &obj->value.tuple[0])); + CHECK(cfg_parse_obj(pctx, fields[1].type, &obj->value.tuple[1])); + /* + * parse cname domain only after "policy cname" + */ + if (cfg_obj_isvoid(obj->value.tuple[1]) || + strcasecmp("cname", cfg_obj_asstring(obj->value.tuple[1]))) { + CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[2])); + } else { + CHECK(cfg_parse_obj(pctx, fields[2].type, &obj->value.tuple[2])); + } + + *ret = obj; + return (ISC_R_SUCCESS); + +cleanup: + CLEANUP_OBJ(obj); + return (result); +} + +static const char *rpz_policies[] = { + "given", "no-op", "nxdomain", "nodata", "cname", NULL +}; +static cfg_type_t cfg_type_rpz_policylist = { + "policies", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, + &cfg_rep_string, &rpz_policies +}; +static keyword_type_t rpz_policies_kw = { + "policy", &cfg_type_rpz_policylist +}; +static cfg_type_t cfg_type_rpz_policy = { + "optional_policy", parse_optional_keyvalue, print_keyvalue, + doc_rpz_policies, &cfg_rep_string, &rpz_policies_kw +}; +static cfg_type_t cfg_type_cname = { + "domain", cfg_parse_astring, print_rpz_cname, doc_rpz_cname, + &cfg_rep_string, NULL +}; +static cfg_tuplefielddef_t rpzone_fields[] = { + { "name", &cfg_type_astring, 0 }, + { "policy", &cfg_type_rpz_policy, 0 }, + { "cname", &cfg_type_cname, 0 }, + { NULL, NULL, 0 } +}; +static cfg_type_t cfg_type_rpzone = { + "rpzone", parse_rpz, cfg_print_tuple, cfg_doc_tuple, + &cfg_rep_tuple, rpzone_fields +}; +static cfg_clausedef_t rpz_clauses[] = { + { "zone", &cfg_type_rpzone, CFG_CLAUSEFLAG_MULTI }, + { NULL, NULL, 0 } +}; +static cfg_clausedef_t *rpz_clausesets[] = { + rpz_clauses, + NULL +}; +static cfg_type_t cfg_type_rpz = { + "rpz", cfg_parse_map, cfg_print_map, cfg_doc_map, + &cfg_rep_map, rpz_clausesets +}; + + + /*% * dnssec-lookaside */ static keyword_type_t trustanchor_kw = { "trust-anchor", &cfg_type_astring }; -static cfg_type_t cfg_type_trustanchor = { - "trust-anchor", parse_keyvalue, print_keyvalue, doc_keyvalue, - &cfg_rep_string, &trustanchor_kw +static cfg_type_t cfg_type_optional_trustanchor = { + "optional_trustanchor", parse_optional_keyvalue, print_keyvalue, + doc_keyvalue, &cfg_rep_string, &trustanchor_kw }; static cfg_tuplefielddef_t lookaside_fields[] = { { "domain", &cfg_type_astring, 0 }, - { "trust-anchor", &cfg_type_trustanchor, 0 }, + { "trust-anchor", &cfg_type_optional_trustanchor, 0 }, { NULL, NULL, 0 } }; @@ -780,6 +1149,31 @@ static cfg_type_t cfg_type_lookaside = { &cfg_rep_tuple, lookaside_fields }; +/* + * DNS64. + */ +static cfg_clausedef_t +dns64_clauses[] = { + { "clients", &cfg_type_bracketed_aml, 0 }, + { "mapped", &cfg_type_bracketed_aml, 0 }, + { "exclude", &cfg_type_bracketed_aml, 0 }, + { "suffix", &cfg_type_netaddr6, 0 }, + { "recursive-only", &cfg_type_boolean, 0 }, + { "break-dnssec", &cfg_type_boolean, 0 }, + { NULL, NULL, 0 }, +}; + +static cfg_clausedef_t * +dns64_clausesets[] = { + dns64_clauses, + NULL +}; + +static cfg_type_t cfg_type_dns64 = { + "dns64", cfg_parse_netprefix_map, cfg_print_map, cfg_doc_map, + &cfg_rep_map, dns64_clausesets +}; + /*% * Clauses that can be found within the 'view' statement, * with defaults in the 'options' statement. @@ -791,26 +1185,33 @@ view_clauses[] = { { "acache-enable", &cfg_type_boolean, 0 }, { "additional-from-auth", &cfg_type_boolean, 0 }, { "additional-from-cache", &cfg_type_boolean, 0 }, + { "allow-new-zones", &cfg_type_boolean, 0 }, { "allow-query-cache", &cfg_type_bracketed_aml, 0 }, { "allow-query-cache-on", &cfg_type_bracketed_aml, 0 }, { "allow-recursion", &cfg_type_bracketed_aml, 0 }, { "allow-recursion-on", &cfg_type_bracketed_aml, 0 }, { "allow-v6-synthesis", &cfg_type_bracketed_aml, CFG_CLAUSEFLAG_OBSOLETE }, + { "attach-cache", &cfg_type_astring, 0 }, { "auth-nxdomain", &cfg_type_boolean, CFG_CLAUSEFLAG_NEWDEFAULT }, { "cache-file", &cfg_type_qstring, 0 }, { "check-names", &cfg_type_checknames, CFG_CLAUSEFLAG_MULTI }, { "cleaning-interval", &cfg_type_uint32, 0 }, { "clients-per-query", &cfg_type_uint32, 0 }, + { "deny-answer-addresses", &cfg_type_denyaddresses, 0 }, + { "deny-answer-aliases", &cfg_type_denyaliases, 0 }, { "disable-algorithms", &cfg_type_disablealgorithm, CFG_CLAUSEFLAG_MULTI }, { "disable-empty-zone", &cfg_type_astring, CFG_CLAUSEFLAG_MULTI }, + { "dns64", &cfg_type_dns64, CFG_CLAUSEFLAG_MULTI }, + { "dns64-server", &cfg_type_astring, 0 }, + { "dns64-contact", &cfg_type_astring, 0 }, { "dnssec-accept-expired", &cfg_type_boolean, 0 }, { "dnssec-enable", &cfg_type_boolean, 0 }, { "dnssec-lookaside", &cfg_type_lookaside, CFG_CLAUSEFLAG_MULTI }, { "dnssec-must-be-secure", &cfg_type_mustbesecure, CFG_CLAUSEFLAG_MULTI }, - { "dnssec-validation", &cfg_type_boolean, 0 }, + { "dnssec-validation", &cfg_type_boolorauto, 0 }, { "dual-stack-servers", &cfg_type_nameportiplist, 0 }, { "edns-udp-size", &cfg_type_uint32, 0 }, { "empty-contact", &cfg_type_astring, 0 }, @@ -841,6 +1242,7 @@ view_clauses[] = { { "recursion", &cfg_type_boolean, 0 }, { "request-ixfr", &cfg_type_boolean, 0 }, { "request-nsid", &cfg_type_boolean, 0 }, + { "resolver-query-timeout", &cfg_type_uint32, 0 }, { "rfc2308-type1", &cfg_type_boolean, CFG_CLAUSEFLAG_NYI }, { "root-delegation-only", &cfg_type_optional_exclude, 0 }, { "rrset-order", &cfg_type_rrsetorder, 0 }, @@ -850,6 +1252,16 @@ view_clauses[] = { { "transfer-format", &cfg_type_transferformat, 0 }, { "use-queryport-pool", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, { "zero-no-soa-ttl-cache", &cfg_type_boolean, 0 }, +#ifdef ALLOW_FILTER_AAAA_ON_V4 + { "filter-aaaa", &cfg_type_bracketed_aml, 0 }, + { "filter-aaaa-on-v4", &cfg_type_v4_aaaa, 0 }, +#else + { "filter-aaaa", &cfg_type_bracketed_aml, + CFG_CLAUSEFLAG_NOTCONFIGURED }, + { "filter-aaaa-on-v4", &cfg_type_v4_aaaa, + CFG_CLAUSEFLAG_NOTCONFIGURED }, +#endif + { "response-policy", &cfg_type_rpz, 0 }, { NULL, NULL, 0 } }; @@ -920,6 +1332,7 @@ zone_clauses[] = { { "also-notify", &cfg_type_portiplist, 0 }, { "alt-transfer-source", &cfg_type_sockaddr4wild, 0 }, { "alt-transfer-source-v6", &cfg_type_sockaddr6wild, 0 }, + { "check-dup-records", &cfg_type_checkmode, 0 }, { "check-integrity", &cfg_type_boolean, 0 }, { "check-mx", &cfg_type_checkmode, 0 }, { "check-mx-cname", &cfg_type_checkmode, 0 }, @@ -927,6 +1340,8 @@ zone_clauses[] = { { "check-srv-cname", &cfg_type_checkmode, 0 }, { "check-wildcard", &cfg_type_boolean, 0 }, { "dialup", &cfg_type_dialuptype, 0 }, + { "dnssec-dnskey-kskonly", &cfg_type_boolean, 0 }, + { "dnssec-secure-to-insecure", &cfg_type_boolean, 0 }, { "forward", &cfg_type_forwardtype, 0 }, { "forwarders", &cfg_type_portiplist, 0 }, { "key-directory", &cfg_type_qstring, 0 }, @@ -986,6 +1401,9 @@ zone_only_clauses[] = { */ { "check-names", &cfg_type_checkmode, 0 }, { "ixfr-from-differences", &cfg_type_boolean, 0 }, + { "auto-dnssec", &cfg_type_autodnssec, 0 }, + { "server-addresses", &cfg_type_bracketed_sockaddrlist, 0 }, + { "server-names", &cfg_type_namelist, 0 }, { NULL, NULL, 0 } }; @@ -998,12 +1416,40 @@ namedconf_clausesets[] = { namedconf_or_view_clauses, NULL }; - LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_namedconf = { "namedconf", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody, &cfg_rep_map, namedconf_clausesets }; +/*% The bind.keys syntax (trusted-keys/managed-keys only). */ +static cfg_clausedef_t * +bindkeys_clausesets[] = { + bindkeys_clauses, + NULL +}; +LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_bindkeys = { + "bindkeys", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody, + &cfg_rep_map, bindkeys_clausesets +}; + +/*% The new-zone-file syntax (for zones added by 'rndc addzone') */ +static cfg_clausedef_t +newzones_clauses[] = { + { "zone", &cfg_type_zone, CFG_CLAUSEFLAG_MULTI }, + { NULL, NULL, 0 } +}; + +static cfg_clausedef_t * +newzones_clausesets[] = { + newzones_clauses, + NULL +}; + +LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_newzones = { + "newzones", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody, + &cfg_rep_map, newzones_clausesets +}; + /*% The "options" statement syntax. */ static cfg_clausedef_t * @@ -1166,6 +1612,38 @@ static cfg_type_t cfg_type_logging = { "logging", cfg_parse_map, cfg_print_map, cfg_doc_map, &cfg_rep_map, logging_clausesets }; +/*% + * For parsing an 'addzone' statement + */ + +static cfg_tuplefielddef_t addzone_fields[] = { + { "name", &cfg_type_astring, 0 }, + { "class", &cfg_type_optional_class, 0 }, + { "view", &cfg_type_optional_class, 0 }, + { "options", &cfg_type_zoneopts, 0 }, + { NULL, NULL, 0 } +}; +static cfg_type_t cfg_type_addzone = { + "addzone", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, addzone_fields }; + +static cfg_clausedef_t +addzoneconf_clauses[] = { + { "addzone", &cfg_type_addzone, 0 }, + { NULL, NULL, 0 } +}; + +static cfg_clausedef_t * +addzoneconf_clausesets[] = { + addzoneconf_clauses, + NULL +}; + +LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_addzoneconf = { + "addzoneconf", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody, + &cfg_rep_map, addzoneconf_clausesets +}; + + static isc_result_t parse_unitstring(char *str, isc_resourcevalue_t *valuep) { char *endp; @@ -1385,6 +1863,17 @@ static cfg_type_t cfg_type_ixfrdifftype = { &cfg_rep_string, ixfrdiff_enums, }; +static const char *v4_aaaa_enums[] = { "break-dnssec", NULL }; +static isc_result_t +parse_v4_aaaa(cfg_parser_t *pctx, const cfg_type_t *type, + cfg_obj_t **ret) { + return (parse_enum_or_other(pctx, type, &cfg_type_boolean, ret)); +} +static cfg_type_t cfg_type_v4_aaaa = { + "v4_aaaa", parse_v4_aaaa, cfg_print_ustring, + doc_enum_or_other, &cfg_rep_string, v4_aaaa_enums, +}; + static keyword_type_t key_kw = { "key", &cfg_type_astring }; LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_keyref = { @@ -2082,6 +2571,15 @@ LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_rndckey = { &cfg_rep_map, rndckey_clausesets }; +/* + * session.key has exactly the same syntax as rndc.key, but it's defined + * separately for clarity (and so we can extend it someday, if needed). + */ +LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_sessionkey = { + "sessionkey", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody, + &cfg_rep_map, rndckey_clausesets +}; + static cfg_tuplefielddef_t nameport_fields[] = { { "name", &cfg_type_astring, 0 }, { "port", &cfg_type_optional_port, 0 }, diff --git a/lib/isccfg/parser.c b/lib/isccfg/parser.c index 2f64a09..87ad391 100644 --- a/lib/isccfg/parser.c +++ b/lib/isccfg/parser.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: parser.c,v 1.129 2008-09-25 04:02:39 tbox Exp $ */ +/* $Id: parser.c,v 1.139 2011-01-04 23:47:14 tbox Exp $ */ /*! \file */ @@ -29,12 +29,12 @@ #include #include #include +#include #include #include #include -#include -#include #include +#include #include #include @@ -387,6 +387,12 @@ cfg_parser_create(isc_mem_t *mctx, isc_log_t *lctx, cfg_parser_t **ret) { if (pctx == NULL) return (ISC_R_NOMEMORY); + result = isc_refcount_init(&pctx->references, 1); + if (result != ISC_R_SUCCESS) { + isc_mem_put(mctx, pctx, sizeof(*pctx)); + return (result); + } + pctx->mctx = mctx; pctx->lctx = lctx; pctx->lexer = NULL; @@ -400,6 +406,7 @@ cfg_parser_create(isc_mem_t *mctx, isc_log_t *lctx, cfg_parser_t **ret) { pctx->callback = NULL; pctx->callbackarg = NULL; pctx->token.type = isc_tokentype_unknown; + pctx->flags = 0; memset(specials, 0, sizeof(specials)); specials['{'] = 1; @@ -526,17 +533,30 @@ cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer, } void +cfg_parser_attach(cfg_parser_t *src, cfg_parser_t **dest) { + REQUIRE(src != NULL); + REQUIRE(dest != NULL && *dest == NULL); + isc_refcount_increment(&src->references, NULL); + *dest = src; +} + +void cfg_parser_destroy(cfg_parser_t **pctxp) { cfg_parser_t *pctx = *pctxp; - isc_lex_destroy(&pctx->lexer); - /* - * Cleaning up open_files does not - * close the files; that was already done - * by closing the lexer. - */ - CLEANUP_OBJ(pctx->open_files); - CLEANUP_OBJ(pctx->closed_files); - isc_mem_put(pctx->mctx, pctx, sizeof(*pctx)); + unsigned int refs; + + isc_refcount_decrement(&pctx->references, &refs); + if (refs == 0) { + isc_lex_destroy(&pctx->lexer); + /* + * Cleaning up open_files does not + * close the files; that was already done + * by closing the lexer. + */ + CLEANUP_OBJ(pctx->open_files); + CLEANUP_OBJ(pctx->closed_files); + isc_mem_put(pctx->mctx, pctx, sizeof(*pctx)); + } *pctxp = NULL; } @@ -848,8 +868,8 @@ cfg_obj_asboolean(const cfg_obj_t *obj) { return (obj->value.boolean); } -static isc_result_t -parse_boolean(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) +isc_result_t +cfg_parse_boolean(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { isc_result_t result; isc_boolean_t value; @@ -888,8 +908,8 @@ parse_boolean(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) return (result); } -static void -print_boolean(cfg_printer_t *pctx, const cfg_obj_t *obj) { +void +cfg_print_boolean(cfg_printer_t *pctx, const cfg_obj_t *obj) { if (obj->value.boolean) cfg_print_chars(pctx, "yes", 3); else @@ -897,7 +917,7 @@ print_boolean(cfg_printer_t *pctx, const cfg_obj_t *obj) { } cfg_type_t cfg_type_boolean = { - "boolean", parse_boolean, print_boolean, cfg_doc_terminal, + "boolean", cfg_parse_boolean, cfg_print_boolean, cfg_doc_terminal, &cfg_rep_boolean, NULL }; @@ -1132,7 +1152,7 @@ cfg_list_length(const cfg_obj_t *obj, isc_boolean_t recurse) { return (count); } -const cfg_obj_t * +cfg_obj_t * cfg_listelt_value(const cfg_listelt_t *elt) { REQUIRE(elt != NULL); return (elt->obj); @@ -1237,6 +1257,14 @@ cfg_parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) if ((clause->flags & CFG_CLAUSEFLAG_NYI) != 0) cfg_parser_warning(pctx, 0, "option '%s' is " "not implemented", clause->name); + + if ((clause->flags & CFG_CLAUSEFLAG_NOTCONFIGURED) != 0) { + cfg_parser_warning(pctx, 0, "option '%s' is not " + "configured", clause->name); + result = ISC_R_FAILURE; + goto cleanup; + } + /* * Don't log options with CFG_CLAUSEFLAG_NEWDEFAULT * set here - we need to log the *lack* of such an option, @@ -1478,6 +1506,7 @@ static struct flagtext { { CFG_CLAUSEFLAG_OBSOLETE, "obsolete" }, { CFG_CLAUSEFLAG_NEWDEFAULT, "default changed" }, { CFG_CLAUSEFLAG_TESTONLY, "test only" }, + { CFG_CLAUSEFLAG_NOTCONFIGURED, "not configured" }, { 0, NULL } }; @@ -2305,6 +2334,7 @@ cfg_obj_line(const cfg_obj_t *obj) { isc_result_t cfg_create_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { + isc_result_t result; cfg_obj_t *obj; obj = isc_mem_get(pctx->mctx, sizeof(cfg_obj_t)); @@ -2313,10 +2343,16 @@ cfg_create_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { obj->type = type; obj->file = current_file(pctx); obj->line = pctx->line; + result = isc_refcount_init(&obj->references, 1); + if (result != ISC_R_SUCCESS) { + isc_mem_put(pctx->mctx, obj, sizeof(cfg_obj_t)); + return (result); + } *ret = obj; return (ISC_R_SUCCESS); } + static void map_symtabitem_destroy(char *key, unsigned int type, isc_symvalue_t symval, void *userarg) @@ -2370,11 +2406,25 @@ cfg_obj_istype(const cfg_obj_t *obj, const cfg_type_t *type) { void cfg_obj_destroy(cfg_parser_t *pctx, cfg_obj_t **objp) { cfg_obj_t *obj = *objp; - obj->type->rep->free(pctx, obj); - isc_mem_put(pctx->mctx, obj, sizeof(cfg_obj_t)); + unsigned int refs; + + isc_refcount_decrement(&obj->references, &refs); + if (refs == 0) { + obj->type->rep->free(pctx, obj); + isc_refcount_destroy(&obj->references); + isc_mem_put(pctx->mctx, obj, sizeof(cfg_obj_t)); + } *objp = NULL; } +void +cfg_obj_attach(cfg_obj_t *src, cfg_obj_t **dest) { + REQUIRE(src != NULL); + REQUIRE(dest != NULL && *dest == NULL); + isc_refcount_increment(&src->references, NULL); + *dest = src; +} + static void free_noop(cfg_parser_t *pctx, cfg_obj_t *obj) { UNUSED(pctx); diff --git a/lib/lwres/api b/lib/lwres/api index fbbf923..94575eb 100644 --- a/lib/lwres/api +++ b/lib/lwres/api @@ -1,3 +1,3 @@ -LIBINTERFACE = 50 -LIBREVISION = 3 +LIBINTERFACE = 80 +LIBREVISION = 0 LIBAGE = 0 diff --git a/lib/lwres/context.c b/lib/lwres/context.c index 1310022..e8f0eda 100644 --- a/lib/lwres/context.c +++ b/lib/lwres/context.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: context.c,v 1.50.332.5 2009-09-01 23:47:05 tbox Exp $ */ +/* $Id: context.c,v 1.55 2009-09-02 23:48:03 tbox Exp $ */ /*! \file context.c lwres_context_create() creates a #lwres_context_t structure for use in diff --git a/lib/lwres/context_p.h b/lib/lwres/context_p.h index 663b1da..0976951 100644 --- a/lib/lwres/context_p.h +++ b/lib/lwres/context_p.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: context_p.h,v 1.17.332.2 2008-12-30 23:46:49 tbox Exp $ */ +/* $Id: context_p.h,v 1.19 2008-12-17 23:47:58 tbox Exp $ */ #ifndef LWRES_CONTEXT_P_H #define LWRES_CONTEXT_P_H 1 diff --git a/lib/lwres/getaddrinfo.c b/lib/lwres/getaddrinfo.c index 665205a..81534fc 100644 --- a/lib/lwres/getaddrinfo.c +++ b/lib/lwres/getaddrinfo.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * This code is derived from software contributed to ISC by @@ -18,7 +18,7 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: getaddrinfo.c,v 1.52.254.2 2009-03-31 23:47:16 tbox Exp $ */ +/* $Id: getaddrinfo.c,v 1.54 2008-11-25 23:47:23 tbox Exp $ */ /*! \file */ diff --git a/lib/lwres/getipnode.c b/lib/lwres/getipnode.c index b9eadee..bc90c74 100644 --- a/lib/lwres/getipnode.c +++ b/lib/lwres/getipnode.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: getipnode.c,v 1.42.332.5 2009-09-01 23:47:05 tbox Exp $ */ +/* $Id: getipnode.c,v 1.47 2009-09-01 23:47:45 tbox Exp $ */ /*! \file */ diff --git a/lib/lwres/include/lwres/context.h b/lib/lwres/include/lwres/context.h index 46be27a..2421b57 100644 --- a/lib/lwres/include/lwres/context.h +++ b/lib/lwres/include/lwres/context.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: context.h,v 1.21.332.2 2008-12-30 23:46:49 tbox Exp $ */ +/* $Id: context.h,v 1.23 2008-12-17 23:47:58 tbox Exp $ */ #ifndef LWRES_CONTEXT_H #define LWRES_CONTEXT_H 1 diff --git a/lib/lwres/include/lwres/netdb.h.in b/lib/lwres/include/lwres/netdb.h.in index 7531ca3..8eedd27 100644 --- a/lib/lwres/include/lwres/netdb.h.in +++ b/lib/lwres/include/lwres/netdb.h.in @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: netdb.h.in,v 1.39.332.2 2009-01-18 23:47:41 tbox Exp $ */ +/* $Id: netdb.h.in,v 1.41 2009-01-18 23:48:14 tbox Exp $ */ /*! \file */ diff --git a/lib/lwres/lwconfig.c b/lib/lwres/lwconfig.c index 356c106..764ff2a 100644 --- a/lib/lwres/lwconfig.c +++ b/lib/lwres/lwconfig.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lwconfig.c,v 1.46.332.2 2008-12-30 23:46:49 tbox Exp $ */ +/* $Id: lwconfig.c,v 1.48 2008-12-17 23:47:58 tbox Exp $ */ /*! \file */ diff --git a/lib/lwres/man/lwres.3 b/lib/lwres/man/lwres.3 index 77f96b6..c2c0bb6 100644 --- a/lib/lwres/man/lwres.3 +++ b/lib/lwres/man/lwres.3 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: lwres.3,v 1.28.418.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: lwres.3,v 1.29 2009-07-11 01:12:46 tbox Exp $ .\" .hy 0 .ad l diff --git a/lib/lwres/man/lwres.html b/lib/lwres/man/lwres.html index 3844c01..6cfb750 100644 --- a/lib/lwres/man/lwres.html +++ b/lib/lwres/man/lwres.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -22,7 +22,7 @@
    -
    +

    Name

    lwres — introduction to the lightweight resolver library

    @@ -32,7 +32,7 @@
    #include <lwres/lwres.h>
    -

    DESCRIPTION

    +

    DESCRIPTION

    The BIND 9 lightweight resolver library is a simple, name service independent stub resolver library. It provides hostname-to-address @@ -47,7 +47,7 @@

    -

    OVERVIEW

    +

    OVERVIEW

    The lwresd library implements multiple name service APIs. The standard @@ -101,7 +101,7 @@

    -

    CLIENT-SIDE LOW-LEVEL API CALL FLOW

    +

    CLIENT-SIDE LOW-LEVEL API CALL FLOW

    When a client program wishes to make an lwres request using the native low-level API, it typically performs the following @@ -149,7 +149,7 @@

    -

    SERVER-SIDE LOW-LEVEL API CALL FLOW

    +

    SERVER-SIDE LOW-LEVEL API CALL FLOW

    When implementing the server side of the lightweight resolver protocol using the lwres library, a sequence of actions like the @@ -191,7 +191,7 @@

    -

    SEE ALSO

    +

    SEE ALSO

    lwres_gethostent(3), lwres_getipnode(3), diff --git a/lib/lwres/man/lwres_buffer.3 b/lib/lwres/man/lwres_buffer.3 index 89b9b65..0fc5225 100644 --- a/lib/lwres/man/lwres_buffer.3 +++ b/lib/lwres/man/lwres_buffer.3 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: lwres_buffer.3,v 1.26.418.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: lwres_buffer.3,v 1.27 2009-07-11 01:12:46 tbox Exp $ .\" .hy 0 .ad l diff --git a/lib/lwres/man/lwres_buffer.html b/lib/lwres/man/lwres_buffer.html index 7f3934a..b7e034f 100644 --- a/lib/lwres/man/lwres_buffer.html +++ b/lib/lwres/man/lwres_buffer.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -22,7 +22,7 @@

    -
    +

    Name

    lwres_buffer_init, lwres_buffer_invalidate, lwres_buffer_add, lwres_buffer_subtract, lwres_buffer_clear, lwres_buffer_first, lwres_buffer_forward, lwres_buffer_back, lwres_buffer_getuint8, lwres_buffer_putuint8, lwres_buffer_getuint16, lwres_buffer_putuint16, lwres_buffer_getuint32, lwres_buffer_putuint32, lwres_buffer_putmem, lwres_buffer_getmem — lightweight resolver buffer management

    @@ -262,7 +262,7 @@ void
    -

    DESCRIPTION

    +

    DESCRIPTION

    These functions provide bounds checked access to a region of memory where data is being read or written. diff --git a/lib/lwres/man/lwres_config.3 b/lib/lwres/man/lwres_config.3 index 5b8a728..0ea1320 100644 --- a/lib/lwres/man/lwres_config.3 +++ b/lib/lwres/man/lwres_config.3 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: lwres_config.3,v 1.26.418.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: lwres_config.3,v 1.27 2009-07-11 01:12:46 tbox Exp $ .\" .hy 0 .ad l diff --git a/lib/lwres/man/lwres_config.html b/lib/lwres/man/lwres_config.html index 2cee5ef..8c330a3 100644 --- a/lib/lwres/man/lwres_config.html +++ b/lib/lwres/man/lwres_config.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -22,7 +22,7 @@

    -
    +

    Name

    lwres_conf_init, lwres_conf_clear, lwres_conf_parse, lwres_conf_print, lwres_conf_get — lightweight resolver configuration

    @@ -90,7 +90,7 @@ lwres_conf_t *
    -

    DESCRIPTION

    +

    DESCRIPTION

    lwres_conf_init() creates an empty lwres_conf_t @@ -123,7 +123,7 @@ lwres_conf_t *

    -

    RETURN VALUES

    +

    RETURN VALUES

    lwres_conf_parse() returns LWRES_R_SUCCESS if it successfully read and parsed @@ -142,13 +142,13 @@ lwres_conf_t *

    -

    SEE ALSO

    +

    SEE ALSO

    stdio(3), resolver(5).

    -

    FILES

    +

    FILES

    /etc/resolv.conf

    diff --git a/lib/lwres/man/lwres_context.3 b/lib/lwres/man/lwres_context.3 index a96a075..fdcaf55 100644 --- a/lib/lwres/man/lwres_context.3 +++ b/lib/lwres/man/lwres_context.3 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: lwres_context.3,v 1.28.418.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: lwres_context.3,v 1.29 2009-07-11 01:12:46 tbox Exp $ .\" .hy 0 .ad l diff --git a/lib/lwres/man/lwres_context.html b/lib/lwres/man/lwres_context.html index d525a4b..50d5d9f 100644 --- a/lib/lwres/man/lwres_context.html +++ b/lib/lwres/man/lwres_context.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -22,7 +22,7 @@
    -
    +

    Name

    lwres_context_create, lwres_context_destroy, lwres_context_nextserial, lwres_context_initserial, lwres_context_freemem, lwres_context_allocmem, lwres_context_sendrecv — lightweight resolver context management

    @@ -172,7 +172,7 @@ void *
    -

    DESCRIPTION

    +

    DESCRIPTION

    lwres_context_create() creates a lwres_context_t structure for use in lightweight resolver operations. It holds a socket and other @@ -258,7 +258,7 @@ void *

    -

    RETURN VALUES

    +

    RETURN VALUES

    lwres_context_create() returns LWRES_R_NOMEMORY if memory for the struct lwres_context could not be allocated, @@ -283,7 +283,7 @@ void *

    -

    SEE ALSO

    +

    SEE ALSO

    lwres_conf_init(3), malloc(3), diff --git a/lib/lwres/man/lwres_gabn.3 b/lib/lwres/man/lwres_gabn.3 index 28ea7e1..769c952 100644 --- a/lib/lwres/man/lwres_gabn.3 +++ b/lib/lwres/man/lwres_gabn.3 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: lwres_gabn.3,v 1.27.418.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: lwres_gabn.3,v 1.28 2009-07-11 01:12:46 tbox Exp $ .\" .hy 0 .ad l diff --git a/lib/lwres/man/lwres_gabn.html b/lib/lwres/man/lwres_gabn.html index b69f432..32b5f21 100644 --- a/lib/lwres/man/lwres_gabn.html +++ b/lib/lwres/man/lwres_gabn.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -22,7 +22,7 @@

    -
    +

    Name

    lwres_gabnrequest_render, lwres_gabnresponse_render, lwres_gabnrequest_parse, lwres_gabnresponse_parse, lwres_gabnresponse_free, lwres_gabnrequest_free — lightweight resolver getaddrbyname message handling

    @@ -178,7 +178,7 @@ void
    -

    DESCRIPTION

    +

    DESCRIPTION

    These are low-level routines for creating and parsing lightweight resolver name-to-address lookup request and @@ -278,7 +278,7 @@ typedef struct {

    -

    RETURN VALUES

    +

    RETURN VALUES

    The getaddrbyname opcode functions lwres_gabnrequest_render(), @@ -316,7 +316,7 @@ typedef struct {

    -

    SEE ALSO

    +

    SEE ALSO

    lwres_packet(3)

    diff --git a/lib/lwres/man/lwres_gai_strerror.3 b/lib/lwres/man/lwres_gai_strerror.3 index 3d80727..2527896 100644 --- a/lib/lwres/man/lwres_gai_strerror.3 +++ b/lib/lwres/man/lwres_gai_strerror.3 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: lwres_gai_strerror.3,v 1.27.418.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: lwres_gai_strerror.3,v 1.28 2009-07-11 01:12:46 tbox Exp $ .\" .hy 0 .ad l diff --git a/lib/lwres/man/lwres_gai_strerror.html b/lib/lwres/man/lwres_gai_strerror.html index 616eebe..9ff330b 100644 --- a/lib/lwres/man/lwres_gai_strerror.html +++ b/lib/lwres/man/lwres_gai_strerror.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -22,7 +22,7 @@
    -
    +

    Name

    lwres_gai_strerror — print suitable error string

    @@ -42,7 +42,7 @@ char *
    -

    DESCRIPTION

    +

    DESCRIPTION

    lwres_gai_strerror() returns an error message corresponding to an error code returned by getaddrinfo(). @@ -110,7 +110,7 @@ char *

    -

    SEE ALSO

    +

    SEE ALSO

    strerror(3), lwres_getaddrinfo(3), diff --git a/lib/lwres/man/lwres_getaddrinfo.3 b/lib/lwres/man/lwres_getaddrinfo.3 index 2953f3b..cfc4aec 100644 --- a/lib/lwres/man/lwres_getaddrinfo.3 +++ b/lib/lwres/man/lwres_getaddrinfo.3 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: lwres_getaddrinfo.3,v 1.31.418.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: lwres_getaddrinfo.3,v 1.32 2009-07-11 01:12:46 tbox Exp $ .\" .hy 0 .ad l diff --git a/lib/lwres/man/lwres_getaddrinfo.html b/lib/lwres/man/lwres_getaddrinfo.html index 013e878..d367f51 100644 --- a/lib/lwres/man/lwres_getaddrinfo.html +++ b/lib/lwres/man/lwres_getaddrinfo.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -22,7 +22,7 @@

    -
    +

    Name

    lwres_getaddrinfo, lwres_freeaddrinfo — socket address structure to host and service name

    @@ -89,7 +89,7 @@ struct addrinfo {

    -

    DESCRIPTION

    +

    DESCRIPTION

    lwres_getaddrinfo() is used to get a list of IP addresses and port numbers for host hostname and service @@ -283,7 +283,7 @@ struct addrinfo {

    -

    RETURN VALUES

    +

    RETURN VALUES

    lwres_getaddrinfo() returns zero on success or one of the error codes listed in gai_strerror(3) @@ -294,7 +294,7 @@ struct addrinfo {

    -

    SEE ALSO

    +

    SEE ALSO

    lwres(3), lwres_getaddrinfo(3), diff --git a/lib/lwres/man/lwres_gethostent.3 b/lib/lwres/man/lwres_gethostent.3 index 35ea1c2..7acc506 100644 --- a/lib/lwres/man/lwres_gethostent.3 +++ b/lib/lwres/man/lwres_gethostent.3 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: lwres_gethostent.3,v 1.29.418.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: lwres_gethostent.3,v 1.30 2009-07-11 01:12:46 tbox Exp $ .\" .hy 0 .ad l diff --git a/lib/lwres/man/lwres_gethostent.html b/lib/lwres/man/lwres_gethostent.html index fd27dcf..fdaa062 100644 --- a/lib/lwres/man/lwres_gethostent.html +++ b/lib/lwres/man/lwres_gethostent.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -22,7 +22,7 @@

    -
    +

    Name

    lwres_gethostbyname, lwres_gethostbyname2, lwres_gethostbyaddr, lwres_gethostent, lwres_sethostent, lwres_endhostent, lwres_gethostbyname_r, lwres_gethostbyaddr_r, lwres_gethostent_r, lwres_sethostent_r, lwres_endhostent_r — lightweight resolver get network host entry

    @@ -228,7 +228,7 @@ void
    -

    DESCRIPTION

    +

    DESCRIPTION

    These functions provide hostname-to-address and address-to-hostname lookups by means of the lightweight resolver. @@ -366,7 +366,7 @@ struct hostent {

    -

    RETURN VALUES

    +

    RETURN VALUES

    The functions lwres_gethostbyname(), @@ -430,7 +430,7 @@ struct hostent {

    -

    SEE ALSO

    +

    SEE ALSO

    gethostent(3), lwres_getipnode(3), @@ -439,7 +439,7 @@ struct hostent {

    -

    BUGS

    +

    BUGS

    lwres_gethostbyname(), lwres_gethostbyname2(), lwres_gethostbyaddr() diff --git a/lib/lwres/man/lwres_getipnode.3 b/lib/lwres/man/lwres_getipnode.3 index b46e78f..40ba59c 100644 --- a/lib/lwres/man/lwres_getipnode.3 +++ b/lib/lwres/man/lwres_getipnode.3 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: lwres_getipnode.3,v 1.28.418.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: lwres_getipnode.3,v 1.29 2009-07-11 01:12:46 tbox Exp $ .\" .hy 0 .ad l diff --git a/lib/lwres/man/lwres_getipnode.html b/lib/lwres/man/lwres_getipnode.html index 20c6d30..9f54cb6 100644 --- a/lib/lwres/man/lwres_getipnode.html +++ b/lib/lwres/man/lwres_getipnode.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -22,7 +22,7 @@

    -
    +

    Name

    lwres_getipnodebyname, lwres_getipnodebyaddr, lwres_freehostent — lightweight resolver nodename / address translation API

    @@ -98,7 +98,7 @@ void
    -

    DESCRIPTION

    +

    DESCRIPTION

    These functions perform thread safe, protocol independent nodename-to-address and address-to-nodename @@ -217,7 +217,7 @@ struct hostent {

    -

    RETURN VALUES

    +

    RETURN VALUES

    If an error occurs, lwres_getipnodebyname() @@ -261,7 +261,7 @@ struct hostent {

    -

    SEE ALSO

    +

    SEE ALSO

    RFC2553, lwres(3), diff --git a/lib/lwres/man/lwres_getnameinfo.3 b/lib/lwres/man/lwres_getnameinfo.3 index 3a75efb..5674fb2 100644 --- a/lib/lwres/man/lwres_getnameinfo.3 +++ b/lib/lwres/man/lwres_getnameinfo.3 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: lwres_getnameinfo.3,v 1.29.418.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: lwres_getnameinfo.3,v 1.30 2009-07-11 01:12:46 tbox Exp $ .\" .hy 0 .ad l diff --git a/lib/lwres/man/lwres_getnameinfo.html b/lib/lwres/man/lwres_getnameinfo.html index fb7837f..1048543 100644 --- a/lib/lwres/man/lwres_getnameinfo.html +++ b/lib/lwres/man/lwres_getnameinfo.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -22,7 +22,7 @@

    -
    +

    Name

    lwres_getnameinfo — lightweight resolver socket address structure to hostname and @@ -82,7 +82,7 @@ int

    -

    DESCRIPTION

    +

    DESCRIPTION

    This function is equivalent to the getnameinfo(3) function defined in RFC2133. @@ -149,13 +149,13 @@ int

    -

    RETURN VALUES

    +

    RETURN VALUES

    lwres_getnameinfo() returns 0 on success or a non-zero error code if an error occurs.

    -

    SEE ALSO

    +

    SEE ALSO

    RFC2133, getservbyport(3), lwres(3), @@ -165,7 +165,7 @@ int

    -

    BUGS

    +

    BUGS

    RFC2133 fails to define what the nonzero return values of getnameinfo(3) diff --git a/lib/lwres/man/lwres_getrrsetbyname.3 b/lib/lwres/man/lwres_getrrsetbyname.3 index c804e11..2aa1a9c 100644 --- a/lib/lwres/man/lwres_getrrsetbyname.3 +++ b/lib/lwres/man/lwres_getrrsetbyname.3 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: lwres_getrrsetbyname.3,v 1.25.418.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: lwres_getrrsetbyname.3,v 1.26 2009-07-11 01:12:46 tbox Exp $ .\" .hy 0 .ad l diff --git a/lib/lwres/man/lwres_getrrsetbyname.html b/lib/lwres/man/lwres_getrrsetbyname.html index 9d9dc04..3a7fb9f 100644 --- a/lib/lwres/man/lwres_getrrsetbyname.html +++ b/lib/lwres/man/lwres_getrrsetbyname.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -22,7 +22,7 @@

    -
    +

    Name

    lwres_getrrsetbyname, lwres_freerrset — retrieve DNS records

    @@ -102,7 +102,7 @@ struct rrsetinfo {

    -

    DESCRIPTION

    +

    DESCRIPTION

    lwres_getrrsetbyname() gets a set of resource records associated with a hostname, class, @@ -150,7 +150,7 @@ struct rrsetinfo {

    -

    RETURN VALUES

    +

    RETURN VALUES

    lwres_getrrsetbyname() returns zero on success, and one of the following error codes if an error occurred: @@ -184,7 +184,7 @@ struct rrsetinfo {

    -

    SEE ALSO

    +

    SEE ALSO

    lwres(3).

    diff --git a/lib/lwres/man/lwres_gnba.3 b/lib/lwres/man/lwres_gnba.3 index b34fc05..ad9d627 100644 --- a/lib/lwres/man/lwres_gnba.3 +++ b/lib/lwres/man/lwres_gnba.3 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: lwres_gnba.3,v 1.27.418.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: lwres_gnba.3,v 1.28 2009-07-11 01:12:46 tbox Exp $ .\" .hy 0 .ad l diff --git a/lib/lwres/man/lwres_gnba.html b/lib/lwres/man/lwres_gnba.html index 158f4d0..8c7691e 100644 --- a/lib/lwres/man/lwres_gnba.html +++ b/lib/lwres/man/lwres_gnba.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -22,7 +22,7 @@
    -
    +

    Name

    lwres_gnbarequest_render, lwres_gnbaresponse_render, lwres_gnbarequest_parse, lwres_gnbaresponse_parse, lwres_gnbaresponse_free, lwres_gnbarequest_free — lightweight resolver getnamebyaddress message handling

    @@ -183,7 +183,7 @@ void
    -

    DESCRIPTION

    +

    DESCRIPTION

    These are low-level routines for creating and parsing lightweight resolver address-to-name lookup request and @@ -270,7 +270,7 @@ typedef struct {

    -

    RETURN VALUES

    +

    RETURN VALUES

    The getnamebyaddr opcode functions lwres_gnbarequest_render(), @@ -308,7 +308,7 @@ typedef struct {

    -

    SEE ALSO

    +

    SEE ALSO

    lwres_packet(3).

    diff --git a/lib/lwres/man/lwres_hstrerror.3 b/lib/lwres/man/lwres_hstrerror.3 index f65ba54..b9d5316 100644 --- a/lib/lwres/man/lwres_hstrerror.3 +++ b/lib/lwres/man/lwres_hstrerror.3 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: lwres_hstrerror.3,v 1.27.418.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: lwres_hstrerror.3,v 1.28 2009-07-11 01:12:46 tbox Exp $ .\" .hy 0 .ad l diff --git a/lib/lwres/man/lwres_hstrerror.html b/lib/lwres/man/lwres_hstrerror.html index d5d25ec..df1c425 100644 --- a/lib/lwres/man/lwres_hstrerror.html +++ b/lib/lwres/man/lwres_hstrerror.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -22,7 +22,7 @@
    -
    +

    Name

    lwres_herror, lwres_hstrerror — lightweight resolver error message generation

    @@ -50,7 +50,7 @@ const char *
    -

    DESCRIPTION

    +

    DESCRIPTION

    lwres_herror() prints the string s on stderr followed by the string generated by @@ -84,7 +84,7 @@ const char *

    -

    RETURN VALUES

    +

    RETURN VALUES

    The string Unknown resolver error is returned by lwres_hstrerror() @@ -94,7 +94,7 @@ const char *

    -

    SEE ALSO

    +

    SEE ALSO

    herror(3), lwres_hstrerror(3). diff --git a/lib/lwres/man/lwres_inetntop.3 b/lib/lwres/man/lwres_inetntop.3 index 6bd063a..be85906 100644 --- a/lib/lwres/man/lwres_inetntop.3 +++ b/lib/lwres/man/lwres_inetntop.3 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: lwres_inetntop.3,v 1.26.418.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: lwres_inetntop.3,v 1.27 2009-07-11 01:12:46 tbox Exp $ .\" .hy 0 .ad l diff --git a/lib/lwres/man/lwres_inetntop.html b/lib/lwres/man/lwres_inetntop.html index 8467e4b..f0ea41a 100644 --- a/lib/lwres/man/lwres_inetntop.html +++ b/lib/lwres/man/lwres_inetntop.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -22,7 +22,7 @@

    -
    +

    Name

    lwres_net_ntop — lightweight resolver IP address presentation

    @@ -62,7 +62,7 @@ const char *
    -

    DESCRIPTION

    +

    DESCRIPTION

    lwres_net_ntop() converts an IP address of protocol family af — IPv4 or IPv6 — at @@ -80,7 +80,7 @@ const char *

    -

    RETURN VALUES

    +

    RETURN VALUES

    If successful, the function returns dst: a pointer to a string containing the presentation format of the @@ -93,7 +93,7 @@ const char *

    -

    SEE ALSO

    +

    SEE ALSO

    RFC1884, inet_ntop(3), errno(3). diff --git a/lib/lwres/man/lwres_noop.3 b/lib/lwres/man/lwres_noop.3 index fd05e7e..3be40b2 100644 --- a/lib/lwres/man/lwres_noop.3 +++ b/lib/lwres/man/lwres_noop.3 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: lwres_noop.3,v 1.28.418.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: lwres_noop.3,v 1.29 2009-07-11 01:12:46 tbox Exp $ .\" .hy 0 .ad l diff --git a/lib/lwres/man/lwres_noop.html b/lib/lwres/man/lwres_noop.html index 4a94836..8f9d402 100644 --- a/lib/lwres/man/lwres_noop.html +++ b/lib/lwres/man/lwres_noop.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -22,7 +22,7 @@

    -
    +

    Name

    lwres_nooprequest_render, lwres_noopresponse_render, lwres_nooprequest_parse, lwres_noopresponse_parse, lwres_noopresponse_free, lwres_nooprequest_free — lightweight resolver no-op message handling

    @@ -179,7 +179,7 @@ void
    -

    DESCRIPTION

    +

    DESCRIPTION

    These are low-level routines for creating and parsing lightweight resolver no-op request and response messages. @@ -270,7 +270,7 @@ typedef struct {

    -

    RETURN VALUES

    +

    RETURN VALUES

    The no-op opcode functions lwres_nooprequest_render(), @@ -309,7 +309,7 @@ typedef struct {

    -

    SEE ALSO

    +

    SEE ALSO

    lwres_packet(3)

    diff --git a/lib/lwres/man/lwres_packet.3 b/lib/lwres/man/lwres_packet.3 index 5c096b5..ad4a82c 100644 --- a/lib/lwres/man/lwres_packet.3 +++ b/lib/lwres/man/lwres_packet.3 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: lwres_packet.3,v 1.29.418.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: lwres_packet.3,v 1.30 2009-07-11 01:12:46 tbox Exp $ .\" .hy 0 .ad l diff --git a/lib/lwres/man/lwres_packet.html b/lib/lwres/man/lwres_packet.html index 096b4bb..84eafc1 100644 --- a/lib/lwres/man/lwres_packet.html +++ b/lib/lwres/man/lwres_packet.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -22,7 +22,7 @@
    -
    +

    Name

    lwres_lwpacket_renderheader, lwres_lwpacket_parseheader — lightweight resolver packet handling functions

    @@ -66,7 +66,7 @@ lwres_result_t
    -

    DESCRIPTION

    +

    DESCRIPTION

    These functions rely on a struct lwres_lwpacket @@ -219,7 +219,7 @@ struct lwres_lwpacket {

    -

    RETURN VALUES

    +

    RETURN VALUES

    Successful calls to lwres_lwpacket_renderheader() and diff --git a/lib/lwres/man/lwres_resutil.3 b/lib/lwres/man/lwres_resutil.3 index 6e17797..04cad4e 100644 --- a/lib/lwres/man/lwres_resutil.3 +++ b/lib/lwres/man/lwres_resutil.3 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: lwres_resutil.3,v 1.28.418.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: lwres_resutil.3,v 1.29 2009-07-11 01:12:46 tbox Exp $ .\" .hy 0 .ad l diff --git a/lib/lwres/man/lwres_resutil.html b/lib/lwres/man/lwres_resutil.html index 1d2aa76..b4de764 100644 --- a/lib/lwres/man/lwres_resutil.html +++ b/lib/lwres/man/lwres_resutil.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -22,7 +22,7 @@

    -
    +

    Name

    lwres_string_parse, lwres_addr_parse, lwres_getaddrsbyname, lwres_getnamebyaddr — lightweight resolver utility functions

    @@ -134,7 +134,7 @@ lwres_result_t
    -

    DESCRIPTION

    +

    DESCRIPTION

    lwres_string_parse() retrieves a DNS-encoded string starting the current pointer of lightweight resolver buffer b: i.e. @@ -210,7 +210,7 @@ typedef struct {

    -

    RETURN VALUES

    +

    RETURN VALUES

    Successful calls to lwres_string_parse() @@ -248,7 +248,7 @@ typedef struct {

    -

    SEE ALSO

    +

    SEE ALSO

    lwres_buffer(3), lwres_gabn(3). diff --git a/lib/lwres/print_p.h b/lib/lwres/print_p.h index e2f6ad6..ed71535 100644 --- a/lib/lwres/print_p.h +++ b/lib/lwres/print_p.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: print_p.h,v 1.4.332.2 2010-08-16 23:45:48 tbox Exp $ */ +/* $Id: print_p.h,v 1.6 2010-08-16 23:46:52 tbox Exp $ */ #ifndef LWRES_PRINT_P_H #define LWRES_PRINT_P_H 1 diff --git a/make/rules.in b/make/rules.in index d848480..12c9d5f 100644 --- a/make/rules.in +++ b/make/rules.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: rules.in,v 1.64.130.2 2009-01-10 23:46:57 tbox Exp $ +# $Id: rules.in,v 1.68 2009-09-01 18:40:25 jinmei Exp $ ### ### Common Makefile rules for BIND 9. @@ -35,6 +35,8 @@ sysconfdir = @sysconfdir@ localstatedir = @localstatedir@ mandir = @mandir@ datarootdir = @datarootdir@ +export_libdir = @export_libdir@ +export_includedir = @export_includedir@ DESTDIR = @@ -122,7 +124,7 @@ ALL_CPPFLAGS = \ ALL_CFLAGS = ${EXT_CFLAGS} ${ALL_CPPFLAGS} ${CFLAGS} \ ${ALWAYS_WARNINGS} ${STD_CWARNINGS} ${CWARNINGS} -.c.@O@: +@BIND9_CO_RULE@ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c $< SHELL = @SHELL@ @@ -134,12 +136,83 @@ PURIFY = @PURIFY@ MKDEP = ${SHELL} ${top_builddir}/make/mkdep +### +### This is a template compound command to build an executable binary with +### an internal symbol table. +### This process is tricky. We first link all objects including a tentative +### empty symbol table, then get a tentative list of symbols from the resulting +### binary ($@tmp0). Next, we re-link all objects, but this time with the +### symbol table just created ($tmp@1). The set of symbols should be the same, +### but the corresponding addresses would be changed due to the difference on +### the size of symbol tables. So we create the symbol table and re-create the +### objects once again. Finally, we check the symbol table embedded in the +### final binaryis consistent with the binary itself; otherwise the process is +### terminated. +### +### To minimize the overhead of creating symbol tables, the autoconf switch +### --enable-symtable takes an argument so that the symbol table can be created +### on a per application basis: unless the argument is set to "all", the symbol +### table is created only when a shell (environment) variable "MAKE_SYMTABLE" is +### set to a non-null value in the rule to build the executable binary. +### +### Each Makefile.in that uses this macro is expected to define "LIBS" and +### "NOSYMLIBS"; the former includes libisc with an empty symbol table, and +### the latter includes libisc without the definition of a symbol table. +### The rule to make the executable binary will look like this +### binary@EXEEXT@: ${OBJS} +### #export MAKE_SYMTABLE="yes"; \ <- enable if symtable is always needed +### export BASEOBJS="${OBJS}"; \ +### ${FINALBUILDCMD} +### +### Normally, ${LIBS} includes all necessary libraries to build the binary; +### there are some exceptions however, where the rule lists some of the +### necessary libraries explicitly in addition to (or instead of) ${LIBS}, +### like this: +### binary@EXEEXT@: ${OBJS} +### cc -o $@ ${OBJS} ${OTHERLIB1} ${OTHERLIB2} ${lIBS} +### in order to modify such a rule to use this compound command, a separate +### variable "LIBS0" should be deinfed for the explicitly listed libraries, +### while making sure ${LIBS} still includes libisc. So the above rule would +### be modified as follows: +### binary@EXEEXT@: ${OBJS} +### export BASEOBJS="${OBJS}"; \ +### export LIBS0="${OTHERLIB1} ${OTHERLIB2}"; \ +### ${FINALBUILDCMD} +### See bin/check/Makefile.in for a complete example of the use of LIBS0. +### +FINALBUILDCMD = if [ X"${MKSYMTBL_PROGRAM}" = X -o X"$${MAKE_SYMTABLE:-${ALWAYS_MAKE_SYMTABLE}}" = X ] ; then \ + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} \ + -o $@ $${BASEOBJS} $${LIBS0} ${LIBS}; \ + else \ + rm -f $@tmp0; \ + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} \ + -o $@tmp0 $${BASEOBJS} $${LIBS0} ${LIBS} || exit 1; \ + rm -f $@-symtbl.c $@-symtbl.@O@; \ + ${MKSYMTBL_PROGRAM} ${top_srcdir}/util/mksymtbl.pl \ + -o $@-symtbl.c $@tmp0 || exit 1; \ + $(MAKE) $@-symtbl.@O@ || exit 1; \ + rm -f $@tmp1; \ + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} \ + -o $@tmp1 $${BASEOBJS} $@-symtbl.@O@ $${LIBS0} ${NOSYMLIBS} || exit 1; \ + rm -f $@-symtbl.c $@-symtbl.@O@; \ + ${MKSYMTBL_PROGRAM} ${top_srcdir}/util/mksymtbl.pl \ + -o $@-symtbl.c $@tmp1 || exit 1; \ + $(MAKE) $@-symtbl.@O@ || exit 1; \ + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} \ + -o $@tmp2 $${BASEOBJS} $@-symtbl.@O@ $${LIBS0} ${NOSYMLIBS}; \ + ${MKSYMTBL_PROGRAM} ${top_srcdir}/util/mksymtbl.pl \ + -o $@-symtbl2.c $@tmp2; \ + diff $@-symtbl.c $@-symtbl2.c || exit 1;\ + mv $@tmp2 $@; \ + rm -f $@tmp0 $@tmp1 $@tmp2 $@-symtbl2.c; \ + fi + cleandir: distclean superclean: maintainer-clean clean distclean maintainer-clean:: - rm -f *.@O@ *.o *.lo *.la core *.core .depend - rm -rf .libs + rm -f *.@O@ *.o *.lo *.la core *.core *-symtbl.c *tmp0 *tmp1 *tmp2 + rm -rf .depend .libs distclean maintainer-clean:: rm -f Makefile @@ -217,6 +290,16 @@ PDFLATEX = @PDFLATEX@ W3M = @W3M@ ### +### Script language program used to create internal symbol tables +### +MKSYMTBL_PROGRAM = @MKSYMTBL_PROGRAM@ + +### +### Switch to create internal symbol table selectively +### +ALWAYS_MAKE_SYMTABLE = @ALWAYS_MAKE_SYMTABLE@ + +### ### DocBook -> HTML ### DocBook -> man page ### diff --git a/version b/version index e6bfe44..1d9fbd2 100644 --- a/version +++ b/version @@ -1,10 +1,10 @@ -# $Id: version,v 1.43.12.11.2.2.2.3 2011-06-21 20:35:59 each Exp $ +# $Id: version,v 1.53.8.2.2.4 2011-06-21 20:44:01 each Exp $ # # This file must follow /bin/sh rules. It is imported directly via # configure. # MAJORVER=9 -MINORVER=6 -PATCHVER= -RELEASETYPE=-ESV -RELEASEVER=-R4-P3 +MINORVER=8 +PATCHVER=0 +RELEASETYPE=-P +RELEASEVER=4 -- cgit v1.1